Merge remote-tracking branch 'origin/main' into notebook/dev

This commit is contained in:
rebornix 2021-04-01 12:27:15 -07:00
commit ef1e9bfa2c
No known key found for this signature in database
GPG key ID: 181FC90D15393C20
106 changed files with 1247 additions and 1069 deletions

View file

@ -223,6 +223,11 @@
"default": false,
"description": "%emmetPreferencesOutputReverseAttributes%"
},
"output.selfClosingStyle": {
"type": "string",
"default": "html",
"description": "%emmetPreferencesOutputSelfClosingStyle%"
},
"css.color.short": {
"type": "boolean",
"default": true,

View file

@ -57,5 +57,6 @@
"emmetOptimizeStylesheetParsing": "When set to `false`, the whole file is parsed to determine if current position is valid for expanding Emmet abbreviations. When set to `true`, only the content around the current position in CSS/SCSS/Less files is parsed.",
"emmetPreferencesOutputInlineBreak": "The number of sibling inline elements needed for line breaks to be placed between those elements. If `0`, inline elements are always expanded onto a single line.",
"emmetPreferencesOutputReverseAttributes": "If `true`, reverses attribute merging directions when resolving snippets.",
"emmetPreferencesOutputSelfClosingStyle": "Style of self-closing tags: html (`<br>`), xml (`<br/>`) or xhtml (`<br />`).",
"emmetPreferencesCssColorShort": "If `true`, color values like #f will be expanded to #fff instead of #ffffff."
}

View file

@ -19,7 +19,7 @@ export function nextItemHTML(document: vscode.TextDocument, selectionStart: vsco
if (currentNode.type !== 'comment') {
// If cursor is in the tag name, select tag
if (currentNode.open &&
selectionEndOffset < currentNode.open.start + currentNode.name.length) {
selectionEndOffset <= currentNode.open.start + currentNode.name.length) {
return getSelectionFromNode(document, currentNode);
}

View file

@ -439,7 +439,7 @@ suite('Tests for jsx, xml and xsl', () => {
return withRandomFileEditor('img', 'javascriptreact', async (editor, _doc) => {
editor.selection = new Selection(0, 6, 0, 6);
await expandEmmetAbbreviation({ language: 'javascriptreact' });
assert.strictEqual(editor.document.getText(), '<img src="" alt=""/>');
assert.strictEqual(editor.document.getText(), '<img src="" alt="" />');
return Promise.resolve();
});
});
@ -449,7 +449,7 @@ suite('Tests for jsx, xml and xsl', () => {
return withRandomFileEditor('img', 'javascriptreact', async (editor, _doc) => {
editor.selection = new Selection(0, 6, 0, 6);
await expandEmmetAbbreviation({ language: 'javascriptreact' });
assert.strictEqual(editor.document.getText(), '<img src=\'\' alt=\'\'/>');
assert.strictEqual(editor.document.getText(), '<img src=\'\' alt=\'\' />');
return workspace.getConfiguration('emmet').update('syntaxProfiles', oldValueForSyntaxProfiles ? oldValueForSyntaxProfiles.globalValue : undefined, ConfigurationTarget.Global);
});
});

View file

@ -84,19 +84,19 @@ export function migrateEmmetExtensionsPath() {
* Mapping between languages that support Emmet and completion trigger characters
*/
export const LANGUAGE_MODES: { [id: string]: string[] } = {
'html': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'jade': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'slim': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'haml': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'xml': ['.', '}', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'xsl': ['!', '.', '}', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'html': ['!', '.', '}', ':', '*', '$', ']', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'jade': ['!', '.', '}', ':', '*', '$', ']', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'slim': ['!', '.', '}', ':', '*', '$', ']', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'haml': ['!', '.', '}', ':', '*', '$', ']', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'xml': ['.', '}', '*', '$', ']', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'xsl': ['!', '.', '}', '*', '$', '/', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'css': [':', '!', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'scss': [':', '!', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'sass': [':', '!', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'less': [':', '!', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'stylus': [':', '!', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'javascriptreact': ['!', '.', '}', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'typescriptreact': ['!', '.', '}', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
'javascriptreact': ['!', '.', '}', '*', '$', ']', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'typescriptreact': ['!', '.', '}', '*', '$', ']', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
};
export function isStyleSheet(syntax: string): boolean {
@ -376,32 +376,36 @@ export const allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-t
* If position is inside a script tag of type template, then it will be parsed to find the inner HTML node as well
*/
export function getHtmlFlatNode(documentText: string, root: FlatNode | undefined, offset: number, includeNodeBoundary: boolean): HtmlFlatNode | undefined {
const currentNode: HtmlFlatNode | undefined = <HtmlFlatNode | undefined>getFlatNode(root, offset, includeNodeBoundary);
let currentNode: HtmlFlatNode | undefined = <HtmlFlatNode | undefined>getFlatNode(root, offset, includeNodeBoundary);
if (!currentNode) { return; }
const isTemplateScript = currentNode.name === 'script' &&
(currentNode.attributes &&
currentNode.attributes.some(x => x.name.toString() === 'type'
&& allowedMimeTypesInScriptTag.includes(x.value.toString())));
if (isTemplateScript
&& currentNode.open
&& offset > currentNode.open.end
&& (!currentNode.close || offset < currentNode.close.start)) {
// blank out the rest of the document and search for the node within
const beforePadding = ' '.repeat(currentNode.open.end);
const endToUse = currentNode.close ? currentNode.close.start : currentNode.end;
const scriptBodyText = beforePadding + documentText.substring(currentNode.open.end, endToUse);
const innerRoot: HtmlFlatNode = parse(scriptBodyText);
const scriptBodyNode = getHtmlFlatNode(scriptBodyText, innerRoot, offset, includeNodeBoundary);
if (scriptBodyNode) {
scriptBodyNode.parent = currentNode;
currentNode.children.push(scriptBodyNode);
return scriptBodyNode;
}
// If the currentNode is a script one, first set up its subtree and then find HTML node.
if (currentNode.name === 'script' && currentNode.children.length === 0) {
setUpScriptNodeSubtree(documentText, currentNode);
currentNode = <HtmlFlatNode | undefined>getFlatNode(currentNode, offset, includeNodeBoundary) ?? currentNode;
}
return currentNode;
}
export function setUpScriptNodeSubtree(documentText: string, scriptNode: HtmlFlatNode): void {
const isTemplateScript = scriptNode.name === 'script' &&
(scriptNode.attributes &&
scriptNode.attributes.some(x => x.name.toString() === 'type'
&& allowedMimeTypesInScriptTag.includes(x.value.toString())));
if (isTemplateScript
&& scriptNode.open) {
// blank out the rest of the document and generate the subtree.
const beforePadding = ' '.repeat(scriptNode.open.end);
const endToUse = scriptNode.close ? scriptNode.close.start : scriptNode.end;
const scriptBodyText = beforePadding + documentText.substring(scriptNode.open.end, endToUse);
const innerRoot: HtmlFlatNode = parse(scriptBodyText);
innerRoot.children.forEach(child => {
scriptNode.children.push(child);
child.parent = scriptNode;
});
}
}
export function isOffsetInsideOpenOrCloseTag(node: FlatNode, offset: number): boolean {
const htmlNode = node as HtmlFlatNode;
if ((htmlNode.open && offset > htmlNode.open.start && offset < htmlNode.open.end)
@ -579,7 +583,7 @@ export function getEmmetConfiguration(syntax: string) {
) {
syntaxProfiles[syntax] = {
...syntaxProfiles[syntax],
selfClosingStyle: 'xml'
selfClosingStyle: syntax === 'jsx' ? 'xhtml' : 'xml'
};
}
}

View file

@ -77,9 +77,9 @@ jsonc-parser@^2.3.0:
integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==
vscode-emmet-helper@^2.3.0:
version "2.4.3"
resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.4.3.tgz#c536006b7a36deec746725bde10331dca733936a"
integrity sha512-9VpzAMSF99TMqXrhptHu9reCoyAgELk1mw5Jdyaf9jFL2dGwrejY+636jLdIwCGLmZBOZVJ1ZV9R44Elx2HIoA==
version "2.4.4"
resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.4.4.tgz#f255120de921e2a017c5d48ca2f06e021430af99"
integrity sha512-I7yjgf4vMJRXFD1fN6kWt8WgCidjmcxGa4h+1nO0gSrtoj1/f0FNJ06o64HWt+2rTkwp8eQ9OU3imt5kQkdZ5A==
dependencies:
emmet "^2.3.0"
jsonc-parser "^2.3.0"

View file

@ -11,7 +11,7 @@ import * as which from 'which';
import { EventEmitter } from 'events';
import * as iconv from 'iconv-lite-umd';
import * as filetype from 'file-type';
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter } from './util';
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter, Versions } from './util';
import { CancellationToken, Progress, Uri } from 'vscode';
import { detectEncoding } from './encoding';
import { Ref, RefType, Branch, Remote, ForcePushMode, GitErrorCodes, LogOptions, Change, Status, CommitOptions, BranchQuery } from './api/git';
@ -377,6 +377,10 @@ export class Git {
this.env = options.env || {};
}
compareGitVersionTo(version: string): -1 | 0 | 1 {
return Versions.compare(Versions.fromString(this.version), Versions.fromString(version));
}
open(repository: string, dotGit: string): Repository {
return new Repository(this, repository, dotGit);
}
@ -1977,7 +1981,16 @@ export class Repository {
return this.getHEAD();
}
const args = ['for-each-ref', '--format=%(refname)%00%(upstream:short)%00%(upstream:track)%00%(objectname)'];
const args = ['for-each-ref'];
let supportsAheadBehind = true;
if (this._git.compareGitVersionTo('1.9.0') === -1) {
args.push('--format=%(refname)%00%(upstream:short)%00%(objectname)');
supportsAheadBehind = false;
} else {
args.push('--format=%(refname)%00%(upstream:short)%00%(objectname)%00%(upstream:track)');
}
if (/^refs\/(head|remotes)\//i.test(name)) {
args.push(name);
} else {
@ -1986,7 +1999,7 @@ export class Repository {
const result = await this.exec(args);
const branches: Branch[] = result.stdout.trim().split('\n').map<Branch | undefined>(line => {
let [branchName, upstream, status, ref] = line.trim().split('\0');
let [branchName, upstream, ref, status] = line.trim().split('\0');
if (branchName.startsWith('refs/heads/')) {
branchName = branchName.substring(11);
@ -2026,7 +2039,19 @@ export class Repository {
}).filter((b?: Branch): b is Branch => !!b);
if (branches.length) {
return branches[0];
const [branch] = branches;
if (!supportsAheadBehind && branch.upstream) {
try {
const result = await this.exec(['rev-list', '--left-right', '--count', `${branch.name}...${branch.upstream.remote}/${branch.upstream.name}`]);
const [ahead, behind] = result.stdout.trim().split('\t');
(branch as any).ahead = Number(ahead) || 0;
(branch as any).behind = Number(behind) || 0;
} catch { }
}
return branch;
}
return Promise.reject<Branch>(new Error('No such branch'));

View file

@ -414,3 +414,56 @@ export class PromiseSource<T> {
}
}
}
export namespace Versions {
declare type VersionComparisonResult = -1 | 0 | 1;
export interface Version {
major: number;
minor: number;
patch: number;
pre?: string;
}
export function compare(v1: string | Version, v2: string | Version): VersionComparisonResult {
if (typeof v1 === 'string') {
v1 = fromString(v1);
}
if (typeof v2 === 'string') {
v2 = fromString(v2);
}
if (v1.major > v2.major) { return 1; }
if (v1.major < v2.major) { return -1; }
if (v1.minor > v2.minor) { return 1; }
if (v1.minor < v2.minor) { return -1; }
if (v1.patch > v2.patch) { return 1; }
if (v1.patch < v2.patch) { return -1; }
if (v1.pre === undefined && v2.pre !== undefined) { return 1; }
if (v1.pre !== undefined && v2.pre === undefined) { return -1; }
if (v1.pre !== undefined && v2.pre !== undefined) {
return v1.pre.localeCompare(v2.pre) as VersionComparisonResult;
}
return 0;
}
export function from(major: string | number, minor: string | number, patch?: string | number, pre?: string): Version {
return {
major: typeof major === 'string' ? parseInt(major, 10) : major,
minor: typeof minor === 'string' ? parseInt(minor, 10) : minor,
patch: patch === undefined || patch === null ? 0 : typeof patch === 'string' ? parseInt(patch, 10) : patch,
pre: pre,
};
}
export function fromString(version: string): Version {
const [ver, pre] = version.split('-');
const [major, minor, patch] = ver.split('.');
return from(major, minor, patch, pre);
}
}

View file

@ -39,7 +39,7 @@ export class TypeScriptVersionManager extends Disposable {
}
} else {
setImmediate(() => {
vscode.workspace.requireWorkspaceTrust({ modal: false })
vscode.workspace.requestWorkspaceTrust({ modal: false })
.then(trustState => {
if (trustState === vscode.WorkspaceTrustState.Trusted && this.versionProvider.localVersion) {
this.updateActiveVersion(this.versionProvider.localVersion);
@ -120,7 +120,7 @@ export class TypeScriptVersionManager extends Disposable {
description: version.displayName,
detail: version.pathLabel,
run: async () => {
const trustState = await vscode.workspace.requireWorkspaceTrust();
const trustState = await vscode.workspace.requestWorkspaceTrust();
if (trustState === vscode.WorkspaceTrustState.Trusted) {
await this.workspaceState.update(useWorkspaceTsdkStorageKey, true);
const tsConfig = vscode.workspace.getConfiguration('typescript');

View file

@ -1,3 +0,0 @@
std::tuple_element<0, std::pair<pugi::xml_node, std::map<std::basic_string<char>, pugi::xml_node, std::less<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, pugi::xml_node> > > > >::type dnode
std::_Rb_tree_iterator<std::pair<const long, std::pair<pugi::xml_node, std::map<std::basic_string<char>, pugi::xml_node, std::less<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, pugi::xml_node> > > > > > dnode_it = dnodes_.find(uid.position)

View file

@ -1,24 +0,0 @@
[
{
"c": "std::tuple_element<0, std::pair<pugi::xml_node, std::map<std::basic_string<char>, pugi::xml_node, std::less<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, pugi::xml_node> > > > >::type dnode",
"t": "source.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "std::_Rb_tree_iterator<std::pair<const long, std::pair<pugi::xml_node, std::map<std::basic_string<char>, pugi::xml_node, std::less<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, pugi::xml_node> > > > > > dnode_it = dnodes_.find(uid.position)",
"t": "source.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
}
]

View file

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.56.0",
"distro": "0f81994093bec05b2cf192fc9fdb76ce5f114fcf",
"distro": "307045ac2e7717469648489b42182dfca29bdb30",
"author": {
"name": "Microsoft Corporation"
},
@ -79,7 +79,7 @@
"tas-client-umd": "0.1.4",
"v8-inspect-profiler": "^0.0.20",
"vscode-oniguruma": "1.3.1",
"vscode-proxy-agent": "^0.9.0",
"vscode-proxy-agent": "^0.8.2",
"vscode-regexpp": "^3.1.0",
"vscode-ripgrep": "^1.11.1",
"vscode-sqlite3": "4.0.10",

View file

@ -93,7 +93,7 @@
},
{
"name": "ms-vscode.js-debug",
"version": "1.55.1",
"version": "1.55.2",
"repo": "https://github.com/microsoft/vscode-js-debug",
"metadata": {
"id": "25629058-ddac-4e17-abba-74678e126c5d",

View file

@ -18,7 +18,7 @@
"spdlog": "^0.11.1",
"tas-client-umd": "0.1.4",
"vscode-oniguruma": "1.3.1",
"vscode-proxy-agent": "^0.9.0",
"vscode-proxy-agent": "^0.8.2",
"vscode-regexpp": "^3.1.0",
"vscode-ripgrep": "^1.11.1",
"vscode-textmate": "5.2.0",

View file

@ -2,11 +2,6 @@
# yarn lockfile v1
"@tootallnate/once@1", "@tootallnate/once@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
agent-base@4:
version "4.2.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce"
@ -19,13 +14,6 @@ agent-base@5:
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c"
integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==
agent-base@6, agent-base@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
debug "4"
agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
@ -33,6 +21,13 @@ agent-base@^4.3.0:
dependencies:
es6-promisify "^5.0.0"
agent-base@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
dependencies:
es6-promisify "^5.0.0"
anymatch@~3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
@ -94,16 +89,6 @@ cookie@^0.4.0:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
data-uri-to-buffer@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636"
integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==
debug@3.1.0, debug@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
@ -118,13 +103,6 @@ debug@4:
dependencies:
ms "^2.1.1"
debug@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
dependencies:
ms "2.1.2"
diagnostic-channel-publishers@0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
@ -161,11 +139,6 @@ file-uri-to-path@1.0.0:
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
file-uri-to-path@2:
version "2.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba"
integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
@ -173,40 +146,11 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"
fs-extra@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^4.0.0"
universalify "^0.1.0"
fsevents@~2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f"
integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==
ftp@^0.3.10:
version "0.3.10"
resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d"
integrity sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=
dependencies:
readable-stream "1.1.x"
xregexp "2.0.0"
get-uri@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c"
integrity sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==
dependencies:
"@tootallnate/once" "1"
data-uri-to-buffer "3"
debug "4"
file-uri-to-path "2"
fs-extra "^8.1.0"
ftp "^0.3.10"
glob-parent@~5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2"
@ -219,11 +163,6 @@ graceful-fs@4.2.3:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.6"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
http-proxy-agent@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
@ -232,15 +171,6 @@ http-proxy-agent@^2.1.0:
agent-base "4"
debug "3.1.0"
http-proxy-agent@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
dependencies:
"@tootallnate/once" "1"
agent-base "6"
debug "4"
https-proxy-agent@^2.2.3:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
@ -257,24 +187,11 @@ https-proxy-agent@^4.0.0:
agent-base "5"
debug "4"
https-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
dependencies:
agent-base "6"
debug "4"
iconv-lite-umd@0.6.8:
version "0.6.8"
resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0"
integrity sha512-zvXJ5gSwMC9JD3wDzH8CoZGc1pbiJn12Tqjk8BXYCnYz3hYL5GRjHW8LEykjXhV9WgNGI4rgpgHcbIiBfrRq6A==
inherits@~2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
@ -304,23 +221,11 @@ is-number@^7.0.0:
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
jschardet@2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.3.0.tgz#06e2636e16c8ada36feebbdc08aa34e6a9b3ff75"
integrity sha512-6I6xT7XN/7sBB7q8ObzKbmv5vN+blzLcboDE1BNEsEfmRXJValMxO6OIRT69ylPBRemS3rw6US+CMCar0OBc9g==
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
optionalDependencies:
graceful-fs "^4.1.6"
minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
@ -338,7 +243,7 @@ ms@2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@2.1.2, ms@^2.1.1:
ms@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
@ -407,16 +312,6 @@ proxy-from-env@^1.1.0:
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
readable-stream@1.1.x:
version "1.1.14"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "0.0.1"
string_decoder "~0.10.x"
readdirp@~3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
@ -429,27 +324,26 @@ semver@^5.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
smart-buffer@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba"
integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==
smart-buffer@4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d"
integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==
socks-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz#7c0f364e7b1cf4a7a437e71253bed72e9004be60"
integrity sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==
socks-proxy-agent@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386"
integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==
dependencies:
agent-base "6"
debug "4"
socks "^2.3.3"
agent-base "~4.2.1"
socks "~2.3.2"
socks@^2.3.3:
version "2.6.0"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.0.tgz#6b984928461d39871b3666754b9000ecf39dfac2"
integrity sha512-mNmr9owlinMplev0Wd7UHFlqI4ofnBnNzFuzrm63PPaHgbkqCFe4T5LzwKmtQ/f2tX0NTpcdVLyD/FHxFBstYw==
socks@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.2.tgz#ade388e9e6d87fdb11649c15746c578922a5883e"
integrity sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==
dependencies:
ip "^1.1.5"
smart-buffer "^4.1.0"
smart-buffer "4.0.2"
spdlog@^0.11.1:
version "0.11.1"
@ -460,11 +354,6 @@ spdlog@^0.11.1:
mkdirp "^0.5.1"
nan "^2.14.0"
string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
tas-client-umd@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.1.4.tgz#49db4130dd63a8342fabf77185a740fc6a7bea80"
@ -477,28 +366,20 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
vscode-oniguruma@1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.1.tgz#e2383879c3485b19f533ec34efea9d7a2b14be8f"
integrity sha512-gz6ZBofA7UXafVA+m2Yt2zHKgXC2qedArprIsHAPKByTkwq9l5y/izAGckqxYml7mSbYxTRTfdRwsFq3cwF4LQ==
vscode-proxy-agent@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/vscode-proxy-agent/-/vscode-proxy-agent-0.9.0.tgz#da6501b0bb9a6c8cc2fe0e31756c91eb4d5d900b"
integrity sha512-DvLLaYNy8MBlm7O2CBUpmSpQCnNH88f95yXT1l9ovKO7GmTKkbbEJ6ZtzatUezqOlUuOFI0CwenhGGPYAlJ37A==
vscode-proxy-agent@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/vscode-proxy-agent/-/vscode-proxy-agent-0.8.2.tgz#5125e7f1efedd84e0114abe9f38cef3f7b33eb50"
integrity sha512-pRNhgAqrgMB4k1rZTHthCLVH+CtJ3TFlKKhFlt4IMxDRZnMEAbPiAGthvEt/Ku6qS4Vuca8b2PqT+rJlbmnznQ==
dependencies:
"@tootallnate/once" "^1.1.2"
agent-base "^6.0.2"
debug "^4.3.1"
get-uri "^3.0.2"
http-proxy-agent "^4.0.1"
https-proxy-agent "^5.0.0"
socks-proxy-agent "^5.0.0"
debug "^3.1.0"
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.3"
socks-proxy-agent "^4.0.1"
vscode-regexpp@^3.1.0:
version "3.1.0"
@ -537,11 +418,6 @@ windows-process-tree@0.2.4:
dependencies:
nan "^2.13.2"
xregexp@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=
xterm-addon-search@0.9.0-beta.1:
version "0.9.0-beta.1"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.1.tgz#139515da723a129c6d27c4e1a2319ef1344d76a6"

View file

@ -34,11 +34,9 @@
* @param {string[]} modulePaths
* @param {(result: unknown, configuration: import('./vs/base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => Promise<unknown> | undefined} resultCallback
* @param {{
* forceEnableDeveloperKeybindings?: boolean,
* disallowReloadKeybinding?: boolean,
* removeDeveloperKeybindingsAfterLoad?: boolean,
* configureDeveloperKeybindings?: (config: import('./vs/base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => {forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean},
* canModifyDOM?: (config: import('./vs/base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => void,
* beforeLoaderConfig?: (config: import('./vs/base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration, loaderConfig: object) => void,
* beforeLoaderConfig?: (loaderConfig: object) => void,
* beforeRequire?: () => void
* }} [options]
*/
@ -55,11 +53,12 @@
const configuration = await preloadGlobals.context.configuration;
performance.mark('code/didWaitForWindowConfig');
// Developer tools
const enableDeveloperKeybindings = safeProcess.env['VSCODE_DEV'] || configuration.forceEnableDeveloperKeybindings || options?.forceEnableDeveloperKeybindings;
// Developer keybindings
const { forceEnableDeveloperKeybindings, disallowReloadKeybinding, removeDeveloperKeybindingsAfterLoad } = typeof options?.configureDeveloperKeybindings === 'function' ? options.configureDeveloperKeybindings(configuration) : { forceEnableDeveloperKeybindings: false, disallowReloadKeybinding: false, removeDeveloperKeybindingsAfterLoad: false };
const enableDeveloperKeybindings = safeProcess.env['VSCODE_DEV'] || forceEnableDeveloperKeybindings;
let developerDeveloperKeybindingsDisposable;
if (enableDeveloperKeybindings) {
developerDeveloperKeybindingsDisposable = registerDeveloperKeybindings(options?.disallowReloadKeybinding);
developerDeveloperKeybindingsDisposable = registerDeveloperKeybindings(disallowReloadKeybinding);
}
// Enable ASAR support
@ -143,7 +142,7 @@
// Signal before require.config()
if (typeof options?.beforeLoaderConfig === 'function') {
options.beforeLoaderConfig(configuration, loaderConfig);
options.beforeLoaderConfig(loaderConfig);
}
// Configure loader
@ -177,7 +176,7 @@
if (callbackResult instanceof Promise) {
await callbackResult;
if (developerDeveloperKeybindingsDisposable && options?.removeDeveloperKeybindingsAfterLoad) {
if (developerDeveloperKeybindingsDisposable && removeDeveloperKeybindingsAfterLoad) {
developerDeveloperKeybindingsDisposable();
}
}
@ -267,7 +266,6 @@
}
return {
load,
globals
load
};
}));

View file

@ -680,12 +680,12 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
if (this.supportDynamicHeights) {
this._rerender(this.scrollTop, this.renderHeight);
}
}
if (this.horizontalScrolling) {
this.scrollableElement.setScrollDimensions({
width: typeof width === 'number' ? width : getContentWidth(this.domNode)
});
}
if (this.horizontalScrolling) {
this.scrollableElement.setScrollDimensions({
width: typeof width === 'number' ? width : getContentWidth(this.domNode)
});
}
}

View file

@ -0,0 +1,161 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IStringDictionary } from 'vs/base/common/collections';
export interface IBuiltInExtension {
readonly name: string;
readonly version: string;
readonly repo: string;
readonly metadata: any;
}
export type ConfigurationSyncStore = {
url: string,
insidersUrl: string,
stableUrl: string,
canSwitch: boolean,
authenticationProviders: IStringDictionary<{ scopes: string[] }>
};
export interface IProductConfiguration {
readonly version: string;
readonly date?: string;
readonly quality?: string;
readonly commit?: string;
readonly nameShort: string;
readonly nameLong: string;
readonly win32AppUserModelId?: string;
readonly win32MutexName?: string;
readonly applicationName: string;
readonly urlProtocol: string;
readonly dataFolderName: string; // location for extensions (e.g. ~/.vscode-insiders)
readonly builtInExtensions?: IBuiltInExtension[];
readonly downloadUrl?: string;
readonly updateUrl?: string;
readonly webEndpointUrl?: string;
readonly target?: string;
readonly settingsSearchBuildId?: number;
readonly settingsSearchUrl?: string;
readonly tasConfig?: {
endpoint: string;
telemetryEventName: string;
featuresTelemetryPropertyName: string;
assignmentContextTelemetryPropertyName: string;
};
readonly experimentsUrl?: string;
readonly extensionsGallery?: {
readonly serviceUrl: string;
readonly itemUrl: string;
readonly controlUrl: string;
readonly recommendationsUrl: string;
};
readonly extensionTips?: { [id: string]: string; };
readonly extensionImportantTips?: IStringDictionary<ImportantExtensionTip>;
readonly configBasedExtensionTips?: { [id: string]: IConfigBasedExtensionTip; };
readonly exeBasedExtensionTips?: { [id: string]: IExeBasedExtensionTip; };
readonly remoteExtensionTips?: { [remoteName: string]: IRemoteExtensionTip; };
readonly extensionKeywords?: { [extension: string]: readonly string[]; };
readonly keymapExtensionTips?: readonly string[];
readonly trustedExtensionUrlPublicKeys?: { [id: string]: string[]; };
readonly crashReporter?: {
readonly companyName: string;
readonly productName: string;
};
readonly enableTelemetry?: boolean;
readonly aiConfig?: {
readonly asimovKey: string;
};
readonly sendASmile?: {
readonly reportIssueUrl: string,
readonly requestFeatureUrl: string
};
readonly documentationUrl?: string;
readonly releaseNotesUrl?: string;
readonly keyboardShortcutsUrlMac?: string;
readonly keyboardShortcutsUrlLinux?: string;
readonly keyboardShortcutsUrlWin?: string;
readonly introductoryVideosUrl?: string;
readonly tipsAndTricksUrl?: string;
readonly newsletterSignupUrl?: string;
readonly twitterUrl?: string;
readonly requestFeatureUrl?: string;
readonly reportIssueUrl?: string;
readonly reportMarketplaceIssueUrl?: string;
readonly licenseUrl?: string;
readonly privacyStatementUrl?: string;
readonly telemetryOptOutUrl?: string;
readonly npsSurveyUrl?: string;
readonly cesSurveyUrl?: string;
readonly surveys?: readonly ISurveyData[];
readonly checksums?: { [path: string]: string; };
readonly checksumFailMoreInfoUrl?: string;
readonly appCenter?: IAppCenterConfiguration;
readonly portable?: string;
readonly extensionKind?: { readonly [extensionId: string]: ('ui' | 'workspace' | 'web')[]; };
readonly extensionSyncedKeys?: { readonly [extensionId: string]: string[]; };
readonly extensionAllowedProposedApi?: readonly string[];
readonly msftInternalDomains?: string[];
readonly linkProtectionTrustedDomains?: readonly string[];
readonly 'configurationSync.store'?: ConfigurationSyncStore;
readonly darwinUniversalAssetId?: string;
}
export type ImportantExtensionTip = { name: string; languages?: string[]; pattern?: string; isExtensionPack?: boolean };
export interface IAppCenterConfiguration {
readonly 'win32-ia32': string;
readonly 'win32-x64': string;
readonly 'linux-x64': string;
readonly 'darwin': string;
}
export interface IConfigBasedExtensionTip {
configPath: string;
configName: string;
recommendations: IStringDictionary<{ name: string, remotes?: string[], important?: boolean, isExtensionPack?: boolean }>;
}
export interface IExeBasedExtensionTip {
friendlyName: string;
windowsPath?: string;
important?: boolean;
recommendations: IStringDictionary<{ name: string, important?: boolean, isExtensionPack?: boolean }>;
}
export interface IRemoteExtensionTip {
friendlyName: string;
extensionId: string;
}
export interface ISurveyData {
surveyId: string;
surveyUrl: string;
languageId: string;
editCount: number;
userProbability: number;
}

View file

@ -24,6 +24,4 @@ export interface ISandboxConfiguration {
zoomLevel?: number;
nodeCachedDataDir?: string;
forceEnableDeveloperKeybindings?: boolean;
}

View file

@ -238,6 +238,7 @@
try {
if (validateIPC(windowConfigIpcChannel)) {
/** @type {import('../common/sandboxTypes').ISandboxConfiguration} */
const configuration = await ipcRenderer.invoke(windowConfigIpcChannel);
// Apply zoom level early before even building the

View file

@ -7,11 +7,13 @@ import * as assert from 'assert';
import { ipcRenderer, crashReporter, webFrame, context, process } from 'vs/base/parts/sandbox/electron-sandbox/globals';
suite('Sandbox', () => {
test('globals', () => {
test('globals', async () => {
assert.ok(typeof ipcRenderer.send === 'function');
assert.ok(typeof crashReporter.addExtraParameter === 'function');
assert.ok(typeof webFrame.setZoomLevel === 'function');
assert.ok(context.configuration instanceof Promise);
assert.ok(typeof process.platform === 'string');
const config = await context.configuration;
assert.ok(config);
});
});

View file

@ -28,7 +28,16 @@
/**
* @returns {{
* load: (modules: string[], resultCallback: (result, configuration: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => unknown) => Promise<unknown>
* load: (
* modules: string[],
* resultCallback: (result, configuration: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => unknown,
* options?: {
* configureDeveloperKeybindings?: (config: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => {forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean},
* canModifyDOM?: (config: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => void,
* beforeLoaderConfig?: (loaderConfig: object) => void,
* beforeRequire?: () => void
* }
* ) => Promise<unknown>
* }}
*/
function bootstrapWindowLib() {

View file

@ -32,11 +32,16 @@
return require('vs/workbench/electron-browser/desktop.main').main(configuration);
},
{
removeDeveloperKeybindingsAfterLoad: true,
configureDeveloperKeybindings: function (windowConfig) {
return {
forceEnableDeveloperKeybindings: Array.isArray(windowConfig.extensionDevelopmentPath),
removeDeveloperKeybindingsAfterLoad: true
};
},
canModifyDOM: function (windowConfig) {
showPartsSplash(windowConfig);
},
beforeLoaderConfig: function (windowConfig, loaderConfig) {
beforeLoaderConfig: function (loaderConfig) {
loaderConfig.recordStats = true;
},
beforeRequire: function () {
@ -66,7 +71,16 @@
/**
* @returns {{
* load: (modules: string[], resultCallback: (result, configuration: import('../../../platform/windows/common/windows').INativeWindowConfiguration) => unknown, options: object) => Promise<unknown>
* load: (
* modules: string[],
* resultCallback: (result, configuration: import('../../../platform/windows/common/windows').INativeWindowConfiguration) => unknown,
* options?: {
* configureDeveloperKeybindings?: (config: import('../../../platform/windows/common/windows').INativeWindowConfiguration & object) => {forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean},
* canModifyDOM?: (config: import('../../../platform/windows/common/windows').INativeWindowConfiguration & object) => void,
* beforeLoaderConfig?: (loaderConfig: object) => void,
* beforeRequire?: () => void
* }
* ) => Promise<unknown>
* }}
*/
function bootstrapWindowLib() {

View file

@ -11,12 +11,30 @@
// Load issue reporter into window
bootstrapWindow.load(['vs/code/electron-sandbox/issue/issueReporterMain'], function (issueReporter, configuration) {
issueReporter.startup(configuration);
}, { forceEnableDeveloperKeybindings: true, disallowReloadKeybinding: true });
return issueReporter.startup(configuration);
},
{
configureDeveloperKeybindings: function () {
return {
forceEnableDeveloperKeybindings: true,
disallowReloadKeybinding: true
};
}
}
);
/**
* @returns {{
* load: (modules: string[], resultCallback: (result, configuration: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => unknown, options?: { forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean }) => Promise<unknown>
* load: (
* modules: string[],
* resultCallback: (result, configuration: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => unknown,
* options?: {
* configureDeveloperKeybindings?: (config: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => {forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean},
* canModifyDOM?: (config: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => void,
* beforeLoaderConfig?: (loaderConfig: object) => void,
* beforeRequire?: () => void
* }
* ) => Promise<unknown>
* }}
*/
function bootstrapWindowLib() {

View file

@ -11,12 +11,27 @@
// Load process explorer into window
bootstrapWindow.load(['vs/code/electron-sandbox/processExplorer/processExplorerMain'], function (processExplorer, configuration) {
processExplorer.startup(configuration);
}, { forceEnableDeveloperKeybindings: true });
return processExplorer.startup(configuration);
}, {
configureDeveloperKeybindings: function () {
return {
forceEnableDeveloperKeybindings: true
};
},
});
/**
* @returns {{
* load: (modules: string[], resultCallback: (result, configuration: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => unknown, options?: { forceEnableDeveloperKeybindings?: boolean }) => Promise<unknown>
* load: (
* modules: string[],
* resultCallback: (result, configuration: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => unknown,
* options?: {
* configureDeveloperKeybindings?: (config: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => {forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean},
* canModifyDOM?: (config: import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration) => void,
* beforeLoaderConfig?: (loaderConfig: object) => void,
* beforeRequire?: () => void
* }
* ) => Promise<unknown>
* }}
*/
function bootstrapWindowLib() {

View file

@ -32,11 +32,16 @@
return require('vs/workbench/electron-sandbox/desktop.main').main(configuration);
},
{
removeDeveloperKeybindingsAfterLoad: true,
configureDeveloperKeybindings: function (windowConfig) {
return {
forceEnableDeveloperKeybindings: Array.isArray(windowConfig.extensionDevelopmentPath),
removeDeveloperKeybindingsAfterLoad: true
};
},
canModifyDOM: function (windowConfig) {
// TODO@sandbox part-splash is non-sandboxed only
},
beforeLoaderConfig: function (windowConfig, loaderConfig) {
beforeLoaderConfig: function (loaderConfig) {
loaderConfig.recordStats = true;
},
beforeRequire: function () {
@ -66,7 +71,16 @@
/**
* @returns {{
* load: (modules: string[], resultCallback: (result, configuration: import('../../../platform/windows/common/windows').INativeWindowConfiguration) => unknown, options: object) => Promise<unknown>
* load: (
* modules: string[],
* resultCallback: (result, configuration: import('../../../platform/windows/common/windows').INativeWindowConfiguration) => unknown,
* options?: {
* configureDeveloperKeybindings?: (config: import('../../../platform/windows/common/windows').INativeWindowConfiguration & object) => {forceEnableDeveloperKeybindings?: boolean, disallowReloadKeybinding?: boolean, removeDeveloperKeybindingsAfterLoad?: boolean},
* canModifyDOM?: (config: import('../../../platform/windows/common/windows').INativeWindowConfiguration & object) => void,
* beforeLoaderConfig?: (loaderConfig: object) => void,
* beforeRequire?: () => void
* }
* ) => Promise<unknown>
* }}
*/
function bootstrapWindowLib() {

View file

@ -2106,10 +2106,42 @@ export class TextModel extends Disposable implements model.ITextModel {
return this._matchBracket(this.validatePosition(position));
}
private _establishBracketSearchOffsets(position: Position, lineTokens: LineTokens, modeBrackets: RichEditBrackets, tokenIndex: number) {
const tokenCount = lineTokens.getCount();
const currentLanguageId = lineTokens.getLanguageId(tokenIndex);
// limit search to not go before `maxBracketLength`
let searchStartOffset = Math.max(0, position.column - 1 - modeBrackets.maxBracketLength);
for (let i = tokenIndex - 1; i >= 0; i--) {
const tokenEndOffset = lineTokens.getEndOffset(i);
if (tokenEndOffset <= searchStartOffset) {
break;
}
if (ignoreBracketsInToken(lineTokens.getStandardTokenType(i)) || lineTokens.getLanguageId(i) !== currentLanguageId) {
searchStartOffset = tokenEndOffset;
break;
}
}
// limit search to not go after `maxBracketLength`
let searchEndOffset = Math.min(lineTokens.getLineContent().length, position.column - 1 + modeBrackets.maxBracketLength);
for (let i = tokenIndex + 1; i < tokenCount; i++) {
const tokenStartOffset = lineTokens.getStartOffset(i);
if (tokenStartOffset >= searchEndOffset) {
break;
}
if (ignoreBracketsInToken(lineTokens.getStandardTokenType(i)) || lineTokens.getLanguageId(i) !== currentLanguageId) {
searchEndOffset = tokenStartOffset;
break;
}
}
return { searchStartOffset, searchEndOffset };
}
private _matchBracket(position: Position): [Range, Range] | null {
const lineNumber = position.lineNumber;
const lineTokens = this._getLineTokens(lineNumber);
const tokenCount = lineTokens.getCount();
const lineText = this._buffer.getLineContent(lineNumber);
const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
@ -2120,19 +2152,8 @@ export class TextModel extends Disposable implements model.ITextModel {
// check that the token is not to be ignored
if (currentModeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex))) {
// limit search to not go before `maxBracketLength`
let searchStartOffset = Math.max(0, position.column - 1 - currentModeBrackets.maxBracketLength);
for (let i = tokenIndex - 1; i >= 0; i--) {
const tokenEndOffset = lineTokens.getEndOffset(i);
if (tokenEndOffset <= searchStartOffset) {
break;
}
if (ignoreBracketsInToken(lineTokens.getStandardTokenType(i))) {
searchStartOffset = tokenEndOffset;
}
}
// limit search to not go after `maxBracketLength`
const searchEndOffset = Math.min(lineText.length, position.column - 1 + currentModeBrackets.maxBracketLength);
let { searchStartOffset, searchEndOffset } = this._establishBracketSearchOffsets(position, lineTokens, currentModeBrackets, tokenIndex);
// it might be the case that [currentTokenStart -> currentTokenEnd] contains multiple brackets
// `bestResult` will contain the most right-side result
@ -2171,18 +2192,9 @@ export class TextModel extends Disposable implements model.ITextModel {
// check that previous token is not to be ignored
if (prevModeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(prevTokenIndex))) {
// limit search in case previous token is very large, there's no need to go beyond `maxBracketLength`
const searchStartOffset = Math.max(0, position.column - 1 - prevModeBrackets.maxBracketLength);
let searchEndOffset = Math.min(lineText.length, position.column - 1 + prevModeBrackets.maxBracketLength);
for (let i = prevTokenIndex + 1; i < tokenCount; i++) {
const tokenStartOffset = lineTokens.getStartOffset(i);
if (tokenStartOffset >= searchEndOffset) {
break;
}
if (ignoreBracketsInToken(lineTokens.getStandardTokenType(i))) {
searchEndOffset = tokenStartOffset;
}
}
let { searchStartOffset, searchEndOffset } = this._establishBracketSearchOffsets(position, lineTokens, prevModeBrackets, prevTokenIndex);
const foundBracket = BracketsUtils.findPrevBracketInRange(prevModeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
// check that we didn't hit a bracket too far away from position

View file

@ -313,11 +313,21 @@ export class ThemeTrieElementRule {
export class ExternalThemeTrieElement {
public readonly mainRule: ThemeTrieElementRule;
public readonly children: { [segment: string]: ExternalThemeTrieElement };
public readonly children: Map<string, ExternalThemeTrieElement>;
constructor(mainRule: ThemeTrieElementRule, children?: { [segment: string]: ExternalThemeTrieElement }) {
constructor(
mainRule: ThemeTrieElementRule,
children: Map<string, ExternalThemeTrieElement> | { [key: string]: ExternalThemeTrieElement } = new Map<string, ExternalThemeTrieElement>()
) {
this.mainRule = mainRule;
this.children = children || Object.create(null);
if (children instanceof Map) {
this.children = children;
} else {
this.children = new Map<string, ExternalThemeTrieElement>();
for (const key in children) {
this.children.set(key, children[key]);
}
}
}
}
@ -336,9 +346,9 @@ export class ThemeTrieElement {
* used for testing purposes
*/
public toExternalThemeTrieElement(): ExternalThemeTrieElement {
let children: { [segment: string]: ExternalThemeTrieElement } = Object.create(null);
const children = new Map<string, ExternalThemeTrieElement>();
this._children.forEach((element, index) => {
children[index] = element.toExternalThemeTrieElement();
children.set(index, element.toExternalThemeTrieElement());
});
return new ExternalThemeTrieElement(this._mainRule, children);
}

View file

@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IMode, LanguageId, LanguageIdentifier } from 'vs/editor/common/modes';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
@ -22,7 +21,7 @@ export interface ILanguageExtensionPoint {
configuration?: URI;
}
export interface ILanguageSelection extends IDisposable {
export interface ILanguageSelection {
readonly languageIdentifier: LanguageIdentifier;
readonly onDidChange: Event<LanguageIdentifier>;
}

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IMode, LanguageId, LanguageIdentifier } from 'vs/editor/common/modes';
import { FrankensteinMode } from 'vs/editor/common/modes/abstractMode';
@ -13,20 +13,28 @@ import { LanguagesRegistry } from 'vs/editor/common/services/languagesRegistry';
import { ILanguageSelection, IModeService } from 'vs/editor/common/services/modeService';
import { firstOrDefault } from 'vs/base/common/arrays';
class LanguageSelection extends Disposable implements ILanguageSelection {
class LanguageSelection implements ILanguageSelection {
public languageIdentifier: LanguageIdentifier;
private readonly _selector: () => LanguageIdentifier;
private readonly _onDidChange: Emitter<LanguageIdentifier> = this._register(new Emitter<LanguageIdentifier>());
public readonly onDidChange: Event<LanguageIdentifier> = this._onDidChange.event;
private readonly _onDidChange: Emitter<LanguageIdentifier>;
public readonly onDidChange: Event<LanguageIdentifier>;
constructor(onLanguagesMaybeChanged: Event<void>, selector: () => LanguageIdentifier) {
super();
this._selector = selector;
this.languageIdentifier = this._selector();
this._register(onLanguagesMaybeChanged(() => this._evaluate()));
let listener: IDisposable;
this._onDidChange = new Emitter<LanguageIdentifier>({
onFirstListenerAdd: () => {
listener = onLanguagesMaybeChanged(() => this._evaluate());
},
onLastListenerRemove: () => {
listener.dispose();
}
});
this.onDidChange = this._onDidChange.event;
}
private _evaluate(): void {

View file

@ -78,10 +78,6 @@ class ModelData implements IDisposable {
this._languageSelectionListener.dispose();
this._languageSelectionListener = null;
}
if (this._languageSelection) {
this._languageSelection.dispose();
this._languageSelection = null;
}
}
public dispose(): void {

View file

@ -28,5 +28,4 @@ export class MockMode extends Disposable implements IMode {
export class StaticLanguageSelector implements ILanguageSelection {
readonly onDidChange: Event<LanguageIdentifier> = Event.None;
constructor(public readonly languageIdentifier: LanguageIdentifier) { }
public dispose(): void { }
}

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { IDisposable } from 'vs/base/common/lifecycle';
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { TokenizationResult2 } from 'vs/editor/common/core/token';
@ -337,6 +337,97 @@ suite('TextModelWithTokens', () => {
registration.dispose();
});
test('issue #95843: Highlighting of closing braces is indicating wrong brace when cursor is behind opening brace', () => {
const mode1 = new LanguageIdentifier('testMode1', 3);
const mode2 = new LanguageIdentifier('testMode2', 4);
const otherMetadata1 = (
(mode1.id << MetadataConsts.LANGUAGEID_OFFSET)
| (StandardTokenType.Other << MetadataConsts.TOKEN_TYPE_OFFSET)
) >>> 0;
const otherMetadata2 = (
(mode2.id << MetadataConsts.LANGUAGEID_OFFSET)
| (StandardTokenType.Other << MetadataConsts.TOKEN_TYPE_OFFSET)
) >>> 0;
const tokenizationSupport: ITokenizationSupport = {
getInitialState: () => NULL_STATE,
tokenize: undefined!,
tokenize2: (line, hasEOL, state) => {
switch (line) {
case 'function f() {': {
const tokens = new Uint32Array([
0, otherMetadata1,
8, otherMetadata1,
9, otherMetadata1,
10, otherMetadata1,
11, otherMetadata1,
12, otherMetadata1,
13, otherMetadata1,
]);
return new TokenizationResult2(tokens, state);
}
case ' return <p>{true}</p>;': {
const tokens = new Uint32Array([
0, otherMetadata1,
2, otherMetadata1,
8, otherMetadata1,
9, otherMetadata2,
10, otherMetadata2,
11, otherMetadata2,
12, otherMetadata2,
13, otherMetadata1,
17, otherMetadata2,
18, otherMetadata2,
20, otherMetadata2,
21, otherMetadata2,
22, otherMetadata2,
]);
return new TokenizationResult2(tokens, state);
}
case '}': {
const tokens = new Uint32Array([
0, otherMetadata1
]);
return new TokenizationResult2(tokens, state);
}
}
throw new Error(`Unexpected`);
}
};
const disposableStore = new DisposableStore();
disposableStore.add(TokenizationRegistry.register(mode1.language, tokenizationSupport));
disposableStore.add(LanguageConfigurationRegistry.register(mode1, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
}));
disposableStore.add(LanguageConfigurationRegistry.register(mode2, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
}));
const model = disposableStore.add(createTextModel([
'function f() {',
' return <p>{true}</p>;',
'}',
].join('\n'), undefined, mode1));
model.forceTokenization(1);
model.forceTokenization(2);
model.forceTokenization(3);
assert.deepStrictEqual(model.matchBracket(new Position(2, 14)), [new Range(2, 13, 2, 14), new Range(2, 18, 2, 19)]);
disposableStore.dispose();
});
test('issue #88075: TypeScript brace matching is incorrect in `${}` strings', () => {
const mode = new LanguageIdentifier('testMode', 3);
const otherMetadata = (

View file

@ -243,60 +243,60 @@ suite('Token theme resolving', () => {
});
test('defaults are inherited', () => {
let actual = TokenTheme.createFromParsedTokenTheme([
const actual = TokenTheme.createFromParsedTokenTheme([
new ParsedTokenThemeRule('', -1, FontStyle.NotSet, 'F8F8F2', '272822'),
new ParsedTokenThemeRule('var', -1, FontStyle.NotSet, 'ff0000', null)
], []);
let colorMap = new ColorMap();
const colorMap = new ColorMap();
const _A = colorMap.getId('F8F8F2');
const _B = colorMap.getId('272822');
const _C = colorMap.getId('ff0000');
assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap());
let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
const root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _C, _B))
});
assert.deepEqual(actual.getThemeTrieElement(), root);
assert.deepStrictEqual(actual.getThemeTrieElement(), root);
});
test('same rules get merged', () => {
let actual = TokenTheme.createFromParsedTokenTheme([
const actual = TokenTheme.createFromParsedTokenTheme([
new ParsedTokenThemeRule('', -1, FontStyle.NotSet, 'F8F8F2', '272822'),
new ParsedTokenThemeRule('var', 1, FontStyle.Bold, null, null),
new ParsedTokenThemeRule('var', 0, FontStyle.NotSet, 'ff0000', null),
], []);
let colorMap = new ColorMap();
const colorMap = new ColorMap();
const _A = colorMap.getId('F8F8F2');
const _B = colorMap.getId('272822');
const _C = colorMap.getId('ff0000');
assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap());
let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
const root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _C, _B))
});
assert.deepEqual(actual.getThemeTrieElement(), root);
assert.deepStrictEqual(actual.getThemeTrieElement(), root);
});
test('rules are inherited 1', () => {
let actual = TokenTheme.createFromParsedTokenTheme([
const actual = TokenTheme.createFromParsedTokenTheme([
new ParsedTokenThemeRule('', -1, FontStyle.NotSet, 'F8F8F2', '272822'),
new ParsedTokenThemeRule('var', -1, FontStyle.Bold, 'ff0000', null),
new ParsedTokenThemeRule('var.identifier', -1, FontStyle.NotSet, '00ff00', null),
], []);
let colorMap = new ColorMap();
const colorMap = new ColorMap();
const _A = colorMap.getId('F8F8F2');
const _B = colorMap.getId('272822');
const _C = colorMap.getId('ff0000');
const _D = colorMap.getId('00ff00');
assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap());
let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
const root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _C, _B), {
'identifier': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _D, _B))
})
});
assert.deepEqual(actual.getThemeTrieElement(), root);
assert.deepStrictEqual(actual.getThemeTrieElement(), root);
});
test('rules are inherited 2', () => {
let actual = TokenTheme.createFromParsedTokenTheme([
const actual = TokenTheme.createFromParsedTokenTheme([
new ParsedTokenThemeRule('', -1, FontStyle.NotSet, 'F8F8F2', '272822'),
new ParsedTokenThemeRule('var', -1, FontStyle.Bold, 'ff0000', null),
new ParsedTokenThemeRule('var.identifier', -1, FontStyle.NotSet, '00ff00', null),
@ -306,7 +306,7 @@ suite('Token theme resolving', () => {
new ParsedTokenThemeRule('constant.numeric.oct', 7, FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, null, null),
new ParsedTokenThemeRule('constant.numeric.dec', 8, FontStyle.None, '300000', null),
], []);
let colorMap = new ColorMap();
const colorMap = new ColorMap();
const _A = colorMap.getId('F8F8F2');
const _B = colorMap.getId('272822');
const _C = colorMap.getId('100000');
@ -315,7 +315,7 @@ suite('Token theme resolving', () => {
const _F = colorMap.getId('ff0000');
const _G = colorMap.getId('00ff00');
assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap());
let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
const root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _F, _B), {
'identifier': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _G, _B))
}),
@ -327,7 +327,7 @@ suite('Token theme resolving', () => {
})
})
});
assert.deepEqual(actual.getThemeTrieElement(), root);
assert.deepStrictEqual(actual.getThemeTrieElement(), root);
});
test('custom colors are first in color map', () => {

View file

@ -763,6 +763,9 @@ var AMDLoader;
require.resolve = function resolve(request, options) {
return Module._resolveFilename(request, mod, false, options);
};
require.resolve.paths = function paths(request) {
return Module._resolveLookupPaths(request, mod);
};
require.main = process.mainModule;
require.extensions = Module._extensions;
require.cache = Module._cache;

View file

@ -4,7 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
import { IProductService, IConfigBasedExtensionTip as IRawConfigBasedExtensionTip } from 'vs/platform/product/common/productService';
import { IProductService } from 'vs/platform/product/common/productService';
import { IConfigBasedExtensionTip as IRawConfigBasedExtensionTip } from 'vs/base/common/product';
import { IFileService } from 'vs/platform/files/common/files';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { IExtensionTipsService, IExecutableBasedExtensionTip, IWorkspaceTips, IConfigBasedExtensionTip } from 'vs/platform/extensionManagement/common/extensionManagement';

View file

@ -189,18 +189,9 @@ export class IssueMainService implements ICommonIssueService {
if (this.issueReporterParentWindow) {
const issueReporterDisposables = new DisposableStore();
interface IIssueReporterWindowConfig extends ISandboxConfiguration {
[key: string]: unknown;
}
const issueReporterWindowConfigUrl = issueReporterDisposables.add(this.protocolMainService.createIPCObjectUrl<IIssueReporterWindowConfig>());
const position = this.getWindowPosition(this.issueReporterParentWindow, 700, 800);
this.issueReporterWindow = this.createBrowserWindow(position, issueReporterWindowConfigUrl, data.styles.backgroundColor, localize('issueReporter', "Issue Reporter"), data.zoomLevel);
const configuration: IIssueReporterWindowConfig = {
const configuration = {
appRoot: this.environmentMainService.appRoot,
windowId: this.issueReporterWindow.id,
windowId: 0, // filled in later
machineId: this.machineId,
userEnv: this.userEnv,
data,
@ -221,6 +212,14 @@ export class IssueMainService implements ICommonIssueService {
}
};
interface IIssueReporterWindowConfig extends ISandboxConfiguration, Extract<typeof configuration, any> { }
const issueReporterWindowConfigUrl = issueReporterDisposables.add(this.protocolMainService.createIPCObjectUrl<IIssueReporterWindowConfig>());
const position = this.getWindowPosition(this.issueReporterParentWindow, 700, 800);
this.issueReporterWindow = this.createBrowserWindow(position, issueReporterWindowConfigUrl, data.styles.backgroundColor, localize('issueReporter', "Issue Reporter"), data.zoomLevel);
configuration.windowId = this.issueReporterWindow.id;
// Store into config object URL
issueReporterWindowConfigUrl.update(configuration);
@ -254,22 +253,21 @@ export class IssueMainService implements ICommonIssueService {
if (this.processExplorerParentWindow) {
const processExplorerDisposables = new DisposableStore();
interface IProcessExplorerWindowConfig extends ISandboxConfiguration {
[key: string]: unknown;
}
const configuration = {
appRoot: this.environmentMainService.appRoot,
windowId: 0, // filled in later
userEnv: this.userEnv,
machineId: this.machineId,
data
};
interface IProcessExplorerWindowConfig extends ISandboxConfiguration, Extract<typeof configuration, any> { }
const processExplorerWindowConfigUrl = processExplorerDisposables.add(this.protocolMainService.createIPCObjectUrl<IProcessExplorerWindowConfig>());
const position = this.getWindowPosition(this.processExplorerParentWindow, 800, 500);
this.processExplorerWindow = this.createBrowserWindow(position, processExplorerWindowConfigUrl, data.styles.backgroundColor, localize('issueReporter', "Issue Reporter"), data.zoomLevel);
const configuration: IProcessExplorerWindowConfig = {
appRoot: this.environmentMainService.appRoot,
windowId: this.processExplorerWindow.id,
userEnv: this.userEnv,
machineId: this.machineId,
data
};
configuration.windowId = this.processExplorerWindow.id;
// Store into config object URL
processExplorerWindowConfigUrl.update(configuration);

View file

@ -7,7 +7,7 @@ import { FileAccess } from 'vs/base/common/network';
import { isWeb } from 'vs/base/common/platform';
import { env } from 'vs/base/common/process';
import { dirname, joinPath } from 'vs/base/common/resources';
import { IProductConfiguration } from 'vs/platform/product/common/productService';
import { IProductConfiguration } from 'vs/base/common/product';
let product: IProductConfiguration;

View file

@ -4,8 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ExtensionKind } from 'vs/platform/extensions/common/extensions';
import { IStringDictionary } from 'vs/base/common/collections';
import { IProductConfiguration } from 'vs/base/common/product';
export const IProductService = createDecorator<IProductService>('productService');
@ -14,158 +13,3 @@ export interface IProductService extends Readonly<IProductConfiguration> {
readonly _serviceBrand: undefined;
}
export interface IBuiltInExtension {
readonly name: string;
readonly version: string;
readonly repo: string;
readonly metadata: any;
}
export type ConfigurationSyncStore = {
url: string,
insidersUrl: string,
stableUrl: string,
canSwitch: boolean,
authenticationProviders: IStringDictionary<{ scopes: string[] }>
};
export interface IProductConfiguration {
readonly version: string;
readonly date?: string;
readonly quality?: string;
readonly commit?: string;
readonly nameShort: string;
readonly nameLong: string;
readonly win32AppUserModelId?: string;
readonly win32MutexName?: string;
readonly applicationName: string;
readonly urlProtocol: string;
readonly dataFolderName: string; // location for extensions (e.g. ~/.vscode-insiders)
readonly builtInExtensions?: IBuiltInExtension[];
readonly downloadUrl?: string;
readonly updateUrl?: string;
readonly webEndpointUrl?: string;
readonly target?: string;
readonly settingsSearchBuildId?: number;
readonly settingsSearchUrl?: string;
readonly tasConfig?: {
endpoint: string;
telemetryEventName: string;
featuresTelemetryPropertyName: string;
assignmentContextTelemetryPropertyName: string;
};
readonly experimentsUrl?: string;
readonly extensionsGallery?: {
readonly serviceUrl: string;
readonly itemUrl: string;
readonly controlUrl: string;
readonly recommendationsUrl: string;
};
readonly extensionTips?: { [id: string]: string; };
readonly extensionImportantTips?: IStringDictionary<ImportantExtensionTip>;
readonly configBasedExtensionTips?: { [id: string]: IConfigBasedExtensionTip; };
readonly exeBasedExtensionTips?: { [id: string]: IExeBasedExtensionTip; };
readonly remoteExtensionTips?: { [remoteName: string]: IRemoteExtensionTip; };
readonly extensionKeywords?: { [extension: string]: readonly string[]; };
readonly keymapExtensionTips?: readonly string[];
readonly trustedExtensionUrlPublicKeys?: { [id: string]: string[]; };
readonly crashReporter?: {
readonly companyName: string;
readonly productName: string;
};
readonly enableTelemetry?: boolean;
readonly aiConfig?: {
readonly asimovKey: string;
};
readonly sendASmile?: {
readonly reportIssueUrl: string,
readonly requestFeatureUrl: string
};
readonly documentationUrl?: string;
readonly releaseNotesUrl?: string;
readonly keyboardShortcutsUrlMac?: string;
readonly keyboardShortcutsUrlLinux?: string;
readonly keyboardShortcutsUrlWin?: string;
readonly introductoryVideosUrl?: string;
readonly tipsAndTricksUrl?: string;
readonly newsletterSignupUrl?: string;
readonly twitterUrl?: string;
readonly requestFeatureUrl?: string;
readonly reportIssueUrl?: string;
readonly reportMarketplaceIssueUrl?: string;
readonly licenseUrl?: string;
readonly privacyStatementUrl?: string;
readonly telemetryOptOutUrl?: string;
readonly npsSurveyUrl?: string;
readonly cesSurveyUrl?: string;
readonly surveys?: readonly ISurveyData[];
readonly checksums?: { [path: string]: string; };
readonly checksumFailMoreInfoUrl?: string;
readonly appCenter?: IAppCenterConfiguration;
readonly portable?: string;
readonly extensionKind?: { readonly [extensionId: string]: ExtensionKind[]; };
readonly extensionSyncedKeys?: { readonly [extensionId: string]: string[]; };
readonly extensionAllowedProposedApi?: readonly string[];
readonly msftInternalDomains?: string[];
readonly linkProtectionTrustedDomains?: readonly string[];
readonly 'configurationSync.store'?: ConfigurationSyncStore;
readonly darwinUniversalAssetId?: string;
}
export type ImportantExtensionTip = { name: string; languages?: string[]; pattern?: string; isExtensionPack?: boolean };
export interface IAppCenterConfiguration {
readonly 'win32-ia32': string;
readonly 'win32-x64': string;
readonly 'linux-x64': string;
readonly 'darwin': string;
}
export interface IConfigBasedExtensionTip {
configPath: string;
configName: string;
recommendations: IStringDictionary<{ name: string, remotes?: string[], important?: boolean, isExtensionPack?: boolean }>;
}
export interface IExeBasedExtensionTip {
friendlyName: string;
windowsPath?: string;
important?: boolean;
recommendations: IStringDictionary<{ name: string, important?: boolean, isExtensionPack?: boolean }>;
}
export interface IRemoteExtensionTip {
friendlyName: string;
extensionId: string;
}
export interface ISurveyData {
surveyId: string;
surveyUrl: string;
languageId: string;
editCount: number;
userProbability: number;
}

View file

@ -181,7 +181,8 @@ export class SharedProcess extends Disposable implements ISharedProcess {
}
});
const config: ISharedProcessConfiguration = {
// Store into config object URL
configObjectUrl.update({
machineId: this.machineId,
windowId: this.window.id,
appRoot: this.environmentMainService.appRoot,
@ -190,10 +191,7 @@ export class SharedProcess extends Disposable implements ISharedProcess {
userEnv: this.userEnv,
args: this.environmentMainService.args,
logLevel: this.logService.getLevel()
};
// Store into config object URL
configObjectUrl.update(config);
});
// Load with config
this.window.loadURL(FileAccess.asBrowserUri('vs/code/electron-browser/sharedProcess/sharedProcess.html', require).toString(true));

View file

@ -96,6 +96,7 @@ export interface IOffProcessTerminalService {
listProcesses(reduceGraceTime?: boolean): Promise<IProcessDetails[]>;
setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise<void>;
getTerminalLayoutInfo(): Promise<ITerminalsLayoutInfo | undefined>;
reduceConnectionGraceTime(): void;
}
export const ILocalTerminalService = createDecorator<ILocalTerminalService>('localTerminalService');
@ -111,8 +112,8 @@ export interface IPtyService {
readonly onPtyHostStart?: Event<void>;
readonly onPtyHostUnresponsive?: Event<void>;
readonly onPtyHostResponsive?: Event<void>;
readonly onProcessData: Event<{ id: number, event: IProcessDataEvent | string }>;
readonly onProcessBinary: Event<{ id: number, event: string }>;
readonly onProcessExit: Event<{ id: number, event: number | undefined }>;
readonly onProcessReady: Event<{ id: number, event: { pid: number, cwd: string } }>;
readonly onProcessTitleChanged: Event<{ id: number, event: string }>;
@ -142,10 +143,8 @@ export interface IPtyService {
/**
* Lists all orphaned processes, ie. those without a connected frontend.
* @param reduceGraceTime Whether to reduce the reconnection grace time for all orphaned
* terminals.
*/
listProcesses(reduceGraceTime: boolean): Promise<IProcessDetails[]>;
listProcesses(): Promise<IProcessDetails[]>;
start(id: number): Promise<ITerminalLaunchError | undefined>;
shutdown(id: number, immediate: boolean): Promise<void>;
@ -155,11 +154,13 @@ export interface IPtyService {
getCwd(id: number): Promise<string>;
getLatency(id: number): Promise<number>;
acknowledgeDataEvent(id: number, charCount: number): Promise<void>;
processBinary(id: number, data: string): void;
/** Confirm the process is _not_ an orphan. */
orphanQuestionReply(id: number): Promise<void>;
setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): Promise<void>;
getTerminalLayoutInfo(args: IGetTerminalLayoutInfoArgs): Promise<ITerminalsLayoutInfo | undefined>;
reduceConnectionGraceTime(): void;
}
export enum HeartbeatConstants {
@ -346,6 +347,7 @@ export interface ITerminalChildProcess {
*/
shutdown(immediate: boolean): void;
input(data: string): void;
processBinary(data: string): void;
resize(cols: number, rows: number): void;
/**

View file

@ -49,9 +49,10 @@ export class PtyHostService extends Disposable implements IPtyService {
readonly onPtyHostUnresponsive = this._onPtyHostUnresponsive.event;
private readonly _onPtyHostResponsive = this._register(new Emitter<void>());
readonly onPtyHostResponsive = this._onPtyHostResponsive.event;
private readonly _onProcessData = this._register(new Emitter<{ id: number, event: IProcessDataEvent | string }>());
readonly onProcessData = this._onProcessData.event;
private readonly _onProcessBinary = this._register(new Emitter<{ id: number, event: string }>());
readonly onProcessBinary = this._onProcessBinary.event;
private readonly _onProcessExit = this._register(new Emitter<{ id: number, event: number | undefined }>());
readonly onProcessExit = this._onProcessExit.event;
private readonly _onProcessReady = this._register(new Emitter<{ id: number, event: { pid: number, cwd: string } }>());
@ -123,6 +124,7 @@ export class PtyHostService extends Disposable implements IPtyService {
// Create proxy and forward events
const proxy = ProxyChannel.toService<IPtyService>(client.getChannel(TerminalIpcChannels.PtyHost));
this._register(proxy.onProcessData(e => this._onProcessData.fire(e)));
this._register(proxy.onProcessBinary(e => this._onProcessBinary.fire(e)));
this._register(proxy.onProcessExit(e => this._onProcessExit.fire(e)));
this._register(proxy.onProcessReady(e => this._onProcessReady.fire(e)));
this._register(proxy.onProcessTitleChanged(e => this._onProcessTitleChanged.fire(e)));
@ -153,10 +155,12 @@ export class PtyHostService extends Disposable implements IPtyService {
detachFromProcess(id: number): Promise<void> {
return this._proxy.detachFromProcess(id);
}
listProcesses(reduceGraceTime: boolean): Promise<IProcessDetails[]> {
return this._proxy.listProcesses(reduceGraceTime);
listProcesses(): Promise<IProcessDetails[]> {
return this._proxy.listProcesses();
}
reduceConnectionGraceTime(): void {
return this._proxy.reduceConnectionGraceTime();
}
start(id: number): Promise<ITerminalLaunchError | undefined> {
return this._proxy.start(id);
}
@ -188,6 +192,9 @@ export class PtyHostService extends Disposable implements IPtyService {
setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): Promise<void> {
return this._proxy.setTerminalLayoutInfo(args);
}
processBinary(id: number, data: string): void {
this._proxy.processBinary(id, data);
}
async getTerminalLayoutInfo(args: IGetTerminalLayoutInfoArgs): Promise<ITerminalsLayoutInfo | undefined> {
return await this._proxy.getTerminalLayoutInfo(args);
}

View file

@ -27,6 +27,8 @@ export class PtyService extends Disposable implements IPtyService {
private readonly _onProcessData = this._register(new Emitter<{ id: number, event: IProcessDataEvent | string }>());
readonly onProcessData = this._onProcessData.event;
private readonly _onProcessBinary = this._register(new Emitter<{ id: number, event: string }>());
readonly onProcessBinary = this._onProcessBinary.event;
private readonly _onProcessReplay = this._register(new Emitter<{ id: number, event: IPtyHostProcessReplayEvent }>());
readonly onProcessReplay = this._onProcessReplay.event;
private readonly _onProcessExit = this._register(new Emitter<{ id: number, event: number | undefined }>());
@ -114,13 +116,13 @@ export class PtyService extends Disposable implements IPtyService {
this._throwIfNoPty(id).detach();
}
async listProcesses(reduceGraceTime: boolean): Promise<IProcessDetails[]> {
if (reduceGraceTime) {
for (const pty of this._ptys.values()) {
pty.reduceGraceTime();
}
reduceConnectionGraceTime(): void {
for (const pty of this._ptys.values()) {
pty.reduceGraceTime();
}
}
async listProcesses(): Promise<IProcessDetails[]> {
const persistentProcesses = Array.from(this._ptys.entries()).filter(([_, pty]) => pty.shouldPersistTerminal);
this._logService.info(`Listing ${persistentProcesses.length} persistent terminals, ${this._ptys.size} total terminals`);
@ -157,6 +159,10 @@ export class PtyService extends Disposable implements IPtyService {
return this._throwIfNoPty(id).orphanQuestionReply();
}
processBinary(id: number, data: string): void {
return this._throwIfNoPty(id).writeBinary(data);
}
async setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): Promise<void> {
this._workspaceLayoutInfos.set(args.workspaceId, args);
}
@ -337,6 +343,9 @@ export class PersistentTerminalProcess extends Disposable {
}
return this._terminalProcess.input(data);
}
writeBinary(data: string): void {
return this._terminalProcess.processBinary(data);
}
resize(cols: number, rows: number): void {
if (this._inReplay) {
return;

View file

@ -311,23 +311,27 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
}
}
public input(data: string): void {
public input(data: string, isBinary?: boolean): void {
if (this._isDisposed || !this._ptyProcess) {
return;
}
for (let i = 0; i <= Math.floor(data.length / WRITE_MAX_CHUNK_SIZE); i++) {
this._writeQueue.push(data.substr(i * WRITE_MAX_CHUNK_SIZE, WRITE_MAX_CHUNK_SIZE));
}
this._startWrite();
this._startWrite(isBinary);
}
private _startWrite(): void {
public processBinary(data: string): void {
this.input(data, true);
}
private _startWrite(isBinary?: boolean): void {
// Don't write if it's already queued of is there is nothing to write
if (this._writeTimeout !== undefined || this._writeQueue.length === 0) {
return;
}
this._doWrite();
this._doWrite(isBinary);
// Don't queue more writes if the queue is empty
if (this._writeQueue.length === 0) {
@ -342,10 +346,16 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
}, WRITE_INTERVAL_MS);
}
private _doWrite(): void {
private _doWrite(isBinary?: boolean): void {
console.info('writing binary', isBinary);
const data = this._writeQueue.shift()!;
this._logService.trace('IPty#write', `${data.length} characters`);
this._ptyProcess!.write(data);
if (isBinary) {
this._logService.info('IPty#write (binary)', `${data.length} characters`);
this._ptyProcess!.write(Buffer.from(data, 'binary') as any);
} else {
this._logService.info('IPty#write', `${data.length} characters`);
this._ptyProcess!.write(data);
}
}
public resize(cols: number, rows: number): void {

View file

@ -10,7 +10,8 @@ import { joinPath, relativePath } from 'vs/base/common/resources';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IHeaders, IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IProductService, ConfigurationSyncStore } from 'vs/platform/product/common/productService';
import { IProductService } from 'vs/platform/product/common/productService';
import { ConfigurationSyncStore } from 'vs/base/common/product';
import { getServiceMachineId } from 'vs/platform/serviceMachineId/common/serviceMachineId';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IFileService } from 'vs/platform/files/common/files';

View file

@ -7,7 +7,8 @@ import * as assert from 'assert';
import { IUserDataSyncStoreService, SyncResource, UserDataSyncErrorCode, UserDataSyncStoreError, IUserDataSyncStoreManagementService, IUserDataSyncStore } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncClient, UserDataSyncTestServer } from 'vs/platform/userDataSync/test/common/userDataSyncClient';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IProductService, ConfigurationSyncStore } from 'vs/platform/product/common/productService';
import { IProductService } from 'vs/platform/product/common/productService';
import { ConfigurationSyncStore } from 'vs/base/common/product';
import { isWeb } from 'vs/base/common/platform';
import { RequestsSession, UserDataSyncStoreService, UserDataSyncStoreManagementService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
import { CancellationToken } from 'vs/base/common/cancellation';

View file

@ -871,9 +871,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
release: release()
};
// Force enable developer tools for extension development
configuration.forceEnableDeveloperKeybindings = Array.isArray(configuration.extensionDevelopmentPath);
// Store into config object URL
this.configObjectUrl.update(configuration);
}

View file

@ -45,14 +45,14 @@ export interface IWorkspaceTrustModel {
}
export interface WorkspaceTrustRequestButton {
label: string;
type: 'ContinueWithTrust' | 'ContinueWithoutTrust' | 'Manage' | 'Cancel'
readonly label: string;
readonly type: 'ContinueWithTrust' | 'ContinueWithoutTrust' | 'Manage' | 'Cancel'
}
export interface WorkspaceTrustRequestOptions {
buttons?: WorkspaceTrustRequestButton[];
message?: string;
modal: boolean;
readonly buttons?: WorkspaceTrustRequestButton[];
readonly message?: string;
readonly modal: boolean;
}
export interface IWorkspaceTrustRequestModel {
@ -68,8 +68,8 @@ export interface IWorkspaceTrustRequestModel {
}
export interface WorkspaceTrustStateChangeEvent {
previousTrustState: WorkspaceTrustState;
currentTrustState: WorkspaceTrustState;
readonly previousTrustState: WorkspaceTrustState;
readonly currentTrustState: WorkspaceTrustState;
}
export type WorkspaceTrustChangeEvent = Event<WorkspaceTrustStateChangeEvent>;
@ -84,7 +84,7 @@ export interface IWorkspaceTrustService {
onDidChangeTrustState: WorkspaceTrustChangeEvent;
getWorkspaceTrustState(): WorkspaceTrustState;
isWorkspaceTrustEnabled(): boolean;
requireWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<WorkspaceTrustState>;
requestWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<WorkspaceTrustState | undefined>;
}
export interface IWorkspaceTrustUriInfo {

View file

@ -2806,12 +2806,12 @@ declare module 'vscode' {
/**
* Previous trust state of the workspace
*/
previousTrustState: WorkspaceTrustState;
readonly previousTrustState: WorkspaceTrustState;
/**
* Current trust state of the workspace
*/
currentTrustState: WorkspaceTrustState;
readonly currentTrustState: WorkspaceTrustState;
}
/**
@ -2822,7 +2822,7 @@ declare module 'vscode' {
* When true, a modal dialog will be used to request workspace trust.
* When false, a badge will be displayed on the Setting activity bar item
*/
modal: boolean;
readonly modal: boolean;
}
export namespace workspace {
@ -2836,7 +2836,7 @@ declare module 'vscode' {
* @param options Optional object describing the properties of the
* workspace trust request
*/
export function requireWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Thenable<WorkspaceTrustState>;
export function requestWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Thenable<WorkspaceTrustState | undefined>;
/**
* Event that fires when the trust state of the current workspace changes

View file

@ -422,7 +422,7 @@ export class MainThreadTask implements MainThreadTaskShape {
if (execution.task?.execution && CustomExecutionDTO.is(execution.task.execution) && event.resolvedVariables) {
const dictionary: IStringDictionary<string> = {};
Array.from(event.resolvedVariables.entries()).forEach(entry => dictionary[entry[0]] = entry[1]);
resolvedDefinition = await this._configurationResolverService.resolveAny(task.getWorkspaceFolder(),
resolvedDefinition = await this._configurationResolverService.resolveAnyAsync(task.getWorkspaceFolder(),
execution.task.definition, dictionary);
}
this._proxy.$onDidStartTask(execution, event.terminalId!, resolvedDefinition);

View file

@ -100,9 +100,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
public dispose(): void {
this._toDispose.dispose();
this._linkProvider?.dispose();
// TODO@Daniel: Should all the previously created terminals be disposed
// when the extension host process goes down ?
}
private _getTerminalId(id: TerminalIdentifier): number | undefined {
@ -157,17 +154,11 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
}
public $dispose(id: TerminalIdentifier): void {
const terminalInstance = this._getTerminalInstance(id);
if (terminalInstance) {
terminalInstance.dispose();
}
this._getTerminalInstance(id)?.dispose();
}
public $sendText(id: TerminalIdentifier, text: string, addNewLine: boolean): void {
const terminalInstance = this._getTerminalInstance(id);
if (terminalInstance) {
terminalInstance.sendText(text, addNewLine);
}
this._getTerminalInstance(id)?.sendText(text, addNewLine);
}
public $startSendingDataEvents(): void {
@ -183,10 +174,8 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
}
public $stopSendingDataEvents(): void {
if (this._dataEventTracker) {
this._dataEventTracker.dispose();
this._dataEventTracker = undefined;
}
this._dataEventTracker?.dispose();
this._dataEventTracker = undefined;
}
public $startLinkProvider(): void {
@ -276,60 +265,35 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
}
public $sendProcessTitle(terminalId: number, title: string): void {
const terminalProcess = this._terminalProcessProxies.get(terminalId);
if (terminalProcess) {
terminalProcess.emitTitle(title);
}
this._terminalProcessProxies.get(terminalId)?.emitTitle(title);
}
public $sendProcessData(terminalId: number, data: string): void {
const terminalProcess = this._terminalProcessProxies.get(terminalId);
if (terminalProcess) {
terminalProcess.emitData(data);
}
this._terminalProcessProxies.get(terminalId)?.emitData(data);
}
public $sendProcessReady(terminalId: number, pid: number, cwd: string): void {
const terminalProcess = this._terminalProcessProxies.get(terminalId);
if (terminalProcess) {
terminalProcess.emitReady(pid, cwd);
}
this._terminalProcessProxies.get(terminalId)?.emitReady(pid, cwd);
}
public $sendProcessExit(terminalId: number, exitCode: number | undefined): void {
const terminalProcess = this._terminalProcessProxies.get(terminalId);
if (terminalProcess) {
terminalProcess.emitExit(exitCode);
this._terminalProcessProxies.delete(terminalId);
}
this._terminalProcessProxies.get(terminalId)?.emitExit(exitCode);
}
public $sendOverrideDimensions(terminalId: number, dimensions: ITerminalDimensions | undefined): void {
const terminalProcess = this._terminalProcessProxies.get(terminalId);
if (terminalProcess) {
terminalProcess.emitOverrideDimensions(dimensions);
}
this._terminalProcessProxies.get(terminalId)?.emitOverrideDimensions(dimensions);
}
public $sendProcessInitialCwd(terminalId: number, initialCwd: string): void {
const terminalProcess = this._terminalProcessProxies.get(terminalId);
if (terminalProcess) {
terminalProcess.emitInitialCwd(initialCwd);
}
this._terminalProcessProxies.get(terminalId)?.emitInitialCwd(initialCwd);
}
public $sendProcessCwd(terminalId: number, cwd: string): void {
const terminalProcess = this._terminalProcessProxies.get(terminalId);
if (terminalProcess) {
terminalProcess.emitCwd(cwd);
}
this._terminalProcessProxies.get(terminalId)?.emitCwd(cwd);
}
public $sendResolvedLaunchConfig(terminalId: number, shellLaunchConfig: IShellLaunchConfig): void {
const instance = this._terminalService.getInstanceFromId(terminalId);
if (instance) {
this._getTerminalProcess(terminalId)?.emitResolvedShellLaunchConfig(shellLaunchConfig);
}
this._getTerminalProcess(terminalId)?.emitResolvedShellLaunchConfig(shellLaunchConfig);
}
private async _onRequestLatency(terminalId: number): Promise<void> {

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { MainThreadWebviews, reviveWebviewContentOptions, reviveWebviewExtension } from 'vs/workbench/api/browser/mainThreadWebviews';
@ -81,7 +81,6 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
private readonly _webviewInputs = new WebviewInputStore();
private readonly _editorProviders = new Map<string, IDisposable>();
private readonly _webviewFromDiffEditorHandles = new Set<string>();
private readonly _revivers = new Map<string, IDisposable>();
@ -99,18 +98,17 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
this._proxy = context.getProxy(extHostProtocol.ExtHostContext.ExtHostWebviewPanels);
this._register(_editorService.onDidActiveEditorChange(() => {
const activeInput = this._editorService.activeEditor;
if (activeInput instanceof DiffEditorInput && activeInput.primary instanceof WebviewInput && activeInput.secondary instanceof WebviewInput) {
this.registerWebviewFromDiffEditorListeners(activeInput);
}
this.updateWebviewViewStates(activeInput);
this.updateWebviewViewStates(this._editorService.activeEditor);
}));
this._register(_editorService.onDidVisibleEditorsChange(() => {
this.updateWebviewViewStates(this._editorService.activeEditor);
}));
this._register(_webviewWorkbenchService.onDidChangeActiveWebviewEditor(input => {
this.updateWebviewViewStates(input);
}));
// This reviver's only job is to activate extensions.
// This should trigger the real reviver to be registered from the extension host side.
this._register(_webviewWorkbenchService.registerResolver({
@ -260,27 +258,6 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
this._revivers.delete(viewType);
}
private registerWebviewFromDiffEditorListeners(diffEditorInput: DiffEditorInput): void {
const primary = diffEditorInput.primary as WebviewInput;
const secondary = diffEditorInput.secondary as WebviewInput;
if (this._webviewFromDiffEditorHandles.has(primary.id) || this._webviewFromDiffEditorHandles.has(secondary.id)) {
return;
}
this._webviewFromDiffEditorHandles.add(primary.id);
this._webviewFromDiffEditorHandles.add(secondary.id);
const disposables = new DisposableStore();
disposables.add(primary.webview.onDidFocus(() => this.updateWebviewViewStates(primary)));
disposables.add(secondary.webview.onDidFocus(() => this.updateWebviewViewStates(secondary)));
disposables.add(diffEditorInput.onWillDispose(() => {
this._webviewFromDiffEditorHandles.delete(primary.id);
this._webviewFromDiffEditorHandles.delete(secondary.id);
dispose(disposables);
}));
}
private updateWebviewViewStates(activeEditorInput: IEditorInput | undefined) {
if (!this._webviewInputs.size) {
return;

View file

@ -208,8 +208,8 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
// --- trust ---
$requireWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<WorkspaceTrustState> {
return this._workspaceTrustService.requireWorkspaceTrust(options);
$requestWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<WorkspaceTrustState | undefined> {
return this._workspaceTrustService.requestWorkspaceTrust(options);
}
private getWorkspaceTrustState(): WorkspaceTrustState {

View file

@ -912,9 +912,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostWorkspace.trustState;
},
requireWorkspaceTrust: (options?: vscode.WorkspaceTrustRequestOptions) => {
requestWorkspaceTrust: (options?: vscode.WorkspaceTrustRequestOptions) => {
checkProposedApiEnabled(extension);
return extHostWorkspace.requireWorkspaceTrust(options);
return extHostWorkspace.requestWorkspaceTrust(options);
},
onDidChangeWorkspaceTrustState: (listener, thisArgs?, disposables?) => {
return extHostWorkspace.onDidChangeWorkspaceTrustState(listener, thisArgs, disposables);

View file

@ -927,7 +927,7 @@ export interface MainThreadWorkspaceShape extends IDisposable {
$saveAll(includeUntitled?: boolean): Promise<boolean>;
$updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, workspaceFoldersToAdd: { uri: UriComponents, name?: string; }[]): Promise<void>;
$resolveProxy(url: string): Promise<string | undefined>;
$requireWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<WorkspaceTrustState>;
$requestWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<WorkspaceTrustState | undefined>;
}
export interface IFileChangeDto {

View file

@ -225,6 +225,10 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
}
}
processBinary(data: string) {
throw new Error('not implemented');
}
acknowledgeDataEvent(charCount: number): void {
// No-op, flow control is not supported in extension owned terminals. If this is ever
// implemented it will need new pause and resume VS Code APIs.

View file

@ -563,8 +563,8 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
return this._workspaceTrustState;
}
requireWorkspaceTrust(options?: vscode.WorkspaceTrustRequestOptions): Promise<WorkspaceTrustState> {
return this._proxy.$requireWorkspaceTrust(options);
requestWorkspaceTrust(options?: vscode.WorkspaceTrustRequestOptions): Promise<WorkspaceTrustState | undefined> {
return this._proxy.$requestWorkspaceTrust(options);
}
$onDidChangeWorkspaceTrustState(state: WorkspaceTrustStateChangeEvent): void {

View file

@ -153,19 +153,19 @@ export class ExtHostTask extends ExtHostTaskBase {
}
};
for (let variable of toResolve.variables) {
result.variables[variable] = resolver.resolve(ws, variable);
result.variables[variable] = await resolver.resolveAsync(ws, variable);
}
if (toResolve.process !== undefined) {
let paths: string[] | undefined = undefined;
if (toResolve.process.path !== undefined) {
paths = toResolve.process.path.split(path.delimiter);
for (let i = 0; i < paths.length; i++) {
paths[i] = resolver.resolve(ws, paths[i]);
paths[i] = await resolver.resolveAsync(ws, paths[i]);
}
}
result.process = await win32.findExecutable(
resolver.resolve(ws, toResolve.process.name),
toResolve.process.cwd !== undefined ? resolver.resolve(ws, toResolve.process.cwd) : undefined,
await resolver.resolveAsync(ws, toResolve.process.name),
toResolve.process.cwd !== undefined ? await resolver.resolveAsync(ws, toResolve.process.cwd) : undefined,
paths
);
}

View file

@ -70,7 +70,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
protected async _beforeAlmostReadyToRunExtensions(): Promise<void> {
const mainThreadConsole = this._extHostContext.getProxy(MainContext.MainThreadConsole);
wrapConsoleMethods(mainThreadConsole);
wrapConsoleMethods(mainThreadConsole, this._initData.environment.isExtensionDevelopmentDebug);
// initialize API and register actors
const apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors);
@ -173,15 +173,19 @@ function ensureSuffix(path: string, suffix: string): string {
}
// copied from bootstrap-fork.js
function wrapConsoleMethods(service: MainThreadConsoleShape) {
function wrapConsoleMethods(service: MainThreadConsoleShape, callToNative: boolean) {
wrap('info', 'log');
wrap('log', 'log');
wrap('warn', 'warn');
wrap('error', 'error');
function wrap(method: 'error' | 'warn' | 'info' | 'log', severity: 'error' | 'warn' | 'log') {
const original = console[method];
console[method] = function () {
service.$logExtensionHostMessage({ type: '__$console', severity, arguments: safeToArray(arguments) });
if (callToNative) {
original.apply(console, arguments as any);
}
};
}

View file

@ -149,7 +149,7 @@ class ViewMenuActions extends CompositeMenuActions {
const scopedContextKeyService = contextKeyService.createScoped(element);
scopedContextKeyService.createKey('view', viewId);
const viewLocationKey = scopedContextKeyService.createKey('viewLocation', ViewContainerLocationToString(viewDescriptorService.getViewLocationById(viewId)!));
super(menuId, contextMenuId, undefined, scopedContextKeyService, menuService);
super(menuId, contextMenuId, { shouldForwardArgs: true }, scopedContextKeyService, menuService);
this._register(scopedContextKeyService);
this._register(Event.filter(viewDescriptorService.onDidChangeLocation, e => e.views.some(view => view.id === viewId))(() => viewLocationKey.set(ViewContainerLocationToString(viewDescriptorService.getViewLocationById(viewId)!))));
}

View file

@ -305,7 +305,7 @@ class ViewContainerMenuActions extends CompositeMenuActions {
const scopedContextKeyService = contextKeyService.createScoped(element);
scopedContextKeyService.createKey('viewContainer', viewContainer.id);
const viewContainerLocationKey = scopedContextKeyService.createKey('viewContainerLocation', ViewContainerLocationToString(viewDescriptorService.getViewContainerLocation(viewContainer)!));
super(MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext, undefined, scopedContextKeyService, menuService);
super(MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext, { shouldForwardArgs: true }, scopedContextKeyService, menuService);
this._register(scopedContextKeyService);
this._register(Event.filter(viewDescriptorService.onDidChangeContainerLocation, e => e.viewContainer === viewContainer)(() => viewContainerLocationKey.set(ViewContainerLocationToString(viewDescriptorService.getViewContainerLocation(viewContainer)!))));
}

View file

@ -12,7 +12,8 @@ import { IExtensionsViewPaneContainer, IExtensionsWorkbenchService, IExtension }
import { CancellationToken } from 'vs/base/common/cancellation';
import { localize } from 'vs/nls';
import { StorageScope, IStorageService, StorageTarget } from 'vs/platform/storage/common/storage';
import { ImportantExtensionTip, IProductService } from 'vs/platform/product/common/productService';
import { IProductService } from 'vs/platform/product/common/productService';
import { ImportantExtensionTip } from 'vs/base/common/product';
import { forEach, IStringDictionary } from 'vs/base/common/collections';
import { ITextModel } from 'vs/editor/common/model';
import { Schemas } from 'vs/base/common/network';

View file

@ -270,7 +270,8 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
updateItems.push({
output: key,
cellTop: cellTop,
outputOffset: outputOffset
outputOffset: outputOffset,
forceDisplay: false
});
}
}
@ -280,7 +281,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
removedItems.forEach(output => activeWebview.removeInset(output));
if (updateItems.length) {
activeWebview.updateViewScrollTop(-scrollTop, false, updateItems);
activeWebview.updateScrollTops(updateItems, []);
}
}
}
@ -575,10 +576,9 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
await activeWebview.createOutput({ diffElement: cellDiffViewModel, cellHandle: cellViewModel.handle, cellId: cellViewModel.id, cellUri: cellViewModel.uri }, output, cellTop, getOffset());
} else {
const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel);
const scrollTop = this._list.scrollTop;
const outputIndex = cellViewModel.outputsViewModels.indexOf(output.source);
const outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex);
activeWebview.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]);
activeWebview.updateScrollTops([{ output: output.source, cellTop, outputOffset, forceDisplay: true }], []);
}
});
}
@ -622,10 +622,9 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
}
const cellTop = this._list.getAbsoluteTopOfElement(cellDiffViewModel);
const scrollTop = this._list.scrollTop;
const outputIndex = cellViewModel.outputsViewModels.indexOf(displayOutput);
const outputOffset = cellTop + cellDiffViewModel.getOutputOffsetInCell(diffSide, outputIndex);
activeWebview.updateViewScrollTop(-scrollTop, true, [{ output: displayOutput, cellTop, outputOffset }]);
activeWebview.updateScrollTops([{ output: displayOutput, cellTop, outputOffset, forceDisplay: true }], []);
});
}

View file

@ -140,6 +140,7 @@ export interface IDisplayOutputLayoutUpdateRequest {
output: IDisplayOutputViewModel;
cellTop: number;
outputOffset: number;
forceDisplay: boolean;
}
export interface ICommonCellInfo {
@ -480,7 +481,6 @@ export interface INotebookEditor extends ICommonNotebookEditor {
unhideMarkdownPreview(cell: ICellViewModel): Promise<void>;
hideMarkdownPreview(cell: ICellViewModel): Promise<void>;
removeMarkdownPreview(cell: ICellViewModel): Promise<void>;
updateMarkdownPreviewSelectionState(cell: ICellViewModel, isSelected: boolean): Promise<void>;
/**
* Render the output in webview layer

View file

@ -1119,87 +1119,80 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this._localStore.add(this.viewModel.onDidChangeSelection(() => {
this._onDidChangeSelection.fire();
this.updateSelectedMarkdownPreviews();
}));
this._localStore.add(this._list.onWillScroll(e => {
if (this._webview?.isResolved()) {
this._webview.updateViewScrollTop(-e.scrollTop, true, []);
this._webviewTransparentCover!.style.top = `${e.scrollTop}px`;
}
}));
let hasPendingChangeContentHeight = false;
this._localStore.add(this._list.onDidChangeContentHeight(() => {
if (hasPendingChangeContentHeight) {
return;
}
hasPendingChangeContentHeight = true;
DOM.scheduleAtNextAnimationFrame(() => {
if (this._isDisposed) {
hasPendingChangeContentHeight = false;
if (this._isDisposed || !this._webview?.isResolved()) {
return;
}
const scrollTop = this._list.scrollTop;
const scrollHeight = this._list.scrollHeight;
if (!this._webview?.isResolved()) {
return;
}
this._webview!.element.style.height = `${scrollHeight}px`;
if (this._webview?.insetMapping) {
const updateItems: IDisplayOutputLayoutUpdateRequest[] = [];
const removedItems: ICellOutputViewModel[] = [];
this._webview?.insetMapping.forEach((value, key) => {
const cell = this.viewModel?.getCellByHandle(value.cellInfo.cellHandle);
if (!cell || !(cell instanceof CodeCellViewModel)) {
return;
}
const updateItems: IDisplayOutputLayoutUpdateRequest[] = [];
const removedItems: ICellOutputViewModel[] = [];
this._webview?.insetMapping.forEach((value, key) => {
const cell = this.viewModel?.getCellByHandle(value.cellInfo.cellHandle);
if (!cell || !(cell instanceof CodeCellViewModel)) {
return;
}
const viewIndex = this._list.getViewIndex(cell);
this.viewModel?.viewCells.find(cell => cell.handle === value.cellInfo.cellHandle);
const viewIndex = this._list.getViewIndex(cell);
if (viewIndex === undefined) {
return;
}
if (viewIndex === undefined) {
return;
}
if (cell.outputsViewModels.indexOf(key) < 0) {
// output is already gone
removedItems.push(key);
}
if (cell.outputsViewModels.indexOf(key) < 0) {
// output is already gone
removedItems.push(key);
}
const cellTop = this._list.getAbsoluteTopOfElement(cell);
if (this._webview!.shouldUpdateInset(cell, key, cellTop)) {
const outputIndex = cell.outputsViewModels.indexOf(key);
const outputOffset = cellTop + cell.getOutputOffset(outputIndex);
updateItems.push({
output: key,
cellTop: cellTop,
outputOffset,
forceDisplay: false,
});
}
});
removedItems.forEach(output => this._webview?.removeInset(output));
const markdownUpdateItems: { id: string, top: number }[] = [];
for (const cellId of this._webview.markdownPreviewMapping.keys()) {
const cell = this.viewModel?.viewCells.find(cell => cell.id === cellId);
if (cell) {
const cellTop = this._list.getAbsoluteTopOfElement(cell);
if (this._webview!.shouldUpdateInset(cell, key, cellTop)) {
const outputIndex = cell.outputsViewModels.indexOf(key);
const outputOffset = cellTop + cell.getOutputOffset(outputIndex);
updateItems.push({
output: key,
cellTop: cellTop,
outputOffset
});
}
});
removedItems.forEach(output => this._webview?.removeInset(output));
if (updateItems.length) {
this._debug('_list.onDidChangeContentHeight/outputs', updateItems);
this._webview?.updateViewScrollTop(-scrollTop, false, updateItems);
markdownUpdateItems.push({ id: cellId, top: cellTop });
}
}
if (this._webview?.markdownPreviewMapping) {
const updateItems: { id: string, top: number }[] = [];
this._webview.markdownPreviewMapping.forEach((_, cellId) => {
const cell = this.viewModel?.viewCells.find(cell => cell.id === cellId);
if (cell) {
const cellTop = this._list.getAbsoluteTopOfElement(cell);
updateItems.push({ id: cellId, top: cellTop });
}
});
if (updateItems.length) {
this._debug('_list.onDidChangeContentHeight/markdown', updateItems);
this._webview?.updateMarkdownScrollTop(updateItems);
}
if (markdownUpdateItems.length || updateItems.length) {
this._debug('_list.onDidChangeContentHeight/markdown', markdownUpdateItems);
this._webview?.updateScrollTops(updateItems, markdownUpdateItems);
}
});
}));
@ -1308,10 +1301,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
// no cached view state so we are rendering the first viewport
// after above async call, we already get init height for markdown cells, we can update their offset
let offset = 0;
let offsetUpdateRequests: { id: string, top: number }[] = [];
const offsetUpdateRequests: { id: string, top: number }[] = [];
const scrollBottom = Math.max(this._dimension?.height ?? 0, 1080);
for (let i = 0; i < viewModel.length; i++) {
const cell = viewModel.cellAt(i)!;
for (const cell of viewModel.viewCells) {
if (cell.cellKind === CellKind.Markdown) {
offsetUpdateRequests.push({ id: cell.id, top: offset });
}
@ -1323,7 +1315,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
}
}
this._webview?.updateMarkdownScrollTop(offsetUpdateRequests);
this._webview?.updateScrollTops([], offsetUpdateRequests);
}
}
@ -2196,13 +2188,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
await this._webview?.removeMarkdownPreview(cell.id);
}
async updateMarkdownPreviewSelectionState(cell: ICellViewModel, isSelected: boolean): Promise<void> {
if (!this.useRenderer) {
// TODO: handle case where custom renderer is disabled?
return;
}
if (!this._webview) {
private async updateSelectedMarkdownPreviews(): Promise<void> {
if (!this.useRenderer || !this._webview) {
return;
}
@ -2210,7 +2197,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
await this._resolveWebview();
}
await this._webview?.updateMarkdownPreviewSelectionState(cell.id, isSelected);
const selectedCells = this.getSelectionViewModels().map(cell => cell.id);
// Only show selection when there is more than 1 cell selected
await this._webview?.updateMarkdownPreviewSelections(selectedCells.length > 1 ? selectedCells : []);
}
async createOutput(cell: CodeCellViewModel, output: IInsetRenderOutput, offset: number): Promise<void> {
@ -2223,16 +2213,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
await this._resolveWebview();
}
const cellTop = this._list.getAbsoluteTopOfElement(cell);
if (!this._webview!.insetMapping.has(output.source)) {
const cellTop = this._list.getAbsoluteTopOfElement(cell);
await this._webview!.createOutput({ cellId: cell.id, cellHandle: cell.handle, cellUri: cell.uri }, output, cellTop, offset);
} else {
const cellTop = this._list.getAbsoluteTopOfElement(cell);
const scrollTop = this._list.scrollTop;
const outputIndex = cell.outputsViewModels.indexOf(output.source);
const outputOffset = cellTop + cell.getOutputOffset(outputIndex);
this._webview!.updateViewScrollTop(-scrollTop, true, [{ output: output.source, cellTop, outputOffset }]);
this._webview!.updateScrollTops([{ output: output.source, cellTop, outputOffset, forceDisplay: true }], []);
}
});
}

View file

@ -26,6 +26,7 @@ import { IWebviewService, WebviewContentPurpose, WebviewElement } from 'vs/workb
import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import * as nls from 'vs/nls';
import { coalesce } from 'vs/base/common/arrays';
interface BaseToWebviewMessage {
readonly __vscode_notebook_message: true;
@ -35,14 +36,18 @@ export interface WebviewIntialized extends BaseToWebviewMessage {
type: 'initialized';
}
export interface IDimensionMessage extends BaseToWebviewMessage {
type: 'dimension';
export interface DimensionUpdate {
id: string;
init?: boolean;
data: { height: number };
isOutput?: boolean;
}
export interface IDimensionMessage extends BaseToWebviewMessage {
type: 'dimension';
updates: readonly DimensionUpdate[];
}
export interface IMouseEnterMessage extends BaseToWebviewMessage {
type: 'mouseenter';
id: string;
@ -183,20 +188,13 @@ export interface ICreationRequestMessage {
export interface IContentWidgetTopRequest {
id: string;
top: number;
left: number;
forceDisplay: boolean;
}
export interface IViewScrollTopRequestMessage {
type: 'view-scroll';
top?: number;
forceDisplay: boolean;
widgets: IContentWidgetTopRequest[];
version: number;
}
export interface IViewScrollMarkdownRequestMessage {
type: 'view-scroll-markdown';
cells: { id: string; top: number }[];
markdownPreviews: { id: string; top: number }[];
}
export interface IScrollRequestMessage {
@ -287,10 +285,9 @@ export interface IShowMarkdownMessage {
top: number;
}
export interface IUpdateMarkdownPreviewSelectionState {
readonly type: 'updateMarkdownPreviewSelectionState',
readonly id: string;
readonly isSelected: boolean;
export interface IUpdateSelectedMarkdownPreviews {
readonly type: 'updateSelectedMarkdownPreviews',
readonly selectedCellIds: readonly string[]
}
export interface IInitializeMarkdownMessage {
@ -337,9 +334,8 @@ export type ToWebviewMessage =
| IShowMarkdownMessage
| IHideMarkdownMessage
| IUnhideMarkdownMessage
| IUpdateMarkdownPreviewSelectionState
| IInitializeMarkdownMessage
| IViewScrollMarkdownRequestMessage;
| IUpdateSelectedMarkdownPreviews
| IInitializeMarkdownMessage;
export type AnyMessage = FromWebviewMessage | ToWebviewMessage;
@ -367,12 +363,11 @@ export interface IResolvedBackLayerWebview {
webview: WebviewElement;
}
let version = 0;
export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
element: HTMLElement;
webview: WebviewElement | undefined = undefined;
insetMapping: Map<IDisplayOutputViewModel, ICachedInset<T>> = new Map();
markdownPreviewMapping = new Map<string, { version: number, visible: boolean }>();
readonly markdownPreviewMapping = new Map<string, { version: number, visible: boolean }>();
hiddenInsetMapping: Set<IDisplayOutputViewModel> = new Set();
reversedInsetMapping: Map<string, IDisplayOutputViewModel> = new Map();
localResourceRootsCache: URI[] | undefined = undefined;
@ -838,18 +833,20 @@ var requirejs = (function() {
switch (data.type) {
case 'dimension':
{
if (data.isOutput) {
const height = data.data.height;
const outputHeight = height;
for (const update of data.updates) {
if (update.isOutput) {
const height = update.data.height;
const outputHeight = height;
const resolvedResult = this.resolveOutputId(data.id);
if (resolvedResult) {
const { cellInfo, output } = resolvedResult;
this.notebookEditor.updateOutputHeight(cellInfo, output, outputHeight, !!data.init, 'webview#dimension');
const resolvedResult = this.resolveOutputId(update.id);
if (resolvedResult) {
const { cellInfo, output } = resolvedResult;
this.notebookEditor.updateOutputHeight(cellInfo, output, outputHeight, !!update.init, 'webview#dimension');
}
} else {
const cellId = update.id.substr(0, update.id.length - '_preview'.length);
this.notebookEditor.updateMarkdownCellHeight(cellId, update.data.height, !!update.init);
}
} else {
const cellId = data.id.substr(0, data.id.length - '_preview'.length);
this.notebookEditor.updateMarkdownCellHeight(cellId, data.data.height, !!data.init);
}
break;
}
@ -1109,20 +1106,16 @@ var requirejs = (function() {
return true;
}
updateMarkdownScrollTop(items: { id: string, top: number }[]) {
this._sendMessageToWebview({
type: 'view-scroll-markdown',
cells: items
});
}
updateViewScrollTop(top: number, forceDisplay: boolean, items: IDisplayOutputLayoutUpdateRequest[]) {
updateScrollTops(outputs: IDisplayOutputLayoutUpdateRequest[], markdownPreviews: { id: string, top: number }[]) {
if (this._disposed) {
return;
}
const widgets: IContentWidgetTopRequest[] = items.map(item => {
const outputCache = this.insetMapping.get(item.output)!;
const widgets = coalesce(outputs.map((item): IContentWidgetTopRequest | undefined => {
const outputCache = this.insetMapping.get(item.output);
if (!outputCache) {
return;
}
const id = outputCache.outputId;
const outputOffset = item.outputOffset;
outputCache.cachedCreation.top = outputOffset;
@ -1131,16 +1124,18 @@ var requirejs = (function() {
return {
id: id,
top: outputOffset,
left: 0
forceDisplay: item.forceDisplay,
};
});
}));
if (!widgets.length && !markdownPreviews.length) {
return;
}
this._sendMessageToWebview({
top,
type: 'view-scroll',
version: version++,
forceDisplay,
widgets: widgets
widgets: widgets,
markdownPreviews,
});
}
@ -1256,21 +1251,14 @@ var requirejs = (function() {
});
}
async updateMarkdownPreviewSelectionState(cellId: any, isSelected: boolean) {
async updateMarkdownPreviewSelections(selectedCellsIds: string[]) {
if (this._disposed) {
return;
}
if (!this.markdownPreviewMapping.has(cellId)) {
// TODO: this currently seems expected on first load
// console.error(`Try to update selection state for preview that does not exist: ${cellId}`);
return;
}
this._sendMessageToWebview({
type: 'updateMarkdownPreviewSelectionState',
id: cellId,
isSelected
type: 'updateSelectedMarkdownPreviews',
selectedCellIds: selectedCellsIds.filter(id => this.markdownPreviewMapping.has(id)),
});
}

View file

@ -198,15 +198,6 @@ export class StatefulMarkdownCell extends Disposable {
if (this.viewCell.layoutInfo.totalHeight > 0) {
this.relayoutCell();
}
// Update for selection
this._register(this.notebookEditor.onDidChangeSelection(() => {
const selectedCells = this.notebookEditor.getSelectionViewModels();
// Only show selection if there are more than one cells selected
const isSelected = selectedCells.length > 1 && selectedCells.some(selectedCell => selectedCell === viewCell);
this.notebookEditor.updateMarkdownPreviewSelectionState(viewCell, isSelected);
}));
}
// apply decorations

View file

@ -6,7 +6,7 @@
import type { Event } from 'vs/base/common/event';
import type { IDisposable } from 'vs/base/common/lifecycle';
import { RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { FromWebviewMessage, IBlurOutputMessage, ICellDropMessage, ICellDragMessage, ICellDragStartMessage, IClickedDataUrlMessage, ICustomRendererMessage, IDimensionMessage, IClickMarkdownPreviewMessage, IMouseEnterMarkdownPreviewMessage, IMouseEnterMessage, IMouseLeaveMarkdownPreviewMessage, IMouseLeaveMessage, IToggleMarkdownPreviewMessage, IWheelMessage, ToWebviewMessage, ICellDragEndMessage, IOutputFocusMessage, IOutputBlurMessage } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
import { FromWebviewMessage, IBlurOutputMessage, ICellDropMessage, ICellDragMessage, ICellDragStartMessage, IClickedDataUrlMessage, ICustomRendererMessage, IDimensionMessage, IClickMarkdownPreviewMessage, IMouseEnterMarkdownPreviewMessage, IMouseEnterMessage, IMouseLeaveMarkdownPreviewMessage, IMouseLeaveMessage, IToggleMarkdownPreviewMessage, IWheelMessage, ToWebviewMessage, ICellDragEndMessage, IOutputFocusMessage, IOutputBlurMessage, DimensionUpdate } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
// !! IMPORTANT !! everything must be in-line within the webviewPreloads
// function. Imports are not allowed. This is stringifies and injected into
@ -136,6 +136,26 @@ function webviewPreloads() {
const outputObservers = new Map<string, ResizeObserver>();
const dimensionUpdater = new class {
private readonly pending = new Map<string, DimensionUpdate>();
update(id: string, update: DimensionUpdate) {
if (!this.pending.size) {
setTimeout(() => {
if (!this.pending.size) {
return;
}
postNotebookMessage<IDimensionMessage>('dimension', {
updates: Array.from(this.pending.values())
});
this.pending.clear();
}, 0);
}
this.pending.set(id, update);
}
};
const resizeObserve = (container: Element, id: string, output: boolean) => {
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
@ -145,27 +165,20 @@ function webviewPreloads() {
if (entry.target.id === id && entry.contentRect) {
if (output) {
let height = 0;
if (entry.contentRect.height !== 0) {
entry.target.style.padding = `${__outputNodePadding__}px ${__outputNodePadding__}px ${__outputNodePadding__}px ${output ? __outputNodeLeftPadding__ : __leftMargin__}px`;
postNotebookMessage<IDimensionMessage>('dimension', {
id: id,
data: {
height: entry.contentRect.height + __outputNodePadding__ * 2
},
isOutput: true
});
height = entry.contentRect.height + __outputNodePadding__ * 2;
} else {
entry.target.style.padding = `0px`;
postNotebookMessage<IDimensionMessage>('dimension', {
id: id,
data: {
height: entry.contentRect.height
},
isOutput: true
});
}
dimensionUpdater.update(id, {
id: id,
data: { height },
isOutput: true
});
} else {
postNotebookMessage<IDimensionMessage>('dimension', {
dimensionUpdater.update(id, {
id: id,
data: {
// entry.contentRect does not include padding
@ -537,12 +550,22 @@ function webviewPreloads() {
}
}
break;
case 'updateMarkdownPreviewSelectionState':
case 'updateSelectedMarkdownPreviews':
{
const data = event.data;
const previewNode = document.getElementById(`${data.id}_preview`);
if (previewNode) {
previewNode.classList.toggle('selected', data.isSelected);
const selectedCellIds = new Set<string>(event.data.selectedCellIds);
for (const oldSelected of document.querySelectorAll('.preview.selected')) {
const id = oldSelected.id.replace('_preview', '');
if (!selectedCellIds.has(id)) {
oldSelected.classList.remove('selected');
}
}
for (const newSelected of selectedCellIds) {
const previewNode = document.getElementById(`${newSelected}_preview`);
if (previewNode) {
previewNode.classList.add('selected');
}
}
}
break;
@ -634,7 +657,7 @@ function webviewPreloads() {
if (clientHeight !== 0 && cps.padding === '0px') {
// we set padding to zero if the output height is zero (then we can have a zero-height output DOM node)
// thus we need to ensure the padding is accounted when updating the init height of the output
postNotebookMessage<IDimensionMessage>('dimension', {
dimensionUpdater.update(outputId, {
id: outputId,
isOutput: true,
init: true,
@ -645,7 +668,7 @@ function webviewPreloads() {
outputNode.style.padding = `${__outputNodePadding__}px ${__outputNodePadding__}px ${__outputNodePadding__}px ${__outputNodeLeftPadding__}px`;
} else {
postNotebookMessage<IDimensionMessage>('dimension', {
dimensionUpdater.update(outputId, {
id: outputId,
isOutput: true,
init: true,
@ -656,7 +679,7 @@ function webviewPreloads() {
}
// don't hide until after this step so that the height is right
cellOutputContainer.style.display = data.initiallyHidden ? 'none' : 'block';
cellOutputContainer.style.visibility = data.initiallyHidden ? 'hidden' : 'visible';
});
break;
case 'view-scroll':
@ -664,34 +687,22 @@ function webviewPreloads() {
// const date = new Date();
// console.log('----- will scroll ---- ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds());
for (let i = 0; i < event.data.widgets.length; i++) {
const widget = document.getElementById(event.data.widgets[i].id)!;
for (const request of event.data.widgets) {
const widget = document.getElementById(request.id)!;
if (widget) {
widget.style.top = event.data.widgets[i].top + 'px';
if (event.data.forceDisplay) {
widget.parentElement!.style.display = 'block';
widget.style.top = request.top + 'px';
if (request.forceDisplay) {
widget.parentElement!.style.visibility = 'visible';
}
}
}
break;
}
case 'view-scroll-markdown':
{
// const date = new Date();
// console.log(`${date.getSeconds()}:${date.getMilliseconds().toString().padStart(3, '0')}`, '[iframe]: view-scroll-markdown', event.data.cells);
event.data.cells.map(cell => {
const widget = document.getElementById(`${cell.id}_preview`)!;
for (const cell of event.data.markdownPreviews) {
const widget = document.getElementById(`${cell.id}_preview`)!;
if (widget) {
widget.style.top = `${cell.top}px`;
}
const markdownPreview = document.getElementById(`${cell.id}`);
if (markdownPreview) {
markdownPreview.style.display = 'block';
}
});
}
break;
}
@ -721,7 +732,7 @@ function webviewPreloads() {
enqueueOutputAction(event.data, ({ outputId }) => {
const container = document.getElementById(outputId)?.parentElement;
if (container) {
container.style.display = 'none';
container.style.visibility = 'hidden';
}
});
break;
@ -729,10 +740,10 @@ function webviewPreloads() {
enqueueOutputAction(event.data, ({ outputId, top }) => {
const output = document.getElementById(outputId);
if (output) {
output.parentElement!.style.display = 'block';
output.parentElement!.style.visibility = 'visible';
output.style.top = top + 'px';
postNotebookMessage<IDimensionMessage>('dimension', {
dimensionUpdater.update(outputId, {
id: outputId,
isOutput: true,
data: {
@ -767,13 +778,8 @@ function webviewPreloads() {
case 'decorations':
{
const outputContainer = document.getElementById(event.data.cellId);
event.data.addedClassNames.forEach(n => {
outputContainer?.classList.add(n);
});
event.data.removedClassNames.forEach(n => {
outputContainer?.classList.remove(n);
});
outputContainer?.classList.add(...event.data.addedClassNames);
outputContainer?.classList.remove(...event.data.removedClassNames);
}
break;
@ -839,8 +845,7 @@ function webviewPreloads() {
cellContainer.appendChild(previewContainerNode);
previewContainerNode.attachShadow({ mode: 'open' });
const previewRoot = previewContainerNode.shadowRoot! as any as HTMLElement;
const previewRoot = previewContainerNode.attachShadow({ mode: 'open' });
// Add default webview style
const defaultStyles = document.getElementById('_defaultStyles') as HTMLStyleElement;
@ -894,7 +899,7 @@ function webviewPreloads() {
}
}
postNotebookMessage<IDimensionMessage>('dimension', {
dimensionUpdater.update(`${cellId}_preview`, {
id: `${cellId}_preview`,
data: {
height: previewContainerNode.clientHeight,

View file

@ -104,7 +104,6 @@ class PerfModelContentProvider implements ITextModelContentProvider {
this._model.setMode(e);
}
}));
this._modelDisposables.push(langId);
this._modelDisposables.push(this._extensionService.onDidChangeExtensionsStatus(this._updateModel, this));
writeTransientState(this._model, { wordWrapOverride: 'off' }, this._editorService);

View file

@ -1025,24 +1025,21 @@ export class DefaultPreferencesEditor extends BaseTextEditor {
return options;
}
setInput(input: DefaultPreferencesEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
return super.setInput(input, options, context, token)
.then(() => this.input!.resolve()
.then<any>(editorModel => {
if (token.isCancellationRequested) {
return undefined;
}
return editorModel!.resolve();
})
.then(editorModel => {
if (token.isCancellationRequested) {
return;
}
const editor = assertIsDefined(this.getControl());
editor.setModel((<ResourceEditorModel>editorModel).textEditorModel);
}));
async setInput(input: DefaultPreferencesEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
await super.setInput(input, options, context, token);
const editorModel = await this.input!.resolve();
if (!editorModel) {
return;
}
if (token.isCancellationRequested) {
return;
}
await editorModel.resolve();
if (token.isCancellationRequested) {
return;
}
const editor = assertIsDefined(this.getControl());
editor.setModel((<ResourceEditorModel>editorModel).textEditorModel);
}
clearInput(): void {

View file

@ -94,11 +94,11 @@ export class ForwardedPortsView extends Disposable implements IWorkbenchContribu
private enableBadgeAndStatusBar() {
const disposable = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).onViewsRegistered(e => {
if (e.find(view => view.views.find(viewDescriptor => viewDescriptor.id === TUNNEL_VIEW_ID))) {
this._register(this.remoteExplorerService.tunnelModel.onForwardPort(() => {
this._register(Event.debounce(this.remoteExplorerService.tunnelModel.onForwardPort, (_last, e) => e, 50)(() => {
this.updateActivityBadge();
this.updateStatusBar();
}));
this._register(this.remoteExplorerService.tunnelModel.onClosePort(() => {
this._register(Event.debounce(this.remoteExplorerService.tunnelModel.onClosePort, (_last, e) => e, 50)(() => {
this.updateActivityBadge();
this.updateStatusBar();
}));

View file

@ -664,6 +664,10 @@ export class TunnelPanel extends ViewPane {
}));
}
get portCount(): number {
return this.remoteExplorerService.tunnelModel.forwarded.size + this.remoteExplorerService.tunnelModel.detected.size;
}
protected renderBody(container: HTMLElement): void {
super.renderBody(container);
@ -719,8 +723,12 @@ export class TunnelPanel extends ViewPane {
const rerender = () => this.table.splice(0, Number.POSITIVE_INFINITY, this.viewModel.all);
rerender();
this._register(this.viewModel.onForwardedPortsChanged(() => {
this._onDidChangeViewWelcomeState.fire();
let lastPortCount = this.portCount;
this._register(Event.debounce(this.viewModel.onForwardedPortsChanged, (_last, e) => e, 50)(() => {
const newPortCount = this.portCount;
if (((lastPortCount === 0) || (newPortCount === 0)) && (lastPortCount !== newPortCount)) {
this._onDidChangeViewWelcomeState.fire();
}
rerender();
}));

View file

@ -10,7 +10,8 @@ import { IWorkbenchContributionsRegistry, IWorkbenchContribution, Extensions as
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { ISurveyData, IProductService } from 'vs/platform/product/common/productService';
import { IProductService } from 'vs/platform/product/common/productService';
import { ISurveyData } from 'vs/base/common/product';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { Severity, INotificationService } from 'vs/platform/notification/common/notification';
import { ITextFileService, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';

View file

@ -2058,6 +2058,15 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
let workspaceFolder: IWorkspaceFolder = this.contextService.getWorkspace().folders[0];
workspaceFolders.push(workspaceFolder);
executionEngine = this.computeExecutionEngine(workspaceFolder);
const telemetryData: { [key: string]: any; } = {
executionEngineVersion: executionEngine
};
/* __GDPR__
"taskService.engineVersion" : {
"executionEngineVersion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('taskService.engineVersion', telemetryData);
schemaVersion = this.computeJsonSchemaVersion(workspaceFolder);
} else if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
workspace = this.contextService.getWorkspace();

View file

@ -116,7 +116,7 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut
public static async promptForPermission(taskService: ITaskService, storageService: IStorageService, notificationService: INotificationService, workspaceTrustService: IWorkspaceTrustService,
openerService: IOpenerService, workspaceTaskResult: Map<string, WorkspaceFolderTaskResult>) {
const isWorkspaceTrusted = await workspaceTrustService.requireWorkspaceTrust({ modal: false }) === WorkspaceTrustState.Trusted;
const isWorkspaceTrusted = await workspaceTrustService.requestWorkspaceTrust({ modal: false }) === WorkspaceTrustState.Trusted;
if (!isWorkspaceTrusted) {
return;
}

View file

@ -81,21 +81,30 @@ class InstanceManager {
}
class VariableResolver {
private static regex = /\$\{(.*?)\}/g;
constructor(public workspaceFolder: IWorkspaceFolder | undefined, public taskSystemInfo: TaskSystemInfo | undefined, public readonly values: Map<string, string>, private _service: IConfigurationResolverService | undefined) {
}
resolve(value: string): string {
return value.replace(/\$\{(.*?)\}/g, (match: string, variable: string) => {
// Strip out the ${} because the map contains them variables without those characters.
let result = this.values.get(match.substring(2, match.length - 1));
if ((result !== undefined) && (result !== null)) {
return result;
}
if (this._service) {
return this._service.resolve(this.workspaceFolder, match);
}
async resolve(value: string): Promise<string> {
const replacers: Promise<string>[] = [];
value.replace(VariableResolver.regex, (match, ...args) => {
replacers.push(this.replacer(match, args));
return match;
});
const resolvedReplacers = await Promise.all(replacers);
return value.replace(VariableResolver.regex, () => resolvedReplacers.shift()!);
}
private async replacer(match: string, args: string[]): Promise<string> {
// Strip out the ${} because the map contains them variables without those characters.
let result = this.values.get(match.substring(2, match.length - 1));
if ((result !== undefined) && (result !== null)) {
return result;
}
if (this._service) {
return this._service.resolveAsync(this.workspaceFolder, match);
}
return match;
}
}
@ -534,9 +543,9 @@ export class TerminalTaskSystem implements ITaskSystem {
}
private async resolveAndFindExecutable(systemInfo: TaskSystemInfo | undefined, workspaceFolder: IWorkspaceFolder | undefined, task: CustomTask | ContributedTask, cwd: string | undefined, envPath: string | undefined): Promise<string> {
const command = this.configurationResolverService.resolve(workspaceFolder, CommandString.value(task.command.name!));
cwd = cwd ? this.configurationResolverService.resolve(workspaceFolder, cwd) : undefined;
const paths = envPath ? envPath.split(path.delimiter).map(p => this.configurationResolverService.resolve(workspaceFolder, p)) : undefined;
const command = await this.configurationResolverService.resolveAsync(workspaceFolder, CommandString.value(task.command.name!));
cwd = cwd ? await this.configurationResolverService.resolveAsync(workspaceFolder, cwd) : undefined;
const paths = envPath ? await Promise.all(envPath.split(path.delimiter).map(p => this.configurationResolverService.resolveAsync(workspaceFolder, p))) : undefined;
let foundExecutable = await systemInfo?.findExecutable(command, cwd, paths);
if (!foundExecutable) {
foundExecutable = path.join(cwd ?? '', command);
@ -633,7 +642,7 @@ export class TerminalTaskSystem implements ITaskSystem {
if (Platform.isWindows) {
processVarValue = await this.resolveAndFindExecutable(taskSystemInfo, workspaceFolder, task, cwd, envPath);
} else {
processVarValue = this.configurationResolverService.resolve(workspaceFolder, CommandString.value(task.command.name!));
processVarValue = await this.configurationResolverService.resolveAsync(workspaceFolder, CommandString.value(task.command.name!));
}
resolvedVariablesMap.set(TerminalTaskSystem.ProcessVarName, processVarValue);
}
@ -726,7 +735,7 @@ export class TerminalTaskSystem implements ITaskSystem {
let error: TaskError | undefined = undefined;
let promise: Promise<ITaskSummary> | undefined = undefined;
if (task.configurationProperties.isBackground) {
const problemMatchers = this.resolveMatchers(resolver, task.configurationProperties.problemMatchers);
const problemMatchers = await this.resolveMatchers(resolver, task.configurationProperties.problemMatchers);
let watchingProblemMatcher = new WatchingProblemCollector(problemMatchers, this.markerService, this.modelService, this.fileService);
if ((problemMatchers.length > 0) && !watchingProblemMatcher.isWatching()) {
this.appendOutput(nls.localize('TerminalTaskSystem.nonWatchingMatcher', 'Task {0} is a background task but uses a problem matcher without a background pattern', task._label));
@ -871,7 +880,7 @@ export class TerminalTaskSystem implements ITaskSystem {
const mapKey = task.getMapKey();
this.busyTasks[mapKey] = task;
this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Active, task));
let problemMatchers = this.resolveMatchers(resolver, task.configurationProperties.problemMatchers);
let problemMatchers = await this.resolveMatchers(resolver, task.configurationProperties.problemMatchers);
let startStopProblemMatcher = new StartStopProblemCollector(problemMatchers, this.markerService, this.modelService, ProblemHandlingStrategy.Clean, this.fileService);
let skipLine: boolean = (!!task.command.presentation && task.command.presentation.echo);
const onData = terminal.onLineData((line) => {
@ -1006,11 +1015,11 @@ export class TerminalTaskSystem implements ITaskSystem {
let shellOptions: ShellConfiguration | undefined = task.command.options && task.command.options.shell;
if (shellOptions) {
if (shellOptions.executable) {
shellLaunchConfig.executable = this.resolveVariable(variableResolver, shellOptions.executable);
shellLaunchConfig.executable = await this.resolveVariable(variableResolver, shellOptions.executable);
shellSpecified = true;
}
if (shellOptions.args) {
shellLaunchConfig.args = this.resolveVariables(variableResolver, shellOptions.args.slice());
shellLaunchConfig.args = await this.resolveVariables(variableResolver, shellOptions.args.slice());
} else {
shellLaunchConfig.args = [];
}
@ -1082,7 +1091,7 @@ export class TerminalTaskSystem implements ITaskSystem {
} else {
let commandExecutable = (task.command.runtime !== RuntimeType.CustomExecution) ? CommandString.value(command) : undefined;
let executable = !isShellCommand
? this.resolveVariable(variableResolver, this.resolveVariable(variableResolver, '${' + TerminalTaskSystem.ProcessVarName + '}'))
? await this.resolveVariable(variableResolver, await this.resolveVariable(variableResolver, '${' + TerminalTaskSystem.ProcessVarName + '}'))
: commandExecutable;
// When we have a process task there is no need to quote arguments. So we go ahead and take the string value.
@ -1129,7 +1138,7 @@ export class TerminalTaskSystem implements ITaskSystem {
private async createTerminal(task: CustomTask | ContributedTask, resolver: VariableResolver, workspaceFolder: IWorkspaceFolder | undefined): Promise<[ITerminalInstance | undefined, string | undefined, TaskError | undefined]> {
let platform = resolver.taskSystemInfo ? resolver.taskSystemInfo.platform : Platform.platform;
let options = this.resolveOptions(resolver, task.command.options);
let options = await this.resolveOptions(resolver, task.command.options);
let waitOnExit: boolean | string = false;
const presentationOptions = task.command.presentation;
@ -1161,7 +1170,7 @@ export class TerminalTaskSystem implements ITaskSystem {
isFeatureTerminal: true
};
} else {
let resolvedResult: { command: CommandString, args: CommandString[] } = this.resolveCommandAndArgs(resolver, task.command);
let resolvedResult: { command: CommandString, args: CommandString[] } = await this.resolveCommandAndArgs(resolver, task.command);
command = resolvedResult.command;
args = resolvedResult.args;
commandExecutable = CommandString.value(command);
@ -1466,26 +1475,26 @@ export class TerminalTaskSystem implements ITaskSystem {
} while (matches);
}
private resolveCommandAndArgs(resolver: VariableResolver, commandConfig: CommandConfiguration): { command: CommandString, args: CommandString[] } {
private async resolveCommandAndArgs(resolver: VariableResolver, commandConfig: CommandConfiguration): Promise<{ command: CommandString, args: CommandString[] }> {
// First we need to use the command args:
let args: CommandString[] = commandConfig.args ? commandConfig.args.slice() : [];
args = this.resolveVariables(resolver, args);
let command: CommandString = this.resolveVariable(resolver, commandConfig.name);
args = await this.resolveVariables(resolver, args);
let command: CommandString = await this.resolveVariable(resolver, commandConfig.name);
return { command, args };
}
private resolveVariables(resolver: VariableResolver, value: string[]): string[];
private resolveVariables(resolver: VariableResolver, value: CommandString[]): CommandString[];
private resolveVariables(resolver: VariableResolver, value: CommandString[]): CommandString[] {
return value.map(s => this.resolveVariable(resolver, s));
private async resolveVariables(resolver: VariableResolver, value: string[]): Promise<string[]>;
private async resolveVariables(resolver: VariableResolver, value: CommandString[]): Promise<CommandString[]>;
private async resolveVariables(resolver: VariableResolver, value: CommandString[]): Promise<CommandString[]> {
return Promise.all(value.map(s => this.resolveVariable(resolver, s)));
}
private resolveMatchers(resolver: VariableResolver, values: Array<string | ProblemMatcher> | undefined): ProblemMatcher[] {
private async resolveMatchers(resolver: VariableResolver, values: Array<string | ProblemMatcher> | undefined): Promise<ProblemMatcher[]> {
if (values === undefined || values === null || values.length === 0) {
return [];
}
let result: ProblemMatcher[] = [];
values.forEach((value) => {
for (const value of values) {
let matcher: ProblemMatcher;
if (Types.isString(value)) {
if (value[0] === '$') {
@ -1498,7 +1507,7 @@ export class TerminalTaskSystem implements ITaskSystem {
}
if (!matcher) {
this.appendOutput(nls.localize('unknownProblemMatcher', 'Problem matcher {0} can\'t be resolved. The matcher will be ignored'));
return;
continue;
}
let taskSystemInfo: TaskSystemInfo | undefined = resolver.taskSystemInfo;
let hasFilePrefix = matcher.filePrefix !== undefined;
@ -1511,23 +1520,23 @@ export class TerminalTaskSystem implements ITaskSystem {
copy.uriProvider = taskSystemInfo.uriProvider;
}
if (hasFilePrefix) {
copy.filePrefix = this.resolveVariable(resolver, copy.filePrefix);
copy.filePrefix = await this.resolveVariable(resolver, copy.filePrefix);
}
result.push(copy);
}
});
}
return result;
}
private resolveVariable(resolver: VariableResolver, value: string | undefined): string;
private resolveVariable(resolver: VariableResolver, value: CommandString | undefined): CommandString;
private resolveVariable(resolver: VariableResolver, value: CommandString | undefined): CommandString {
private async resolveVariable(resolver: VariableResolver, value: string | undefined): Promise<string>;
private async resolveVariable(resolver: VariableResolver, value: CommandString | undefined): Promise<CommandString>;
private async resolveVariable(resolver: VariableResolver, value: CommandString | undefined): Promise<CommandString> {
// TODO@Dirk Task.getWorkspaceFolder should return a WorkspaceFolder that is defined in workspace.ts
if (Types.isString(value)) {
return resolver.resolve(value);
} else if (value !== undefined) {
return {
value: resolver.resolve(value.value),
value: await resolver.resolve(value.value),
quoting: value.quoting
};
} else { // This should never happen
@ -1535,29 +1544,29 @@ export class TerminalTaskSystem implements ITaskSystem {
}
}
private resolveOptions(resolver: VariableResolver, options: CommandOptions | undefined): CommandOptions {
private async resolveOptions(resolver: VariableResolver, options: CommandOptions | undefined): Promise<CommandOptions> {
if (options === undefined || options === null) {
let cwd: string | undefined;
try {
cwd = this.resolveVariable(resolver, '${workspaceFolder}');
cwd = await this.resolveVariable(resolver, '${workspaceFolder}');
} catch (e) {
// No workspace
}
return { cwd };
}
let result: CommandOptions = Types.isString(options.cwd)
? { cwd: this.resolveVariable(resolver, options.cwd) }
: { cwd: this.resolveVariable(resolver, '${workspaceFolder}') };
? { cwd: await this.resolveVariable(resolver, options.cwd) }
: { cwd: await this.resolveVariable(resolver, '${workspaceFolder}') };
if (options.env) {
result.env = Object.create(null);
Object.keys(options.env).forEach((key) => {
for (const key of Object.keys(options.env)) {
let value: any = options.env![key];
if (Types.isString(value)) {
result.env![key] = this.resolveVariable(resolver, value);
result.env![key] = await this.resolveVariable(resolver, value);
} else {
result.env![key] = value.toString();
}
});
}
}
return result;
}

View file

@ -17,6 +17,8 @@ export class RemotePty extends Disposable implements ITerminalChildProcess {
public readonly _onProcessData = this._register(new Emitter<string | IProcessDataEvent>());
public readonly onProcessData: Event<string | IProcessDataEvent> = this._onProcessData.event;
public readonly _onProcessBinary = this._register(new Emitter<string>());
public readonly onProcessBinary: Event<string> = this._onProcessBinary.event;
private readonly _onProcessExit = this._register(new Emitter<number | undefined>());
public readonly onProcessExit: Event<number | undefined> = this._onProcessExit.event;
public readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>());
@ -118,6 +120,9 @@ export class RemotePty extends Disposable implements ITerminalChildProcess {
handleData(e: string | IProcessDataEvent) {
this._onProcessData.fire(e);
}
processBinary(e: string) {
this._onProcessBinary.fire(e);
}
handleExit(e: number | undefined) {
this._onProcessExit.fire(e);
}

View file

@ -49,6 +49,7 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal
this._remoteTerminalChannel = channel;
channel.onProcessData(e => this._ptys.get(e.id)?.handleData(e.event));
channel.onProcessBinary(e => this._ptys.get(e.id)?.processBinary(e.event));
channel.onProcessExit(e => {
const pty = this._ptys.get(e.id);
if (pty) {
@ -168,8 +169,8 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal
return undefined;
}
public async listProcesses(reduceGraceTime: boolean = false): Promise<IRemoteTerminalAttachTarget[]> {
const terms = this._remoteTerminalChannel ? await this._remoteTerminalChannel.listProcesses(reduceGraceTime) : [];
public async listProcesses(): Promise<IRemoteTerminalAttachTarget[]> {
const terms = this._remoteTerminalChannel ? await this._remoteTerminalChannel.listProcesses() : [];
return terms.map(termDto => {
return <IRemoteTerminalAttachTarget>{
id: termDto.id,
@ -190,8 +191,14 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal
return this._remoteTerminalChannel.setTerminalLayoutInfo(layout);
}
public reduceConnectionGraceTime(): void {
if (!this._remoteTerminalChannel) {
throw new Error('Cannot reduce grace time when there is no remote');
}
this._remoteTerminalChannel.reduceConnectionGraceTime();
}
public async getTerminalLayoutInfo(): Promise<ITerminalsLayoutInfo | undefined> {
await this._remoteTerminalChannel?.listProcesses(true);
if (!this._remoteTerminalChannel) {
throw new Error(`Cannot call getActiveInstanceId when there is no remote`);
}

View file

@ -292,6 +292,11 @@ export interface ITerminalInstance {
*/
onData: Event<string>;
/**
* Attach a listener to the binary data stream coming from xterm and going to pty
*/
onBinary: Event<string>;
/**
* Attach a listener to listen for new lines added to this terminal instance.
*

View file

@ -683,9 +683,13 @@ export function registerTerminalActions() {
const labelService = accessor.get(ILabelService);
const remoteAgentService = accessor.get(IRemoteAgentService);
const notificationService = accessor.get(INotificationService);
const offProcTerminalService = remoteAgentService.getConnection() ? accessor.get(IRemoteTerminalService) : accessor.get(ILocalTerminalService);
const remoteTerms = await offProcTerminalService.listProcesses();
const unattachedTerms = remoteTerms.filter(term => !terminalService.isAttachedToTerminal(term));
let offProcTerminalService = remoteAgentService.getConnection() ? accessor.get(IRemoteTerminalService) : accessor.get(ILocalTerminalService);
const terms = await offProcTerminalService.listProcesses();
offProcTerminalService.reduceConnectionGraceTime();
const unattachedTerms = terms.filter(term => !terminalService.isAttachedToTerminal(term));
const items = unattachedTerms.map(term => {
const cwdLabel = labelService.getUriLabel(URI.file(term.cwd));
return {

View file

@ -184,6 +184,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
public get onTitleChanged(): Event<ITerminalInstance> { return this._onTitleChanged.event; }
private readonly _onData = new Emitter<string>();
public get onData(): Event<string> { return this._onData.event; }
private readonly _onBinary = new Emitter<string>();
public get onBinary(): Event<string> { return this._onBinary.event; }
private readonly _onLineData = new Emitter<string>();
public get onLineData(): Event<string> { return this._onLineData.event; }
private readonly _onRequestExtHostProcess = new Emitter<ITerminalInstance>();
@ -468,6 +470,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._processManager.onProcessData(e => this._onProcessData(e));
this._xterm.onData(data => this._processManager.write(data));
this._xterm.onBinary(data => this._processManager.processBinary(data));
this.processReady.then(async () => {
if (this._linkManager) {
this._linkManager.processCwd = await this._processManager.getInitialCwd();

View file

@ -102,6 +102,10 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
}
}
processBinary(data: string): void {
throw new Error('not implemented');
}
public async start(): Promise<ITerminalLaunchError | undefined> {
if (!this._shellLaunchConfig.isExtensionCustomPtyTerminal) {
throw new Error('Attempt to start an ext host process that is not an extension terminal');

View file

@ -499,6 +499,10 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
}
}
public processBinary(data: string): void {
this._process?.processBinary(data);
}
public getInitialCwd(): Promise<string> {
return Promise.resolve(this._initialCwd ? this._initialCwd : '');
}

View file

@ -189,6 +189,7 @@ export class TerminalService implements ITerminalService {
private async _reconnectToRemoteTerminals(): Promise<void> {
// Reattach to all remote terminals
const layoutInfo = await this._remoteTerminalService.getTerminalLayoutInfo();
this._remoteTerminalService.reduceConnectionGraceTime();
const reconnectCounter = this._recreateTerminalTabs(layoutInfo);
/* __GDPR__
"terminalReconnection" : {
@ -210,6 +211,7 @@ export class TerminalService implements ITerminalService {
}
// Reattach to all local terminals
const layoutInfo = await this._localTerminalService.getTerminalLayoutInfo();
this._localTerminalService.reduceConnectionGraceTime();
if (layoutInfo && layoutInfo.tabs.length > 0) {
this._recreateTerminalTabs(layoutInfo);
}

View file

@ -95,6 +95,9 @@ export class RemoteTerminalChannelClient {
public get onProcessData(): Event<{ id: number, event: IProcessDataEvent | string }> {
return this._channel.listen<{ id: number, event: IProcessDataEvent | string }>('$onProcessDataEvent');
}
public get onProcessBinary(): Event<{ id: number, event: string }> {
return this._channel.listen<{ id: number, event: string }>('$onProcessBinaryEvent');
}
public get onProcessExit(): Event<{ id: number, event: number | undefined }> {
return this._channel.listen<{ id: number, event: number | undefined }>('$onProcessExitEvent');
}
@ -232,11 +235,12 @@ export class RemoteTerminalChannelClient {
public attachToProcess(id: number): Promise<void> {
return this._channel.call('$attachToProcess', [id]);
}
public listProcesses(reduceGraceTime: boolean): Promise<IProcessDetails[]> {
return this._channel.call('$listProcesses', [reduceGraceTime]);
public listProcesses(): Promise<IProcessDetails[]> {
return this._channel.call('$listProcesses');
}
public reduceConnectionGraceTime(): Promise<void> {
return this._channel.call('$reduceConnectionGraceTime');
}
public start(id: number): Promise<ITerminalLaunchError | void> {
return this._channel.call('$start', [id]);
}
@ -261,7 +265,6 @@ export class RemoteTerminalChannelClient {
public orphanQuestionReply(id: number): Promise<void> {
return this._channel.call('$orphanQuestionReply', [id]);
}
public sendCommandResult(reqId: number, isError: boolean, payload: any): Promise<void> {
return this._channel.call<void>('$sendCommandResult', [reqId, isError, payload]);
}

View file

@ -306,6 +306,7 @@ export interface ITerminalProcessManager extends IDisposable {
setDimensions(cols: number, rows: number, sync: false): Promise<void>;
setDimensions(cols: number, rows: number, sync: true): void;
acknowledgeDataEvent(charCount: number): void;
processBinary(data: string): void;
getInitialCwd(): Promise<string>;
getCwd(): Promise<string>;

View file

@ -50,6 +50,12 @@ export class LocalPty extends Disposable implements ITerminalChildProcess {
shutdown(immediate: boolean): void {
this._localPtyService.shutdown(this.id, immediate);
}
processBinary(data: string): void {
if (this._inReplay) {
return;
}
this._localPtyService.processBinary(this.id, data);
}
input(data: string): void {
if (this._inReplay) {
return;

View file

@ -116,8 +116,12 @@ export class LocalTerminalService extends Disposable implements ILocalTerminalSe
return undefined;
}
public async listProcesses(reduceGraceTime: boolean): Promise<IProcessDetails[]> {
return this._localPtyService.listProcesses(reduceGraceTime);
public async listProcesses(): Promise<IProcessDetails[]> {
return this._localPtyService.listProcesses();
}
public reduceConnectionGraceTime(): void {
this._localPtyService.reduceConnectionGraceTime();
}
public async setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise<void> {
@ -136,6 +140,10 @@ export class LocalTerminalService extends Disposable implements ILocalTerminalSe
return result;
}
public processBinary(id: number, data: string): void {
this._localPtyService.processBinary(id, data);
}
private _getWorkspaceId(): string {
return this._workspaceContextService.getWorkspace().id;
}

View file

@ -32,6 +32,11 @@ export interface IWebviewService {
*/
readonly activeWebview: Webview | undefined;
/**
* Fired when the currently focused webview changes.
*/
readonly onDidChangeActiveWebview: Event<Webview | undefined>;
/**
* Create a basic webview dom element.
*/

View file

@ -3,13 +3,15 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/browser/themeing';
import { IWebviewService, Webview, WebviewContentOptions, WebviewElement, WebviewExtensionDescription, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { IFrameWebview } from 'vs/workbench/contrib/webview/browser/webviewElement';
import { DynamicWebviewEditorOverlay } from './dynamicWebviewEditorOverlay';
export class WebviewService implements IWebviewService {
export class WebviewService extends Disposable implements IWebviewService {
declare readonly _serviceBrand: undefined;
protected readonly _webviewThemeDataProvider: WebviewThemeDataProvider;
@ -17,12 +19,24 @@ export class WebviewService implements IWebviewService {
constructor(
@IInstantiationService protected readonly _instantiationService: IInstantiationService,
) {
super();
this._webviewThemeDataProvider = this._instantiationService.createInstance(WebviewThemeDataProvider);
}
private _activeWebview?: Webview;
public get activeWebview() { return this._activeWebview; }
private updateActiveWebview(value: Webview | undefined) {
if (value !== this._activeWebview) {
this._activeWebview = value;
this._onDidChangeActiveWebview.fire(value);
}
}
private readonly _onDidChangeActiveWebview = this._register(new Emitter<Webview | undefined>());
public readonly onDidChangeActiveWebview = this._onDidChangeActiveWebview.event;
createWebviewElement(
id: string,
options: WebviewOptions,
@ -47,12 +61,12 @@ export class WebviewService implements IWebviewService {
protected addWebviewListeners(webview: Webview) {
webview.onDidFocus(() => {
this._activeWebview = webview;
this.updateActiveWebview(webview);
});
const onBlur = () => {
if (this._activeWebview === webview) {
this._activeWebview = undefined;
this.updateActiveWebview(undefined);
}
};

View file

@ -7,11 +7,13 @@ import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { memoize } from 'vs/base/common/decorators';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { Event, Emitter } from 'vs/base/common/event';
import { Iterable } from 'vs/base/common/iterator';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { EditorActivation } from 'vs/platform/editor/common/editor';
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { GroupIdentifier } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { IWebviewService, WebviewContentOptions, WebviewExtensionDescription, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewIconManager, WebviewIcons } from 'vs/workbench/contrib/webviewPanel/browser/webviewIconManager';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@ -69,6 +71,8 @@ export interface IWebviewWorkbenchService {
resolveWebview(
webview: WebviewInput,
): CancelablePromise<void>;
readonly onDidChangeActiveWebviewEditor: Event<WebviewInput | undefined>;
}
export interface WebviewResolver {
@ -171,12 +175,48 @@ export class WebviewEditorService extends Disposable implements IWebviewWorkbenc
super();
this._iconManager = this._register(this._instantiationService.createInstance(WebviewIconManager));
this._register(_editorService.onDidActiveEditorChange(() => {
this.updateActiveWebview();
}));
// The user may have switched focus between two sides of a diff editor
this._register(_webviewService.onDidChangeActiveWebview(() => {
this.updateActiveWebview();
}));
this.updateActiveWebview();
}
get iconManager() {
return this._iconManager;
}
private _activeWebview: WebviewInput | undefined;
private readonly _onDidChangeActiveWebviewEditor = this._register(new Emitter<WebviewInput | undefined>());
public readonly onDidChangeActiveWebviewEditor = this._onDidChangeActiveWebviewEditor.event;
private updateActiveWebview() {
const activeInput = this._editorService.activeEditor;
let newActiveWebview: WebviewInput | undefined;
if (activeInput instanceof WebviewInput) {
newActiveWebview = activeInput;
} else if (activeInput instanceof DiffEditorInput) {
if (activeInput.primary instanceof WebviewInput && activeInput.primary.webview === this._webviewService.activeWebview) {
newActiveWebview = activeInput.primary;
} else if (activeInput.secondary instanceof WebviewInput && activeInput.secondary.webview === this._webviewService.activeWebview) {
newActiveWebview = activeInput.secondary;
}
}
if (newActiveWebview !== this._activeWebview) {
this._activeWebview = newActiveWebview;
this._onDidChangeActiveWebviewEditor.fire(newActiveWebview);
}
}
public createWebview(
id: string,
viewType: string,

View file

@ -279,6 +279,7 @@ class SimpleWebviewService implements IWebviewService {
declare readonly _serviceBrand: undefined;
readonly activeWebview = undefined;
readonly onDidChangeActiveWebview = Event.None;
createWebviewElement(id: string, options: WebviewOptions, contentOptions: WebviewContentOptions, extension: WebviewExtensionDescription | undefined): WebviewElement { throw new Error('Method not implemented.'); }
createWebviewOverlay(id: string, options: WebviewOptions, contentOptions: WebviewContentOptions, extension: WebviewExtensionDescription | undefined): WebviewOverlay { throw new Error('Method not implemented.'); }

View file

@ -6,7 +6,7 @@
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { URI } from 'vs/base/common/uri';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { refineServiceDecorator } from 'vs/platform/instantiation/common/instantiation';
export const FOLDER_CONFIG_FOLDER_NAME = '.vscode';
export const FOLDER_SETTINGS_NAME = 'settings';
@ -45,7 +45,7 @@ export interface IConfigurationCache {
}
export const IWorkbenchConfigurationService = createDecorator<IWorkbenchConfigurationService>('configurationService');
export const IWorkbenchConfigurationService = refineServiceDecorator<IConfigurationService, IWorkbenchConfigurationService>(IConfigurationService);
export interface IWorkbenchConfigurationService extends IConfigurationService {
/**
* A promise that resolves when the remote configuration is loaded in a remote window.

View file

@ -31,6 +31,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
getExecPath: () => string | undefined
},
envVariables: IProcessEnvironment,
envVariablesPromise: Promise<IProcessEnvironment>,
editorService: IEditorService,
private readonly configurationService: IConfigurationService,
private readonly commandService: ICommandService,
@ -101,7 +102,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
}
return undefined;
}
}, labelService, envVariables);
}, labelService, envVariables, envVariablesPromise);
}
public async resolveWithInteractionReplace(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>, target?: ConfigurationTarget): Promise<any> {
@ -367,8 +368,10 @@ export class ConfigurationResolverService extends BaseConfigurationResolverServi
@ICommandService commandService: ICommandService,
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService,
@IQuickInputService quickInputService: IQuickInputService,
@ILabelService labelService: ILabelService
@ILabelService labelService: ILabelService,
) {
super({ getAppRoot: () => undefined, getExecPath: () => undefined }, Object.create(null), editorService, configurationService, commandService, workspaceContextService, quickInputService, labelService);
super({ getAppRoot: () => undefined, getExecPath: () => undefined }, Object.create(null),
Promise.resolve(Object.create(null)), editorService, configurationService,
commandService, workspaceContextService, quickInputService, labelService);
}
}

View file

@ -40,10 +40,10 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
private _envVariables?: IProcessEnvironment;
protected _contributedVariables: Map<string, () => Promise<string | undefined>> = new Map();
constructor(_context: IVariableResolveContext, _labelService?: ILabelService, _envVariables?: IProcessEnvironment) {
constructor(_context: IVariableResolveContext, _labelService?: ILabelService, _envVariables?: IProcessEnvironment, _envVariablesPromise?: Promise<IProcessEnvironment>) {
this._context = _context;
this._labelService = _labelService;
// TODO: delete _envVariables in favor of _envVariablesPromise https://github.com/microsoft/vscode/issues/108804
if (_envVariables) {
if (isWindows) {
// windows env variables are case insensitive
@ -65,6 +65,9 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
return this.recursiveResolve(root ? root.uri : undefined, value);
}
/**
* @deprecated Use the async version of `resolve` instead.
*/
public resolve(root: IWorkspaceFolder | undefined, value: string): string;
public resolve(root: IWorkspaceFolder | undefined, value: string[]): string[];
public resolve(root: IWorkspaceFolder | undefined, value: IStringDictionary<string>): IStringDictionary<string>;
@ -72,6 +75,9 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
return this.recursiveResolve(root ? root.uri : undefined, value);
}
/**
* @deprecated Use the async version of `resolve` instead.
*/
public resolveAnyBase(workspaceFolder: IWorkspaceFolder | undefined, config: any, commandValueMapping?: IStringDictionary<string>, resolvedVariables?: Map<string, string>): any {
const result = objects.deepClone(config) as any;

View file

@ -14,6 +14,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { BaseConfigurationResolverService } from 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
import { env } from 'vs/base/common/process';
import { ILabelService } from 'vs/platform/label/common/label';
import { IShellEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/shellEnvironmentService';
export class ConfigurationResolverService extends BaseConfigurationResolverService {
@ -24,7 +25,8 @@ export class ConfigurationResolverService extends BaseConfigurationResolverServi
@ICommandService commandService: ICommandService,
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService,
@IQuickInputService quickInputService: IQuickInputService,
@ILabelService labelService: ILabelService
@ILabelService labelService: ILabelService,
@IShellEnvironmentService shellEnvironmentService: IShellEnvironmentService
) {
super({
getAppRoot: (): string | undefined => {
@ -33,7 +35,7 @@ export class ConfigurationResolverService extends BaseConfigurationResolverServi
getExecPath: (): string | undefined => {
return environmentService.execPath;
}
}, env, editorService, configurationService, commandService, workspaceContextService, quickInputService, labelService);
}, env, shellEnvironmentService.getShellEnv(), editorService, configurationService, commandService, workspaceContextService, quickInputService, labelService);
}
}

View file

@ -75,7 +75,7 @@ suite('Configuration Resolver Service', () => {
labelService = new MockLabelService();
containingWorkspace = testWorkspace(uri.parse('file:///VSCode/workspaceLocation'));
workspace = containingWorkspace.folders[0];
configurationResolverService = new TestConfigurationResolverService(nullContext, environmentService.userEnv, editorService, new MockInputsConfigurationService(), mockCommandService, new TestContextService(containingWorkspace), quickInputService, labelService);
configurationResolverService = new TestConfigurationResolverService(nullContext, environmentService.userEnv, Promise.resolve(environmentService.userEnv), editorService, new MockInputsConfigurationService(), mockCommandService, new TestContextService(containingWorkspace), quickInputService, labelService);
});
teardown(() => {
@ -214,7 +214,7 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, Promise.resolve(environmentService.userEnv), new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} xyz'), 'abc foo xyz');
});
@ -225,7 +225,7 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, Promise.resolve(environmentService.userEnv), new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
assert.strictEqual(service.resolve(undefined, 'abc ${config:editor.fontFamily} xyz'), 'abc foo xyz');
});
@ -242,7 +242,7 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, Promise.resolve(environmentService.userEnv), new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo bar xyz');
});
@ -259,7 +259,7 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, Promise.resolve(environmentService.userEnv), new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
if (platform.isWindows) {
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${workspaceFolder} ${env:key1} xyz'), 'abc foo \\VSCode\\workspaceLocation Value for key1 xyz');
} else {
@ -280,7 +280,7 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, Promise.resolve(environmentService.userEnv), new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
if (platform.isWindows) {
assert.strictEqual(service.resolve(workspace, '${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} ${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), 'foo bar \\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for key1 - Value for key2');
} else {
@ -314,7 +314,7 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, Promise.resolve(environmentService.userEnv), new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:editor.lineNumbers} ${config:editor.insertSpaces} xyz'), 'abc foo 123 false xyz');
});
@ -324,7 +324,7 @@ suite('Configuration Resolver Service', () => {
editor: {}
});
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, Promise.resolve(environmentService.userEnv), new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
assert.strictEqual(service.resolve(workspace, 'abc ${unknownVariable} xyz'), 'abc ${unknownVariable} xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${env:unknownVariable} xyz'), 'abc xyz');
});
@ -337,7 +337,7 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
let service = new TestConfigurationResolverService(nullContext, environmentService.userEnv, Promise.resolve(environmentService.userEnv), new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService);
assert.throws(() => service.resolve(workspace, 'abc ${env} xyz'));
assert.throws(() => service.resolve(workspace, 'abc ${env:} xyz'));

View file

@ -25,7 +25,7 @@ import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecyc
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IExtensionBisectService } from 'vs/workbench/services/extensionManagement/browser/extensionBisect';
import { IWorkspaceTrustService, WorkspaceTrustState } from 'vs/platform/workspace/common/workspaceTrust';
import { IWorkspaceTrustService, WorkspaceTrustState, WorkspaceTrustStateChangeEvent } from 'vs/platform/workspace/common/workspaceTrust';
import { Promises } from 'vs/base/common/async';
const SOURCE = 'IWorkbenchExtensionEnablementService';
@ -64,18 +64,13 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
this._register(this.globalExtensionEnablementService.onDidChangeEnablement(({ extensions, source }) => this.onDidChangeExtensions(extensions, source)));
this._register(extensionManagementService.onDidInstallExtension(this._onDidInstallExtension, this));
this._register(extensionManagementService.onDidUninstallExtension(this._onDidUninstallExtension, this));
this._register(this.workspaceTrustService.onDidChangeTrustState(this._onDidChangeTrustState, this));
// Trusted extensions notification
// TODO: Confirm that this is the right lifecycle phase
this.lifecycleService.when(LifecyclePhase.Eventually).then(() => {
if (this.extensionsDisabledByTrustRequirement.length > 0) {
this.workspaceTrustService.requireWorkspaceTrust({ modal: false })
.then(trustState => {
if (trustState === WorkspaceTrustState.Trusted) {
this._onEnablementChanged.fire(this.extensionsDisabledByTrustRequirement);
this.extensionsDisabledByTrustRequirement = [];
}
});
this.workspaceTrustService.requestWorkspaceTrust({ modal: false });
}
});
@ -174,7 +169,7 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
const result = await Promises.settled(extensions.map(e => {
if (this._isDisabledByTrustRequirement(e)) {
return this.workspaceTrustService.requireWorkspaceTrust()
return this.workspaceTrustService.requestWorkspaceTrust()
.then(trustState => {
if (trustState === WorkspaceTrustState.Trusted) {
return this._setEnablement(e, newState);
@ -447,7 +442,8 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
private _onDidInstallExtension({ local, error }: DidInstallExtensionEvent): void {
if (local && !error && this._isDisabledByTrustRequirement(local)) {
this.workspaceTrustService.requireWorkspaceTrust();
this.workspaceTrustService.requestWorkspaceTrust({ modal: false });
this._onEnablementChanged.fire([local]);
}
}
@ -457,6 +453,13 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
}
}
private _onDidChangeTrustState({ currentTrustState }: WorkspaceTrustStateChangeEvent): void {
if (currentTrustState === WorkspaceTrustState.Trusted && this.extensionsDisabledByTrustRequirement.length > 0) {
this._onEnablementChanged.fire(this.extensionsDisabledByTrustRequirement);
this.extensionsDisabledByTrustRequirement = [];
}
}
private _reset(extension: IExtensionIdentifier) {
this._removeFromWorkspaceDisabledExtensions(extension);
this._removeFromWorkspaceEnabledExtensions(extension);

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator, refineServiceDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IExtension, IScannedExtension, ExtensionType, ITranslatedScannedExtension, IExtensionManifest } from 'vs/platform/extensions/common/extensions';
import { IExtensionManagementService, IGalleryExtension, IExtensionIdentifier, ILocalExtension, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { URI } from 'vs/base/common/uri';
@ -24,7 +24,7 @@ export interface IExtensionManagementServerService {
getExtensionManagementServer(extension: IExtension): IExtensionManagementServer | null;
}
export const IWorkbenchExtensionManagementService = createDecorator<IWorkbenchExtensionManagementService>('extensionManagementService');
export const IWorkbenchExtensionManagementService = refineServiceDecorator<IExtensionManagementService, IWorkbenchExtensionManagementService>(IExtensionManagementService);
export interface IWorkbenchExtensionManagementService extends IExtensionManagementService {
readonly _serviceBrand: undefined;
installExtensions(extensions: IGalleryExtension[], installOptions?: InstallOptions): Promise<ILocalExtension[]>;

View file

@ -25,7 +25,7 @@ import Severity from 'vs/base/common/severity';
import { canceled } from 'vs/base/common/errors';
import { IUserDataAutoSyncEnablementService, IUserDataSyncResourceEnablementService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
import { Promises } from 'vs/base/common/async';
import { IWorkspaceTrustService, WorkspaceTrustState } from 'vs/platform/workspace/common/workspaceTrust';
import { IWorkspaceTrustService } from 'vs/platform/workspace/common/workspaceTrust';
export class ExtensionManagementService extends Disposable implements IWorkbenchExtensionManagementService {
@ -362,9 +362,21 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
protected async checkForWorkspaceTrust(manifest: IExtensionManifest): Promise<void> {
if (getExtensionWorkspaceTrustRequirement(manifest) === 'onStart') {
const trustState = await this.workspaceTrustService.requireWorkspaceTrust();
return trustState === WorkspaceTrustState.Trusted ? Promise.resolve() : Promise.reject(canceled());
const trustState = await this.workspaceTrustService.requestWorkspaceTrust({
modal: true,
message: localize('extensionInstallWorkspaceTrustMessage', "Enabling this extension requires a trusted workspace."),
buttons: [
{ label: localize('extensionInstallWorkspaceTrustButton', "Trust Workspace & Install"), type: 'ContinueWithTrust' },
{ label: localize('extensionInstallWorkspaceTrustContinueButton', "Install"), type: 'ContinueWithoutTrust' },
{ label: localize('extensionInstallWorkspaceTrustManageButton', "Learn More"), type: 'Manage' }
]
});
if (!trustState) {
Promise.reject(canceled());
}
}
return Promise.resolve();
}
}

Some files were not shown because too many files have changed in this diff Show more