diff --git a/.eslintrc.json b/.eslintrc.json
index e55fa836ac9..70012db4e74 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -951,6 +951,7 @@
"**/test/automation/**",
"@vscode/*",
"@parcel/*",
+ "playwright-core/**",
"*" // node modules
]
},
@@ -1064,7 +1065,7 @@
{
"files": [
"**/vscode.d.ts",
- "**/vscode.proposed.d.ts"
+ "**/vscode.proposed.*.d.ts"
],
"rules": {
"vscode-dts-create-func": "warn",
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bccbb3fef51..81394730d69 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -75,9 +75,20 @@ jobs:
- name: Run Unit Tests (Browser)
run: yarn test-browser --browser chromium
+ - name: Compile Integration Tests
+ run: yarn --cwd test/integration/browser compile
+
- name: Run Integration Tests (Electron)
run: .\scripts\test-integration.bat
+ - name: Run Integration Tests (Browser)
+ timeout-minutes: 10
+ run: .\resources\server\test\test-web-integration.bat --browser firefox
+
+ - name: Run Remote Integration Tests (Electron)
+ timeout-minutes: 10
+ run: .\resources\server\test\test-remote-integration.bat
+
linux:
name: Linux
runs-on: ubuntu-latest
@@ -140,10 +151,22 @@ jobs:
id: browser-unit-tests
run: DISPLAY=:10 yarn test-browser --browser chromium
+ - name: Compile Integration Tests
+ run: yarn --cwd test/integration/browser compile
+
- name: Run Integration Tests (Electron)
id: electron-integration-tests
run: DISPLAY=:10 ./scripts/test-integration.sh
+ - name: Run Integration Tests (Browser)
+ id: browser-integration-tests
+ run: DISPLAY=:10 ./resources/server/test/test-web-integration.sh --browser chromium
+
+ - name: Run Remote Integration Tests (Electron)
+ id: electron-remote-integration-tests
+ timeout-minutes: 7
+ run: DISPLAY=:10 ./resources/server/test/test-remote-integration.sh
+
darwin:
name: macOS
runs-on: macos-latest
@@ -202,9 +225,19 @@ jobs:
- name: Run Unit Tests (Browser)
run: DISPLAY=:10 yarn test-browser --browser chromium
+ - name: Compile Integration Tests
+ run: yarn --cwd test/integration/browser compile
+
- name: Run Integration Tests (Electron)
run: DISPLAY=:10 ./scripts/test-integration.sh
+ - name: Run Integration Tests (Browser)
+ run: DISPLAY=:10 ./resources/server/test/test-web-integration.sh --browser webkit
+
+ - name: Run Remote Integration Tests (Electron)
+ timeout-minutes: 7
+ run: DISPLAY=:10 ./resources/server/test/test-remote-integration.sh
+
hygiene:
name: Hygiene, Layering and Monaco Editor
runs-on: ubuntu-latest
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5d547535187..3d6c01e8335 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,7 +18,7 @@ See the [Feedback Channels](https://github.com/microsoft/vscode/wiki/Feedback-Ch
## Reporting Issues
-Have you identified a reproducible problem in VS Code? Have a feature request? We want to hear about it! Here's how you can make reporting your issue as effective as possible.
+Have you identified a reproducible problem in VS Code? Have a feature request? We want to hear about it! Here's how you can report your issue as effectively as possible.
### Identify Where to Report
@@ -43,7 +43,7 @@ If you cannot find an existing issue that describes your bug or feature, create
File a single issue per problem and feature request. Do not enumerate multiple bugs or feature requests in the same issue.
-Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
+Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar but have different causes.
The more information you can provide, the more likely someone will be successful at reproducing the issue and finding a fix.
diff --git a/README.md b/README.md
index 1883fe4b76b..f6e8f39e2d5 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ This repository ("`Code - OSS`") is where we (Microsoft) develop the [Visual Stu
-[Visual Studio Code](https://code.visualstudio.com) is a distribution of the `Code - OSS` repository with Microsoft specific customizations released under a traditional [Microsoft product license](https://code.visualstudio.com/License/).
+[Visual Studio Code](https://code.visualstudio.com) is a distribution of the `Code - OSS` repository with Microsoft-specific customizations released under a traditional [Microsoft product license](https://code.visualstudio.com/License/).
[Visual Studio Code](https://code.visualstudio.com) combines the simplicity of a code editor with what developers need for their core edit-build-debug cycle. It provides comprehensive code editing, navigation, and understanding support along with lightweight debugging, a rich extensibility model, and lightweight integration with existing tools.
@@ -49,11 +49,11 @@ See our [wiki](https://github.com/microsoft/vscode/wiki/Feedback-Channels) for a
## Related Projects
-Many of the core components and extensions to VS Code live in their own repositories on GitHub. For example, the [node debug adapter](https://github.com/microsoft/vscode-node-debug) and the [mono debug adapter](https://github.com/microsoft/vscode-mono-debug) have their own repositories. For a complete list, please visit the [Related Projects](https://github.com/microsoft/vscode/wiki/Related-Projects) page on our [wiki](https://github.com/microsoft/vscode/wiki).
+Many of the core components and extensions to VS Code live in their own repositories on GitHub. For example, the [node debug adapter](https://github.com/microsoft/vscode-node-debug) and the [mono debug adapter](https://github.com/microsoft/vscode-mono-debug) repositories are separate from each other. For a complete list, please visit the [Related Projects](https://github.com/microsoft/vscode/wiki/Related-Projects) page on our [wiki](https://github.com/microsoft/vscode/wiki).
## Bundled Extensions
-VS Code includes a set of built-in extensions located in the [extensions](extensions) folder, including grammars and snippets for many languages. Extensions that provide rich language support (code completion, Go to Definition) for a language have the suffix `language-features`. For example, the `json` extension provides coloring for `JSON` and the `json-language-features` provides rich language support for `JSON`.
+VS Code includes a set of built-in extensions located in the [extensions](extensions) folder, including grammars and snippets for many languages. Extensions that provide rich language support (code completion, Go to Definition) for a language have the suffix `language-features`. For example, the `json` extension provides coloring for `JSON` and the `json-language-features` extension provides rich language support for `JSON`.
## Development Container
diff --git a/build/.cachesalt b/build/.cachesalt
index 93303e0b977..84414b19100 100644
--- a/build/.cachesalt
+++ b/build/.cachesalt
@@ -1 +1 @@
-2021-08-20T17:19:02.924Z
+2021-11-19T08:23:35Z
diff --git a/build/.moduleignore b/build/.moduleignore
index 5bbca4640b8..233ca72a48a 100644
--- a/build/.moduleignore
+++ b/build/.moduleignore
@@ -51,8 +51,6 @@ spdlog/test/**
spdlog/*.yml
!spdlog/build/Release/*.node
-jschardet/dist/**
-
windows-foreground-love/binding.gyp
windows-foreground-love/build/**
windows-foreground-love/src/**
@@ -132,7 +130,9 @@ node-addon-api/**/*
**/*.ts
!typescript/**/*.d.ts
-jschardet/dist/**
+jschardet/index.js
+jschardet/src/**
+jschardet/dist/jschardet.js
es6-promise/lib/**
diff --git a/build/azure-pipelines/common/createAsset.js b/build/azure-pipelines/common/createAsset.js
index 86e207f63a4..360b1d74363 100644
--- a/build/azure-pipelines/common/createAsset.js
+++ b/build/azure-pipelines/common/createAsset.js
@@ -5,11 +5,11 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
-const url = require("url");
const crypto = require("crypto");
-const azure = require("azure-storage");
+const storage_blob_1 = require("@azure/storage-blob");
const mime = require("mime");
const cosmos_1 = require("@azure/cosmos");
+const identity_1 = require("@azure/identity");
const retry_1 = require("./retry");
if (process.argv.length !== 8) {
console.error('Usage: node createAsset.js PRODUCT OS ARCH TYPE NAME FILE');
@@ -118,20 +118,6 @@ function hashStream(hashName, stream) {
.on('close', () => c(shasum.digest('hex')));
});
}
-async function doesAssetExist(blobService, quality, blobName) {
- const existsResult = await new Promise((c, e) => blobService.doesBlobExist(quality, blobName, (err, r) => err ? e(err) : c(r)));
- return existsResult.exists;
-}
-async function uploadBlob(blobService, quality, blobName, filePath, fileName) {
- const blobOptions = {
- contentSettings: {
- contentType: mime.lookup(filePath),
- contentDisposition: `attachment; filename="${fileName}"`,
- cacheControl: 'max-age=31536000, public'
- }
- };
- await new Promise((c, e) => blobService.createBlockBlobFromLocalFile(quality, blobName, filePath, blobOptions, err => err ? e(err) : c()));
-}
function getEnv(name) {
const result = process.env[name];
if (typeof result === 'undefined') {
@@ -155,28 +141,35 @@ async function main() {
console.log('SHA1:', sha1hash);
console.log('SHA256:', sha256hash);
const blobName = commit + '/' + fileName;
- const storageAccount = process.env['AZURE_STORAGE_ACCOUNT_2'];
- const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2'])
- .withFilter(new azure.ExponentialRetryPolicyFilter(20));
- const blobExists = await doesAssetExist(blobService, quality, blobName);
+ const storagePipelineOptions = { retryOptions: { retryPolicyType: storage_blob_1.StorageRetryPolicyType.EXPONENTIAL, maxTries: 6, tryTimeoutInMs: 10 * 60 * 1000 } };
+ const credential = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
+ const blobServiceClient = new storage_blob_1.BlobServiceClient(`https://vscode.blob.core.windows.net`, credential, storagePipelineOptions);
+ const containerClient = blobServiceClient.getContainerClient(quality);
+ const blobClient = containerClient.getBlockBlobClient(blobName);
+ const blobExists = await blobClient.exists();
if (blobExists) {
console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`);
return;
}
- const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY'], `${storageAccount}.blob.core.chinacloudapi.cn`)
- .withFilter(new azure.ExponentialRetryPolicyFilter(20));
- // mooncake is fussy and far away, this is needed!
- blobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
- mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
+ const mooncakeCredential = new identity_1.ClientSecretCredential(process.env['AZURE_MOONCAKE_TENANT_ID'], process.env['AZURE_MOONCAKE_CLIENT_ID'], process.env['AZURE_MOONCAKE_CLIENT_SECRET']);
+ const mooncakeBlobServiceClient = new storage_blob_1.BlobServiceClient(`https://vscode.blob.core.chinacloudapi.cn`, mooncakeCredential, storagePipelineOptions);
+ const mooncakeContainerClient = mooncakeBlobServiceClient.getContainerClient(quality);
+ const mooncakeBlobClient = mooncakeContainerClient.getBlockBlobClient(blobName);
console.log('Uploading blobs to Azure storage and Mooncake Azure storage...');
+ const blobOptions = {
+ blobHTTPHeaders: {
+ blobContentType: mime.lookup(filePath),
+ blobContentDisposition: `attachment; filename="${fileName}"`,
+ blobCacheControl: 'max-age=31536000, public'
+ }
+ };
await (0, retry_1.retry)(() => Promise.all([
- uploadBlob(blobService, quality, blobName, filePath, fileName),
- uploadBlob(mooncakeBlobService, quality, blobName, filePath, fileName)
+ blobClient.uploadFile(filePath, blobOptions),
+ mooncakeBlobClient.uploadFile(filePath, blobOptions)
]));
console.log('Blobs successfully uploaded.');
- // TODO: Understand if blobName and blobPath are the same and replace blobPath with blobName if so.
const assetUrl = `${process.env['AZURE_CDN_URL']}/${quality}/${blobName}`;
- const blobPath = url.parse(assetUrl).path;
+ const blobPath = new URL(assetUrl).pathname;
const mooncakeUrl = `${process.env['MOONCAKE_CDN_URL']}${blobPath}`;
const asset = {
platform,
@@ -192,7 +185,7 @@ async function main() {
asset.supportsFastUpdate = true;
}
console.log('Asset:', JSON.stringify(asset, null, ' '));
- const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
+ const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials: credential });
const scripts = client.database('builds').container(quality).scripts;
await (0, retry_1.retry)(() => scripts.storedProcedure('createAsset').execute('', [commit, asset, true]));
console.log(` Done ✔️`);
diff --git a/build/azure-pipelines/common/createAsset.ts b/build/azure-pipelines/common/createAsset.ts
index c7e2c07917e..62414d41fcc 100644
--- a/build/azure-pipelines/common/createAsset.ts
+++ b/build/azure-pipelines/common/createAsset.ts
@@ -6,12 +6,12 @@
'use strict';
import * as fs from 'fs';
-import * as url from 'url';
import { Readable } from 'stream';
import * as crypto from 'crypto';
-import * as azure from 'azure-storage';
+import { BlobServiceClient, BlockBlobParallelUploadOptions, StoragePipelineOptions, StorageRetryPolicyType } from '@azure/storage-blob';
import * as mime from 'mime';
import { CosmosClient } from '@azure/cosmos';
+import { ClientSecretCredential } from '@azure/identity';
import { retry } from './retry';
interface Asset {
@@ -137,23 +137,6 @@ function hashStream(hashName: string, stream: Readable): Promise {
});
}
-async function doesAssetExist(blobService: azure.BlobService, quality: string, blobName: string): Promise {
- const existsResult = await new Promise((c, e) => blobService.doesBlobExist(quality, blobName, (err, r) => err ? e(err) : c(r)));
- return existsResult.exists;
-}
-
-async function uploadBlob(blobService: azure.BlobService, quality: string, blobName: string, filePath: string, fileName: string): Promise {
- const blobOptions: azure.BlobService.CreateBlockBlobRequestOptions = {
- contentSettings: {
- contentType: mime.lookup(filePath),
- contentDisposition: `attachment; filename="${fileName}"`,
- cacheControl: 'max-age=31536000, public'
- }
- };
-
- await new Promise((c, e) => blobService.createBlockBlobFromLocalFile(quality, blobName, filePath, blobOptions, err => err ? e(err) : c()));
-}
-
function getEnv(name: string): string {
const result = process.env[name];
@@ -186,37 +169,44 @@ async function main(): Promise {
console.log('SHA256:', sha256hash);
const blobName = commit + '/' + fileName;
- const storageAccount = process.env['AZURE_STORAGE_ACCOUNT_2']!;
- const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']!)
- .withFilter(new azure.ExponentialRetryPolicyFilter(20));
+ const storagePipelineOptions: StoragePipelineOptions = { retryOptions: { retryPolicyType: StorageRetryPolicyType.EXPONENTIAL, maxTries: 6, tryTimeoutInMs: 10 * 60 * 1000 } };
- const blobExists = await doesAssetExist(blobService, quality, blobName);
+ const credential = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
+ const blobServiceClient = new BlobServiceClient(`https://vscode.blob.core.windows.net`, credential, storagePipelineOptions);
+ const containerClient = blobServiceClient.getContainerClient(quality);
+ const blobClient = containerClient.getBlockBlobClient(blobName);
+ const blobExists = await blobClient.exists();
if (blobExists) {
console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`);
return;
}
- const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY']!, `${storageAccount}.blob.core.chinacloudapi.cn`)
- .withFilter(new azure.ExponentialRetryPolicyFilter(20));
-
- // mooncake is fussy and far away, this is needed!
- blobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
- mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
+ const mooncakeCredential = new ClientSecretCredential(process.env['AZURE_MOONCAKE_TENANT_ID']!, process.env['AZURE_MOONCAKE_CLIENT_ID']!, process.env['AZURE_MOONCAKE_CLIENT_SECRET']!);
+ const mooncakeBlobServiceClient = new BlobServiceClient(`https://vscode.blob.core.chinacloudapi.cn`, mooncakeCredential, storagePipelineOptions);
+ const mooncakeContainerClient = mooncakeBlobServiceClient.getContainerClient(quality);
+ const mooncakeBlobClient = mooncakeContainerClient.getBlockBlobClient(blobName);
console.log('Uploading blobs to Azure storage and Mooncake Azure storage...');
+ const blobOptions: BlockBlobParallelUploadOptions = {
+ blobHTTPHeaders: {
+ blobContentType: mime.lookup(filePath),
+ blobContentDisposition: `attachment; filename="${fileName}"`,
+ blobCacheControl: 'max-age=31536000, public'
+ }
+ };
+
await retry(() => Promise.all([
- uploadBlob(blobService, quality, blobName, filePath, fileName),
- uploadBlob(mooncakeBlobService, quality, blobName, filePath, fileName)
+ blobClient.uploadFile(filePath, blobOptions),
+ mooncakeBlobClient.uploadFile(filePath, blobOptions)
]));
console.log('Blobs successfully uploaded.');
- // TODO: Understand if blobName and blobPath are the same and replace blobPath with blobName if so.
const assetUrl = `${process.env['AZURE_CDN_URL']}/${quality}/${blobName}`;
- const blobPath = url.parse(assetUrl).path;
+ const blobPath = new URL(assetUrl).pathname;
const mooncakeUrl = `${process.env['MOONCAKE_CDN_URL']}${blobPath}`;
const asset: Asset = {
@@ -236,7 +226,7 @@ async function main(): Promise {
console.log('Asset:', JSON.stringify(asset, null, ' '));
- const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
+ const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials: credential });
const scripts = client.database('builds').container(quality).scripts;
await retry(() => scripts.storedProcedure('createAsset').execute('', [commit, asset, true]));
diff --git a/build/azure-pipelines/common/createBuild.js b/build/azure-pipelines/common/createBuild.js
index d0e950a50f7..cae7a456142 100644
--- a/build/azure-pipelines/common/createBuild.js
+++ b/build/azure-pipelines/common/createBuild.js
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
+const identity_1 = require("@azure/identity");
const cosmos_1 = require("@azure/cosmos");
const retry_1 = require("./retry");
if (process.argv.length !== 3) {
@@ -38,7 +39,8 @@ async function main() {
assets: [],
updates: {}
};
- const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
+ const aadCredentials = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
+ const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
const scripts = client.database('builds').container(quality).scripts;
await (0, retry_1.retry)(() => scripts.storedProcedure('createBuild').execute('', [Object.assign(Object.assign({}, build), { _partitionKey: '' })]));
}
diff --git a/build/azure-pipelines/common/createBuild.ts b/build/azure-pipelines/common/createBuild.ts
index e314d7c0988..2877cc86303 100644
--- a/build/azure-pipelines/common/createBuild.ts
+++ b/build/azure-pipelines/common/createBuild.ts
@@ -5,6 +5,7 @@
'use strict';
+import { ClientSecretCredential } from '@azure/identity';
import { CosmosClient } from '@azure/cosmos';
import { retry } from './retry';
@@ -47,7 +48,8 @@ async function main(): Promise {
updates: {}
};
- const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
+ const aadCredentials = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
+ const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
const scripts = client.database('builds').container(quality).scripts;
await retry(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]));
}
diff --git a/build/azure-pipelines/common/releaseBuild.js b/build/azure-pipelines/common/releaseBuild.js
index 7aceaa99078..850d4ff2f15 100644
--- a/build/azure-pipelines/common/releaseBuild.js
+++ b/build/azure-pipelines/common/releaseBuild.js
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
+const identity_1 = require("@azure/identity");
const cosmos_1 = require("@azure/cosmos");
const retry_1 = require("./retry");
function getEnv(name) {
@@ -30,7 +31,8 @@ async function getConfig(client, quality) {
async function main() {
const commit = getEnv('BUILD_SOURCEVERSION');
const quality = getEnv('VSCODE_QUALITY');
- const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
+ const aadCredentials = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
+ const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
const config = await getConfig(client, quality);
console.log('Quality config:', config);
if (config.frozen) {
diff --git a/build/azure-pipelines/common/releaseBuild.ts b/build/azure-pipelines/common/releaseBuild.ts
index d42b3f1a078..e798ce490ba 100644
--- a/build/azure-pipelines/common/releaseBuild.ts
+++ b/build/azure-pipelines/common/releaseBuild.ts
@@ -5,6 +5,7 @@
'use strict';
+import { ClientSecretCredential } from '@azure/identity';
import { CosmosClient } from '@azure/cosmos';
import { retry } from './retry';
@@ -46,7 +47,8 @@ async function main(): Promise {
const commit = getEnv('BUILD_SOURCEVERSION');
const quality = getEnv('VSCODE_QUALITY');
- const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, key: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
+ const aadCredentials = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
+ const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
const config = await getConfig(client, quality);
console.log('Quality config:', config);
diff --git a/build/azure-pipelines/darwin/app-entitlements.plist b/build/azure-pipelines/darwin/app-entitlements.plist
index b43b4b283a1..432c66c1dff 100644
--- a/build/azure-pipelines/darwin/app-entitlements.plist
+++ b/build/azure-pipelines/darwin/app-entitlements.plist
@@ -8,6 +8,8 @@
com.apple.security.cs.allow-dyld-environment-variables
+ com.apple.security.cs.disable-library-validation
+
com.apple.security.device.audio-input
com.apple.security.device.camera
diff --git a/build/azure-pipelines/darwin/helper-renderer-entitlements.plist b/build/azure-pipelines/darwin/helper-renderer-entitlements.plist
index be8b7163da7..4efe1ce508f 100644
--- a/build/azure-pipelines/darwin/helper-renderer-entitlements.plist
+++ b/build/azure-pipelines/darwin/helper-renderer-entitlements.plist
@@ -4,11 +4,5 @@
com.apple.security.cs.allow-jit
- com.apple.security.cs.allow-unsigned-executable-memory
-
- com.apple.security.cs.disable-library-validation
-
- com.apple.security.cs.allow-dyld-environment-variables
-
diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml
index ce62104f949..f309fc1dab8 100644
--- a/build/azure-pipelines/darwin/product-build-darwin.yml
+++ b/build/azure-pipelines/darwin/product-build-darwin.yml
@@ -8,7 +8,7 @@ steps:
inputs:
azureSubscription: "vscode-builds-subscription"
KeyVaultName: vscode
- SecretsFilter: 'github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key,ticino-storage-key'
+ SecretsFilter: "github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key"
- task: DownloadPipelineArtifact@2
inputs:
@@ -48,23 +48,23 @@ steps:
git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro")
displayName: Merge distro
- - script: |
- mkdir -p .build
- node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
- displayName: Prepare yarn cache flags
+ # - script: |
+ # mkdir -p .build
+ # node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
+ # displayName: Prepare yarn cache flags
- - task: Cache@2
- inputs:
- key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
- path: .build/node_modules_cache
- cacheHitVar: NODE_MODULES_RESTORED
- displayName: Restore node_modules cache
+ # - task: Cache@2
+ # inputs:
+ # key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
+ # path: .build/node_modules_cache
+ # cacheHitVar: NODE_MODULES_RESTORED
+ # displayName: Restore node_modules cache
- - script: |
- set -e
- tar -xzf .build/node_modules_cache/cache.tgz
- condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Extract node_modules cache
+ # - script: |
+ # set -e
+ # tar -xzf .build/node_modules_cache/cache.tgz
+ # condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Extract node_modules cache
- script: |
set -e
@@ -101,13 +101,13 @@ steps:
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- - script: |
- set -e
- node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
- mkdir -p .build/node_modules_cache
- tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
- condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Create node_modules archive
+ # - script: |
+ # set -e
+ # node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
+ # mkdir -p .build/node_modules_cache
+ # tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
+ # condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Create node_modules archive
# This script brings in the right resources (images, icons, etc) based on the quality (insiders, stable, exploration)
- script: |
@@ -224,7 +224,7 @@ steps:
APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)
APP_NAME="`ls $APP_ROOT | head -n 1`"
yarn smoketest-no-compile --build "$APP_ROOT/$APP_NAME" --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests
- timeoutInMinutes: 5
+ timeoutInMinutes: 10
displayName: Run smoke tests (Electron)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
@@ -234,7 +234,7 @@ steps:
APP_NAME="`ls $APP_ROOT | head -n 1`"
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \
yarn smoketest-no-compile --build "$APP_ROOT/$APP_NAME" --remote --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests-remote
- timeoutInMinutes: 5
+ timeoutInMinutes: 10
displayName: Run smoke tests (Remote)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
@@ -242,7 +242,7 @@ steps:
set -e
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \
yarn smoketest-no-compile --web --headless
- timeoutInMinutes: 5
+ timeoutInMinutes: 10
displayName: Run smoke tests (Browser)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
@@ -301,10 +301,25 @@ steps:
displayName: Publish web server archive
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), ne(variables['VSCODE_PUBLISH'], 'false'))
+ - task: AzureCLI@2
+ inputs:
+ azureSubscription: "vscode-builds-subscription"
+ scriptType: pscore
+ scriptLocation: inlineScript
+ addSpnToEnvironment: true
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey"
+
- script: |
- AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \
+ set -e
+ AZURE_STORAGE_ACCOUNT="ticino" \
+ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
+ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
+ AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
VSCODE_ARCH="$(VSCODE_ARCH)" \
- yarn gulp upload-vscode-configuration
+ node build/azure-pipelines/upload-configuration
displayName: Upload configuration (for Bing settings search)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), ne(variables['VSCODE_PUBLISH'], 'false'))
continueOnError: true
diff --git a/build/azure-pipelines/distro-build.yml b/build/azure-pipelines/distro-build.yml
index 6031405fe37..53b62b47a4e 100644
--- a/build/azure-pipelines/distro-build.yml
+++ b/build/azure-pipelines/distro-build.yml
@@ -18,7 +18,7 @@ steps:
inputs:
azureSubscription: "vscode-builds-subscription"
KeyVaultName: vscode
- SecretsFilter: 'github-distro-mixin-password'
+ SecretsFilter: "github-distro-mixin-password"
- script: |
set -e
diff --git a/build/azure-pipelines/exploration-build.yml b/build/azure-pipelines/exploration-build.yml
index ca78aca17f4..5b6599d8dab 100644
--- a/build/azure-pipelines/exploration-build.yml
+++ b/build/azure-pipelines/exploration-build.yml
@@ -14,7 +14,7 @@ steps:
inputs:
azureSubscription: "vscode-builds-subscription"
KeyVaultName: vscode
- SecretsFilter: 'github-distro-mixin-password'
+ SecretsFilter: "github-distro-mixin-password"
- script: |
set -e
diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml
index 2a74a37f5b0..966111fbac5 100644
--- a/build/azure-pipelines/linux/product-build-alpine.yml
+++ b/build/azure-pipelines/linux/product-build-alpine.yml
@@ -3,16 +3,12 @@ steps:
inputs:
versionSpec: "14.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
-
- task: AzureKeyVault@1
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: "vscode-builds-subscription"
KeyVaultName: vscode
- SecretsFilter: 'github-distro-mixin-password'
+ SecretsFilter: "github-distro-mixin-password"
- task: DownloadPipelineArtifact@2
inputs:
@@ -51,23 +47,23 @@ steps:
git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro")
displayName: Merge distro
- - script: |
- mkdir -p .build
- node build/azure-pipelines/common/computeNodeModulesCacheKey.js "alpine" $ENABLE_TERRAPIN > .build/yarnlockhash
- displayName: Prepare yarn cache flags
+ # - script: |
+ # mkdir -p .build
+ # node build/azure-pipelines/common/computeNodeModulesCacheKey.js "alpine" $ENABLE_TERRAPIN > .build/yarnlockhash
+ # displayName: Prepare yarn cache flags
- - task: Cache@2
- inputs:
- key: 'nodeModules | $(Agent.OS) | .build/yarnlockhash'
- path: .build/node_modules_cache
- cacheHitVar: NODE_MODULES_RESTORED
- displayName: Restore node_modules cache
+ # - task: Cache@2
+ # inputs:
+ # key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
+ # path: .build/node_modules_cache
+ # cacheHitVar: NODE_MODULES_RESTORED
+ # displayName: Restore node_modules cache
- - script: |
- set -e
- tar -xzf .build/node_modules_cache/cache.tgz
- condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Extract node_modules cache
+ # - script: |
+ # set -e
+ # tar -xzf .build/node_modules_cache/cache.tgz
+ # condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Extract node_modules cache
- script: |
set -e
@@ -93,13 +89,13 @@ steps:
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- - script: |
- set -e
- node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
- mkdir -p .build/node_modules_cache
- tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
- condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Create node_modules archive
+ # - script: |
+ # set -e
+ # node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
+ # mkdir -p .build/node_modules_cache
+ # tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
+ # condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Create node_modules archive
- script: |
set -e
@@ -107,7 +103,7 @@ steps:
displayName: Mix in quality
- script: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- displayName: 'Register Docker QEMU'
+ displayName: "Register Docker QEMU"
condition: eq(variables['VSCODE_ARCH'], 'arm64')
- script: |
diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml
index a1bcb6a8a90..641be042f73 100644
--- a/build/azure-pipelines/linux/product-build-linux.yml
+++ b/build/azure-pipelines/linux/product-build-linux.yml
@@ -3,16 +3,12 @@ steps:
inputs:
versionSpec: "14.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
-
- task: AzureKeyVault@1
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: "vscode-builds-subscription"
KeyVaultName: vscode
- SecretsFilter: "github-distro-mixin-password,builds-docdb-key-readwrite,vscode-storage-key,ESRP-PKI,esrp-aad-username,esrp-aad-password"
+ SecretsFilter: "github-distro-mixin-password,ESRP-PKI,esrp-aad-username,esrp-aad-password"
- task: DownloadPipelineArtifact@2
inputs:
@@ -42,23 +38,23 @@ steps:
git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro")
displayName: Merge distro
- - script: |
- mkdir -p .build
- node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
- displayName: Prepare yarn cache flags
+ # - script: |
+ # mkdir -p .build
+ # node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
+ # displayName: Prepare yarn cache flags
- - task: Cache@2
- inputs:
- key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
- path: .build/node_modules_cache
- cacheHitVar: NODE_MODULES_RESTORED
- displayName: Restore node_modules cache
+ # - task: Cache@2
+ # inputs:
+ # key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
+ # path: .build/node_modules_cache
+ # cacheHitVar: NODE_MODULES_RESTORED
+ # displayName: Restore node_modules cache
- - script: |
- set -e
- tar -xzf .build/node_modules_cache/cache.tgz
- condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Extract node_modules cache
+ # - script: |
+ # set -e
+ # tar -xzf .build/node_modules_cache/cache.tgz
+ # condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Extract node_modules cache
- script: |
set -e
@@ -114,13 +110,13 @@ steps:
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- - script: |
- set -e
- node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
- mkdir -p .build/node_modules_cache
- tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
- condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Create node_modules archive
+ # - script: |
+ # set -e
+ # node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
+ # mkdir -p .build/node_modules_cache
+ # tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
+ # condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Create node_modules archive
- script: |
set -e
@@ -212,7 +208,7 @@ steps:
set -e
APP_PATH=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
yarn smoketest-no-compile --build "$APP_PATH" --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader" --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests
- timeoutInMinutes: 5
+ timeoutInMinutes: 10
displayName: Run smoke tests (Electron)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
@@ -221,7 +217,7 @@ steps:
APP_PATH=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \
yarn smoketest-no-compile --build "$APP_PATH" --remote --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader" --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests-remote
- timeoutInMinutes: 5
+ timeoutInMinutes: 10
displayName: Run smoke tests (Remote)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
@@ -229,7 +225,7 @@ steps:
set -e
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \
yarn smoketest-no-compile --web --headless --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader"
- timeoutInMinutes: 5
+ timeoutInMinutes: 10
displayName: Run smoke tests (Browser)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
@@ -293,9 +289,6 @@ steps:
- script: |
set -e
- AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \
- AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \
- VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
VSCODE_ARCH="$(VSCODE_ARCH)" \
./build/azure-pipelines/linux/prepare-publish.sh
displayName: Prepare for Publish
diff --git a/build/azure-pipelines/linux/snap-build-linux.yml b/build/azure-pipelines/linux/snap-build-linux.yml
index a668fec06fb..33a80b74391 100644
--- a/build/azure-pipelines/linux/snap-build-linux.yml
+++ b/build/azure-pipelines/linux/snap-build-linux.yml
@@ -3,10 +3,6 @@ steps:
inputs:
versionSpec: "14.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
-
- task: DownloadPipelineArtifact@0
displayName: "Download Pipeline Artifact"
inputs:
@@ -22,6 +18,13 @@ steps:
# Make sure we get latest packages
sudo apt-get update
sudo apt-get upgrade -y
+ sudo apt-get install -y curl apt-transport-https ca-certificates
+
+ # Yarn
+ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+ sudo apt-get update
+ sudo apt-get install -y yarn
# Define variables
REPO="$(pwd)"
diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml
index a67086500af..c0b619cab09 100644
--- a/build/azure-pipelines/product-build.yml
+++ b/build/azure-pipelines/product-build.yml
@@ -113,10 +113,6 @@ variables:
value: https://az764295.vo.msecnd.net
- name: AZURE_DOCUMENTDB_ENDPOINT
value: https://vscode.documents.azure.com:443/
- - name: AZURE_STORAGE_ACCOUNT
- value: ticino
- - name: AZURE_STORAGE_ACCOUNT_2
- value: vscode
- name: MOONCAKE_CDN_URL
value: https://vscode.cdn.azure.cn
- name: VSCODE_MIXIN_REPO
@@ -152,212 +148,209 @@ stages:
- template: product-compile.yml
- ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_WINDOWS'], true)) }}:
- - stage: Windows
- dependsOn:
- - Compile
- pool:
- vmImage: VS2017-Win2016
- jobs:
+ - stage: Windows
+ dependsOn:
+ - Compile
+ pool:
+ vmImage: VS2017-Win2016
+ jobs:
+ - ${{ if eq(parameters.VSCODE_BUILD_WIN32, true) }}:
+ - job: Windows
+ timeoutInMinutes: 90
+ variables:
+ VSCODE_ARCH: x64
+ steps:
+ - template: win32/product-build-win32.yml
- - ${{ if eq(parameters.VSCODE_BUILD_WIN32, true) }}:
- - job: Windows
- timeoutInMinutes: 90
- variables:
- VSCODE_ARCH: x64
- steps:
- - template: win32/product-build-win32.yml
+ - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_WIN32_32BIT, true)) }}:
+ - job: Windows32
+ timeoutInMinutes: 90
+ variables:
+ VSCODE_ARCH: ia32
+ steps:
+ - template: win32/product-build-win32.yml
- - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_WIN32_32BIT, true)) }}:
- - job: Windows32
- timeoutInMinutes: 90
- variables:
- VSCODE_ARCH: ia32
- steps:
- - template: win32/product-build-win32.yml
-
- - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_WIN32_ARM64, true)) }}:
- - job: WindowsARM64
- timeoutInMinutes: 90
- variables:
- VSCODE_ARCH: arm64
- steps:
- - template: win32/product-build-win32.yml
+ - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_WIN32_ARM64, true)) }}:
+ - job: WindowsARM64
+ timeoutInMinutes: 90
+ variables:
+ VSCODE_ARCH: arm64
+ steps:
+ - template: win32/product-build-win32.yml
- ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_LINUX'], true)) }}:
- - stage: Linux
- dependsOn:
- - Compile
- pool:
- vmImage: "Ubuntu-18.04"
- jobs:
-
- - ${{ if eq(parameters.VSCODE_BUILD_LINUX, true) }}:
- - job: Linux
- container: vscode-x64
- variables:
- VSCODE_ARCH: x64
- NPM_ARCH: x64
- DISPLAY: ":10"
- steps:
- - template: linux/product-build-linux.yml
-
- - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX, true), ne(variables['VSCODE_PUBLISH'], 'false')) }}:
- - job: LinuxSnap
- dependsOn:
- - Linux
- container: snapcraft
- variables:
- VSCODE_ARCH: x64
- steps:
- - template: linux/snap-build-linux.yml
-
- - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true)) }}:
- - job: LinuxArmhf
- container: vscode-armhf
- variables:
- VSCODE_ARCH: armhf
- NPM_ARCH: armv7l
- steps:
- - template: linux/product-build-linux.yml
-
- # TODO@joaomoreno: We don't ship ARM snaps for now
- - ${{ if and(false, eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true)) }}:
- - job: LinuxSnapArmhf
- dependsOn:
- - LinuxArmhf
- container: snapcraft
- variables:
- VSCODE_ARCH: armhf
- steps:
- - template: linux/snap-build-linux.yml
-
- - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARM64, true)) }}:
- - job: LinuxArm64
- container: vscode-arm64
- variables:
- VSCODE_ARCH: arm64
- NPM_ARCH: arm64
- steps:
- - template: linux/product-build-linux.yml
-
- # TODO@joaomoreno: We don't ship ARM snaps for now
- - ${{ if and(false, eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARM64, true)) }}:
- - job: LinuxSnapArm64
- dependsOn:
- - LinuxArm64
- container: snapcraft
- variables:
- VSCODE_ARCH: arm64
- steps:
- - template: linux/snap-build-linux.yml
-
- - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ALPINE, true)) }}:
- - job: LinuxAlpine
- variables:
- VSCODE_ARCH: x64
- steps:
- - template: linux/product-build-alpine.yml
-
- - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ALPINE_ARM64, true)) }}:
- - job: LinuxAlpineArm64
- variables:
- VSCODE_ARCH: arm64
- steps:
- - template: linux/product-build-alpine.yml
-
- - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_WEB, true)) }}:
- - job: LinuxWeb
- variables:
- VSCODE_ARCH: x64
- steps:
- - template: web/product-build-web.yml
-
- - ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_MACOS'], true)) }}:
- - stage: macOS
- dependsOn:
- - Compile
- pool:
- vmImage: macOS-latest
- jobs:
-
- - ${{ if eq(parameters.VSCODE_BUILD_MACOS, true) }}:
- - job: macOS
- timeoutInMinutes: 90
- variables:
- VSCODE_ARCH: x64
- steps:
- - template: darwin/product-build-darwin.yml
- - ${{ if ne(variables['VSCODE_PUBLISH'], 'false') }}:
- - job: macOSSign
- dependsOn:
- - macOS
- timeoutInMinutes: 90
- variables:
- VSCODE_ARCH: x64
- steps:
- - template: darwin/product-build-darwin-sign.yml
-
- - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_MACOS_ARM64, true)) }}:
- - job: macOSARM64
- timeoutInMinutes: 90
- variables:
- VSCODE_ARCH: arm64
- steps:
- - template: darwin/product-build-darwin.yml
- - ${{ if ne(variables['VSCODE_PUBLISH'], 'false') }}:
- - job: macOSARM64Sign
- dependsOn:
- - macOSARM64
- timeoutInMinutes: 90
- variables:
- VSCODE_ARCH: arm64
- steps:
- - template: darwin/product-build-darwin-sign.yml
-
- - ${{ if eq(variables['VSCODE_BUILD_MACOS_UNIVERSAL'], true) }}:
- - job: macOSUniversal
- dependsOn:
- - macOS
- - macOSARM64
- timeoutInMinutes: 90
- variables:
- VSCODE_ARCH: universal
- steps:
- - template: darwin/product-build-darwin.yml
- - ${{ if ne(variables['VSCODE_PUBLISH'], 'false') }}:
- - job: macOSUniversalSign
- dependsOn:
- - macOSUniversal
- timeoutInMinutes: 90
- variables:
- VSCODE_ARCH: universal
- steps:
- - template: darwin/product-build-darwin-sign.yml
-
- - ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), ne(variables['VSCODE_PUBLISH'], 'false')) }}:
- - stage: Publish
- dependsOn:
- - Compile
- pool:
- vmImage: "Ubuntu-18.04"
- variables:
- - name: BUILDS_API_URL
- value: $(System.CollectionUri)$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/
- jobs:
- - job: PublishBuild
- timeoutInMinutes: 180
- displayName: Publish Build
- steps:
- - template: product-publish.yml
-
- - ${{ if or(eq(parameters.VSCODE_RELEASE, true), and(in(parameters.VSCODE_QUALITY, 'insider', 'exploration'), eq(variables['VSCODE_SCHEDULEDBUILD'], true))) }}:
- - stage: Release
+ - stage: Linux
dependsOn:
- - Publish
+ - Compile
pool:
vmImage: "Ubuntu-18.04"
jobs:
- - job: ReleaseBuild
- displayName: Release Build
+ - ${{ if eq(parameters.VSCODE_BUILD_LINUX, true) }}:
+ - job: Linux
+ container: vscode-x64
+ variables:
+ VSCODE_ARCH: x64
+ NPM_ARCH: x64
+ DISPLAY: ":10"
+ steps:
+ - template: linux/product-build-linux.yml
+
+ - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX, true), ne(variables['VSCODE_PUBLISH'], 'false')) }}:
+ - job: LinuxSnap
+ dependsOn:
+ - Linux
+ container: snapcraft
+ variables:
+ VSCODE_ARCH: x64
+ steps:
+ - template: linux/snap-build-linux.yml
+
+ - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true)) }}:
+ - job: LinuxArmhf
+ container: vscode-armhf
+ variables:
+ VSCODE_ARCH: armhf
+ NPM_ARCH: armv7l
+ steps:
+ - template: linux/product-build-linux.yml
+
+ # TODO@joaomoreno: We don't ship ARM snaps for now
+ - ${{ if and(false, eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true)) }}:
+ - job: LinuxSnapArmhf
+ dependsOn:
+ - LinuxArmhf
+ container: snapcraft
+ variables:
+ VSCODE_ARCH: armhf
+ steps:
+ - template: linux/snap-build-linux.yml
+
+ - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARM64, true)) }}:
+ - job: LinuxArm64
+ container: vscode-arm64
+ variables:
+ VSCODE_ARCH: arm64
+ NPM_ARCH: arm64
+ steps:
+ - template: linux/product-build-linux.yml
+
+ # TODO@joaomoreno: We don't ship ARM snaps for now
+ - ${{ if and(false, eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARM64, true)) }}:
+ - job: LinuxSnapArm64
+ dependsOn:
+ - LinuxArm64
+ container: snapcraft
+ variables:
+ VSCODE_ARCH: arm64
+ steps:
+ - template: linux/snap-build-linux.yml
+
+ - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ALPINE, true)) }}:
+ - job: LinuxAlpine
+ variables:
+ VSCODE_ARCH: x64
+ steps:
+ - template: linux/product-build-alpine.yml
+
+ - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ALPINE_ARM64, true)) }}:
+ - job: LinuxAlpineArm64
+ variables:
+ VSCODE_ARCH: arm64
+ steps:
+ - template: linux/product-build-alpine.yml
+
+ - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_WEB, true)) }}:
+ - job: LinuxWeb
+ variables:
+ VSCODE_ARCH: x64
+ steps:
+ - template: web/product-build-web.yml
+
+ - ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_MACOS'], true)) }}:
+ - stage: macOS
+ dependsOn:
+ - Compile
+ pool:
+ vmImage: macOS-latest
+ jobs:
+ - ${{ if eq(parameters.VSCODE_BUILD_MACOS, true) }}:
+ - job: macOS
+ timeoutInMinutes: 90
+ variables:
+ VSCODE_ARCH: x64
+ steps:
+ - template: darwin/product-build-darwin.yml
+ - ${{ if ne(variables['VSCODE_PUBLISH'], 'false') }}:
+ - job: macOSSign
+ dependsOn:
+ - macOS
+ timeoutInMinutes: 90
+ variables:
+ VSCODE_ARCH: x64
+ steps:
+ - template: darwin/product-build-darwin-sign.yml
+
+ - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_MACOS_ARM64, true)) }}:
+ - job: macOSARM64
+ timeoutInMinutes: 90
+ variables:
+ VSCODE_ARCH: arm64
+ steps:
+ - template: darwin/product-build-darwin.yml
+ - ${{ if ne(variables['VSCODE_PUBLISH'], 'false') }}:
+ - job: macOSARM64Sign
+ dependsOn:
+ - macOSARM64
+ timeoutInMinutes: 90
+ variables:
+ VSCODE_ARCH: arm64
+ steps:
+ - template: darwin/product-build-darwin-sign.yml
+
+ - ${{ if eq(variables['VSCODE_BUILD_MACOS_UNIVERSAL'], true) }}:
+ - job: macOSUniversal
+ dependsOn:
+ - macOS
+ - macOSARM64
+ timeoutInMinutes: 90
+ variables:
+ VSCODE_ARCH: universal
+ steps:
+ - template: darwin/product-build-darwin.yml
+ - ${{ if ne(variables['VSCODE_PUBLISH'], 'false') }}:
+ - job: macOSUniversalSign
+ dependsOn:
+ - macOSUniversal
+ timeoutInMinutes: 90
+ variables:
+ VSCODE_ARCH: universal
+ steps:
+ - template: darwin/product-build-darwin-sign.yml
+
+ - ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), ne(variables['VSCODE_PUBLISH'], 'false')) }}:
+ - stage: Publish
+ dependsOn:
+ - Compile
+ pool:
+ vmImage: "Ubuntu-18.04"
+ variables:
+ - name: BUILDS_API_URL
+ value: $(System.CollectionUri)$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/
+ jobs:
+ - job: PublishBuild
+ timeoutInMinutes: 180
+ displayName: Publish Build
steps:
- - template: product-release.yml
+ - template: product-publish.yml
+
+ - ${{ if or(eq(parameters.VSCODE_RELEASE, true), and(in(parameters.VSCODE_QUALITY, 'insider', 'exploration'), eq(variables['VSCODE_SCHEDULEDBUILD'], true))) }}:
+ - stage: Release
+ dependsOn:
+ - Publish
+ pool:
+ vmImage: "Ubuntu-18.04"
+ jobs:
+ - job: ReleaseBuild
+ displayName: Release Build
+ steps:
+ - template: product-release.yml
diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml
index b8c3fd4140c..88af1af2918 100644
--- a/build/azure-pipelines/product-compile.yml
+++ b/build/azure-pipelines/product-compile.yml
@@ -3,16 +3,12 @@ steps:
inputs:
versionSpec: "14.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
-
- task: AzureKeyVault@1
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: "vscode-builds-subscription"
KeyVaultName: vscode
- SecretsFilter: 'github-distro-mixin-password,ticino-storage-key'
+ SecretsFilter: "github-distro-mixin-password"
- script: |
set -e
@@ -31,24 +27,24 @@ steps:
git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro")
displayName: Merge distro
- - script: |
- mkdir -p .build
- node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
- displayName: Prepare yarn cache flags
+ # - script: |
+ # mkdir -p .build
+ # node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
+ # displayName: Prepare yarn cache flags
- # using `genericNodeModules` instead of `nodeModules` here to avoid sharing the cache with builds running inside containers
- - task: Cache@2
- inputs:
- key: "genericNodeModules | $(Agent.OS) | .build/yarnlockhash"
- path: .build/node_modules_cache
- cacheHitVar: NODE_MODULES_RESTORED
- displayName: Restore node_modules cache
+ # # using `genericNodeModules` instead of `nodeModules` here to avoid sharing the cache with builds running inside containers
+ # - task: Cache@2
+ # inputs:
+ # key: "genericNodeModules | $(Agent.OS) | .build/yarnlockhash"
+ # path: .build/node_modules_cache
+ # cacheHitVar: NODE_MODULES_RESTORED
+ # displayName: Restore node_modules cache
- - script: |
- set -e
- tar -xzf .build/node_modules_cache/cache.tgz
- condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Extract node_modules cache
+ # - script: |
+ # set -e
+ # tar -xzf .build/node_modules_cache/cache.tgz
+ # condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Extract node_modules cache
- script: |
set -e
@@ -81,13 +77,13 @@ steps:
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- - script: |
- set -e
- node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
- mkdir -p .build/node_modules_cache
- tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
- condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Create node_modules archive
+ # - script: |
+ # set -e
+ # node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
+ # mkdir -p .build/node_modules_cache
+ # tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
+ # condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Create node_modules archive
# Mixin must run before optimize, because the CSS loader will inline small SVGs
- script: |
@@ -107,9 +103,23 @@ steps:
displayName: Compile test suites
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
+ - task: AzureCLI@2
+ inputs:
+ azureSubscription: "vscode-builds-subscription"
+ scriptType: pscore
+ scriptLocation: inlineScript
+ addSpnToEnvironment: true
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey"
+
- script: |
set -e
- AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \
+ AZURE_STORAGE_ACCOUNT="ticino" \
+ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
+ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
+ AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
node build/azure-pipelines/upload-sourcemaps
displayName: Upload sourcemaps
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'))
diff --git a/build/azure-pipelines/product-publish.yml b/build/azure-pipelines/product-publish.yml
index 6a4406f6a26..c43180ea0a3 100644
--- a/build/azure-pipelines/product-publish.yml
+++ b/build/azure-pipelines/product-publish.yml
@@ -3,16 +3,12 @@ steps:
inputs:
versionSpec: "12.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
-
- task: AzureKeyVault@1
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: "vscode-builds-subscription"
KeyVaultName: vscode
- SecretsFilter: 'builds-docdb-key-readwrite,github-distro-mixin-password,ticino-storage-key,vscode-storage-key,vscode-mooncake-storage-key'
+ SecretsFilter: "github-distro-mixin-password"
- pwsh: |
. build/azure-pipelines/win32/exec.ps1
@@ -21,9 +17,31 @@ steps:
displayName: Install dependencies
- download: current
- patterns: '**/artifacts_processed_*.txt'
+ patterns: "**/artifacts_processed_*.txt"
displayName: Download all artifacts_processed text files
+ - task: AzureCLI@2
+ inputs:
+ azureSubscription: "vscode-builds-subscription"
+ scriptType: pscore
+ scriptLocation: inlineScript
+ addSpnToEnvironment: true
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey"
+
+ - task: AzureCLI@2
+ inputs:
+ azureSubscription: "vscode-builds-mooncake-subscription"
+ scriptType: pscore
+ scriptLocation: inlineScript
+ addSpnToEnvironment: true
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=AZURE_MOONCAKE_TENANT_ID]$env:tenantId"
+ Write-Host "##vso[task.setvariable variable=AZURE_MOONCAKE_CLIENT_ID]$env:servicePrincipalId"
+ Write-Host "##vso[task.setvariable variable=AZURE_MOONCAKE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey"
+
- pwsh: |
. build/azure-pipelines/win32/exec.ps1
@@ -32,7 +50,9 @@ steps:
return
}
- $env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)"
+ $env:AZURE_TENANT_ID = "$(AZURE_TENANT_ID)"
+ $env:AZURE_CLIENT_ID = "$(AZURE_CLIENT_ID)"
+ $env:AZURE_CLIENT_SECRET = "$(AZURE_CLIENT_SECRET)"
$VERSION = node -p "require('./package.json').version"
Write-Host "Creating build with version: $VERSION"
exec { node build/azure-pipelines/common/createBuild.js $VERSION }
@@ -40,10 +60,12 @@ steps:
- pwsh: |
$env:VSCODE_MIXIN_PASSWORD = "$(github-distro-mixin-password)"
- $env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)"
- $env:AZURE_STORAGE_ACCESS_KEY = "$(ticino-storage-key)"
- $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(vscode-storage-key)"
- $env:MOONCAKE_STORAGE_ACCESS_KEY = "$(vscode-mooncake-storage-key)"
+ $env:AZURE_TENANT_ID = "$(AZURE_TENANT_ID)"
+ $env:AZURE_CLIENT_ID = "$(AZURE_CLIENT_ID)"
+ $env:AZURE_CLIENT_SECRET = "$(AZURE_CLIENT_SECRET)"
+ $env:AZURE_MOONCAKE_TENANT_ID = "$(AZURE_MOONCAKE_TENANT_ID)"
+ $env:AZURE_MOONCAKE_CLIENT_ID = "$(AZURE_MOONCAKE_CLIENT_ID)"
+ $env:AZURE_MOONCAKE_CLIENT_SECRET = "$(AZURE_MOONCAKE_CLIENT_SECRET)"
build/azure-pipelines/product-publish.ps1
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
diff --git a/build/azure-pipelines/product-release.yml b/build/azure-pipelines/product-release.yml
index d62723be90e..fa6396b1486 100644
--- a/build/azure-pipelines/product-release.yml
+++ b/build/azure-pipelines/product-release.yml
@@ -3,21 +3,21 @@ steps:
inputs:
versionSpec: "14.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
-
- - task: AzureKeyVault@1
- displayName: "Azure Key Vault: Get Secrets"
+ - task: AzureCLI@2
inputs:
azureSubscription: "vscode-builds-subscription"
- KeyVaultName: vscode
- SecretsFilter: 'builds-docdb-key-readwrite'
+ scriptType: pscore
+ scriptLocation: inlineScript
+ addSpnToEnvironment: true
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey"
- script: |
set -e
-
(cd build ; yarn)
-
- AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \
+ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
+ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
+ AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
node build/azure-pipelines/common/releaseBuild.js
diff --git a/build/azure-pipelines/publish-types/publish-types.yml b/build/azure-pipelines/publish-types/publish-types.yml
index f557e56279e..043bb5141ba 100644
--- a/build/azure-pipelines/publish-types/publish-types.yml
+++ b/build/azure-pipelines/publish-types/publish-types.yml
@@ -14,10 +14,6 @@ steps:
inputs:
versionSpec: "14.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
-
- bash: |
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
CHANNEL="C1C14HJ2F"
diff --git a/build/azure-pipelines/sdl-scan.yml b/build/azure-pipelines/sdl-scan.yml
index edccd0845b0..d1cd72b3d95 100644
--- a/build/azure-pipelines/sdl-scan.yml
+++ b/build/azure-pipelines/sdl-scan.yml
@@ -32,209 +32,201 @@ variables:
value: x64
stages:
-- stage: Windows
- condition: eq(variables.SCAN_WINDOWS, 'true')
- pool:
- vmImage: VS2017-Win2016
- jobs:
- - job: WindowsJob
- timeoutInMinutes: 0
- steps:
- - task: CredScan@3
- continueOnError: true
- inputs:
- scanFolder: '$(Build.SourcesDirectory)'
- outputFormat: 'pre'
- - task: NodeTool@0
- inputs:
- versionSpec: "14.x"
+ - stage: Windows
+ condition: eq(variables.SCAN_WINDOWS, 'true')
+ pool:
+ vmImage: VS2017-Win2016
+ jobs:
+ - job: WindowsJob
+ timeoutInMinutes: 0
+ steps:
+ - task: CredScan@3
+ continueOnError: true
+ inputs:
+ scanFolder: "$(Build.SourcesDirectory)"
+ outputFormat: "pre"
+ - task: NodeTool@0
+ inputs:
+ versionSpec: "14.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
+ - task: AzureKeyVault@1
+ displayName: "Azure Key Vault: Get Secrets"
+ inputs:
+ azureSubscription: "vscode-builds-subscription"
+ KeyVaultName: vscode
+ SecretsFilter: "github-distro-mixin-password"
- - task: AzureKeyVault@1
- displayName: "Azure Key Vault: Get Secrets"
- inputs:
- azureSubscription: "vscode-builds-subscription"
- KeyVaultName: vscode
- SecretsFilter: "github-distro-mixin-password"
+ - powershell: |
+ . build/azure-pipelines/win32/exec.ps1
+ $ErrorActionPreference = "Stop"
+ "machine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
- - powershell: |
- . build/azure-pipelines/win32/exec.ps1
- $ErrorActionPreference = "Stop"
- "machine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
+ exec { git config user.email "vscode@microsoft.com" }
+ exec { git config user.name "VSCode" }
+ displayName: Prepare tooling
- exec { git config user.email "vscode@microsoft.com" }
- exec { git config user.name "VSCode" }
- displayName: Prepare tooling
+ - powershell: |
+ . build/azure-pipelines/win32/exec.ps1
+ $ErrorActionPreference = "Stop"
+ exec { git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") }
+ displayName: Merge distro
- - powershell: |
- . build/azure-pipelines/win32/exec.ps1
- $ErrorActionPreference = "Stop"
- exec { git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") }
- displayName: Merge distro
+ - powershell: |
+ . build/azure-pipelines/win32/exec.ps1
+ $ErrorActionPreference = "Stop"
+ exec { npx https://aka.ms/enablesecurefeed standAlone }
+ timeoutInMinutes: 5
+ condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true'))
+ displayName: Switch to Terrapin packages
- - powershell: |
- . build/azure-pipelines/win32/exec.ps1
- $ErrorActionPreference = "Stop"
- exec { npx https://aka.ms/enablesecurefeed standAlone }
- timeoutInMinutes: 5
- condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true'))
- displayName: Switch to Terrapin packages
+ - task: Semmle@1
+ inputs:
+ sourceCodeDirectory: "$(Build.SourcesDirectory)"
+ language: "cpp"
+ buildCommandsString: "yarn --frozen-lockfile"
+ querySuite: "Required"
+ timeout: "1800"
+ ram: "16384"
+ addProjectDirToScanningExclusionList: true
+ env:
+ npm_config_arch: "$(NPM_ARCH)"
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+ GITHUB_TOKEN: "$(github-distro-mixin-password)"
+ displayName: CodeQL
- - task: Semmle@1
- inputs:
- sourceCodeDirectory: '$(Build.SourcesDirectory)'
- language: 'cpp'
- buildCommandsString: 'yarn --frozen-lockfile'
- querySuite: 'Required'
- timeout: '1800'
- ram: '16384'
- addProjectDirToScanningExclusionList: true
- env:
- npm_config_arch: "$(NPM_ARCH)"
- PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
- GITHUB_TOKEN: "$(github-distro-mixin-password)"
- displayName: CodeQL
+ - powershell: |
+ . build/azure-pipelines/win32/exec.ps1
+ . build/azure-pipelines/win32/retry.ps1
+ $ErrorActionPreference = "Stop"
+ retry { exec { yarn --frozen-lockfile } }
+ env:
+ npm_config_arch: "$(NPM_ARCH)"
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+ GITHUB_TOKEN: "$(github-distro-mixin-password)"
+ CHILD_CONCURRENCY: 1
+ displayName: Install dependencies
- - powershell: |
- . build/azure-pipelines/win32/exec.ps1
- . build/azure-pipelines/win32/retry.ps1
- $ErrorActionPreference = "Stop"
- retry { exec { yarn --frozen-lockfile } }
- env:
- npm_config_arch: "$(NPM_ARCH)"
- PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
- GITHUB_TOKEN: "$(github-distro-mixin-password)"
- CHILD_CONCURRENCY: 1
- displayName: Install dependencies
+ - powershell: |
+ . build/azure-pipelines/win32/exec.ps1
+ $ErrorActionPreference = "Stop"
+ exec { yarn gulp "vscode-symbols-win32-$(VSCODE_ARCH)" }
+ displayName: Download Symbols
- - powershell: |
- . build/azure-pipelines/win32/exec.ps1
- $ErrorActionPreference = "Stop"
- exec { yarn gulp "vscode-symbols-win32-$(VSCODE_ARCH)" }
- displayName: Download Symbols
+ - task: BinSkim@4
+ inputs:
+ InputType: "Basic"
+ Function: "analyze"
+ TargetPattern: "guardianGlob"
+ AnalyzeTargetGlob: '$(agent.builddirectory)\scanbin\**.dll;$(agent.builddirectory)\scanbin\**.exe;$(agent.builddirectory)\scanbin\**.node'
+ AnalyzeLocalSymbolDirectories: '$(agent.builddirectory)\scanbin\VSCode-win32-$(VSCODE_ARCH)\pdb'
- - task: BinSkim@4
- inputs:
- InputType: 'Basic'
- Function: 'analyze'
- TargetPattern: 'guardianGlob'
- AnalyzeTargetGlob: '$(agent.builddirectory)\scanbin\**.dll;$(agent.builddirectory)\scanbin\**.exe;$(agent.builddirectory)\scanbin\**.node'
- AnalyzeLocalSymbolDirectories: '$(agent.builddirectory)\scanbin\VSCode-win32-$(VSCODE_ARCH)\pdb'
+ - task: TSAUpload@2
+ inputs:
+ GdnPublishTsaOnboard: true
+ GdnPublishTsaConfigFile: '$(Build.SourcesDirectory)\build\azure-pipelines\.gdntsa'
- - task: TSAUpload@2
- inputs:
- GdnPublishTsaOnboard: true
- GdnPublishTsaConfigFile: '$(Build.SourcesDirectory)\build\azure-pipelines\.gdntsa'
+ - stage: Linux
+ dependsOn: []
+ condition: eq(variables.SCAN_LINUX, 'true')
+ pool:
+ vmImage: "Ubuntu-18.04"
+ jobs:
+ - job: LinuxJob
+ steps:
+ - task: CredScan@2
+ inputs:
+ toolMajorVersion: "V2"
+ - task: NodeTool@0
+ inputs:
+ versionSpec: "14.x"
-- stage: Linux
- dependsOn: []
- condition: eq(variables.SCAN_LINUX, 'true')
- pool:
- vmImage: "Ubuntu-18.04"
- jobs:
- - job: LinuxJob
- steps:
- - task: CredScan@2
- inputs:
- toolMajorVersion: 'V2'
- - task: NodeTool@0
- inputs:
- versionSpec: "14.x"
+ - task: AzureKeyVault@1
+ displayName: "Azure Key Vault: Get Secrets"
+ inputs:
+ azureSubscription: "vscode-builds-subscription"
+ KeyVaultName: vscode
+ SecretsFilter: "github-distro-mixin-password"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
+ - script: |
+ set -e
+ cat << EOF > ~/.netrc
+ machine github.com
+ login vscode
+ password $(github-distro-mixin-password)
+ EOF
- - task: AzureKeyVault@1
- displayName: "Azure Key Vault: Get Secrets"
- inputs:
- azureSubscription: "vscode-builds-subscription"
- KeyVaultName: vscode
- SecretsFilter: "github-distro-mixin-password"
+ git config user.email "vscode@microsoft.com"
+ git config user.name "VSCode"
+ displayName: Prepare tooling
- - script: |
- set -e
- cat << EOF > ~/.netrc
- machine github.com
- login vscode
- password $(github-distro-mixin-password)
- EOF
+ - script: |
+ set -e
+ git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro")
+ displayName: Merge distro
- git config user.email "vscode@microsoft.com"
- git config user.name "VSCode"
- displayName: Prepare tooling
+ - script: |
+ set -e
+ npx https://aka.ms/enablesecurefeed standAlone
+ timeoutInMinutes: 5
+ condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['ENABLE_TERRAPIN'], 'true'))
+ displayName: Switch to Terrapin packages
- - script: |
- set -e
- git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro")
- displayName: Merge distro
+ - script: |
+ set -e
+ yarn --cwd build
+ yarn --cwd build compile
+ displayName: Compile build tools
- - script: |
- set -e
- npx https://aka.ms/enablesecurefeed standAlone
- timeoutInMinutes: 5
- condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['ENABLE_TERRAPIN'], 'true'))
- displayName: Switch to Terrapin packages
+ - script: |
+ set -e
+ export npm_config_arch=$(NPM_ARCH)
- - script: |
- set -e
- yarn --cwd build
- yarn --cwd build compile
- displayName: Compile build tools
+ if [ -z "$CC" ] || [ -z "$CXX" ]; then
+ # Download clang based on chromium revision used by vscode
+ curl -s https://raw.githubusercontent.com/chromium/chromium/91.0.4472.164/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux
+ # Download libcxx headers and objects from upstream electron releases
+ DEBUG=libcxx-fetcher \
+ VSCODE_LIBCXX_OBJECTS_DIR=$PWD/.build/libcxx-objects \
+ VSCODE_LIBCXX_HEADERS_DIR=$PWD/.build/libcxx_headers \
+ VSCODE_LIBCXXABI_HEADERS_DIR=$PWD/.build/libcxxabi_headers \
+ VSCODE_ARCH="$(NPM_ARCH)" \
+ node build/linux/libcxx-fetcher.js
+ # Set compiler toolchain
+ export CC=$PWD/.build/CR_Clang/bin/clang
+ export CXX=$PWD/.build/CR_Clang/bin/clang++
+ export CXXFLAGS="-nostdinc++ -D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS -isystem$PWD/.build/libcxx_headers/include -isystem$PWD/.build/libcxxabi_headers/include -fPIC -flto=thin -fsplit-lto-unit"
+ export LDFLAGS="-stdlib=libc++ -fuse-ld=lld -flto=thin -fsplit-lto-unit -L$PWD/.build/libcxx-objects -lc++abi"
+ fi
- - script: |
- set -e
- export npm_config_arch=$(NPM_ARCH)
+ if [ "$VSCODE_ARCH" == "x64" ]; then
+ export VSCODE_REMOTE_CC=$(which gcc-4.8)
+ export VSCODE_REMOTE_CXX=$(which g++-4.8)
+ fi
- if [ -z "$CC" ] || [ -z "$CXX" ]; then
- # Download clang based on chromium revision used by vscode
- curl -s https://raw.githubusercontent.com/chromium/chromium/91.0.4472.164/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux
- # Download libcxx headers and objects from upstream electron releases
- DEBUG=libcxx-fetcher \
- VSCODE_LIBCXX_OBJECTS_DIR=$PWD/.build/libcxx-objects \
- VSCODE_LIBCXX_HEADERS_DIR=$PWD/.build/libcxx_headers \
- VSCODE_LIBCXXABI_HEADERS_DIR=$PWD/.build/libcxxabi_headers \
- VSCODE_ARCH="$(NPM_ARCH)" \
- node build/linux/libcxx-fetcher.js
- # Set compiler toolchain
- export CC=$PWD/.build/CR_Clang/bin/clang
- export CXX=$PWD/.build/CR_Clang/bin/clang++
- export CXXFLAGS="-nostdinc++ -D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS -isystem$PWD/.build/libcxx_headers/include -isystem$PWD/.build/libcxxabi_headers/include -fPIC -flto=thin -fsplit-lto-unit"
- export LDFLAGS="-stdlib=libc++ -fuse-ld=lld -flto=thin -fsplit-lto-unit -L$PWD/.build/libcxx-objects -lc++abi"
- fi
+ for i in {1..3}; do # try 3 times, for Terrapin
+ yarn --frozen-lockfile && break
+ if [ $i -eq 3 ]; then
+ echo "Yarn failed too many times" >&2
+ exit 1
+ fi
+ echo "Yarn failed $i, trying again..."
+ done
+ env:
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+ GITHUB_TOKEN: "$(github-distro-mixin-password)"
+ displayName: Install dependencies
- if [ "$VSCODE_ARCH" == "x64" ]; then
- export VSCODE_REMOTE_CC=$(which gcc-4.8)
- export VSCODE_REMOTE_CXX=$(which g++-4.8)
- fi
+ - script: |
+ set -e
+ yarn gulp vscode-symbols-linux-$(VSCODE_ARCH)
+ displayName: Build
- for i in {1..3}; do # try 3 times, for Terrapin
- yarn --frozen-lockfile && break
- if [ $i -eq 3 ]; then
- echo "Yarn failed too many times" >&2
- exit 1
- fi
- echo "Yarn failed $i, trying again..."
- done
- env:
- PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
- GITHUB_TOKEN: "$(github-distro-mixin-password)"
- displayName: Install dependencies
+ - task: BinSkim@3
+ inputs:
+ toolVersion: Latest
+ InputType: CommandLine
+ arguments: analyze $(agent.builddirectory)\scanbin\exe\*.* --recurse --local-symbol-directories $(agent.builddirectory)\scanbin\VSCode-linux-$(VSCODE_ARCH)\pdb
- - script: |
- set -e
- yarn gulp vscode-symbols-linux-$(VSCODE_ARCH)
- displayName: Build
-
- - task: BinSkim@3
- inputs:
- toolVersion: Latest
- InputType: CommandLine
- arguments: analyze $(agent.builddirectory)\scanbin\exe\*.* --recurse --local-symbol-directories $(agent.builddirectory)\scanbin\VSCode-linux-$(VSCODE_ARCH)\pdb
-
- - task: TSAUpload@2
- inputs:
- GdnPublishTsaConfigFile: '$(Build.SourceDirectory)\build\azure-pipelines\.gdntsa'
+ - task: TSAUpload@2
+ inputs:
+ GdnPublishTsaConfigFile: '$(Build.SourceDirectory)\build\azure-pipelines\.gdntsa'
diff --git a/build/azure-pipelines/upload-cdn.js b/build/azure-pipelines/upload-cdn.js
index 16a072905a0..fe3817c9183 100644
--- a/build/azure-pipelines/upload-cdn.js
+++ b/build/azure-pipelines/upload-cdn.js
@@ -10,26 +10,35 @@ const vfs = require("vinyl-fs");
const util = require("../lib/util");
const filter = require("gulp-filter");
const gzip = require("gulp-gzip");
+const identity_1 = require("@azure/identity");
const azure = require('gulp-azure-storage');
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
+const credential = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
function main() {
- return vfs.src('**', { cwd: '../vscode-web', base: '../vscode-web', dot: true })
- .pipe(filter(f => !f.isDirectory()))
- .pipe(gzip({ append: false }))
- .pipe(es.through(function (data) {
- console.log('Uploading CDN file:', data.relative); // debug
- this.emit('data', data);
- }))
- .pipe(azure.upload({
- account: process.env.AZURE_STORAGE_ACCOUNT,
- key: process.env.AZURE_STORAGE_ACCESS_KEY,
- container: process.env.VSCODE_QUALITY,
- prefix: commit + '/',
- contentSettings: {
- contentEncoding: 'gzip',
- cacheControl: 'max-age=31536000, public'
- }
- }));
+ return new Promise((c, e) => {
+ vfs.src('**', { cwd: '../vscode-web', base: '../vscode-web', dot: true })
+ .pipe(filter(f => !f.isDirectory()))
+ .pipe(gzip({ append: false }))
+ .pipe(es.through(function (data) {
+ console.log('Uploading CDN file:', data.relative); // debug
+ this.emit('data', data);
+ }))
+ .pipe(azure.upload({
+ account: process.env.AZURE_STORAGE_ACCOUNT,
+ credential,
+ container: process.env.VSCODE_QUALITY,
+ prefix: commit + '/',
+ contentSettings: {
+ contentEncoding: 'gzip',
+ cacheControl: 'max-age=31536000, public'
+ }
+ }))
+ .on('end', () => c())
+ .on('error', (err) => e(err));
+ });
}
-main();
+main().catch(err => {
+ console.error(err);
+ process.exit(1);
+});
diff --git a/build/azure-pipelines/upload-cdn.ts b/build/azure-pipelines/upload-cdn.ts
index 71589033867..c35582017d7 100644
--- a/build/azure-pipelines/upload-cdn.ts
+++ b/build/azure-pipelines/upload-cdn.ts
@@ -12,29 +12,38 @@ import * as vfs from 'vinyl-fs';
import * as util from '../lib/util';
import * as filter from 'gulp-filter';
import * as gzip from 'gulp-gzip';
+import { ClientSecretCredential } from '@azure/identity';
const azure = require('gulp-azure-storage');
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
+const credential = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
-function main() {
- return vfs.src('**', { cwd: '../vscode-web', base: '../vscode-web', dot: true })
- .pipe(filter(f => !f.isDirectory()))
- .pipe(gzip({ append: false }))
- .pipe(es.through(function (data: Vinyl) {
- console.log('Uploading CDN file:', data.relative); // debug
- this.emit('data', data);
- }))
- .pipe(azure.upload({
- account: process.env.AZURE_STORAGE_ACCOUNT,
- key: process.env.AZURE_STORAGE_ACCESS_KEY,
- container: process.env.VSCODE_QUALITY,
- prefix: commit + '/',
- contentSettings: {
- contentEncoding: 'gzip',
- cacheControl: 'max-age=31536000, public'
- }
- }));
+function main(): Promise {
+ return new Promise((c, e) => {
+ vfs.src('**', { cwd: '../vscode-web', base: '../vscode-web', dot: true })
+ .pipe(filter(f => !f.isDirectory()))
+ .pipe(gzip({ append: false }))
+ .pipe(es.through(function (data: Vinyl) {
+ console.log('Uploading CDN file:', data.relative); // debug
+ this.emit('data', data);
+ }))
+ .pipe(azure.upload({
+ account: process.env.AZURE_STORAGE_ACCOUNT,
+ credential,
+ container: process.env.VSCODE_QUALITY,
+ prefix: commit + '/',
+ contentSettings: {
+ contentEncoding: 'gzip',
+ cacheControl: 'max-age=31536000, public'
+ }
+ }))
+ .on('end', () => c())
+ .on('error', (err: any) => e(err));
+ });
}
-main();
+main().catch(err => {
+ console.error(err);
+ process.exit(1);
+});
diff --git a/build/azure-pipelines/upload-configuration.js b/build/azure-pipelines/upload-configuration.js
new file mode 100644
index 00000000000..689d99fdae0
--- /dev/null
+++ b/build/azure-pipelines/upload-configuration.js
@@ -0,0 +1,112 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+'use strict';
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.getSettingsSearchBuildId = exports.shouldSetupSettingsSearch = void 0;
+const path = require("path");
+const os = require("os");
+const cp = require("child_process");
+const vfs = require("vinyl-fs");
+const util = require("../lib/util");
+const identity_1 = require("@azure/identity");
+const azure = require('gulp-azure-storage');
+const packageJson = require("../../package.json");
+const root = path.dirname(path.dirname(__dirname));
+const commit = util.getVersion(root);
+function generateVSCodeConfigurationTask() {
+ return new Promise((resolve, reject) => {
+ const buildDir = process.env['AGENT_BUILDDIRECTORY'];
+ if (!buildDir) {
+ return reject(new Error('$AGENT_BUILDDIRECTORY not set'));
+ }
+ if (!shouldSetupSettingsSearch()) {
+ console.log(`Only runs on main and release branches, not ${process.env.BUILD_SOURCEBRANCH}`);
+ return resolve(undefined);
+ }
+ if (process.env.VSCODE_QUALITY !== 'insider' && process.env.VSCODE_QUALITY !== 'stable') {
+ console.log(`Only runs on insider and stable qualities, not ${process.env.VSCODE_QUALITY}`);
+ return resolve(undefined);
+ }
+ const result = path.join(os.tmpdir(), 'configuration.json');
+ const userDataDir = path.join(os.tmpdir(), 'tmpuserdata');
+ const extensionsDir = path.join(os.tmpdir(), 'tmpextdir');
+ const arch = process.env['VSCODE_ARCH'];
+ const appRoot = path.join(buildDir, `VSCode-darwin-${arch}`);
+ const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app';
+ const appPath = path.join(appRoot, appName, 'Contents', 'Resources', 'app', 'bin', 'code');
+ const codeProc = cp.exec(`${appPath} --export-default-configuration='${result}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`, (err, stdout, stderr) => {
+ clearTimeout(timer);
+ if (err) {
+ console.log(`err: ${err} ${err.message} ${err.toString()}`);
+ reject(err);
+ }
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+ if (stderr) {
+ console.log(`stderr: ${stderr}`);
+ }
+ resolve(result);
+ });
+ const timer = setTimeout(() => {
+ codeProc.kill();
+ reject(new Error('export-default-configuration process timed out'));
+ }, 12 * 1000);
+ codeProc.on('error', err => {
+ clearTimeout(timer);
+ reject(err);
+ });
+ });
+}
+function shouldSetupSettingsSearch() {
+ const branch = process.env.BUILD_SOURCEBRANCH;
+ return !!(branch && (/\/main$/.test(branch) || branch.indexOf('/release/') >= 0));
+}
+exports.shouldSetupSettingsSearch = shouldSetupSettingsSearch;
+function getSettingsSearchBuildId(packageJson) {
+ try {
+ const branch = process.env.BUILD_SOURCEBRANCH;
+ const branchId = branch.indexOf('/release/') >= 0 ? 0 :
+ /\/main$/.test(branch) ? 1 :
+ 2; // Some unexpected branch
+ const out = cp.execSync(`git rev-list HEAD --count`);
+ const count = parseInt(out.toString());
+ //
+ // 1.25.1, 1,234,567 commits, main = 1250112345671
+ return util.versionStringToNumber(packageJson.version) * 1e8 + count * 10 + branchId;
+ }
+ catch (e) {
+ throw new Error('Could not determine build number: ' + e.toString());
+ }
+}
+exports.getSettingsSearchBuildId = getSettingsSearchBuildId;
+async function main() {
+ const configPath = await generateVSCodeConfigurationTask();
+ if (!configPath) {
+ return;
+ }
+ const settingsSearchBuildId = getSettingsSearchBuildId(packageJson);
+ if (!settingsSearchBuildId) {
+ throw new Error('Failed to compute build number');
+ }
+ const credential = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
+ return new Promise((c, e) => {
+ vfs.src(configPath)
+ .pipe(azure.upload({
+ account: process.env.AZURE_STORAGE_ACCOUNT,
+ credential,
+ container: 'configuration',
+ prefix: `${settingsSearchBuildId}/${commit}/`
+ }))
+ .on('end', () => c())
+ .on('error', (err) => e(err));
+ });
+}
+if (require.main === module) {
+ main().catch(err => {
+ console.error(err);
+ process.exit(1);
+ });
+}
diff --git a/build/azure-pipelines/upload-configuration.ts b/build/azure-pipelines/upload-configuration.ts
new file mode 100644
index 00000000000..3acc337e749
--- /dev/null
+++ b/build/azure-pipelines/upload-configuration.ts
@@ -0,0 +1,132 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+import * as path from 'path';
+import * as os from 'os';
+import * as cp from 'child_process';
+import * as vfs from 'vinyl-fs';
+import * as util from '../lib/util';
+import { ClientSecretCredential } from '@azure/identity';
+const azure = require('gulp-azure-storage');
+import * as packageJson from '../../package.json';
+
+const root = path.dirname(path.dirname(__dirname));
+const commit = util.getVersion(root);
+
+function generateVSCodeConfigurationTask(): Promise {
+ return new Promise((resolve, reject) => {
+ const buildDir = process.env['AGENT_BUILDDIRECTORY'];
+ if (!buildDir) {
+ return reject(new Error('$AGENT_BUILDDIRECTORY not set'));
+ }
+
+ if (!shouldSetupSettingsSearch()) {
+ console.log(`Only runs on main and release branches, not ${process.env.BUILD_SOURCEBRANCH}`);
+ return resolve(undefined);
+ }
+
+ if (process.env.VSCODE_QUALITY !== 'insider' && process.env.VSCODE_QUALITY !== 'stable') {
+ console.log(`Only runs on insider and stable qualities, not ${process.env.VSCODE_QUALITY}`);
+ return resolve(undefined);
+ }
+
+ const result = path.join(os.tmpdir(), 'configuration.json');
+ const userDataDir = path.join(os.tmpdir(), 'tmpuserdata');
+ const extensionsDir = path.join(os.tmpdir(), 'tmpextdir');
+ const arch = process.env['VSCODE_ARCH'];
+ const appRoot = path.join(buildDir, `VSCode-darwin-${arch}`);
+ const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app';
+ const appPath = path.join(appRoot, appName, 'Contents', 'Resources', 'app', 'bin', 'code');
+ const codeProc = cp.exec(
+ `${appPath} --export-default-configuration='${result}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`,
+ (err, stdout, stderr) => {
+ clearTimeout(timer);
+ if (err) {
+ console.log(`err: ${err} ${err.message} ${err.toString()}`);
+ reject(err);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.log(`stderr: ${stderr}`);
+ }
+
+ resolve(result);
+ }
+ );
+ const timer = setTimeout(() => {
+ codeProc.kill();
+ reject(new Error('export-default-configuration process timed out'));
+ }, 12 * 1000);
+
+ codeProc.on('error', err => {
+ clearTimeout(timer);
+ reject(err);
+ });
+ });
+}
+
+export function shouldSetupSettingsSearch(): boolean {
+ const branch = process.env.BUILD_SOURCEBRANCH;
+ return !!(branch && (/\/main$/.test(branch) || branch.indexOf('/release/') >= 0));
+}
+
+export function getSettingsSearchBuildId(packageJson: { version: string }) {
+ try {
+ const branch = process.env.BUILD_SOURCEBRANCH!;
+ const branchId = branch.indexOf('/release/') >= 0 ? 0 :
+ /\/main$/.test(branch) ? 1 :
+ 2; // Some unexpected branch
+
+ const out = cp.execSync(`git rev-list HEAD --count`);
+ const count = parseInt(out.toString());
+
+ //
+ // 1.25.1, 1,234,567 commits, main = 1250112345671
+ return util.versionStringToNumber(packageJson.version) * 1e8 + count * 10 + branchId;
+ } catch (e) {
+ throw new Error('Could not determine build number: ' + e.toString());
+ }
+}
+
+async function main(): Promise {
+ const configPath = await generateVSCodeConfigurationTask();
+
+ if (!configPath) {
+ return;
+ }
+
+ const settingsSearchBuildId = getSettingsSearchBuildId(packageJson);
+
+ if (!settingsSearchBuildId) {
+ throw new Error('Failed to compute build number');
+ }
+
+ const credential = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
+
+ return new Promise((c, e) => {
+ vfs.src(configPath)
+ .pipe(azure.upload({
+ account: process.env.AZURE_STORAGE_ACCOUNT,
+ credential,
+ container: 'configuration',
+ prefix: `${settingsSearchBuildId}/${commit}/`
+ }))
+ .on('end', () => c())
+ .on('error', (err: any) => e(err));
+ });
+}
+
+if (require.main === module) {
+ main().catch(err => {
+ console.error(err);
+ process.exit(1);
+ });
+}
diff --git a/build/azure-pipelines/upload-nlsmetadata.js b/build/azure-pipelines/upload-nlsmetadata.js
index 27c9438187f..a09d569f7f6 100644
--- a/build/azure-pipelines/upload-nlsmetadata.js
+++ b/build/azure-pipelines/upload-nlsmetadata.js
@@ -10,79 +10,88 @@ const vfs = require("vinyl-fs");
const util = require("../lib/util");
const merge = require("gulp-merge-json");
const gzip = require("gulp-gzip");
+const identity_1 = require("@azure/identity");
const azure = require('gulp-azure-storage');
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
+const credential = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
function main() {
- return es.merge(vfs.src('out-vscode-web-min/nls.metadata.json', { base: 'out-vscode-web-min' }), vfs.src('.build/extensions/**/nls.metadata.json', { base: '.build/extensions' }), vfs.src('.build/extensions/**/nls.metadata.header.json', { base: '.build/extensions' }), vfs.src('.build/extensions/**/package.nls.json', { base: '.build/extensions' }))
- .pipe(merge({
- fileName: 'combined.nls.metadata.json',
- jsonSpace: '',
- edit: (parsedJson, file) => {
- let key;
- if (file.base === 'out-vscode-web-min') {
- return { vscode: parsedJson };
- }
- // Handle extensions and follow the same structure as the Core nls file.
- switch (file.basename) {
- case 'package.nls.json':
- // put package.nls.json content in Core NlsMetadata format
- // language packs use the key "package" to specify that
- // translations are for the package.json file
- parsedJson = {
- messages: {
- package: Object.values(parsedJson)
- },
- keys: {
- package: Object.keys(parsedJson)
- },
- bundles: {
- main: ['package']
+ return new Promise((c, e) => {
+ es.merge(vfs.src('out-vscode-web-min/nls.metadata.json', { base: 'out-vscode-web-min' }), vfs.src('.build/extensions/**/nls.metadata.json', { base: '.build/extensions' }), vfs.src('.build/extensions/**/nls.metadata.header.json', { base: '.build/extensions' }), vfs.src('.build/extensions/**/package.nls.json', { base: '.build/extensions' }))
+ .pipe(merge({
+ fileName: 'combined.nls.metadata.json',
+ jsonSpace: '',
+ edit: (parsedJson, file) => {
+ let key;
+ if (file.base === 'out-vscode-web-min') {
+ return { vscode: parsedJson };
+ }
+ // Handle extensions and follow the same structure as the Core nls file.
+ switch (file.basename) {
+ case 'package.nls.json':
+ // put package.nls.json content in Core NlsMetadata format
+ // language packs use the key "package" to specify that
+ // translations are for the package.json file
+ parsedJson = {
+ messages: {
+ package: Object.values(parsedJson)
+ },
+ keys: {
+ package: Object.keys(parsedJson)
+ },
+ bundles: {
+ main: ['package']
+ }
+ };
+ break;
+ case 'nls.metadata.header.json':
+ parsedJson = { header: parsedJson };
+ break;
+ case 'nls.metadata.json':
+ // put nls.metadata.json content in Core NlsMetadata format
+ const modules = Object.keys(parsedJson);
+ const json = {
+ keys: {},
+ messages: {},
+ bundles: {
+ main: []
+ }
+ };
+ for (const module of modules) {
+ json.messages[module] = parsedJson[module].messages;
+ json.keys[module] = parsedJson[module].keys;
+ json.bundles.main.push(module);
}
- };
- break;
- case 'nls.metadata.header.json':
- parsedJson = { header: parsedJson };
- break;
- case 'nls.metadata.json':
- // put nls.metadata.json content in Core NlsMetadata format
- const modules = Object.keys(parsedJson);
- const json = {
- keys: {},
- messages: {},
- bundles: {
- main: []
- }
- };
- for (const module of modules) {
- json.messages[module] = parsedJson[module].messages;
- json.keys[module] = parsedJson[module].keys;
- json.bundles.main.push(module);
- }
- parsedJson = json;
- break;
+ parsedJson = json;
+ break;
+ }
+ key = 'vscode.' + file.relative.split('/')[0];
+ return { [key]: parsedJson };
+ },
+ }))
+ .pipe(gzip({ append: false }))
+ .pipe(vfs.dest('./nlsMetadata'))
+ .pipe(es.through(function (data) {
+ console.log(`Uploading ${data.path}`);
+ // trigger artifact upload
+ console.log(`##vso[artifact.upload containerfolder=nlsmetadata;artifactname=combined.nls.metadata.json]${data.path}`);
+ this.emit('data', data);
+ }))
+ .pipe(azure.upload({
+ account: process.env.AZURE_STORAGE_ACCOUNT,
+ credential,
+ container: 'nlsmetadata',
+ prefix: commit + '/',
+ contentSettings: {
+ contentEncoding: 'gzip',
+ cacheControl: 'max-age=31536000, public'
}
- key = 'vscode.' + file.relative.split('/')[0];
- return { [key]: parsedJson };
- },
- }))
- .pipe(gzip({ append: false }))
- .pipe(vfs.dest('./nlsMetadata'))
- .pipe(es.through(function (data) {
- console.log(`Uploading ${data.path}`);
- // trigger artifact upload
- console.log(`##vso[artifact.upload containerfolder=nlsmetadata;artifactname=combined.nls.metadata.json]${data.path}`);
- this.emit('data', data);
- }))
- .pipe(azure.upload({
- account: process.env.AZURE_STORAGE_ACCOUNT,
- key: process.env.AZURE_STORAGE_ACCESS_KEY,
- container: 'nlsmetadata',
- prefix: commit + '/',
- contentSettings: {
- contentEncoding: 'gzip',
- cacheControl: 'max-age=31536000, public'
- }
- }));
+ }))
+ .on('end', () => c())
+ .on('error', (err) => e(err));
+ });
}
-main();
+main().catch(err => {
+ console.error(err);
+ process.exit(1);
+});
diff --git a/build/azure-pipelines/upload-nlsmetadata.ts b/build/azure-pipelines/upload-nlsmetadata.ts
index 72a6701dddd..b3a19b218e3 100644
--- a/build/azure-pipelines/upload-nlsmetadata.ts
+++ b/build/azure-pipelines/upload-nlsmetadata.ts
@@ -12,10 +12,12 @@ import * as vfs from 'vinyl-fs';
import * as util from '../lib/util';
import * as merge from 'gulp-merge-json';
import * as gzip from 'gulp-gzip';
+import { ClientSecretCredential } from '@azure/identity';
const azure = require('gulp-azure-storage');
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
+const credential = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
interface NlsMetadata {
keys: { [module: string]: string },
@@ -23,85 +25,94 @@ interface NlsMetadata {
bundles: { [bundle: string]: string[] },
}
-function main() {
- return es.merge(
- vfs.src('out-vscode-web-min/nls.metadata.json', { base: 'out-vscode-web-min' }),
- vfs.src('.build/extensions/**/nls.metadata.json', { base: '.build/extensions' }),
- vfs.src('.build/extensions/**/nls.metadata.header.json', { base: '.build/extensions' }),
- vfs.src('.build/extensions/**/package.nls.json', { base: '.build/extensions' }))
- .pipe(merge({
- fileName: 'combined.nls.metadata.json',
- jsonSpace: '',
- edit: (parsedJson, file) => {
- let key;
- if (file.base === 'out-vscode-web-min') {
- return { vscode: parsedJson };
- }
+function main(): Promise {
+ return new Promise((c, e) => {
- // Handle extensions and follow the same structure as the Core nls file.
- switch (file.basename) {
- case 'package.nls.json':
- // put package.nls.json content in Core NlsMetadata format
- // language packs use the key "package" to specify that
- // translations are for the package.json file
- parsedJson = {
- messages: {
- package: Object.values(parsedJson)
- },
- keys: {
- package: Object.keys(parsedJson)
- },
- bundles: {
- main: ['package']
+ es.merge(
+ vfs.src('out-vscode-web-min/nls.metadata.json', { base: 'out-vscode-web-min' }),
+ vfs.src('.build/extensions/**/nls.metadata.json', { base: '.build/extensions' }),
+ vfs.src('.build/extensions/**/nls.metadata.header.json', { base: '.build/extensions' }),
+ vfs.src('.build/extensions/**/package.nls.json', { base: '.build/extensions' }))
+ .pipe(merge({
+ fileName: 'combined.nls.metadata.json',
+ jsonSpace: '',
+ edit: (parsedJson, file) => {
+ let key;
+ if (file.base === 'out-vscode-web-min') {
+ return { vscode: parsedJson };
+ }
+
+ // Handle extensions and follow the same structure as the Core nls file.
+ switch (file.basename) {
+ case 'package.nls.json':
+ // put package.nls.json content in Core NlsMetadata format
+ // language packs use the key "package" to specify that
+ // translations are for the package.json file
+ parsedJson = {
+ messages: {
+ package: Object.values(parsedJson)
+ },
+ keys: {
+ package: Object.keys(parsedJson)
+ },
+ bundles: {
+ main: ['package']
+ }
+ };
+ break;
+
+ case 'nls.metadata.header.json':
+ parsedJson = { header: parsedJson };
+ break;
+
+ case 'nls.metadata.json':
+ // put nls.metadata.json content in Core NlsMetadata format
+ const modules = Object.keys(parsedJson);
+
+ const json: NlsMetadata = {
+ keys: {},
+ messages: {},
+ bundles: {
+ main: []
+ }
+ };
+ for (const module of modules) {
+ json.messages[module] = parsedJson[module].messages;
+ json.keys[module] = parsedJson[module].keys;
+ json.bundles.main.push(module);
}
- };
- break;
-
- case 'nls.metadata.header.json':
- parsedJson = { header: parsedJson };
- break;
-
- case 'nls.metadata.json':
- // put nls.metadata.json content in Core NlsMetadata format
- const modules = Object.keys(parsedJson);
-
- const json: NlsMetadata = {
- keys: {},
- messages: {},
- bundles: {
- main: []
- }
- };
- for (const module of modules) {
- json.messages[module] = parsedJson[module].messages;
- json.keys[module] = parsedJson[module].keys;
- json.bundles.main.push(module);
- }
- parsedJson = json;
- break;
+ parsedJson = json;
+ break;
+ }
+ key = 'vscode.' + file.relative.split('/')[0];
+ return { [key]: parsedJson };
+ },
+ }))
+ .pipe(gzip({ append: false }))
+ .pipe(vfs.dest('./nlsMetadata'))
+ .pipe(es.through(function (data: Vinyl) {
+ console.log(`Uploading ${data.path}`);
+ // trigger artifact upload
+ console.log(`##vso[artifact.upload containerfolder=nlsmetadata;artifactname=combined.nls.metadata.json]${data.path}`);
+ this.emit('data', data);
+ }))
+ .pipe(azure.upload({
+ account: process.env.AZURE_STORAGE_ACCOUNT,
+ credential,
+ container: 'nlsmetadata',
+ prefix: commit + '/',
+ contentSettings: {
+ contentEncoding: 'gzip',
+ cacheControl: 'max-age=31536000, public'
}
- key = 'vscode.' + file.relative.split('/')[0];
- return { [key]: parsedJson };
- },
- }))
- .pipe(gzip({ append: false }))
- .pipe(vfs.dest('./nlsMetadata'))
- .pipe(es.through(function (data: Vinyl) {
- console.log(`Uploading ${data.path}`);
- // trigger artifact upload
- console.log(`##vso[artifact.upload containerfolder=nlsmetadata;artifactname=combined.nls.metadata.json]${data.path}`);
- this.emit('data', data);
- }))
- .pipe(azure.upload({
- account: process.env.AZURE_STORAGE_ACCOUNT,
- key: process.env.AZURE_STORAGE_ACCESS_KEY,
- container: 'nlsmetadata',
- prefix: commit + '/',
- contentSettings: {
- contentEncoding: 'gzip',
- cacheControl: 'max-age=31536000, public'
- }
- }));
+ }))
+ .on('end', () => c())
+ .on('error', (err: any) => e(err));
+ });
}
-main();
+main().catch(err => {
+ console.error(err);
+ process.exit(1);
+});
+
diff --git a/build/azure-pipelines/upload-sourcemaps.js b/build/azure-pipelines/upload-sourcemaps.js
index b2a886f6c7c..4edcd2ccd70 100644
--- a/build/azure-pipelines/upload-sourcemaps.js
+++ b/build/azure-pipelines/upload-sourcemaps.js
@@ -10,9 +10,11 @@ const vfs = require("vinyl-fs");
const util = require("../lib/util");
// @ts-ignore
const deps = require("../lib/dependencies");
+const identity_1 = require("@azure/identity");
const azure = require('gulp-azure-storage');
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
+const credential = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
// optionally allow to pass in explicit base/maps to upload
const [, , base, maps] = process.argv;
function src(base, maps = `${base}/**/*.map`) {
@@ -40,16 +42,23 @@ function main() {
else {
sources.push(src(base, maps));
}
- return es.merge(...sources)
- .pipe(es.through(function (data) {
- console.log('Uploading Sourcemap', data.relative); // debug
- this.emit('data', data);
- }))
- .pipe(azure.upload({
- account: process.env.AZURE_STORAGE_ACCOUNT,
- key: process.env.AZURE_STORAGE_ACCESS_KEY,
- container: 'sourcemaps',
- prefix: commit + '/'
- }));
+ return new Promise((c, e) => {
+ es.merge(...sources)
+ .pipe(es.through(function (data) {
+ console.log('Uploading Sourcemap', data.relative); // debug
+ this.emit('data', data);
+ }))
+ .pipe(azure.upload({
+ account: process.env.AZURE_STORAGE_ACCOUNT,
+ credential,
+ container: 'sourcemaps',
+ prefix: commit + '/'
+ }))
+ .on('end', () => c())
+ .on('error', (err) => e(err));
+ });
}
-main();
+main().catch(err => {
+ console.error(err);
+ process.exit(1);
+});
diff --git a/build/azure-pipelines/upload-sourcemaps.ts b/build/azure-pipelines/upload-sourcemaps.ts
index 769e224e6f7..f065ff2cf38 100644
--- a/build/azure-pipelines/upload-sourcemaps.ts
+++ b/build/azure-pipelines/upload-sourcemaps.ts
@@ -12,10 +12,12 @@ import * as vfs from 'vinyl-fs';
import * as util from '../lib/util';
// @ts-ignore
import * as deps from '../lib/dependencies';
+import { ClientSecretCredential } from '@azure/identity';
const azure = require('gulp-azure-storage');
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
+const credential = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
// optionally allow to pass in explicit base/maps to upload
const [, , base, maps] = process.argv;
@@ -28,8 +30,8 @@ function src(base: string, maps = `${base}/**/*.map`) {
}));
}
-function main() {
- const sources = [];
+function main(): Promise {
+ const sources: any[] = [];
// vscode client maps (default)
if (!base) {
@@ -51,17 +53,25 @@ function main() {
sources.push(src(base, maps));
}
- return es.merge(...sources)
- .pipe(es.through(function (data: Vinyl) {
- console.log('Uploading Sourcemap', data.relative); // debug
- this.emit('data', data);
- }))
- .pipe(azure.upload({
- account: process.env.AZURE_STORAGE_ACCOUNT,
- key: process.env.AZURE_STORAGE_ACCESS_KEY,
- container: 'sourcemaps',
- prefix: commit + '/'
- }));
+ return new Promise((c, e) => {
+ es.merge(...sources)
+ .pipe(es.through(function (data: Vinyl) {
+ console.log('Uploading Sourcemap', data.relative); // debug
+ this.emit('data', data);
+ }))
+ .pipe(azure.upload({
+ account: process.env.AZURE_STORAGE_ACCOUNT,
+ credential,
+ container: 'sourcemaps',
+ prefix: commit + '/'
+ }))
+ .on('end', () => c())
+ .on('error', (err: any) => e(err));
+ });
}
-main();
+main().catch(err => {
+ console.error(err);
+ process.exit(1);
+});
+
diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml
index 4977207b896..2a467124141 100644
--- a/build/azure-pipelines/web/product-build-web.yml
+++ b/build/azure-pipelines/web/product-build-web.yml
@@ -3,16 +3,12 @@ steps:
inputs:
versionSpec: "14.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
-
- task: AzureKeyVault@1
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: "vscode-builds-subscription"
KeyVaultName: vscode
- SecretsFilter: 'github-distro-mixin-password,web-storage-account,web-storage-key,ticino-storage-key'
+ SecretsFilter: "github-distro-mixin-password"
- task: DownloadPipelineArtifact@2
inputs:
@@ -42,23 +38,23 @@ steps:
git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro")
displayName: Merge distro
- - script: |
- mkdir -p .build
- node build/azure-pipelines/common/computeNodeModulesCacheKey.js "web" $ENABLE_TERRAPIN > .build/yarnlockhash
- displayName: Prepare yarn cache flags
+ # - script: |
+ # mkdir -p .build
+ # node build/azure-pipelines/common/computeNodeModulesCacheKey.js "web" $ENABLE_TERRAPIN > .build/yarnlockhash
+ # displayName: Prepare yarn cache flags
- - task: Cache@2
- inputs:
- key: 'nodeModules | $(Agent.OS) | .build/yarnlockhash'
- path: .build/node_modules_cache
- cacheHitVar: NODE_MODULES_RESTORED
- displayName: Restore node_modules cache
+ # - task: Cache@2
+ # inputs:
+ # key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
+ # path: .build/node_modules_cache
+ # cacheHitVar: NODE_MODULES_RESTORED
+ # displayName: Restore node_modules cache
- - script: |
- set -e
- tar -xzf .build/node_modules_cache/cache.tgz
- condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Extract node_modules cache
+ # - script: |
+ # set -e
+ # tar -xzf .build/node_modules_cache/cache.tgz
+ # condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Extract node_modules cache
- script: |
set -e
@@ -84,13 +80,13 @@ steps:
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- - script: |
- set -e
- node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
- mkdir -p .build/node_modules_cache
- tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
- condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Create node_modules archive
+ # - script: |
+ # set -e
+ # node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
+ # mkdir -p .build/node_modules_cache
+ # tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
+ # condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Create node_modules archive
- script: |
set -e
@@ -103,11 +99,24 @@ steps:
yarn gulp vscode-web-min-ci
displayName: Build
+ - task: AzureCLI@2
+ inputs:
+ azureSubscription: "vscode-builds-subscription"
+ scriptType: pscore
+ scriptLocation: inlineScript
+ addSpnToEnvironment: true
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
+ Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey"
+
- script: |
set -e
- AZURE_STORAGE_ACCOUNT="$(web-storage-account)" \
- AZURE_STORAGE_ACCESS_KEY="$(web-storage-key)" \
- node build/azure-pipelines/upload-cdn.js
+ AZURE_STORAGE_ACCOUNT="vscodeweb" \
+ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
+ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
+ AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
+ node build/azure-pipelines/upload-cdn
displayName: Upload to CDN
# upload only the workbench.web.api.js source maps because
@@ -115,13 +124,19 @@ steps:
# general task to upload source maps has already been run
- script: |
set -e
- AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \
+ AZURE_STORAGE_ACCOUNT="ticino" \
+ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
+ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
+ AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.api.js.map
displayName: Upload sourcemaps (Web)
- script: |
set -e
- AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \
+ AZURE_STORAGE_ACCOUNT="ticino" \
+ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
+ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
+ AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
node build/azure-pipelines/upload-nlsmetadata
displayName: Upload NLS Metadata
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'))
diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml
index ccd863c615b..6ff2da9724a 100644
--- a/build/azure-pipelines/win32/product-build-win32.yml
+++ b/build/azure-pipelines/win32/product-build-win32.yml
@@ -3,10 +3,6 @@ steps:
inputs:
versionSpec: "14.x"
- - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
- inputs:
- versionSpec: "1.x"
-
- task: UsePythonVersion@0
inputs:
versionSpec: "2.x"
@@ -17,7 +13,7 @@ steps:
inputs:
azureSubscription: "vscode-builds-subscription"
KeyVaultName: vscode
- SecretsFilter: "github-distro-mixin-password,vscode-storage-key,builds-docdb-key-readwrite,ESRP-PKI,esrp-aad-username,esrp-aad-password"
+ SecretsFilter: "github-distro-mixin-password,ESRP-PKI,esrp-aad-username,esrp-aad-password"
- task: DownloadPipelineArtifact@2
inputs:
@@ -46,25 +42,25 @@ steps:
exec { git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro") }
displayName: Merge distro
- - powershell: |
- "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch
- "$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin
- node build/azure-pipelines/common/computeNodeModulesCacheKey.js > .build/yarnlockhash
- displayName: Prepare yarn cache flags
+ # - powershell: |
+ # "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch
+ # "$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin
+ # node build/azure-pipelines/common/computeNodeModulesCacheKey.js > .build/yarnlockhash
+ # displayName: Prepare yarn cache flags
- - task: Cache@2
- inputs:
- key: "nodeModules | $(Agent.OS) | .build/arch, .build/terrapin, .build/yarnlockhash"
- path: .build/node_modules_cache
- cacheHitVar: NODE_MODULES_RESTORED
- displayName: Restore node_modules cache
+ # - task: Cache@2
+ # inputs:
+ # key: "nodeModules | $(Agent.OS) | .build/arch, .build/terrapin, .build/yarnlockhash"
+ # path: .build/node_modules_cache
+ # cacheHitVar: NODE_MODULES_RESTORED
+ # displayName: Restore node_modules cache
- - powershell: |
- . build/azure-pipelines/win32/exec.ps1
- $ErrorActionPreference = "Stop"
- exec { 7z.exe x .build/node_modules_cache/cache.7z -aos }
- condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Extract node_modules cache
+ # - powershell: |
+ # . build/azure-pipelines/win32/exec.ps1
+ # $ErrorActionPreference = "Stop"
+ # exec { 7z.exe x .build/node_modules_cache/cache.7z -aos }
+ # condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Extract node_modules cache
- powershell: |
. build/azure-pipelines/win32/exec.ps1
@@ -88,14 +84,14 @@ steps:
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- - powershell: |
- . build/azure-pipelines/win32/exec.ps1
- $ErrorActionPreference = "Stop"
- exec { node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt }
- exec { mkdir -Force .build/node_modules_cache }
- exec { 7z.exe a .build/node_modules_cache/cache.7z -mx3 `@.build/node_modules_list.txt }
- condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- displayName: Create node_modules archive
+ # - powershell: |
+ # . build/azure-pipelines/win32/exec.ps1
+ # $ErrorActionPreference = "Stop"
+ # exec { node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt }
+ # exec { mkdir -Force .build/node_modules_cache }
+ # exec { 7z.exe a .build/node_modules_cache/cache.7z -mx3 `@.build/node_modules_list.txt }
+ # condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
+ # displayName: Create node_modules archive
- powershell: |
. build/azure-pipelines/win32/exec.ps1
@@ -208,7 +204,7 @@ steps:
$AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
exec { yarn smoketest-no-compile --build "$AppRoot" --screenshots $(Build.SourcesDirectory)\.build\logs\smoke-tests }
displayName: Run smoke tests (Electron)
- timeoutInMinutes: 5
+ timeoutInMinutes: 10
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
- powershell: |
@@ -218,7 +214,7 @@ steps:
$env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"
exec { yarn smoketest-no-compile --build "$AppRoot" --remote --screenshots $(Build.SourcesDirectory)\.build\logs\smoke-tests-remote }
displayName: Run smoke tests (Remote)
- timeoutInMinutes: 5
+ timeoutInMinutes: 10
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
- powershell: |
@@ -227,7 +223,7 @@ steps:
$env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-web-win32-$(VSCODE_ARCH)"
exec { yarn smoketest-no-compile --web --browser firefox --headless }
displayName: Run smoke tests (Browser)
- timeoutInMinutes: 5
+ timeoutInMinutes: 10
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
- task: PublishPipelineArtifact@0
@@ -310,9 +306,6 @@ steps:
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
- $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(vscode-storage-key)"
- $env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)"
- $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)"
.\build\azure-pipelines\win32\prepare-publish.ps1
displayName: Publish
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'))
diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js
index e292abeda2c..250eb01bcdd 100644
--- a/build/gulpfile.vscode.js
+++ b/build/gulpfile.vscode.js
@@ -32,6 +32,7 @@ const createAsar = require('./lib/asar').createAsar;
const minimist = require('minimist');
const { compileBuildTask } = require('./gulpfile.compile');
const { compileExtensionsBuildTask } = require('./gulpfile.extensions');
+const { getSettingsSearchBuildId, shouldSetupSettingsSearch } = require('./azure-pipelines/upload-configuration');
// Build
const vscodeEntryPoints = _.flatten([
@@ -475,110 +476,3 @@ gulp.task('vscode-translations-import', function () {
.pipe(vfs.dest(`./build/win32/i18n`));
}));
});
-
-// This task is only run for the MacOS build
-const generateVSCodeConfigurationTask = task.define('generate-vscode-configuration', () => {
- return new Promise((resolve, reject) => {
- const buildDir = process.env['AGENT_BUILDDIRECTORY'];
- if (!buildDir) {
- return reject(new Error('$AGENT_BUILDDIRECTORY not set'));
- }
-
- if (process.env.VSCODE_QUALITY !== 'insider' && process.env.VSCODE_QUALITY !== 'stable') {
- return resolve();
- }
-
- const userDataDir = path.join(os.tmpdir(), 'tmpuserdata');
- const extensionsDir = path.join(os.tmpdir(), 'tmpextdir');
- const arch = process.env['VSCODE_ARCH'];
- const appRoot = path.join(buildDir, `VSCode-darwin-${arch}`);
- const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app';
- const appPath = path.join(appRoot, appName, 'Contents', 'Resources', 'app', 'bin', 'code');
- const codeProc = cp.exec(
- `${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`,
- (err, stdout, stderr) => {
- clearTimeout(timer);
- if (err) {
- console.log(`err: ${err} ${err.message} ${err.toString()}`);
- reject(err);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.log(`stderr: ${stderr}`);
- }
-
- resolve();
- }
- );
- const timer = setTimeout(() => {
- codeProc.kill();
- reject(new Error('export-default-configuration process timed out'));
- }, 12 * 1000);
-
- codeProc.on('error', err => {
- clearTimeout(timer);
- reject(err);
- });
- });
-});
-
-const allConfigDetailsPath = path.join(os.tmpdir(), 'configuration.json');
-gulp.task(task.define(
- 'upload-vscode-configuration',
- task.series(
- generateVSCodeConfigurationTask,
- () => {
- const azure = require('gulp-azure-storage');
-
- if (!shouldSetupSettingsSearch()) {
- const branch = process.env.BUILD_SOURCEBRANCH;
- console.log(`Only runs on main and release branches, not ${branch}`);
- return;
- }
-
- if (!fs.existsSync(allConfigDetailsPath)) {
- throw new Error(`configuration file at ${allConfigDetailsPath} does not exist`);
- }
-
- const settingsSearchBuildId = getSettingsSearchBuildId(packageJson);
- if (!settingsSearchBuildId) {
- throw new Error('Failed to compute build number');
- }
-
- return gulp.src(allConfigDetailsPath)
- .pipe(azure.upload({
- account: process.env.AZURE_STORAGE_ACCOUNT,
- key: process.env.AZURE_STORAGE_ACCESS_KEY,
- container: 'configuration',
- prefix: `${settingsSearchBuildId}/${commit}/`
- }));
- }
- )
-));
-
-function shouldSetupSettingsSearch() {
- const branch = process.env.BUILD_SOURCEBRANCH;
- return branch && (/\/main$/.test(branch) || branch.indexOf('/release/') >= 0);
-}
-
-function getSettingsSearchBuildId(packageJson) {
- try {
- const branch = process.env.BUILD_SOURCEBRANCH;
- const branchId = branch.indexOf('/release/') >= 0 ? 0 :
- /\/main$/.test(branch) ? 1 :
- 2; // Some unexpected branch
-
- const out = cp.execSync(`git rev-list HEAD --count`);
- const count = parseInt(out.toString());
-
- //
- // 1.25.1, 1,234,567 commits, main = 1250112345671
- return util.versionStringToNumber(packageJson.version) * 1e8 + count * 10 + branchId;
- } catch (e) {
- throw new Error('Could not determine build number: ' + e.toString());
- }
-}
diff --git a/build/lib/compilation.js b/build/lib/compilation.js
index 5a882c3f88a..b81e714fa41 100644
--- a/build/lib/compilation.js
+++ b/build/lib/compilation.js
@@ -183,7 +183,7 @@ function apiProposalNamesGenerator() {
try {
const t1 = Date.now();
const proposalNames = [];
- for (let file of fs.readdirSync(dtsFolder)) {
+ for (let file of fs.readdirSync(dtsFolder).sort()) {
const match = pattern.exec(file);
if (match) {
proposalNames.push([match[1], `https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/${file}`]);
diff --git a/build/lib/compilation.ts b/build/lib/compilation.ts
index 120c0403755..892acaa4216 100644
--- a/build/lib/compilation.ts
+++ b/build/lib/compilation.ts
@@ -224,7 +224,7 @@ function apiProposalNamesGenerator() {
const t1 = Date.now();
const proposalNames: [name: string, url: string][] = [];
- for (let file of fs.readdirSync(dtsFolder)) {
+ for (let file of fs.readdirSync(dtsFolder).sort()) {
const match = pattern.exec(file);
if (match) {
proposalNames.push([match[1], `https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/${file}`]);
diff --git a/build/package.json b/build/package.json
index 337cac1406a..7b1131e894c 100644
--- a/build/package.json
+++ b/build/package.json
@@ -3,14 +3,15 @@
"version": "1.0.0",
"license": "MIT",
"devDependencies": {
- "@azure/cosmos": "^3.9.3",
- "@azure/storage-blob": "^12.4.0",
+ "@azure/cosmos": "^3.14.1",
+ "@azure/identity": "^2.0.1",
+ "@azure/storage-blob": "^12.8.0",
"@electron/get": "^1.12.4",
"@types/ansi-colors": "^3.2.0",
- "@types/azure": "0.9.19",
"@types/byline": "^4.2.32",
"@types/cssnano": "^4.0.0",
"@types/debounce": "^1.0.0",
+ "@types/debug": "4.1.5",
"@types/eslint": "4.16.1",
"@types/fancy-log": "^1.3.0",
"@types/fs-extra": "^9.0.12",
@@ -43,7 +44,6 @@
"@typescript-eslint/experimental-utils": "~2.13.0",
"@typescript-eslint/parser": "^3.3.0",
"applicationinsights": "1.0.8",
- "azure-storage": "^2.1.0",
"byline": "^5.0.0",
"colors": "^1.4.0",
"commander": "^7.0.0",
@@ -54,7 +54,7 @@
"fs-extra": "^9.1.0",
"got": "11.8.1",
"gulp-merge-json": "^2.1.1",
- "iconv-lite-umd": "0.6.8",
+ "iconv-lite-umd": "0.6.10",
"jsonc-parser": "^2.3.0",
"mime": "^1.4.1",
"mkdirp": "^1.0.4",
@@ -62,7 +62,7 @@
"plist": "^3.0.1",
"source-map": "0.6.1",
"tmp": "^0.2.1",
- "typescript": "^4.6.0-dev.20211108",
+ "typescript": "^4.6.0-dev.20211115",
"vsce": "^1.100.0",
"vscode-universal-bundler": "^0.0.2"
},
diff --git a/build/yarn.lock b/build/yarn.lock
index c2ca84ea946..bf575cab8d4 100644
--- a/build/yarn.lock
+++ b/build/yarn.lock
@@ -14,44 +14,56 @@
resolved "https://registry.yarnpkg.com/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.0.tgz#dcccebb88406e5c76e0e1d52e8cc4c43a68b3ee7"
integrity sha512-kmv8CGrPfN9SwMwrkiBK9VTQYxdFQEGe0BmQk+M8io56P9KNzpAxcWE/1fxJj7uouwN4kXF0BHW8DNlgx+wtCg==
-"@azure/core-auth@^1.1.3":
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.1.4.tgz#af9a334acf3cb9c49e6013e6caf6dc9d43476030"
- integrity sha512-+j1embyH1jqf04AIfJPdLafd5SC1y6z1Jz4i+USR1XkTp6KM8P5u4/AjmWMVoEQdM/M29PJcRDZcCEWjK9S1bw==
+"@azure/core-auth@^1.3.0":
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.3.2.tgz#6a2c248576c26df365f6c7881ca04b7f6d08e3d0"
+ integrity sha512-7CU6DmCHIZp5ZPiZ9r3J17lTKMmYsm/zGvNkjArQwPkrLlZ1TZ+EUYfGgh2X31OLMVAQCTJZW4cXHJi02EbJnA==
dependencies:
"@azure/abort-controller" "^1.0.0"
- tslib "^2.0.0"
+ tslib "^2.2.0"
-"@azure/core-http@^1.2.0":
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-1.2.2.tgz#a6f7717184fd2657d3acabd1d64dfdc0bd531ce3"
- integrity sha512-9eu2OcbR7e44gqBy4U1Uv8NTWgLIMwKXMEGgO2MahsJy5rdTiAhs5fJHQffPq8uX2MFh21iBODwO9R/Xlov88A==
+"@azure/core-client@^1.0.0":
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/@azure/core-client/-/core-client-1.3.2.tgz#c0e999a069e9ea16b4b2c623a24d5443f67c6bfa"
+ integrity sha512-qfkRYKmeEmisluMdGTbBtXeyBLaImjFeVW0gcT5yRAwxJmlnTvSyD+a3PjukAtjIrl/tnb4WSJOBpONSJ91+5Q==
dependencies:
"@azure/abort-controller" "^1.0.0"
- "@azure/core-auth" "^1.1.3"
- "@azure/core-tracing" "1.0.0-preview.9"
+ "@azure/core-asynciterator-polyfill" "^1.0.0"
+ "@azure/core-auth" "^1.3.0"
+ "@azure/core-rest-pipeline" "^1.1.0"
+ "@azure/core-tracing" "1.0.0-preview.13"
+ tslib "^2.2.0"
+
+"@azure/core-http@^2.0.0":
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-2.2.2.tgz#573798f087d808d39aa71fd7c52b8d7b89f440da"
+ integrity sha512-V1DdoO9V/sFimKpdWoNBgsE+QUjQgpXYnxrTdUp5RyhsTJjvEVn/HKmTQXIHuLUUo6IyIWj+B+Dg4VaXse9dIA==
+ dependencies:
+ "@azure/abort-controller" "^1.0.0"
+ "@azure/core-asynciterator-polyfill" "^1.0.0"
+ "@azure/core-auth" "^1.3.0"
+ "@azure/core-tracing" "1.0.0-preview.13"
"@azure/logger" "^1.0.0"
- "@opentelemetry/api" "^0.10.2"
"@types/node-fetch" "^2.5.0"
- "@types/tunnel" "^0.0.1"
- form-data "^3.0.0"
+ "@types/tunnel" "^0.0.3"
+ form-data "^4.0.0"
node-fetch "^2.6.0"
process "^0.11.10"
tough-cookie "^4.0.0"
- tslib "^2.0.0"
+ tslib "^2.2.0"
tunnel "^0.0.6"
uuid "^8.3.0"
xml2js "^0.4.19"
-"@azure/core-lro@^1.0.2":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-1.0.3.tgz#1ddfb4ecdb81ce87b5f5d972ffe2acbbc46e524e"
- integrity sha512-Py2crJ84qx1rXkzIwfKw5Ni4WJuzVU7KAF6i1yP3ce8fbynUeu8eEWS4JGtSQgU7xv02G55iPDROifmSDbxeHA==
+"@azure/core-lro@^2.2.0":
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.2.1.tgz#5527b41037c658d3aefc19d68633e51e53d6e6a3"
+ integrity sha512-HE6PBl+mlKa0eBsLwusHqAqjLc5n9ByxeDo3Hz4kF3B1hqHvRkBr4oMgoT6tX7Hc3q97KfDctDUon7EhvoeHPA==
dependencies:
"@azure/abort-controller" "^1.0.0"
- "@azure/core-http" "^1.2.0"
- events "^3.0.0"
- tslib "^2.0.0"
+ "@azure/core-tracing" "1.0.0-preview.13"
+ "@azure/logger" "^1.0.0"
+ tslib "^2.2.0"
"@azure/core-paging@^1.1.1":
version "1.1.3"
@@ -60,32 +72,76 @@
dependencies:
"@azure/core-asynciterator-polyfill" "^1.0.0"
-"@azure/core-tracing@1.0.0-preview.9":
- version "1.0.0-preview.9"
- resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.0-preview.9.tgz#84f3b85572013f9d9b85e1e5d89787aa180787eb"
- integrity sha512-zczolCLJ5QG42AEPQ+Qg9SRYNUyB+yZ5dzof4YEc+dyWczO9G2sBqbAjLB7IqrsdHN2apkiB2oXeDKCsq48jug==
+"@azure/core-rest-pipeline@^1.1.0", "@azure/core-rest-pipeline@^1.2.0":
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.3.2.tgz#82bfb4e960b4ecf4f1a1cdb1afde4ce9192aef09"
+ integrity sha512-kymICKESeHBpVLgQiAxllgWdSTopkqtmfPac8ITwMCxNEC6hzbSpqApYbjzxbBNkBMgoD4GESo6LLhR/sPh6kA==
+ dependencies:
+ "@azure/abort-controller" "^1.0.0"
+ "@azure/core-auth" "^1.3.0"
+ "@azure/core-tracing" "1.0.0-preview.13"
+ "@azure/logger" "^1.0.0"
+ form-data "^4.0.0"
+ http-proxy-agent "^4.0.1"
+ https-proxy-agent "^5.0.0"
+ tslib "^2.2.0"
+ uuid "^8.3.0"
+
+"@azure/core-tracing@1.0.0-preview.13":
+ version "1.0.0-preview.13"
+ resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz#55883d40ae2042f6f1e12b17dd0c0d34c536d644"
+ integrity sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==
+ dependencies:
+ "@opentelemetry/api" "^1.0.1"
+ tslib "^2.2.0"
+
+"@azure/core-util@^1.0.0-beta.1":
+ version "1.0.0-beta.1"
+ resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.0.0-beta.1.tgz#2efd2c74b4b0a38180369f50fe274a3c4cd36e98"
+ integrity sha512-pS6cup979/qyuyNP9chIybK2qVkJ3MarbY/bx3JcGKE6An6dRweLnsfJfU2ydqUI/B51Rjnn59ajHIhCUTwWZw==
dependencies:
- "@opencensus/web-types" "0.0.7"
- "@opentelemetry/api" "^0.10.2"
tslib "^2.0.0"
-"@azure/cosmos@^3.9.3":
- version "3.9.3"
- resolved "https://registry.yarnpkg.com/@azure/cosmos/-/cosmos-3.9.3.tgz#7e95ff92e5c3e9da7e8316bc50c9cc928be6c1d6"
- integrity sha512-1mh8a6LAIykz24tJvQpafXiABUfq+HSAZBFJVZXea0Rd0qG8Ia9z8AK9FtPbC1nPvDC2RID2mRIjJvYbxRM/BA==
+"@azure/cosmos@^3.14.1":
+ version "3.14.1"
+ resolved "https://registry.yarnpkg.com/@azure/cosmos/-/cosmos-3.14.1.tgz#974087eca9a76f9826d14898414219f19474f314"
+ integrity sha512-i8HJOlmVfr1P5qMNgKbEpszddtT8Ooskj2pJm0ZD7jeMuwN2tYlQ68eLyCmynv1j5PQimLGjlobBVuFuM8uNAA==
dependencies:
- "@types/debug" "^4.1.4"
+ "@azure/core-auth" "^1.3.0"
+ "@azure/core-rest-pipeline" "^1.2.0"
debug "^4.1.1"
- fast-json-stable-stringify "^2.0.0"
+ fast-json-stable-stringify "^2.1.0"
jsbi "^3.1.3"
- node-abort-controller "^1.0.4"
- node-fetch "^2.6.0"
+ node-abort-controller "^1.2.0"
priorityqueuejs "^1.0.0"
semaphore "^1.0.5"
- tslib "^2.0.0"
+ tslib "^2.2.0"
universal-user-agent "^6.0.0"
uuid "^8.3.0"
+"@azure/identity@^2.0.1":
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-2.0.1.tgz#31107506371e520bc874647a9e4384cfd2f85103"
+ integrity sha512-gdGGuLKlKIQaf2RefA84keoBfmWfiAntbW2SzcdKvwLSGzsio/qkyY3sYUpXRz/sqLDxguuimgZukp7TPgwIlg==
+ dependencies:
+ "@azure/abort-controller" "^1.0.0"
+ "@azure/core-auth" "^1.3.0"
+ "@azure/core-client" "^1.0.0"
+ "@azure/core-rest-pipeline" "^1.1.0"
+ "@azure/core-tracing" "1.0.0-preview.13"
+ "@azure/core-util" "^1.0.0-beta.1"
+ "@azure/logger" "^1.0.0"
+ "@azure/msal-browser" "^2.16.0"
+ "@azure/msal-common" "^4.5.1"
+ "@azure/msal-node" "^1.3.0"
+ "@types/stoppable" "^1.1.0"
+ events "^3.0.0"
+ jws "^4.0.0"
+ open "^8.0.0"
+ stoppable "^1.1.0"
+ tslib "^2.2.0"
+ uuid "^8.3.0"
+
"@azure/logger@^1.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.1.tgz#19b333203d1b2931353d8879e814b64a7274837a"
@@ -93,20 +149,50 @@
dependencies:
tslib "^2.0.0"
-"@azure/storage-blob@^12.4.0":
- version "12.4.0"
- resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.4.0.tgz#7127ddd9f413105e2c3688691bc4c6245d0806b3"
- integrity sha512-OnhVSoKD1HzBB79/rFzPbC4w9TdzFXeoOwkX+aIu3rb8qvN0VaqvUqZXSrBCyG2LcLyVkY4MPCJQBrmEUm9kvw==
+"@azure/msal-browser@^2.16.0":
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-2.19.0.tgz#6915d200e0679eb8b26368bf0e0fc02ee4a8617a"
+ integrity sha512-nVMMSbFeocGv3SUYGBD+3pkE/pbAciGhER3KCjsBu6Sy9EDaBCiQ418KZfHBcCcrNQgFxf3nleWdeYoYX7281g==
+ dependencies:
+ "@azure/msal-common" "^5.1.0"
+
+"@azure/msal-common@^4.5.1":
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-4.5.1.tgz#f35af8b634ae24aebd0906deb237c0db1afa5826"
+ integrity sha512-/i5dXM+QAtO+6atYd5oHGBAx48EGSISkXNXViheliOQe+SIFMDo3gSq3lL54W0suOSAsVPws3XnTaIHlla0PIQ==
+ dependencies:
+ debug "^4.1.1"
+
+"@azure/msal-common@^5.1.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-5.1.0.tgz#e3a75a8ba1602da040698046161961d6dc59bbc4"
+ integrity sha512-4zHZ5Ec7jAgTIWZO3ap1ozgIPGAirF1wL8UhsmPF9QDoZz0cMHdaNmtov5i2+6Xq37YMzhN5s50EFHBuXd7sDQ==
+ dependencies:
+ debug "^4.1.1"
+
+"@azure/msal-node@^1.3.0":
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-1.3.3.tgz#3b977fa371d0c5fcd63df2e458353044a1eb64a1"
+ integrity sha512-ZtVCVzr7V4xEeqICa7E9g6BY3noZv96XG11ENuqEiz/PA1OzPD1/x0QF6BPHVldST8wwoevXxPw+t/h3AFII7w==
+ dependencies:
+ "@azure/msal-common" "^5.1.0"
+ axios "^0.21.4"
+ jsonwebtoken "^8.5.1"
+ uuid "^8.3.0"
+
+"@azure/storage-blob@^12.8.0":
+ version "12.8.0"
+ resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.8.0.tgz#97b7ecc6c7b17bcbaf0281c79c16af6f512d6130"
+ integrity sha512-c8+Wz19xauW0bGkTCoqZH4dYfbtBniPiGiRQOn1ca6G5jsjr4azwaTk9gwjVY8r3vY2Taf95eivLzipfIfiS4A==
dependencies:
"@azure/abort-controller" "^1.0.0"
- "@azure/core-http" "^1.2.0"
- "@azure/core-lro" "^1.0.2"
+ "@azure/core-http" "^2.0.0"
+ "@azure/core-lro" "^2.2.0"
"@azure/core-paging" "^1.1.1"
- "@azure/core-tracing" "1.0.0-preview.9"
+ "@azure/core-tracing" "1.0.0-preview.13"
"@azure/logger" "^1.0.0"
- "@opentelemetry/api" "^0.10.2"
events "^3.0.0"
- tslib "^2.0.0"
+ tslib "^2.2.0"
"@electron/get@^1.12.4":
version "1.12.4"
@@ -131,22 +217,10 @@
dependencies:
cross-spawn "^7.0.1"
-"@opencensus/web-types@0.0.7":
- version "0.0.7"
- resolved "https://registry.yarnpkg.com/@opencensus/web-types/-/web-types-0.0.7.tgz#4426de1fe5aa8f624db395d2152b902874f0570a"
- integrity sha512-xB+w7ZDAu3YBzqH44rCmG9/RlrOmFuDPt/bpf17eJr8eZSrLt7nc7LnWdxM9Mmoj/YKMHpxRg28txu3TcpiL+g==
-
-"@opentelemetry/api@^0.10.2":
- version "0.10.2"
- resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-0.10.2.tgz#9647b881f3e1654089ff7ea59d587b2d35060654"
- integrity sha512-GtpMGd6vkzDMYcpu2t9LlhEgMy/SzBwRnz48EejlRArYqZzqSzAsKmegUK7zHgl+EOIaK9mKHhnRaQu3qw20cA==
- dependencies:
- "@opentelemetry/context-base" "^0.10.2"
-
-"@opentelemetry/context-base@^0.10.2":
- version "0.10.2"
- resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.10.2.tgz#55bea904b2b91aa8a8675df9eaba5961bddb1def"
- integrity sha512-hZNKjKOYsckoOEgBziGMnBcX0M7EtstnCmwz5jZUOUYwlZ+/xxX6z3jPu1XVO2Jivk0eLfuP9GP+vFD49CMetw==
+"@opentelemetry/api@^1.0.1":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.0.3.tgz#13a12ae9e05c2a782f7b5e84c3cbfda4225eaf80"
+ integrity sha512-puWxACExDe9nxbBB3lOymQFrLYml2dVOrd7USiVRnSbgXE+KwBu+HxFvxrzfqsiSda9IWsXJG1ef7C1O2/GmKQ==
"@sindresorhus/is@^0.14.0":
version "0.14.0"
@@ -172,18 +246,16 @@
dependencies:
defer-to-connect "^2.0.0"
+"@tootallnate/once@1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
+ integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
+
"@types/ansi-colors@^3.2.0":
version "3.2.0"
resolved "https://registry.yarnpkg.com/@types/ansi-colors/-/ansi-colors-3.2.0.tgz#3e4fe85d9131ce1c6994f3040bd0b25306c16a6e"
integrity sha512-0caWAhXht9N2lOdMzJLXybsSkYCx1QOdxx6pae48tswI9QV3DFX26AoOpy0JxwhCb+zISTqmd6H8t9Zby9BoZg==
-"@types/azure@0.9.19":
- version "0.9.19"
- resolved "https://registry.yarnpkg.com/@types/azure/-/azure-0.9.19.tgz#1a6a9bd856b437ddecf3f9fc8407a683c869ba02"
- integrity sha1-Gmqb2Fa0N93s8/n8hAemg8hpugI=
- dependencies:
- "@types/node" "*"
-
"@types/byline@^4.2.32":
version "4.2.32"
resolved "https://registry.yarnpkg.com/@types/byline/-/byline-4.2.32.tgz#9d35ec15968056118548412ee24c2c3026c997dc"
@@ -226,7 +298,7 @@
resolved "https://registry.yarnpkg.com/@types/debounce/-/debounce-1.0.0.tgz#417560200331e1bb84d72da85391102c2fcd61b7"
integrity sha1-QXVgIAMx4buE1y2oU5EQLC/NYbc=
-"@types/debug@^4.1.4":
+"@types/debug@4.1.5":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd"
integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==
@@ -471,6 +543,13 @@
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
+"@types/stoppable@^1.1.0":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@types/stoppable/-/stoppable-1.1.1.tgz#a6f1f280e29f8f3c743277534425e0a75041d2f9"
+ integrity sha512-b8N+fCADRIYYrGZOcmOR8ZNBOqhktWTB/bMUl5LvGtT201QKJZOOH5UsFyI3qtteM6ZAJbJqZoBcLqqxKIwjhw==
+ dependencies:
+ "@types/node" "*"
+
"@types/tapable@^1":
version "1.0.8"
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310"
@@ -500,10 +579,10 @@
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.2.tgz#e0d481d8bb282ad8a8c9e100ceb72c995fb5e709"
integrity sha512-vOVmaruQG5EatOU/jM6yU2uCp3Lz6mK1P5Ztu4iJjfM4SVHU9XYktPUQtKlIXuahqXHdEyUarMrBEwg5Cwu+bA==
-"@types/tunnel@^0.0.1":
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.1.tgz#0d72774768b73df26f25df9184273a42da72b19c"
- integrity sha512-AOqu6bQu5MSWwYvehMXLukFHnupHrpZ8nvgae5Ggie9UwzDR1CCwoXgSSWNZJuyOlCdfdsWMA5F2LlmvyoTv8A==
+"@types/tunnel@^0.0.3":
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9"
+ integrity sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==
dependencies:
"@types/node" "*"
@@ -652,15 +731,12 @@
dependencies:
eslint-visitor-keys "^1.1.0"
-ajv@^6.12.3:
- version "6.12.6"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
- integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+agent-base@6:
+ 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:
- fast-deep-equal "^3.1.1"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.4.1"
- uri-js "^4.2.2"
+ debug "4"
ansi-colors@^1.0.1:
version "1.1.0"
@@ -727,18 +803,6 @@ asar@^3.0.3:
optionalDependencies:
"@types/glob" "^7.1.1"
-asn1@~0.2.3:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
- integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
- dependencies:
- safer-buffer "~2.1.0"
-
-assert-plus@1.0.0, assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
- integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
-
assign-symbols@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
@@ -754,15 +818,12 @@ at-least-node@^1.0.0:
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
-aws-sign2@~0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
- integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
-
-aws4@^1.8.0:
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
- integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
+axios@^0.21.4:
+ version "0.21.4"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
+ integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
+ dependencies:
+ follow-redirects "^1.14.0"
azure-devops-node-api@^11.0.1:
version "11.0.1"
@@ -772,23 +833,6 @@ azure-devops-node-api@^11.0.1:
tunnel "0.0.6"
typed-rest-client "^1.8.4"
-azure-storage@^2.1.0:
- version "2.10.3"
- resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.10.3.tgz#c5966bf929d87587d78f6847040ea9a4b1d4a50a"
- integrity sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ==
- dependencies:
- browserify-mime "~1.2.9"
- extend "^3.0.2"
- json-edm-parser "0.1.2"
- md5.js "1.3.4"
- readable-stream "~2.0.0"
- request "^2.86.0"
- underscore "~1.8.3"
- uuid "^3.0.0"
- validator "~9.4.1"
- xml2js "0.2.8"
- xmlbuilder "^9.0.7"
-
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@@ -799,13 +843,6 @@ base64-js@^1.2.3:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
-bcrypt-pbkdf@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
- integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
- dependencies:
- tweetnacl "^0.14.3"
-
bluebird@^3.5.0:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
@@ -829,11 +866,6 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"
-browserify-mime@~1.2.9:
- version "1.2.9"
- resolved "https://registry.yarnpkg.com/browserify-mime/-/browserify-mime-1.2.9.tgz#aeb1af28de6c0d7a6a2ce40adb68ff18422af31f"
- integrity sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8=
-
buffer-alloc-unsafe@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
@@ -852,6 +884,11 @@ buffer-crc32@~0.2.3:
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
+buffer-equal-constant-time@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
+ integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
+
buffer-equal@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe"
@@ -906,11 +943,6 @@ call-bind@^1.0.0:
function-bind "^1.1.1"
get-intrinsic "^1.0.2"
-caseless@~0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
- integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-
chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@@ -1002,7 +1034,7 @@ colors@^1.4.0:
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
-combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
+combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@@ -1054,7 +1086,7 @@ core-js@^3.6.5:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.15.2.tgz#740660d2ff55ef34ce664d7e2455119c5bdd3d61"
integrity sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==
-core-util-is@1.0.2, core-util-is@~1.0.0:
+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=
@@ -1084,12 +1116,12 @@ css-what@^5.0.0, css-what@^5.0.1:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.1.tgz#3efa820131f4669a8ac2408f9c32e7c7de9f4cad"
integrity sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==
-dashdash@^1.12.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
- integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
+debug@4, debug@^4.1.0, debug@^4.3.2:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
+ integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
dependencies:
- assert-plus "^1.0.0"
+ ms "2.1.2"
debug@^2.6.8:
version "2.6.9"
@@ -1098,13 +1130,6 @@ debug@^2.6.8:
dependencies:
ms "2.0.0"
-debug@^4.1.0, debug@^4.3.2:
- version "4.3.2"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
- integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
- dependencies:
- ms "2.1.2"
-
debug@^4.1.1, debug@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
@@ -1136,6 +1161,11 @@ defer-to-connect@^2.0.0:
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1"
integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==
+define-lazy-prop@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
+ integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+
define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -1215,13 +1245,12 @@ duplexer3@^0.1.4:
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
-ecc-jsbn@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
- integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
+ecdsa-sig-formatter@1.0.11:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
+ integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
dependencies:
- jsbn "~0.1.0"
- safer-buffer "^2.1.0"
+ safe-buffer "^5.0.1"
electron-osx-sign@^0.4.16:
version "0.4.16"
@@ -1327,11 +1356,6 @@ extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
-extend@^3.0.2, extend@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
- integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-
extract-zip@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
@@ -1343,22 +1367,7 @@ extract-zip@^2.0.1:
optionalDependencies:
"@types/yauzl" "^2.9.1"
-extsprintf@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
- integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
-
-extsprintf@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
- integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
-
-fast-deep-equal@^3.1.1:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
- integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-
-fast-json-stable-stringify@^2.0.0:
+fast-json-stable-stringify@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
@@ -1370,10 +1379,10 @@ fd-slicer@~1.1.0:
dependencies:
pend "~1.2.0"
-forever-agent@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
- integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
+follow-redirects@^1.14.0:
+ version "1.14.5"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381"
+ integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==
form-data@^3.0.0:
version "3.0.0"
@@ -1384,13 +1393,13 @@ form-data@^3.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"
-form-data@~2.3.2:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
- integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+form-data@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
- combined-stream "^1.0.6"
+ combined-stream "^1.0.8"
mime-types "^2.1.12"
fs-extra@^8.1.0:
@@ -1445,13 +1454,6 @@ get-stream@^5.1.0:
dependencies:
pump "^3.0.0"
-getpass@^0.1.1:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
- integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
- dependencies:
- assert-plus "^1.0.0"
-
glob@^7.0.6:
version "7.1.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
@@ -1561,19 +1563,6 @@ gulp-merge-json@^2.1.1:
through "^2.3.8"
vinyl "^2.1.0"
-har-schema@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
- integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
-
-har-validator@~5.1.3:
- version "5.1.5"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
- integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
- dependencies:
- ajv "^6.12.3"
- har-schema "^2.0.0"
-
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -1591,15 +1580,6 @@ has@^1.0.3:
dependencies:
function-bind "^1.1.1"
-hash-base@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
- integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
- dependencies:
- inherits "^2.0.4"
- readable-stream "^3.6.0"
- safe-buffer "^5.2.0"
-
hosted-git-info@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961"
@@ -1622,14 +1602,14 @@ http-cache-semantics@^4.0.0:
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
-http-signature@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
- integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
+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:
- assert-plus "^1.0.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
+ "@tootallnate/once" "1"
+ agent-base "6"
+ debug "4"
http2-wrapper@^1.0.0-beta.5.2:
version "1.0.0-beta.5.2"
@@ -1639,10 +1619,18 @@ http2-wrapper@^1.0.0-beta.5.2:
quick-lru "^5.1.1"
resolve-alpn "^1.0.0"
-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==
+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.10:
+ version "0.6.10"
+ resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.10.tgz#faec47521e095b8e3a7175ae08e1b4ae0359a735"
+ integrity sha512-8NtgTa/m1jVq7vdywmD5+SqIlZsB59wtsjaylQuExyCojMq1tHVQxmHjeqVSYwKwnmQbH4mZ1Dxx1eqDkPgaqA==
inflight@^1.0.4:
version "1.0.6"
@@ -1652,21 +1640,21 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@^2.0.1, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@^2.0.1, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-inherits@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
- integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-
ini@^1.3.4:
version "1.3.8"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+is-docker@^2.0.0, is-docker@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
+ integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
+
is-extendable@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
@@ -1693,10 +1681,12 @@ is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
-is-typedarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
- integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+is-wsl@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
isarray@~1.0.0:
version "1.0.0"
@@ -1720,21 +1710,11 @@ isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
-isstream@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
- integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-
jsbi@^3.1.3:
version "3.1.4"
resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.1.4.tgz#9654dd02207a66a4911b4e4bb74265bc2cbc9dd0"
integrity sha512-52QRRFSsi9impURE8ZUbzAMCLjPm4THO7H2fcuIvaaeFTbSysvkodbQQXIVsNgq/ypDbq6dJiuGKL0vZ/i9hUg==
-jsbn@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
- integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-
json-buffer@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
@@ -1745,24 +1725,7 @@ json-buffer@3.0.1:
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
-json-edm-parser@0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/json-edm-parser/-/json-edm-parser-0.1.2.tgz#1e60b0fef1bc0af67bc0d146dfdde5486cd615b4"
- integrity sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=
- dependencies:
- jsonparse "~1.2.0"
-
-json-schema-traverse@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
- integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
-
-json-schema@0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
- integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-
-json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
+json-stringify-safe@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
@@ -1795,20 +1758,55 @@ jsonfile@^6.0.1:
optionalDependencies:
graceful-fs "^4.1.6"
-jsonparse@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.2.0.tgz#5c0c5685107160e72fe7489bddea0b44c2bc67bd"
- integrity sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70=
-
-jsprim@^1.2.2:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
- integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
+jsonwebtoken@^8.5.1:
+ version "8.5.1"
+ resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
+ integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
dependencies:
- assert-plus "1.0.0"
- extsprintf "1.3.0"
- json-schema "0.2.3"
- verror "1.10.0"
+ jws "^3.2.2"
+ lodash.includes "^4.3.0"
+ lodash.isboolean "^3.0.3"
+ lodash.isinteger "^4.0.4"
+ lodash.isnumber "^3.0.3"
+ lodash.isplainobject "^4.0.6"
+ lodash.isstring "^4.0.1"
+ lodash.once "^4.0.0"
+ ms "^2.1.1"
+ semver "^5.6.0"
+
+jwa@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
+ integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
+ dependencies:
+ buffer-equal-constant-time "1.0.1"
+ ecdsa-sig-formatter "1.0.11"
+ safe-buffer "^5.0.1"
+
+jwa@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc"
+ integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==
+ dependencies:
+ buffer-equal-constant-time "1.0.1"
+ ecdsa-sig-formatter "1.0.11"
+ safe-buffer "^5.0.1"
+
+jws@^3.2.2:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
+ integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
+ dependencies:
+ jwa "^1.4.1"
+ safe-buffer "^5.0.1"
+
+jws@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4"
+ integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==
+ dependencies:
+ jwa "^2.0.0"
+ safe-buffer "^5.0.1"
keyv@^3.0.0:
version "3.1.0"
@@ -1836,11 +1834,46 @@ linkify-it@^2.0.0:
dependencies:
uc.micro "^1.0.1"
+lodash.includes@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
+ integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
+
+lodash.isboolean@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
+ integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
+
+lodash.isinteger@^4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
+ integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
+
+lodash.isnumber@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
+ integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
+
+lodash.isplainobject@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+ integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
+
+lodash.isstring@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
+ integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
+
lodash.mergewith@^4.6.1:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
+lodash.once@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
+ integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
+
lodash.unescape@4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
@@ -1886,14 +1919,6 @@ matcher@^3.0.0:
dependencies:
escape-string-regexp "^4.0.0"
-md5.js@1.3.4:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d"
- integrity sha1-6b296UogpawYsENA/Fdk1bCdkB0=
- dependencies:
- hash-base "^3.0.0"
- inherits "^2.0.1"
-
mdurl@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
@@ -1904,7 +1929,7 @@ mime-db@1.45.0:
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea"
integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==
-mime-types@^2.1.12, mime-types@~2.1.19:
+mime-types@^2.1.12:
version "2.1.28"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd"
integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==
@@ -1963,15 +1988,20 @@ ms@2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+ms@^2.1.1:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+ integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
mute-stream@~0.0.4:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
-node-abort-controller@^1.0.4:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-1.1.0.tgz#8a734a631b022af29963be7245c1483cbb9e070d"
- integrity sha512-dEYmUqjtbivotqjraOe8UvhT/poFfog1BQRNsZm/MSEDDESk2cQ1tvD8kGyuN07TM/zoW+n42odL8zTeJupYdQ==
+node-abort-controller@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-1.2.1.tgz#1eddb57eb8fea734198b11b28857596dc6165708"
+ integrity sha512-79PYeJuj6S9+yOHirR0JBLFOgjB6sQCir10uN6xRx25iD+ZD4ULqgRn3MwWBRaQGB0vEgReJzWwJo42T1R6YbQ==
node-fetch@^2.6.0:
version "2.6.1"
@@ -2003,11 +2033,6 @@ nth-check@^2.0.0:
dependencies:
boolbase "^1.0.0"
-oauth-sign@~0.9.0:
- version "0.9.0"
- resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
- integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-
object-inspect@^1.9.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
@@ -2025,6 +2050,15 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
+open@^8.0.0:
+ version "8.4.0"
+ resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8"
+ integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==
+ dependencies:
+ define-lazy-prop "^2.0.0"
+ is-docker "^2.1.1"
+ is-wsl "^2.2.0"
+
os-homedir@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
@@ -2094,11 +2128,6 @@ pend@~1.2.0:
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
-performance-now@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
- integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-
picomatch@^2.0.4:
version "2.3.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
@@ -2152,11 +2181,6 @@ process-nextick-args@^2.0.0, process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-process-nextick-args@~1.0.6:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
- integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=
-
process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
@@ -2172,7 +2196,7 @@ proto-list@~1.2.1:
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
-psl@^1.1.28, psl@^1.1.33:
+psl@^1.1.33:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
@@ -2185,7 +2209,7 @@ pump@^3.0.0:
end-of-stream "^1.1.0"
once "^1.3.1"
-punycode@^2.1.0, punycode@^2.1.1:
+punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
@@ -2197,11 +2221,6 @@ qs@^6.9.1:
dependencies:
side-channel "^1.0.4"
-qs@~6.5.2:
- version "6.5.2"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
- integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
-
quick-lru@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
@@ -2227,27 +2246,6 @@ readable-stream@^2.3.5:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
-readable-stream@^3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
- integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
- dependencies:
- inherits "^2.0.3"
- string_decoder "^1.1.1"
- util-deprecate "^1.0.1"
-
-readable-stream@~2.0.0:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
- integrity sha1-j5A0HmilPMySh4jaz80Rs265t44=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "~1.0.0"
- process-nextick-args "~1.0.6"
- string_decoder "~0.10.x"
- util-deprecate "~1.0.1"
-
remove-trailing-separator@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
@@ -2258,32 +2256,6 @@ replace-ext@^1.0.0:
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a"
integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==
-request@^2.86.0:
- version "2.88.2"
- resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
- integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
- dependencies:
- aws-sign2 "~0.7.0"
- aws4 "^1.8.0"
- caseless "~0.12.0"
- combined-stream "~1.0.6"
- extend "~3.0.2"
- forever-agent "~0.6.1"
- form-data "~2.3.2"
- har-validator "~5.1.3"
- http-signature "~1.2.0"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.19"
- oauth-sign "~0.9.0"
- performance-now "^2.1.0"
- qs "~6.5.2"
- safe-buffer "^5.1.2"
- tough-cookie "~2.5.0"
- tunnel-agent "^0.6.0"
- uuid "^3.3.2"
-
resolve-alpn@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.0.0.tgz#745ad60b3d6aff4b4a48e01b8c0bdc70959e0e8c"
@@ -2322,7 +2294,7 @@ roarr@^2.15.3:
semver-compare "^1.0.0"
sprintf-js "^1.1.2"
-safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0:
+safe-buffer@^5.0.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -2332,16 +2304,6 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
- integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
-sax@0.5.x:
- version "0.5.8"
- resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
- integrity sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=
-
sax@>=0.6.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
@@ -2362,6 +2324,11 @@ semver@^5.1.0, semver@^5.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
+semver@^5.6.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+ integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
semver@^6.2.0, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
@@ -2422,33 +2389,18 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-sshpk@^1.7.0:
- version "1.16.1"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
- integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
- dependencies:
- asn1 "~0.2.3"
- assert-plus "^1.0.0"
- bcrypt-pbkdf "^1.0.0"
- dashdash "^1.12.0"
- ecc-jsbn "~0.1.1"
- getpass "^0.1.1"
- jsbn "~0.1.0"
- safer-buffer "^2.0.2"
- tweetnacl "~0.14.0"
+stoppable@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b"
+ integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==
-string_decoder@^1.1.1, string_decoder@~1.1.1:
+string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies:
safe-buffer "~5.1.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=
-
sumchecker@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42"
@@ -2496,14 +2448,6 @@ tough-cookie@^4.0.0:
punycode "^2.1.1"
universalify "^0.1.2"
-tough-cookie@~2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
- integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
- dependencies:
- psl "^1.1.28"
- punycode "^2.1.1"
-
tslib@^1.8.1:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
@@ -2526,23 +2470,11 @@ tsutils@^3.17.1:
dependencies:
tslib "^1.8.1"
-tunnel-agent@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
- integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
- dependencies:
- safe-buffer "^5.0.1"
-
tunnel@0.0.6, tunnel@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
-tweetnacl@^0.14.3, tweetnacl@~0.14.0:
- version "0.14.5"
- resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
- integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-
type-fest@^0.13.1:
version "0.13.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
@@ -2557,10 +2489,10 @@ typed-rest-client@^1.8.4:
tunnel "0.0.6"
underscore "^1.12.1"
-typescript@^4.6.0-dev.20211108:
- version "4.6.0-dev.20211108"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.0-dev.20211108.tgz#d9e65b39f0876ba9d5e82b7955d1183c38d1e40b"
- integrity sha512-5a0mWJq05zNPSb0vF4s6OJbCxT0Cz6XIjgkaiYy5pkSXlu2E8mYRnYlo9IKKn34eUFO5FiO0uwm0Z3dsbcEgDw==
+typescript@^4.6.0-dev.20211115:
+ version "4.6.0-dev.20211115"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.0-dev.20211115.tgz#215e5d032e77cb83f382dc88e901a0757c02cc53"
+ integrity sha512-rYdYp/j8OhCRFs97l7GNOX9xGHndwwgY8AcL7LDzmFXgBOXC2VLoQP48nCg8FgVzjK6s0M5V4nijTYHRlwiqGQ==
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.5"
@@ -2572,11 +2504,6 @@ underscore@^1.12.1:
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.1.tgz#0c1c6bd2df54b6b69f2314066d65b6cde6fcf9d1"
integrity sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==
-underscore@~1.8.3:
- version "1.8.3"
- resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
- integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=
-
universal-user-agent@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
@@ -2592,13 +2519,6 @@ universalify@^2.0.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
-uri-js@^4.2.2:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
- integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
- dependencies:
- punycode "^2.1.0"
-
url-join@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/url-join/-/url-join-1.1.0.tgz#741c6c2f4596c4830d6718460920d0c92202dc78"
@@ -2611,35 +2531,16 @@ url-parse-lax@^3.0.0:
dependencies:
prepend-http "^2.0.0"
-util-deprecate@^1.0.1, util-deprecate@~1.0.1:
+util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-uuid@^3.0.0, uuid@^3.3.2:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
- integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-
uuid@^8.3.0:
version "8.3.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
-validator@~9.4.1:
- version "9.4.1"
- resolved "https://registry.yarnpkg.com/validator/-/validator-9.4.1.tgz#abf466d398b561cd243050112c6ff1de6cc12663"
- integrity sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==
-
-verror@1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
- integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
- dependencies:
- assert-plus "^1.0.0"
- core-util-is "1.0.2"
- extsprintf "^1.2.0"
-
vinyl@^2.1.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974"
@@ -2703,13 +2604,6 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-xml2js@0.2.8:
- version "0.2.8"
- resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.8.tgz#9b81690931631ff09d1957549faf54f4f980b3c2"
- integrity sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=
- dependencies:
- sax "0.5.x"
-
xml2js@^0.4.19, xml2js@^0.4.23:
version "0.4.23"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"
diff --git a/extensions/configuration-editing/schemas/attachContainer.schema.json b/extensions/configuration-editing/schemas/attachContainer.schema.json
index 48d51d78f05..6d9d794265b 100644
--- a/extensions/configuration-editing/schemas/attachContainer.schema.json
+++ b/extensions/configuration-editing/schemas/attachContainer.schema.json
@@ -24,7 +24,7 @@
},
{
"type": "string",
- "pattern": "^([a-z0-9\\-]+):(\\d{1,5})$"
+ "pattern": "^([a-z0-9-]+):(\\d{1,5})$"
}
]
}
@@ -32,7 +32,7 @@
"portsAttributes": {
"type": "object",
"patternProperties": {
- "(^\\d+(\\-\\d+)?$)|(.+)": {
+ "(^\\d+(-\\d+)?$)|(.+)": {
"type": "object",
"description": "A port, range of ports (ex. \"40000-55000\"), or regular expression (ex. \".+\\\\/server.js\"). For a port number or range, the attributes will apply to that port number or range of port numbers. Attributes which use a regular expression will apply to ports whose associated process command line matches the expression.",
"properties": {
@@ -179,7 +179,7 @@
"description": "An array of extensions that should be installed into the container.",
"items": {
"type": "string",
- "pattern": "^([a-z0-9A-Z][a-z0-9\\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\\-A-Z]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
+ "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
}
},
diff --git a/extensions/configuration-editing/schemas/devContainer.schema.generated.json b/extensions/configuration-editing/schemas/devContainer.schema.generated.json
index 19e769e95b0..b8a6d3cf5a3 100644
--- a/extensions/configuration-editing/schemas/devContainer.schema.generated.json
+++ b/extensions/configuration-editing/schemas/devContainer.schema.generated.json
@@ -116,7 +116,7 @@
"description": "An array of extensions that should be installed into the container.",
"items": {
"type": "string",
- "pattern": "^([a-z0-9A-Z][a-z0-9\\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\\-A-Z]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
+ "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
}
},
@@ -141,7 +141,7 @@
},
{
"type": "string",
- "pattern": "^([a-z0-9\\-]+):(\\d{1,5})$"
+ "pattern": "^([a-z0-9-]+):(\\d{1,5})$"
}
]
}
@@ -149,7 +149,7 @@
"portsAttributes": {
"type": "object",
"patternProperties": {
- "(^\\d+(\\-\\d+)?$)|(.+)": {
+ "(^\\d+(-\\d+)?$)|(.+)": {
"type": "object",
"description": "A port, range of ports (ex. \"40000-55000\"), or regular expression (ex. \".+\\\\/server.js\"). For a port number or range, the attributes will apply to that port number or range of port numbers. Attributes which use a regular expression will apply to ports whose associated process command line matches the expression.",
"properties": {
@@ -519,7 +519,7 @@
"description": "An array of extensions that should be installed into the container.",
"items": {
"type": "string",
- "pattern": "^([a-z0-9A-Z][a-z0-9\\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\\-A-Z]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
+ "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
}
},
@@ -544,7 +544,7 @@
},
{
"type": "string",
- "pattern": "^([a-z0-9\\-]+):(\\d{1,5})$"
+ "pattern": "^([a-z0-9-]+):(\\d{1,5})$"
}
]
}
@@ -552,7 +552,7 @@
"portsAttributes": {
"type": "object",
"patternProperties": {
- "(^\\d+(\\-\\d+)?$)|(.+)": {
+ "(^\\d+(-\\d+)?$)|(.+)": {
"type": "object",
"description": "A port, range of ports (ex. \"40000-55000\"), or regular expression (ex. \".+\\\\/server.js\"). For a port number or range, the attributes will apply to that port number or range of port numbers. Attributes which use a regular expression will apply to ports whose associated process command line matches the expression.",
"properties": {
@@ -888,7 +888,7 @@
"description": "An array of extensions that should be installed into the container.",
"items": {
"type": "string",
- "pattern": "^([a-z0-9A-Z][a-z0-9\\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\\-A-Z]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
+ "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
}
},
@@ -913,7 +913,7 @@
},
{
"type": "string",
- "pattern": "^([a-z0-9\\-]+):(\\d{1,5})$"
+ "pattern": "^([a-z0-9-]+):(\\d{1,5})$"
}
]
}
@@ -921,7 +921,7 @@
"portsAttributes": {
"type": "object",
"patternProperties": {
- "(^\\d+(\\-\\d+)?$)|(.+)": {
+ "(^\\d+(-\\d+)?$)|(.+)": {
"type": "object",
"description": "A port, range of ports (ex. \"40000-55000\"), or regular expression (ex. \".+\\\\/server.js\"). For a port number or range, the attributes will apply to that port number or range of port numbers. Attributes which use a regular expression will apply to ports whose associated process command line matches the expression.",
"properties": {
@@ -1231,7 +1231,7 @@
"description": "An array of extensions that should be installed into the container.",
"items": {
"type": "string",
- "pattern": "^([a-z0-9A-Z][a-z0-9\\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\\-A-Z]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
+ "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
}
},
@@ -1256,7 +1256,7 @@
},
{
"type": "string",
- "pattern": "^([a-z0-9\\-]+):(\\d{1,5})$"
+ "pattern": "^([a-z0-9-]+):(\\d{1,5})$"
}
]
}
@@ -1264,7 +1264,7 @@
"portsAttributes": {
"type": "object",
"patternProperties": {
- "(^\\d+(\\-\\d+)?$)|(.+)": {
+ "(^\\d+(-\\d+)?$)|(.+)": {
"type": "object",
"description": "A port, range of ports (ex. \"40000-55000\"), or regular expression (ex. \".+\\\\/server.js\"). For a port number or range, the attributes will apply to that port number or range of port numbers. Attributes which use a regular expression will apply to ports whose associated process command line matches the expression.",
"properties": {
@@ -1539,7 +1539,7 @@
"description": "An array of extensions that should be installed into the container.",
"items": {
"type": "string",
- "pattern": "^([a-z0-9A-Z][a-z0-9\\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\\-A-Z]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
+ "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
}
},
@@ -1564,7 +1564,7 @@
},
{
"type": "string",
- "pattern": "^([a-z0-9\\-]+):(\\d{1,5})$"
+ "pattern": "^([a-z0-9-]+):(\\d{1,5})$"
}
]
}
@@ -1572,7 +1572,7 @@
"portsAttributes": {
"type": "object",
"patternProperties": {
- "(^\\d+(\\-\\d+)?$)|(.+)": {
+ "(^\\d+(-\\d+)?$)|(.+)": {
"type": "object",
"description": "A port, range of ports (ex. \"40000-55000\"), or regular expression (ex. \".+\\\\/server.js\"). For a port number or range, the attributes will apply to that port number or range of port numbers. Attributes which use a regular expression will apply to ports whose associated process command line matches the expression.",
"properties": {
diff --git a/extensions/configuration-editing/schemas/devContainer.schema.src.json b/extensions/configuration-editing/schemas/devContainer.schema.src.json
index e42d3655d2a..7a11e21a01b 100644
--- a/extensions/configuration-editing/schemas/devContainer.schema.src.json
+++ b/extensions/configuration-editing/schemas/devContainer.schema.src.json
@@ -16,7 +16,7 @@
"description": "An array of extensions that should be installed into the container.",
"items": {
"type": "string",
- "pattern": "^([a-z0-9A-Z][a-z0-9\\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\\-A-Z]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
+ "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
}
},
@@ -41,7 +41,7 @@
},
{
"type": "string",
- "pattern": "^([a-z0-9\\-]+):(\\d{1,5})$"
+ "pattern": "^([a-z0-9-]+):(\\d{1,5})$"
}
]
}
@@ -49,7 +49,7 @@
"portsAttributes": {
"type": "object",
"patternProperties": {
- "(^\\d+(\\-\\d+)?$)|(.+)": {
+ "(^\\d+(-\\d+)?$)|(.+)": {
"type": "object",
"description": "A port, range of ports (ex. \"40000-55000\"), or regular expression (ex. \".+\\\\/server.js\"). For a port number or range, the attributes will apply to that port number or range of port numbers. Attributes which use a regular expression will apply to ports whose associated process command line matches the expression.",
"properties": {
diff --git a/extensions/configuration-editing/src/settingsDocumentHelper.ts b/extensions/configuration-editing/src/settingsDocumentHelper.ts
index e6afeb22d1d..11282899b81 100644
--- a/extensions/configuration-editing/src/settingsDocumentHelper.ts
+++ b/extensions/configuration-editing/src/settingsDocumentHelper.ts
@@ -9,6 +9,7 @@ import * as nls from 'vscode-nls';
import { provideInstalledExtensionProposals } from './extensionsProposals';
const localize = nls.loadMessageBundle();
+const OVERRIDE_IDENTIFIER_REGEX = /\[([^\[\]]*)\]/g;
export class SettingsDocument {
@@ -186,61 +187,60 @@ export class SettingsDocument {
.then(languages => languages.map(l => this.newSimpleCompletionItem(formatFunc(l), range)));
}
- private provideLanguageCompletionItemsForLanguageOverrides(_location: Location, range: vscode.Range, formatFunc: (string: string) => string = (l) => JSON.stringify(l)): Thenable {
- return vscode.languages.getLanguages().then(languages => {
- const completionItems = [];
- const configuration = vscode.workspace.getConfiguration();
- for (const language of languages) {
- const inspect = configuration.inspect(`[${language}]`);
- if (!inspect || !inspect.defaultValue) {
- const item = new vscode.CompletionItem(formatFunc(language));
- item.kind = vscode.CompletionItemKind.Property;
- item.range = range;
- completionItems.push(item);
- }
- }
- return completionItems;
- });
+ private async provideLanguageCompletionItemsForLanguageOverrides(_location: Location, range: vscode.Range): Promise {
+ const languages = await vscode.languages.getLanguages();
+ const completionItems = [];
+ for (const language of languages) {
+ const item = new vscode.CompletionItem(JSON.stringify(language));
+ item.kind = vscode.CompletionItemKind.Property;
+ item.range = range;
+ completionItems.push(item);
+ }
+ return completionItems;
}
- private provideLanguageOverridesCompletionItems(location: Location, position: vscode.Position): vscode.ProviderResult {
-
- if (location.path.length === 0) {
-
- let range = this.document.getWordRangeAtPosition(position, /^\s*\[.*]?/) || new vscode.Range(position, position);
- let text = this.document.getText(range);
- if (text && text.trim().startsWith('[')) {
- range = new vscode.Range(new vscode.Position(range.start.line, range.start.character + text.indexOf('[')), range.end);
- return this.provideLanguageCompletionItemsForLanguageOverrides(location, range, language => `"[${language}]"`);
- }
-
- range = this.document.getWordRangeAtPosition(position) || new vscode.Range(position, position);
- text = this.document.getText(range);
- let snippet = '"[${1:language}]": {\n\t"$0"\n}';
-
- // Suggestion model word matching includes quotes,
- // hence exclude the starting quote from the snippet and the range
- // ending quote gets replaced
- if (text && text.startsWith('"')) {
- range = new vscode.Range(new vscode.Position(range.start.line, range.start.character + 1), range.end);
- snippet = snippet.substring(1);
- }
-
- return Promise.resolve([this.newSnippetCompletionItem({
- label: localize('languageSpecificEditorSettings', "Language specific editor settings"),
- documentation: localize('languageSpecificEditorSettingsDescription', "Override editor settings for language"),
- snippet,
- range
- })]);
- }
-
+ private async provideLanguageOverridesCompletionItems(location: Location, position: vscode.Position): Promise {
if (location.path.length === 1 && location.previousNode && typeof location.previousNode.value === 'string' && location.previousNode.value.startsWith('[')) {
- // Suggestion model word matching includes closed sqaure bracket and ending quote
- // Hence include them in the proposal to replace
- const range = this.document.getWordRangeAtPosition(position) || new vscode.Range(position, position);
- return this.provideLanguageCompletionItemsForLanguageOverrides(location, range, language => `"[${language}]"`);
+ const startPosition = this.document.positionAt(location.previousNode.offset + 1);
+ const endPosition = startPosition.translate(undefined, location.previousNode.value.length);
+ const donotSuggestLanguages: string[] = [];
+ const languageOverridesRanges: vscode.Range[] = [];
+ let matches = OVERRIDE_IDENTIFIER_REGEX.exec(location.previousNode.value);
+ let lastLanguageOverrideRange: vscode.Range | undefined;
+ while (matches?.length) {
+ lastLanguageOverrideRange = new vscode.Range(this.document.positionAt(location.previousNode.offset + 1 + matches.index), this.document.positionAt(location.previousNode.offset + 1 + matches.index + matches[0].length));
+ languageOverridesRanges.push(lastLanguageOverrideRange);
+ /* Suggest the configured language if the position is in the match range */
+ if (!lastLanguageOverrideRange.contains(position)) {
+ donotSuggestLanguages.push(matches[1].trim());
+ }
+ matches = OVERRIDE_IDENTIFIER_REGEX.exec(location.previousNode.value);
+ }
+ const lastLanguageOverrideEndPosition = lastLanguageOverrideRange ? lastLanguageOverrideRange.end : startPosition;
+ if (lastLanguageOverrideEndPosition.isBefore(endPosition)) {
+ languageOverridesRanges.push(new vscode.Range(lastLanguageOverrideEndPosition, endPosition));
+ }
+ const languageOverrideRange = languageOverridesRanges.find(range => range.contains(position));
+
+ /**
+ * Skip if suggestsions are for first language override range
+ * Since VSCode registers language overrides to the schema, JSON language server does suggestions for first language override.
+ */
+ if (languageOverrideRange && !languageOverrideRange.isEqual(languageOverridesRanges[0])) {
+ const languages = await vscode.languages.getLanguages();
+ const completionItems = [];
+ for (const language of languages) {
+ if (!donotSuggestLanguages.includes(language)) {
+ const item = new vscode.CompletionItem(`[${language}]`);
+ item.kind = vscode.CompletionItemKind.Property;
+ item.range = languageOverrideRange;
+ completionItems.push(item);
+ }
+ }
+ return completionItems;
+ }
}
- return Promise.resolve([]);
+ return [];
}
private providePortsAttributesCompletionItem(range: vscode.Range): vscode.CompletionItem[] {
diff --git a/extensions/css-language-features/client/tsconfig.json b/extensions/css-language-features/client/tsconfig.json
index 1e11c9aaccc..573b24b4aa6 100644
--- a/extensions/css-language-features/client/tsconfig.json
+++ b/extensions/css-language-features/client/tsconfig.json
@@ -5,7 +5,6 @@
},
"include": [
"src/**/*",
- "../../../src/vscode-dts/vscode.d.ts",
- "../../../src/vscode-dts/vscode.proposed.d.ts",
+ "../../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json
index 7c3b8e75472..88994a67f44 100644
--- a/extensions/css-language-features/package.json
+++ b/extensions/css-language-features/package.json
@@ -17,7 +17,6 @@
],
"main": "./client/out/node/cssClientMain",
"browser": "./client/dist/browser/cssClientMain",
- "enableProposedApi": true,
"capabilities": {
"virtualWorkspaces": true,
"untrustedWorkspaces": {
diff --git a/extensions/debug-server-ready/package.json b/extensions/debug-server-ready/package.json
index e5c69df006b..64aa227aa53 100644
--- a/extensions/debug-server-ready/package.json
+++ b/extensions/debug-server-ready/package.json
@@ -18,7 +18,9 @@
"supported": true
}
},
- "enableProposedApi": true,
+ "enabledApiProposals": [
+ "terminalDataWriteEvent"
+ ],
"main": "./out/extension",
"scripts": {
"compile": "gulp compile-extension:debug-server-ready",
diff --git a/extensions/debug-server-ready/tsconfig.json b/extensions/debug-server-ready/tsconfig.json
index 88c43e9eba8..9bf747283ca 100644
--- a/extensions/debug-server-ready/tsconfig.json
+++ b/extensions/debug-server-ready/tsconfig.json
@@ -10,6 +10,6 @@
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts",
+ "../../src/vscode-dts/vscode.proposed.terminalDataWriteEvent.d.ts",
]
}
diff --git a/extensions/diff/.vscodeignore b/extensions/diff/.vscodeignore
new file mode 100644
index 00000000000..d9011becfb6
--- /dev/null
+++ b/extensions/diff/.vscodeignore
@@ -0,0 +1,2 @@
+build/**
+cgmanifest.json
diff --git a/extensions/diff/cgmanifest.json b/extensions/diff/cgmanifest.json
new file mode 100644
index 00000000000..04d6573c95e
--- /dev/null
+++ b/extensions/diff/cgmanifest.json
@@ -0,0 +1,32 @@
+{
+ "registrations": [
+ {
+ "component": {
+ "type": "git",
+ "git": {
+ "name": "textmate/diff.tmbundle",
+ "repositoryUrl": "https://github.com/textmate/diff.tmbundle",
+ "commitHash": "0593bb775eab1824af97ef2172fd38822abd97d7"
+ }
+ },
+ "licenseDetail": [
+ "Copyright (c) textmate-diff.tmbundle project authors",
+ "",
+ "If not otherwise specified (see below), files in this repository fall under the following license:",
+ "",
+ "Permission to copy, use, modify, sell and distribute this",
+ "software is granted. This software is provided \"as is\" without",
+ "express or implied warranty, and with no claim as to its",
+ "suitability for any purpose.",
+ "",
+ "An exception is made for files in readable text which contain their own license information,",
+ "or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added",
+ "to the base-name name of the original file, and an extension of txt, html, or similar. For example",
+ "\"tidy\" is accompanied by \"tidy-license.txt\"."
+ ],
+ "license": "TextMate Bundle License",
+ "version": "0.0.0"
+ }
+ ],
+ "version": 1
+}
diff --git a/extensions/git/languages/diff.language-configuration.json b/extensions/diff/language-configuration.json
similarity index 98%
rename from extensions/git/languages/diff.language-configuration.json
rename to extensions/diff/language-configuration.json
index b61fbe63d34..395aff60535 100644
--- a/extensions/git/languages/diff.language-configuration.json
+++ b/extensions/diff/language-configuration.json
@@ -8,4 +8,4 @@
["[", "]"],
["(", ")"]
]
-}
\ No newline at end of file
+}
diff --git a/extensions/diff/package.json b/extensions/diff/package.json
new file mode 100644
index 00000000000..7d23e24ac6b
--- /dev/null
+++ b/extensions/diff/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "diff",
+ "displayName": "%displayName%",
+ "description": "%description%",
+ "version": "1.0.0",
+ "publisher": "vscode",
+ "license": "MIT",
+ "engines": {
+ "vscode": "0.10.x"
+ },
+ "scripts": {
+ "update-grammar": "node ../node_modules/vscode-grammar-updater/bin textmate/diff.tmbundle Syntaxes/Diff.plist ./syntaxes/diff.tmLanguage.json"
+ },
+ "contributes": {
+ "languages": [
+ {
+ "id": "diff",
+ "aliases": [
+ "Diff",
+ "diff"
+ ],
+ "extensions": [
+ ".diff",
+ ".patch",
+ ".rej"
+ ],
+ "configuration": "./language-configuration.json"
+ }
+ ],
+ "grammars": [
+ {
+ "language": "diff",
+ "scopeName": "source.diff",
+ "path": "./syntaxes/diff.tmLanguage.json"
+ }
+ ]
+ }
+}
diff --git a/extensions/diff/package.nls.json b/extensions/diff/package.nls.json
new file mode 100644
index 00000000000..c869050177e
--- /dev/null
+++ b/extensions/diff/package.nls.json
@@ -0,0 +1,4 @@
+{
+ "displayName": "Diff Language Basics",
+ "description": "Provides syntax highlighting & bracket matching in Diff files."
+}
diff --git a/extensions/git/syntaxes/diff.tmLanguage.json b/extensions/diff/syntaxes/diff.tmLanguage.json
similarity index 100%
rename from extensions/git/syntaxes/diff.tmLanguage.json
rename to extensions/diff/syntaxes/diff.tmLanguage.json
diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json
index 6c1f0eb8eda..3dfc882b432 100644
--- a/extensions/emmet/package.json
+++ b/extensions/emmet/package.json
@@ -41,24 +41,7 @@
"onCommand:editor.emmet.action.decrementNumberByTen",
"onCommand:editor.emmet.action.reflectCSSValue",
"onCommand:workbench.action.showEmmetCommands",
- "onLanguage:html",
- "onLanguage:haml",
- "onLanguage:blade",
- "onLanguage:css",
- "onLanguage:sass",
- "onLanguage:scss",
- "onLanguage:less",
- "onLanguage:stylus",
- "onLanguage:slim",
- "onLanguage:stylus",
- "onLanguage:jade",
- "onLanguage:pug",
- "onLanguage:javascriptreact",
- "onLanguage:typescriptreact",
- "onLanguage:php",
- "onLanguage:vue",
- "onLanguage:xsl",
- "onLanguage:xml"
+ "onStartupFinished"
],
"main": "./out/node/emmetNodeMain",
"browser": "./dist/browser/emmetBrowserMain",
diff --git a/extensions/git-base/.vscodeignore b/extensions/git-base/.vscodeignore
new file mode 100644
index 00000000000..d9011becfb6
--- /dev/null
+++ b/extensions/git-base/.vscodeignore
@@ -0,0 +1,2 @@
+build/**
+cgmanifest.json
diff --git a/extensions/git/build/update-grammars.js b/extensions/git-base/build/update-grammars.js
similarity index 86%
rename from extensions/git/build/update-grammars.js
rename to extensions/git-base/build/update-grammars.js
index a5dae9f6850..ad326bff374 100644
--- a/extensions/git/build/update-grammars.js
+++ b/extensions/git-base/build/update-grammars.js
@@ -8,9 +8,3 @@ var updateGrammar = require('vscode-grammar-updater');
updateGrammar.update('textmate/git.tmbundle', 'Syntaxes/Git%20Commit%20Message.tmLanguage', './syntaxes/git-commit.tmLanguage.json');
updateGrammar.update('textmate/git.tmbundle', 'Syntaxes/Git%20Rebase%20Message.tmLanguage', './syntaxes/git-rebase.tmLanguage.json');
-updateGrammar.update('textmate/diff.tmbundle', 'Syntaxes/Diff.plist', './syntaxes/diff.tmLanguage.json');
-
-
-
-
-
diff --git a/extensions/git/cgmanifest.json b/extensions/git-base/cgmanifest.json
similarity index 57%
rename from extensions/git/cgmanifest.json
rename to extensions/git-base/cgmanifest.json
index e8081d6472e..256966aba20 100644
--- a/extensions/git/cgmanifest.json
+++ b/extensions/git-base/cgmanifest.json
@@ -33,34 +33,7 @@
],
"license": "MIT",
"version": "0.0.0"
- },
- {
- "component": {
- "type": "git",
- "git": {
- "name": "textmate/diff.tmbundle",
- "repositoryUrl": "https://github.com/textmate/diff.tmbundle",
- "commitHash": "0593bb775eab1824af97ef2172fd38822abd97d7"
- }
- },
- "licenseDetail": [
- "Copyright (c) textmate-diff.tmbundle project authors",
- "",
- "If not otherwise specified (see below), files in this repository fall under the following license:",
- "",
- "Permission to copy, use, modify, sell and distribute this",
- "software is granted. This software is provided \"as is\" without",
- "express or implied warranty, and with no claim as to its",
- "suitability for any purpose.",
- "",
- "An exception is made for files in readable text which contain their own license information,",
- "or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added",
- "to the base-name name of the original file, and an extension of txt, html, or similar. For example",
- "\"tidy\" is accompanied by \"tidy-license.txt\"."
- ],
- "license": "TextMate Bundle License",
- "version": "0.0.0"
}
],
"version": 1
-}
\ No newline at end of file
+}
diff --git a/extensions/git/languages/git-commit.language-configuration.json b/extensions/git-base/languages/git-commit.language-configuration.json
similarity index 100%
rename from extensions/git/languages/git-commit.language-configuration.json
rename to extensions/git-base/languages/git-commit.language-configuration.json
diff --git a/extensions/git/languages/git-rebase.language-configuration.json b/extensions/git-base/languages/git-rebase.language-configuration.json
similarity index 100%
rename from extensions/git/languages/git-rebase.language-configuration.json
rename to extensions/git-base/languages/git-rebase.language-configuration.json
diff --git a/extensions/git/languages/ignore.language-configuration.json b/extensions/git-base/languages/ignore.language-configuration.json
similarity index 100%
rename from extensions/git/languages/ignore.language-configuration.json
rename to extensions/git-base/languages/ignore.language-configuration.json
diff --git a/extensions/git-base/package.json b/extensions/git-base/package.json
new file mode 100644
index 00000000000..db3cbb7a812
--- /dev/null
+++ b/extensions/git-base/package.json
@@ -0,0 +1,70 @@
+{
+ "name": "git-base",
+ "displayName": "%displayName%",
+ "description": "%description%",
+ "version": "1.0.0",
+ "publisher": "vscode",
+ "license": "MIT",
+ "engines": {
+ "vscode": "0.10.x"
+ },
+ "scripts": {
+ "update-grammar": "node ./build/update-grammars.js"
+ },
+ "contributes": {
+ "languages": [
+ {
+ "id": "git-commit",
+ "aliases": [
+ "Git Commit Message",
+ "git-commit"
+ ],
+ "filenames": [
+ "COMMIT_EDITMSG",
+ "MERGE_MSG"
+ ],
+ "configuration": "./languages/git-commit.language-configuration.json"
+ },
+ {
+ "id": "git-rebase",
+ "aliases": [
+ "Git Rebase Message",
+ "git-rebase"
+ ],
+ "filenames": [
+ "git-rebase-todo"
+ ],
+ "configuration": "./languages/git-rebase.language-configuration.json"
+ },
+ {
+ "id": "ignore",
+ "aliases": [
+ "Ignore",
+ "ignore"
+ ],
+ "extensions": [
+ ".gitignore_global",
+ ".gitignore"
+ ],
+ "configuration": "./languages/ignore.language-configuration.json"
+ }
+ ],
+ "grammars": [
+ {
+ "language": "git-commit",
+ "scopeName": "text.git-commit",
+ "path": "./syntaxes/git-commit.tmLanguage.json"
+ },
+ {
+ "language": "git-rebase",
+ "scopeName": "text.git-rebase",
+ "path": "./syntaxes/git-rebase.tmLanguage.json"
+ },
+ {
+ "language": "ignore",
+ "scopeName": "source.ignore",
+ "path": "./syntaxes/ignore.tmLanguage.json"
+ }
+ ]
+ }
+}
diff --git a/extensions/git-base/package.nls.json b/extensions/git-base/package.nls.json
new file mode 100644
index 00000000000..4c1acedb648
--- /dev/null
+++ b/extensions/git-base/package.nls.json
@@ -0,0 +1,4 @@
+{
+ "displayName": "Git Base",
+ "description": "Git static contributions and pickers."
+}
diff --git a/extensions/git/syntaxes/git-commit.tmLanguage.json b/extensions/git-base/syntaxes/git-commit.tmLanguage.json
similarity index 100%
rename from extensions/git/syntaxes/git-commit.tmLanguage.json
rename to extensions/git-base/syntaxes/git-commit.tmLanguage.json
diff --git a/extensions/git/syntaxes/git-rebase.tmLanguage.json b/extensions/git-base/syntaxes/git-rebase.tmLanguage.json
similarity index 100%
rename from extensions/git/syntaxes/git-rebase.tmLanguage.json
rename to extensions/git-base/syntaxes/git-rebase.tmLanguage.json
diff --git a/extensions/git/syntaxes/ignore.tmLanguage.json b/extensions/git-base/syntaxes/ignore.tmLanguage.json
similarity index 100%
rename from extensions/git/syntaxes/ignore.tmLanguage.json
rename to extensions/git-base/syntaxes/ignore.tmLanguage.json
diff --git a/extensions/git/.vscodeignore b/extensions/git/.vscodeignore
index 7462f7448d3..94d2dc921e0 100644
--- a/extensions/git/.vscodeignore
+++ b/extensions/git/.vscodeignore
@@ -4,5 +4,4 @@ out/**
tsconfig.json
build/**
extension.webpack.config.js
-cgmanifest.json
yarn.lock
diff --git a/extensions/git/package.json b/extensions/git/package.json
index b778540aa91..a26962bab09 100644
--- a/extensions/git/package.json
+++ b/extensions/git/package.json
@@ -9,7 +9,14 @@
"vscode": "^1.5.0"
},
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
- "enableProposedApi": true,
+ "enabledApiProposals": [
+ "diffCommand",
+ "contribViewsWelcome",
+ "scmActionButton",
+ "scmSelectedProvider",
+ "scmValidation",
+ "timeline"
+ ],
"categories": [
"Other"
],
@@ -23,7 +30,6 @@
"compile": "gulp compile-extension:git",
"watch": "gulp watch-extension:git",
"update-emoji": "node ./build/update-emoji.js",
- "update-grammar": "node ./build/update-grammars.js",
"test": "node ../../node_modules/mocha/bin/mocha"
},
"capabilities": {
@@ -75,7 +81,8 @@
"command": "git.openChange",
"title": "%command.openChange%",
"category": "Git",
- "icon": "$(compare-changes)"
+ "icon": "$(compare-changes)",
+ "enablement": "scmActiveResourceHasChanges"
},
{
"command": "git.openAllChanges",
@@ -2290,78 +2297,6 @@
}
}
],
- "languages": [
- {
- "id": "git-commit",
- "aliases": [
- "Git Commit Message",
- "git-commit"
- ],
- "filenames": [
- "COMMIT_EDITMSG",
- "MERGE_MSG"
- ],
- "configuration": "./languages/git-commit.language-configuration.json"
- },
- {
- "id": "git-rebase",
- "aliases": [
- "Git Rebase Message",
- "git-rebase"
- ],
- "filenames": [
- "git-rebase-todo"
- ],
- "configuration": "./languages/git-rebase.language-configuration.json"
- },
- {
- "id": "diff",
- "aliases": [
- "Diff",
- "diff"
- ],
- "extensions": [
- ".diff",
- ".patch",
- ".rej"
- ],
- "configuration": "./languages/diff.language-configuration.json"
- },
- {
- "id": "ignore",
- "aliases": [
- "Ignore",
- "ignore"
- ],
- "extensions": [
- ".gitignore_global",
- ".gitignore"
- ],
- "configuration": "./languages/ignore.language-configuration.json"
- }
- ],
- "grammars": [
- {
- "language": "git-commit",
- "scopeName": "text.git-commit",
- "path": "./syntaxes/git-commit.tmLanguage.json"
- },
- {
- "language": "git-rebase",
- "scopeName": "text.git-rebase",
- "path": "./syntaxes/git-rebase.tmLanguage.json"
- },
- {
- "language": "diff",
- "scopeName": "source.diff",
- "path": "./syntaxes/diff.tmLanguage.json"
- },
- {
- "language": "ignore",
- "scopeName": "source.ignore",
- "path": "./syntaxes/ignore.tmLanguage.json"
- }
- ],
"configurationDefaults": {
"[git-commit]": {
"editor.rulers": [
@@ -2431,7 +2366,7 @@
"dependencies": {
"byline": "^5.0.0",
"file-type": "^7.2.0",
- "iconv-lite-umd": "0.6.8",
+ "iconv-lite-umd": "0.6.10",
"jschardet": "3.0.0",
"vscode-extension-telemetry": "0.4.3",
"vscode-nls": "^4.0.0",
diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts
index 54f5dc55b57..8f6d5c60d88 100644
--- a/extensions/git/src/repository.ts
+++ b/extensions/git/src/repository.ts
@@ -1944,8 +1944,8 @@ export class Repository implements Disposable {
} else {
actionButton = {
command: 'git.publish',
- title: localize('scm button publish title', "$(cloud-upload) Publish Changes"),
- tooltip: localize('scm button publish tooltip', "Publish Changes"),
+ title: localize('scm button publish title', "$(cloud-upload) Publish Branch"),
+ tooltip: localize('scm button publish tooltip', "Publish Branch"),
arguments: [this._sourceControl],
};
}
diff --git a/extensions/git/src/statusbar.ts b/extensions/git/src/statusbar.ts
index fd556024f83..1de71ad94a0 100644
--- a/extensions/git/src/statusbar.ts
+++ b/extensions/git/src/statusbar.ts
@@ -154,7 +154,7 @@ class SyncStatusBar {
} else {
icon = '$(cloud-upload)';
command = 'git.publish';
- tooltip = localize('publish changes', "Publish Changes");
+ tooltip = localize('publish branch', "Publish Branch");
}
} else {
command = '';
diff --git a/extensions/git/src/timelineProvider.ts b/extensions/git/src/timelineProvider.ts
index e43a2a0b84f..f6e543257e2 100644
--- a/extensions/git/src/timelineProvider.ts
+++ b/extensions/git/src/timelineProvider.ts
@@ -166,8 +166,7 @@ export class GitTimelineProvider implements TimelineProvider {
if (showAuthor) {
item.description = c.authorName;
}
- // allow-any-unicode-next-line
- item.detail = `${c.authorName} (${c.authorEmail}) — ${c.hash.substr(0, 8)}\n${dateFormatter.format(date)}\n\n${message}`;
+ item.detail = `${c.authorName} (${c.authorEmail}) \u2014 ${c.hash.substr(0, 8)}\n${dateFormatter.format(date)}\n\n${message}`;
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
if (cmd) {
@@ -192,8 +191,7 @@ export class GitTimelineProvider implements TimelineProvider {
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
item.iconPath = new ThemeIcon('git-commit');
item.description = '';
- // allow-any-unicode-next-line
- item.detail = localize('git.timeline.detail', '{0} — {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format(date), Resource.getStatusText(index.type));
+ item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format(date), Resource.getStatusText(index.type));
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
if (cmd) {
@@ -215,8 +213,7 @@ export class GitTimelineProvider implements TimelineProvider {
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
item.iconPath = new ThemeIcon('git-commit');
item.description = '';
- // allow-any-unicode-next-line
- item.detail = localize('git.timeline.detail', '{0} — {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format(date), Resource.getStatusText(working.type));
+ item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format(date), Resource.getStatusText(working.type));
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
if (cmd) {
diff --git a/extensions/git/test/mocha.opts b/extensions/git/test/mocha.opts
deleted file mode 100644
index 93c2e8fffb6..00000000000
--- a/extensions/git/test/mocha.opts
+++ /dev/null
@@ -1 +0,0 @@
---ui tdd out/test
\ No newline at end of file
diff --git a/extensions/git/tsconfig.json b/extensions/git/tsconfig.json
index 7f8065b28e7..99129079e48 100644
--- a/extensions/git/tsconfig.json
+++ b/extensions/git/tsconfig.json
@@ -10,7 +10,11 @@
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts",
+ "../../src/vscode-dts/vscode.proposed.diffCommand.d.ts",
+ "../../src/vscode-dts/vscode.proposed.scmActionButton.d.ts",
+ "../../src/vscode-dts/vscode.proposed.scmSelectedProvider.d.ts",
+ "../../src/vscode-dts/vscode.proposed.scmValidation.d.ts",
+ "../../src/vscode-dts/vscode.proposed.timeline.d.ts",
"../types/lib.textEncoder.d.ts"
]
}
diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock
index 36a12fb119e..ff535a1ee3a 100644
--- a/extensions/git/yarn.lock
+++ b/extensions/git/yarn.lock
@@ -46,10 +46,10 @@ file-type@^7.2.0:
resolved "https://registry.yarnpkg.com/file-type/-/file-type-7.2.0.tgz#113cfed52e1d6959ab80248906e2f25a8cdccb74"
integrity sha1-ETz+1S4daVmrgCSJBuLyWozcy3Q=
-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==
+iconv-lite-umd@0.6.10:
+ version "0.6.10"
+ resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.10.tgz#faec47521e095b8e3a7175ae08e1b4ae0359a735"
+ integrity sha512-8NtgTa/m1jVq7vdywmD5+SqIlZsB59wtsjaylQuExyCojMq1tHVQxmHjeqVSYwKwnmQbH4mZ1Dxx1eqDkPgaqA==
isexe@^2.0.0:
version "2.0.0"
diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json
index 45c6a4b5175..2dbf469fd26 100644
--- a/extensions/github-authentication/package.json
+++ b/extensions/github-authentication/package.json
@@ -9,7 +9,6 @@
"vscode": "^1.41.0"
},
"icon": "images/icon.png",
- "enableProposedApi": true,
"categories": [
"Other"
],
diff --git a/extensions/github-authentication/tsconfig.json b/extensions/github-authentication/tsconfig.json
index 5001991c9a6..d7aed1836ee 100644
--- a/extensions/github-authentication/tsconfig.json
+++ b/extensions/github-authentication/tsconfig.json
@@ -9,7 +9,6 @@
},
"include": [
"src/**/*",
- "../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/github/package.json b/extensions/github/package.json
index f21080ab6f1..5e3e72a7b1c 100644
--- a/extensions/github/package.json
+++ b/extensions/github/package.json
@@ -9,7 +9,6 @@
"vscode": "^1.41.0"
},
"icon": "images/icon.png",
- "enableProposedApi": true,
"categories": [
"Other"
],
diff --git a/extensions/github/tsconfig.json b/extensions/github/tsconfig.json
index 5001991c9a6..d7aed1836ee 100644
--- a/extensions/github/tsconfig.json
+++ b/extensions/github/tsconfig.json
@@ -9,7 +9,6 @@
},
"include": [
"src/**/*",
- "../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/html-language-features/client/tsconfig.json b/extensions/html-language-features/client/tsconfig.json
index 959c5d37818..573b24b4aa6 100644
--- a/extensions/html-language-features/client/tsconfig.json
+++ b/extensions/html-language-features/client/tsconfig.json
@@ -5,7 +5,6 @@
},
"include": [
"src/**/*",
- "../../../src/vscode-dts/vscode.d.ts",
- "../../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/html-language-features/package.json b/extensions/html-language-features/package.json
index ddaf33bcb65..07bbfe29e9a 100644
--- a/extensions/html-language-features/package.json
+++ b/extensions/html-language-features/package.json
@@ -1,5 +1,4 @@
{
- "enableProposedApi": true,
"name": "html-language-features",
"displayName": "%displayName%",
"description": "%description%",
diff --git a/extensions/image-preview/package.json b/extensions/image-preview/package.json
index c9aa3d23a85..8b730de9790 100644
--- a/extensions/image-preview/package.json
+++ b/extensions/image-preview/package.json
@@ -9,7 +9,6 @@
"version": "1.0.0",
"publisher": "vscode",
"icon": "icon.png",
- "enableProposedApi": true,
"license": "MIT",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"engines": {
diff --git a/extensions/image-preview/tsconfig.json b/extensions/image-preview/tsconfig.json
index c9980a21e38..c5194e2e33c 100644
--- a/extensions/image-preview/tsconfig.json
+++ b/extensions/image-preview/tsconfig.json
@@ -6,7 +6,6 @@
},
"include": [
"src/**/*",
- "../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/ipynb/package.json b/extensions/ipynb/package.json
index cffba92357d..39c35edbb4f 100644
--- a/extensions/ipynb/package.json
+++ b/extensions/ipynb/package.json
@@ -8,7 +8,10 @@
"engines": {
"vscode": "^1.57.0"
},
- "enableProposedApi": true,
+ "enabledApiProposals": [
+ "notebookEditor",
+ "notebookEditorEdit"
+ ],
"activationEvents": [
"onNotebook:jupyter-notebook"
],
@@ -29,23 +32,23 @@
{
"id": "jupyter",
"aliases": [
- "Jupyter"
+ "Jupyter (JSON)"
],
"extensions": [
".ipynb"
]
}
],
- "grammars": [
- {
- "language": "jupyter",
- "scopeName": "source.jupyter",
- "path": "./syntaxes/jupyter.tmLanguage.json",
- "embeddedLanguages": {
- "source.json": "json"
- }
- }
- ],
+ "grammars": [
+ {
+ "language": "jupyter",
+ "scopeName": "source.jupyter",
+ "path": "./syntaxes/jupyter.tmLanguage.json",
+ "embeddedLanguages": {
+ "source.json": "json"
+ }
+ }
+ ],
"notebooks": [
{
"type": "jupyter-notebook",
@@ -59,10 +62,10 @@
}
]
},
- "scripts": {
- "compile": "npx gulp compile-extension:ipynb",
- "watch": "npx gulp watch-extension:ipynb"
- },
+ "scripts": {
+ "compile": "npx gulp compile-extension:ipynb",
+ "watch": "npx gulp watch-extension:ipynb"
+ },
"dependencies": {
"@enonic/fnv-plus": "^1.3.0",
"detect-indent": "^6.0.0",
@@ -72,8 +75,8 @@
"@jupyterlab/coreutils": "^3.1.0",
"@types/uuid": "^8.3.1"
},
- "repository": {
- "type": "git",
- "url": "https://github.com/microsoft/vscode.git"
- }
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/microsoft/vscode.git"
+ }
}
diff --git a/extensions/ipynb/tsconfig.json b/extensions/ipynb/tsconfig.json
index 760d355845b..2032bf87b0d 100644
--- a/extensions/ipynb/tsconfig.json
+++ b/extensions/ipynb/tsconfig.json
@@ -9,6 +9,7 @@
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.proposed.notebookEditor.d.ts",
+ "../../src/vscode-dts/vscode.proposed.notebookEditorEdit.d.ts",
]
}
diff --git a/extensions/json-language-features/client/src/browser/jsonClientMain.ts b/extensions/json-language-features/client/src/browser/jsonClientMain.ts
index 6389dafb5ba..9eb390b545c 100644
--- a/extensions/json-language-features/client/src/browser/jsonClientMain.ts
+++ b/extensions/json-language-features/client/src/browser/jsonClientMain.ts
@@ -5,9 +5,8 @@
import { ExtensionContext, Uri } from 'vscode';
import { LanguageClientOptions } from 'vscode-languageclient';
-import { startClient, LanguageClientConstructor } from '../jsonClient';
+import { startClient, LanguageClientConstructor, SchemaRequestService } from '../jsonClient';
import { LanguageClient } from 'vscode-languageclient/browser';
-import { RequestService } from '../requests';
declare const Worker: {
new(stringUrl: string): any;
@@ -24,7 +23,7 @@ export function activate(context: ExtensionContext) {
return new LanguageClient(id, name, clientOptions, worker);
};
- const http: RequestService = {
+ const schemaRequests: SchemaRequestService = {
getContent(uri: string) {
return fetch(uri, { mode: 'cors' })
.then(function (response: any) {
@@ -32,7 +31,8 @@ export function activate(context: ExtensionContext) {
});
}
};
- startClient(context, newLanguageClient, { http });
+
+ startClient(context, newLanguageClient, { schemaRequests });
} catch (e) {
console.log(e);
diff --git a/extensions/json-language-features/client/src/jsonClient.ts b/extensions/json-language-features/client/src/jsonClient.ts
index 8fb6dda91e1..11c8c615299 100644
--- a/extensions/json-language-features/client/src/jsonClient.ts
+++ b/extensions/json-language-features/client/src/jsonClient.ts
@@ -6,6 +6,8 @@ import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
+export type JSONLanguageStatus = { schemas: string[] };
+
import {
workspace, window, languages, commands, ExtensionContext, extensions, Uri,
Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken,
@@ -18,7 +20,7 @@ import {
} from 'vscode-languageclient';
import { hash } from './utils/hash';
-import { RequestService, joinPath } from './requests';
+import { createLanguageStatusItem } from './languageStatus';
namespace VSCodeContentRequest {
export const type: RequestType = new RequestType('vscode/content');
@@ -32,6 +34,11 @@ namespace ForceValidateRequest {
export const type: RequestType = new RequestType('json/validate');
}
+namespace LanguageStatusRequest {
+ export const type: RequestType = new RequestType('json/languageStatus');
+}
+
+
export interface ISchemaAssociations {
[pattern: string]: string[];
}
@@ -88,10 +95,16 @@ export interface TelemetryReporter {
export type LanguageClientConstructor = (name: string, description: string, clientOptions: LanguageClientOptions) => CommonLanguageClient;
export interface Runtime {
- http: RequestService;
+ schemaRequests: SchemaRequestService;
telemetry?: TelemetryReporter
}
+export interface SchemaRequestService {
+ getContent(uri: string): Promise;
+}
+
+export const languageServerDescription = localize('jsonserver.name', 'JSON Language Server');
+
export function startClient(context: ExtensionContext, newLanguageClient: LanguageClientConstructor, runtime: Runtime) {
const toDispose = context.subscriptions;
@@ -190,7 +203,7 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
};
// Create the language client and start the client.
- const client = newLanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), clientOptions);
+ const client = newLanguageClient('json', languageServerDescription, clientOptions);
client.registerProposedFeatures();
const disposable = client.start();
@@ -220,7 +233,7 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
*/
runtime.telemetry.sendTelemetryEvent('json.schema', { schemaURL: uriPath });
}
- return runtime.http.getContent(uriPath).catch(e => {
+ return runtime.schemaRequests.getContent(uriPath).catch(e => {
return Promise.reject(new ResponseError(4, e.toString()));
});
} else {
@@ -314,6 +327,8 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
}
});
+ toDispose.push(createLanguageStatusItem(documentSelector, (uri: string) => client.sendRequest(LanguageStatusRequest.type, uri)));
+
function updateFormatterRegistration() {
const formatEnabled = workspace.getConfiguration().get(SettingIds.enableFormatter);
if (!formatEnabled && rangeFormatting) {
@@ -376,7 +391,7 @@ function getSchemaAssociations(_context: ExtensionContext): ISchemaAssociation[]
if (Array.isArray(fileMatch) && typeof url === 'string') {
let uri: string = url;
if (uri[0] === '.' && uri[1] === '/') {
- uri = joinPath(extension.extensionUri, uri).toString();
+ uri = Uri.joinPath(extension.extensionUri, uri).toString();
}
fileMatch = fileMatch.map(fm => {
if (fm[0] === '%') {
@@ -497,7 +512,7 @@ function getSchemaId(schema: JSONSchemaSettings, folderUri?: Uri): string | unde
url = schema.schema.id || `vscode://schemas/custom/${encodeURIComponent(hash(schema.schema).toString(16))}`;
}
} else if (folderUri && (url[0] === '.' || url[0] === '/')) {
- url = joinPath(folderUri, url).toString();
+ url = Uri.joinPath(folderUri, url).toString();
}
return url;
}
diff --git a/extensions/json-language-features/client/src/languageStatus.ts b/extensions/json-language-features/client/src/languageStatus.ts
new file mode 100644
index 00000000000..63541be773d
--- /dev/null
+++ b/extensions/json-language-features/client/src/languageStatus.ts
@@ -0,0 +1,139 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { window, languages, Uri, LanguageStatusSeverity, Disposable, commands, QuickPickItem, extensions, workspace } from 'vscode';
+import { JSONLanguageStatus } from './jsonClient';
+
+import * as nls from 'vscode-nls';
+
+const localize = nls.loadMessageBundle();
+
+type ShowSchemasInput = {
+ schemas: string[];
+ uri: string;
+};
+
+interface ShowSchemasItem extends QuickPickItem {
+ uri: Uri;
+}
+
+function equalsIgnoreCase(a: string, b: string): boolean {
+ return a.length === b.length && a.toLowerCase().localeCompare(b.toLowerCase()) === 0;
+}
+
+function isEqualAuthority(a1: string | undefined, a2: string | undefined) {
+ return a1 === a2 || (a1 !== undefined && a2 !== undefined && equalsIgnoreCase(a1, a2));
+}
+
+function findExtension(uri: Uri) {
+ for (const ext of extensions.all) {
+ const parent = ext.extensionUri;
+ if (uri.scheme === parent.scheme && isEqualAuthority(uri.authority, parent.authority) && uri.path.startsWith(parent.path + '/')) {
+ return ext;
+ }
+ }
+ return undefined;
+}
+
+function findWorkspaceFolder(uri: Uri) {
+ if (workspace.workspaceFolders) {
+ for (const wf of workspace.workspaceFolders) {
+ const parent = wf.uri;
+ if (uri.scheme === parent.scheme && isEqualAuthority(uri.authority, parent.authority) && uri.path.startsWith(parent.path + '/')) {
+ return wf;
+ }
+ }
+ }
+ return undefined;
+}
+
+function renderShowSchemasItem(schema: string): ShowSchemasItem {
+ const uri = Uri.parse(schema);
+ const extension = findExtension(uri);
+ if (extension) {
+ return { label: extension.id, description: uri.path.substring(extension.extensionUri.path.length + 1), uri };
+ }
+ const wf = findWorkspaceFolder(uri);
+ if (wf) {
+ return { label: uri.path.substring(wf.uri.path.length + 1), description: 'Workspace', uri };
+ }
+ if (uri.scheme === 'file') {
+ return { label: uri.fsPath, uri };
+ } else if (uri.scheme === 'vscode') {
+ return { label: schema, description: 'internally generated', uri };
+ }
+ return { label: schema, uri };
+}
+
+
+export function createLanguageStatusItem(documentSelector: string[], statusRequest: (uri: string) => Promise): Disposable {
+ const statusItem = languages.createLanguageStatusItem('json.projectStatus', documentSelector);
+ statusItem.name = localize('statusItem.name', "JSON Validation Status");
+ statusItem.severity = LanguageStatusSeverity.Information;
+
+ const showSchemasCommand = commands.registerCommand('_json.showAssociatedSchemaList', (arg: ShowSchemasInput) => {
+ const items: ShowSchemasItem[] = arg.schemas.sort().map(renderShowSchemasItem);
+ const quickPick = window.createQuickPick();
+ quickPick.title = localize('schemaPicker.title', 'JSON Schemas used for {0}', arg.uri.toString());
+ quickPick.placeholder = localize('schemaPicker.placeholder', 'Select the schema to open');
+ quickPick.items = items;
+ quickPick.show();
+ quickPick.onDidAccept(() => {
+ commands.executeCommand('vscode.open', quickPick.selectedItems[0].uri);
+ quickPick.dispose();
+ });
+ });
+
+ const activeEditorListener = window.onDidChangeActiveTextEditor(() => {
+ updateLanguageStatus();
+ });
+
+ async function updateLanguageStatus() {
+ const document = window.activeTextEditor?.document;
+ if (document && documentSelector.indexOf(document.languageId) !== -1) {
+ try {
+ statusItem.text = '$(loading~spin)';
+ statusItem.detail = localize('pending.detail', 'Loading JSON info');
+ statusItem.command = undefined;
+
+ const schemas = (await statusRequest(document.uri.toString())).schemas;
+ statusItem.detail = undefined;
+ if (schemas.length === 0) {
+ statusItem.text = localize('status.noSchema', 'Validated without JSON schema');
+ } else if (schemas.length === 1) {
+ const item = renderShowSchemasItem(schemas[0]);
+ statusItem.text = localize('status.singleSchema', 'Validated with JSON schema');
+ statusItem.command = {
+ command: 'vscode.open',
+ title: localize('status.openSchemaLink', 'Open Schema'),
+ tooltip: item.description ? `${item.label} - ${item.description}` : item.label,
+ arguments: [item.uri]
+ };
+ } else {
+ statusItem.text = localize('status.multipleSchema', 'Validated with multiple JSON schemas');
+ statusItem.command = {
+ command: '_json.showAssociatedSchemaList',
+ title: localize('status.openSchemasLink', 'Show Schemas'),
+ arguments: [{ schemas, uri: document.uri.toString() } as ShowSchemasInput]
+ };
+ }
+ } catch (e) {
+ statusItem.text = localize('status.error', 'Unable to compute used schemas');
+ statusItem.detail = undefined;
+ statusItem.command = undefined;
+ console.log(e);
+ }
+ } else {
+ statusItem.text = localize('status.notJSON', 'Not a JSON editor');
+ statusItem.detail = undefined;
+ statusItem.command = undefined;
+ }
+ }
+
+ updateLanguageStatus();
+
+ return Disposable.from(statusItem, activeEditorListener, showSchemasCommand);
+}
+
diff --git a/extensions/json-language-features/client/src/node/jsonClientMain.ts b/extensions/json-language-features/client/src/node/jsonClientMain.ts
index b8f96f51753..186e7c8f7bf 100644
--- a/extensions/json-language-features/client/src/node/jsonClientMain.ts
+++ b/extensions/json-language-features/client/src/node/jsonClientMain.ts
@@ -3,24 +3,26 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { ExtensionContext } from 'vscode';
-import { startClient, LanguageClientConstructor } from '../jsonClient';
+import { ExtensionContext, OutputChannel, window, workspace } from 'vscode';
+import { startClient, LanguageClientConstructor, SchemaRequestService, languageServerDescription } from '../jsonClient';
import { ServerOptions, TransportKind, LanguageClientOptions, LanguageClient } from 'vscode-languageclient/node';
-import * as fs from 'fs';
-import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light';
+import { promises as fs } from 'fs';
+import * as path from 'path';
+import { xhr, XHRResponse, getErrorStatusDescription, Headers } from 'request-light';
import TelemetryReporter from 'vscode-extension-telemetry';
-import { RequestService } from '../requests';
+import { JSONSchemaCache } from './schemaCache';
let telemetry: TelemetryReporter | undefined;
// this method is called when vs code is activated
-export function activate(context: ExtensionContext) {
-
- const clientPackageJSON = getPackageInfo(context);
+export async function activate(context: ExtensionContext) {
+ const clientPackageJSON = await getPackageInfo(context);
telemetry = new TelemetryReporter(clientPackageJSON.name, clientPackageJSON.version, clientPackageJSON.aiKey);
+ const outputChannel = window.createOutputChannel(languageServerDescription);
+
const serverMain = `./server/${clientPackageJSON.main.indexOf('/dist/') !== -1 ? 'dist' : 'out'}/node/jsonServerMain`;
const serverModule = context.asAbsolutePath(serverMain);
@@ -35,10 +37,15 @@ export function activate(context: ExtensionContext) {
};
const newLanguageClient: LanguageClientConstructor = (id: string, name: string, clientOptions: LanguageClientOptions) => {
+ clientOptions.outputChannel = outputChannel;
return new LanguageClient(id, name, serverOptions, clientOptions);
};
+ const log = getLog(outputChannel);
+ context.subscriptions.push(log);
- startClient(context, newLanguageClient, { http: getHTTPRequestService(), telemetry });
+ const schemaRequests = await getSchemaRequestService(context, log);
+
+ startClient(context, newLanguageClient, { schemaRequests, telemetry });
}
export function deactivate(): Promise {
@@ -52,23 +59,88 @@ interface IPackageInfo {
main: string;
}
-function getPackageInfo(context: ExtensionContext): IPackageInfo {
+async function getPackageInfo(context: ExtensionContext): Promise {
const location = context.asAbsolutePath('./package.json');
try {
- return JSON.parse(fs.readFileSync(location).toString());
+ return JSON.parse((await fs.readFile(location)).toString());
} catch (e) {
console.log(`Problems reading ${location}: ${e}`);
return { name: '', version: '', aiKey: '', main: '' };
}
}
-function getHTTPRequestService(): RequestService {
+interface Log {
+ trace(message: string): void;
+ dispose(): void;
+}
+
+const traceSetting = 'json.trace.server';
+function getLog(outputChannel: OutputChannel): Log {
+ let trace = workspace.getConfiguration().get(traceSetting) === 'verbose';
+ const configListener = workspace.onDidChangeConfiguration(e => {
+ if (e.affectsConfiguration(traceSetting)) {
+ trace = workspace.getConfiguration().get(traceSetting) === 'verbose';
+ }
+ });
return {
- getContent(uri: string, _encoding?: string): Promise {
- const headers = { 'Accept-Encoding': 'gzip, deflate' };
- return xhr({ url: uri, followRedirects: 5, headers }).then(response => {
- return response.responseText;
- }, (error: XHRResponse) => {
+ trace(message: string) {
+ if (trace) {
+ outputChannel.appendLine(message);
+ }
+ },
+ dispose: () => configListener.dispose()
+ };
+}
+
+const retryTimeoutInDays = 2; // 2 days
+const retryTimeoutInMs = retryTimeoutInDays * 24 * 60 * 60 * 1000;
+
+async function getSchemaRequestService(context: ExtensionContext, log: Log): Promise {
+ let cache: JSONSchemaCache | undefined = undefined;
+ const globalStorage = context.globalStorageUri;
+ if (globalStorage.scheme === 'file') {
+ const schemaCacheLocation = path.join(globalStorage.fsPath, 'json-schema-cache');
+ await fs.mkdir(schemaCacheLocation, { recursive: true });
+
+ cache = new JSONSchemaCache(schemaCacheLocation, context.globalState);
+ log.trace(`[json schema cache] initial state: ${JSON.stringify(cache.getCacheInfo(), null, ' ')}`);
+ }
+
+ const isXHRResponse = (error: any): error is XHRResponse => typeof error?.status === 'number';
+
+ const request = async (uri: string, etag?: string): Promise => {
+ const headers: Headers = { 'Accept-Encoding': 'gzip, deflate' };
+ if (etag) {
+ headers['If-None-Match'] = etag;
+ }
+ try {
+ log.trace(`[json schema cache] Requesting schema ${uri} etag ${etag}...`);
+
+ const response = await xhr({ url: uri, followRedirects: 5, headers });
+ if (cache) {
+ const etag = response.headers['etag'];
+ if (typeof etag === 'string') {
+ log.trace(`[json schema cache] Storing schema ${uri} etag ${etag} in cache`);
+ await cache.putSchema(uri, etag, response.responseText);
+ } else {
+ log.trace(`[json schema cache] Response: schema ${uri} no etag`);
+ }
+ }
+ return response.responseText;
+ } catch (error: unknown) {
+ if (isXHRResponse(error)) {
+ if (error.status === 304 && etag && cache) {
+
+ log.trace(`[json schema cache] Response: schema ${uri} unchanged etag ${etag}`);
+
+ const content = await cache.getSchema(uri, etag);
+ if (content) {
+ log.trace(`[json schema cache] Get schema ${uri} etag ${etag} from cache`);
+ return content;
+ }
+ return request(uri);
+ }
+
let status = getErrorStatusDescription(error.status);
if (status && error.responseText) {
status = `${status}\n${error.responseText.substring(0, 200)}`;
@@ -76,8 +148,24 @@ function getHTTPRequestService(): RequestService {
if (!status) {
status = error.toString();
}
- return Promise.reject(status);
- });
+ log.trace(`[json schema cache] Respond schema ${uri} error ${status}`);
+
+ throw status;
+ }
+ throw error;
+ }
+ };
+
+ return {
+ getContent: async (uri: string) => {
+ if (cache && /^https?:\/\/json\.schemastore\.org\//.test(uri)) {
+ const content = await cache.getSchemaIfAccessedSince(uri, retryTimeoutInMs);
+ if (content) {
+ log.trace(`[json schema cache] Schema ${uri} from cache without request (last accessed less than ${retryTimeoutInDays} days ago)`);
+ return content;
+ }
+ }
+ return request(uri, cache?.getETag(uri));
}
};
}
diff --git a/extensions/json-language-features/client/src/node/schemaCache.ts b/extensions/json-language-features/client/src/node/schemaCache.ts
new file mode 100644
index 00000000000..4661c5c7a12
--- /dev/null
+++ b/extensions/json-language-features/client/src/node/schemaCache.ts
@@ -0,0 +1,108 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { promises as fs } from 'fs';
+import * as path from 'path';
+import { createHash } from 'crypto';
+import { Memento } from 'vscode';
+
+interface CacheEntry {
+ etag: string;
+ fileName: string;
+ accessTime: number;
+}
+
+interface CacheInfo {
+ [schemaUri: string]: CacheEntry;
+}
+
+const MEMENTO_KEY = 'json-schema-cache';
+
+export class JSONSchemaCache {
+ private readonly cacheInfo: CacheInfo;
+
+ constructor(private readonly schemaCacheLocation: string, private readonly globalState: Memento) {
+ this.cacheInfo = globalState.get(MEMENTO_KEY, {});
+ }
+
+ getETag(schemaUri: string): string | undefined {
+ return this.cacheInfo[schemaUri]?.etag;
+ }
+
+ async putSchema(schemaUri: string, etag: string, schemaContent: string): Promise {
+ try {
+ const fileName = getCacheFileName(schemaUri);
+ await fs.writeFile(path.join(this.schemaCacheLocation, fileName), schemaContent);
+ const entry: CacheEntry = { etag, fileName, accessTime: new Date().getTime() };
+ this.cacheInfo[schemaUri] = entry;
+ } catch (e) {
+ delete this.cacheInfo[schemaUri];
+ } finally {
+ await this.updateMemento();
+ }
+ }
+
+ async getSchemaIfAccessedSince(schemaUri: string, expirationDuration: number): Promise {
+ const cacheEntry = this.cacheInfo[schemaUri];
+ if (cacheEntry && cacheEntry.accessTime + expirationDuration >= new Date().getTime()) {
+ return this.loadSchemaFile(schemaUri, cacheEntry);
+ }
+ return undefined;
+ }
+
+ async getSchema(schemaUri: string, etag: string): Promise {
+ const cacheEntry = this.cacheInfo[schemaUri];
+ if (cacheEntry) {
+ if (cacheEntry.etag === etag) {
+ return this.loadSchemaFile(schemaUri, cacheEntry);
+ } else {
+ this.deleteSchemaFile(schemaUri, cacheEntry);
+ }
+ }
+ return undefined;
+ }
+
+ private async loadSchemaFile(schemaUri: string, cacheEntry: CacheEntry): Promise {
+ const cacheLocation = path.join(this.schemaCacheLocation, cacheEntry.fileName);
+ try {
+ const content = (await fs.readFile(cacheLocation)).toString();
+ cacheEntry.accessTime = new Date().getTime();
+ return content;
+ } catch (e) {
+ delete this.cacheInfo[schemaUri];
+ return undefined;
+ } finally {
+ await this.updateMemento();
+ }
+ }
+
+ private async deleteSchemaFile(schemaUri: string, cacheEntry: CacheEntry): Promise {
+ const cacheLocation = path.join(this.schemaCacheLocation, cacheEntry.fileName);
+ delete this.cacheInfo[schemaUri];
+ await this.updateMemento();
+ try {
+ await fs.rm(cacheLocation);
+ } catch (e) {
+ // ignore
+ }
+ }
+
+
+ // for debugging
+ public getCacheInfo() {
+ return this.cacheInfo;
+ }
+
+ private async updateMemento() {
+ try {
+ await this.globalState.update(MEMENTO_KEY, this.cacheInfo);
+ } catch (e) {
+ // ignore
+ }
+ }
+}
+function getCacheFileName(uri: string): string {
+ return `${createHash('MD5').update(uri).digest('hex')}.schema.json`;
+}
diff --git a/extensions/json-language-features/client/src/requests.ts b/extensions/json-language-features/client/src/requests.ts
deleted file mode 100644
index ed06ded574f..00000000000
--- a/extensions/json-language-features/client/src/requests.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
-import { Uri } from 'vscode';
-
-export interface RequestService {
- getContent(uri: string, encoding?: string): Promise;
-}
-
-export function getScheme(uri: string) {
- return uri.substr(0, uri.indexOf(':'));
-}
-
-export function dirname(uri: string) {
- const lastIndexOfSlash = uri.lastIndexOf('/');
- return lastIndexOfSlash !== -1 ? uri.substr(0, lastIndexOfSlash) : '';
-}
-
-export function basename(uri: string) {
- const lastIndexOfSlash = uri.lastIndexOf('/');
- return uri.substr(lastIndexOfSlash + 1);
-}
-
-const Slash = '/'.charCodeAt(0);
-const Dot = '.'.charCodeAt(0);
-
-export function isAbsolutePath(path: string) {
- return path.charCodeAt(0) === Slash;
-}
-
-export function resolvePath(uri: Uri, path: string): Uri {
- if (isAbsolutePath(path)) {
- return uri.with({ path: normalizePath(path.split('/')) });
- }
- return joinPath(uri, path);
-}
-
-export function normalizePath(parts: string[]): string {
- const newParts: string[] = [];
- for (const part of parts) {
- if (part.length === 0 || part.length === 1 && part.charCodeAt(0) === Dot) {
- // ignore
- } else if (part.length === 2 && part.charCodeAt(0) === Dot && part.charCodeAt(1) === Dot) {
- newParts.pop();
- } else {
- newParts.push(part);
- }
- }
- if (parts.length > 1 && parts[parts.length - 1].length === 0) {
- newParts.push('');
- }
- let res = newParts.join('/');
- if (parts[0].length === 0) {
- res = '/' + res;
- }
- return res;
-}
-
-
-export function joinPath(uri: Uri, ...paths: string[]): Uri {
- const parts = uri.path.split('/');
- for (let path of paths) {
- parts.push(...path.split('/'));
- }
- return uri.with({ path: normalizePath(parts) });
-}
diff --git a/extensions/json-language-features/client/tsconfig.json b/extensions/json-language-features/client/tsconfig.json
index 959c5d37818..4254a37490e 100644
--- a/extensions/json-language-features/client/tsconfig.json
+++ b/extensions/json-language-features/client/tsconfig.json
@@ -6,6 +6,6 @@
"include": [
"src/**/*",
"../../../src/vscode-dts/vscode.d.ts",
- "../../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../../src/vscode-dts/vscode.proposed.languageStatus.d.ts",
]
}
diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json
index 91dcbb8d554..984d0d2e76a 100644
--- a/extensions/json-language-features/package.json
+++ b/extensions/json-language-features/package.json
@@ -16,13 +16,15 @@
],
"main": "./client/out/node/jsonClientMain",
"browser": "./client/dist/browser/jsonClientMain",
- "enableProposedApi": true,
"capabilities": {
"virtualWorkspaces": true,
"untrustedWorkspaces": {
"supported": true
}
},
+ "enabledApiProposals": [
+ "languageStatus"
+ ],
"scripts": {
"compile": "npx gulp compile-extension:json-language-features-client compile-extension:json-language-features-server",
"watch": "npx gulp watch-extension:json-language-features-client watch-extension:json-language-features-server",
diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json
index cfbbe5e5abb..90ec7eb10d3 100644
--- a/extensions/json-language-features/server/package.json
+++ b/extensions/json-language-features/server/package.json
@@ -14,7 +14,7 @@
"dependencies": {
"jsonc-parser": "^3.0.0",
"request-light": "^0.5.4",
- "vscode-json-languageservice": "^4.1.9",
+ "vscode-json-languageservice": "^4.2.0-next.1",
"vscode-languageserver": "^7.0.0",
"vscode-uri": "^3.0.2"
},
diff --git a/extensions/json-language-features/server/src/jsonServer.ts b/extensions/json-language-features/server/src/jsonServer.ts
index 2fcaa0a82e6..142594e0c3c 100644
--- a/extensions/json-language-features/server/src/jsonServer.ts
+++ b/extensions/json-language-features/server/src/jsonServer.ts
@@ -12,10 +12,12 @@ import {
import { formatError, runSafe, runSafeAsync } from './utils/runner';
import { TextDocument, JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration, ClientCapabilities, Diagnostic, Range, Position } from 'vscode-json-languageservice';
import { getLanguageModelCache } from './languageModelCache';
-import { RequestService, basename, resolvePath } from './requests';
+import { Utils, URI } from 'vscode-uri';
type ISchemaAssociations = Record;
+type JSONLanguageStatus = { schemas: string[] };
+
namespace SchemaAssociationNotification {
export const type: NotificationType = new NotificationType('json/schemaAssociations');
}
@@ -36,14 +38,22 @@ namespace ForceValidateRequest {
export const type: RequestType = new RequestType('json/validate');
}
+namespace LanguageStatusRequest {
+ export const type: RequestType = new RequestType('json/languageStatus');
+}
+
const workspaceContext = {
resolveRelativePath: (relativePath: string, resource: string) => {
- const base = resource.substr(0, resource.lastIndexOf('/') + 1);
- return resolvePath(base, relativePath);
+ const base = resource.substring(0, resource.lastIndexOf('/') + 1);
+ return Utils.resolvePath(URI.parse(base), relativePath).toString();
}
};
+export interface RequestService {
+ getContent(uri: string): Promise;
+}
+
export interface RuntimeEnvironment {
file?: RequestService;
http?: RequestService
@@ -179,7 +189,7 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment)
const showLimitedNotification = (uri: string, resultLimit: number) => {
const warning = pendingWarnings[uri];
- connection.sendNotification(ResultLimitReachedNotification.type, `${basename(uri)}: For performance reasons, ${Object.keys(warning.features).join(' and ')} have been limited to ${resultLimit} items.`);
+ connection.sendNotification(ResultLimitReachedNotification.type, `${Utils.basename(URI.parse(uri))}: For performance reasons, ${Object.keys(warning.features).join(' and ')} have been limited to ${resultLimit} items.`);
warning.timeout = undefined;
};
@@ -255,7 +265,11 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment)
// A schema has changed
connection.onNotification(SchemaContentChangeNotification.type, uri => {
- languageService.resetSchema(uri);
+ if (languageService.resetSchema(uri)) {
+ for (const doc of documents.all()) {
+ triggerValidation(doc);
+ }
+ }
});
// Retry schema validation on all open documents
@@ -273,6 +287,16 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment)
});
});
+ connection.onRequest(LanguageStatusRequest.type, async uri => {
+ const document = documents.get(uri);
+ if (document) {
+ const jsonDocument = getJSONDocument(document);
+ return languageService.getLanguageStatus(document, jsonDocument);
+ } else {
+ return { schemas: [] };
+ }
+ });
+
function updateConfiguration() {
const languageSettings = {
validate: true,
diff --git a/extensions/json-language-features/server/src/node/jsonServerMain.ts b/extensions/json-language-features/server/src/node/jsonServerMain.ts
index 17e0fcd9940..4cb387095aa 100644
--- a/extensions/json-language-features/server/src/node/jsonServerMain.ts
+++ b/extensions/json-language-features/server/src/node/jsonServerMain.ts
@@ -5,8 +5,7 @@
import { createConnection, Connection, Disposable } from 'vscode-languageserver/node';
import { formatError } from '../utils/runner';
-import { RuntimeEnvironment, startServer } from '../jsonServer';
-import { RequestService } from '../requests';
+import { RequestService, RuntimeEnvironment, startServer } from '../jsonServer';
import { xhr, XHRResponse, configure as configureHttpRequests, getErrorStatusDescription } from 'request-light';
import { URI as Uri } from 'vscode-uri';
diff --git a/extensions/json-language-features/server/src/requests.ts b/extensions/json-language-features/server/src/requests.ts
deleted file mode 100644
index a87cf92483f..00000000000
--- a/extensions/json-language-features/server/src/requests.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
-import { URI } from 'vscode-uri';
-
-export interface RequestService {
- getContent(uri: string, encoding?: string): Promise;
-}
-
-export function getScheme(uri: string) {
- return uri.substr(0, uri.indexOf(':'));
-}
-
-export function dirname(uri: string) {
- const lastIndexOfSlash = uri.lastIndexOf('/');
- return lastIndexOfSlash !== -1 ? uri.substr(0, lastIndexOfSlash) : '';
-}
-
-export function basename(uri: string) {
- const lastIndexOfSlash = uri.lastIndexOf('/');
- return uri.substr(lastIndexOfSlash + 1);
-}
-
-
-const Slash = '/'.charCodeAt(0);
-const Dot = '.'.charCodeAt(0);
-
-export function extname(uri: string) {
- for (let i = uri.length - 1; i >= 0; i--) {
- const ch = uri.charCodeAt(i);
- if (ch === Dot) {
- if (i > 0 && uri.charCodeAt(i - 1) !== Slash) {
- return uri.substr(i);
- } else {
- break;
- }
- } else if (ch === Slash) {
- break;
- }
- }
- return '';
-}
-
-export function isAbsolutePath(path: string) {
- return path.charCodeAt(0) === Slash;
-}
-
-export function resolvePath(uriString: string, path: string): string {
- if (isAbsolutePath(path)) {
- const uri = URI.parse(uriString);
- const parts = path.split('/');
- return uri.with({ path: normalizePath(parts) }).toString();
- }
- return joinPath(uriString, path);
-}
-
-export function normalizePath(parts: string[]): string {
- const newParts: string[] = [];
- for (const part of parts) {
- if (part.length === 0 || part.length === 1 && part.charCodeAt(0) === Dot) {
- // ignore
- } else if (part.length === 2 && part.charCodeAt(0) === Dot && part.charCodeAt(1) === Dot) {
- newParts.pop();
- } else {
- newParts.push(part);
- }
- }
- if (parts.length > 1 && parts[parts.length - 1].length === 0) {
- newParts.push('');
- }
- let res = newParts.join('/');
- if (parts[0].length === 0) {
- res = '/' + res;
- }
- return res;
-}
-
-export function joinPath(uriString: string, ...paths: string[]): string {
- const uri = URI.parse(uriString);
- const parts = uri.path.split('/');
- for (let path of paths) {
- parts.push(...path.split('/'));
- }
- return uri.with({ path: normalizePath(parts) }).toString();
-}
diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock
index 06fd41ef116..9b542a82f9c 100644
--- a/extensions/json-language-features/server/yarn.lock
+++ b/extensions/json-language-features/server/yarn.lock
@@ -22,10 +22,10 @@ request-light@^0.5.4:
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.5.4.tgz#497a98c6d8ae49536417a5e2d7f383b934f3e38c"
integrity sha512-t3566CMweOFlUk7Y1DJMu5OrtpoZEb6aSTsLQVT3wtrIEJ5NhcY9G/Oqxvjllzl4a15zXfFlcr9q40LbLVQJqw==
-vscode-json-languageservice@^4.1.9:
- version "4.1.9"
- resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.1.9.tgz#fb48edc69e37167c3cafd447c3fa898052d87b61"
- integrity sha512-kxNHitUy2fCxmP6vAp0SRLrUSuecUYzzxlC+85cC3jJlFHWmvtCJOzikC+kcUnIdls9fQSB8n0yHs8Sl6taxJw==
+vscode-json-languageservice@^4.2.0-next.1:
+ version "4.2.0-next.1"
+ resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.2.0-next.1.tgz#31a8c3be04c87d5aa593c11b98d84258b173a22f"
+ integrity sha512-aQvkkuZpeSPv86QLzyMdKTCgvXR+qSO39nSgj/XGaOcuHmTt7vMZB7ymYGGkQ4cAaQdHs/2G6a479LQybIGSbg==
dependencies:
jsonc-parser "^3.0.0"
vscode-languageserver-textdocument "^1.0.1"
diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json
index ba2157fde37..3734ba11aaf 100644
--- a/extensions/markdown-language-features/package.json
+++ b/extensions/markdown-language-features/package.json
@@ -5,7 +5,6 @@
"version": "1.0.0",
"icon": "icon.png",
"publisher": "vscode",
- "enableProposedApi": true,
"license": "MIT",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"engines": {
diff --git a/extensions/markdown-language-features/src/test/documentLink.test.ts b/extensions/markdown-language-features/src/test/documentLink.test.ts
index 8919f6a1ecf..7c280a82bdf 100644
--- a/extensions/markdown-language-features/src/test/documentLink.test.ts
+++ b/extensions/markdown-language-features/src/test/documentLink.test.ts
@@ -10,18 +10,26 @@ import { joinLines } from './util';
const testFileA = workspaceFile('a.md');
+const debug = false;
+
+function debugLog(...args: any[]) {
+ if (debug) {
+ console.log(...args);
+ }
+}
+
function workspaceFile(...segments: string[]) {
return vscode.Uri.joinPath(vscode.workspace.workspaceFolders![0].uri, ...segments);
}
async function getLinksForFile(file: vscode.Uri): Promise {
- console.log('getting links', file.toString(), Date.now());
+ debugLog('getting links', file.toString(), Date.now());
const r = (await vscode.commands.executeCommand('vscode.executeLinkProvider', file))!;
- console.log('got links', file.toString(), Date.now());
+ debugLog('got links', file.toString(), Date.now());
return r;
}
-suite('Markdown Document links', () => {
+(vscode.env.uiKind === vscode.UIKind.Web ? suite.skip : suite)('Markdown Document links', () => {
setup(async () => {
// the tests make the assumption that link providers are already registered
@@ -149,21 +157,21 @@ function assertActiveDocumentUri(expectedUri: vscode.Uri) {
}
async function withFileContents(file: vscode.Uri, contents: string): Promise {
- console.log('openTextDocument', file.toString(), Date.now());
+ debugLog('openTextDocument', file.toString(), Date.now());
const document = await vscode.workspace.openTextDocument(file);
- console.log('showTextDocument', file.toString(), Date.now());
+ debugLog('showTextDocument', file.toString(), Date.now());
const editor = await vscode.window.showTextDocument(document);
- console.log('editTextDocument', file.toString(), Date.now());
+ debugLog('editTextDocument', file.toString(), Date.now());
await editor.edit(edit => {
edit.replace(new vscode.Range(0, 0, 1000, 0), contents);
});
- console.log('opened done', vscode.window.activeTextEditor?.document.toString(), Date.now());
+ debugLog('opened done', vscode.window.activeTextEditor?.document.toString(), Date.now());
}
async function executeLink(link: vscode.DocumentLink) {
- console.log('executeingLink', link.target?.toString(), Date.now());
+ debugLog('executeingLink', link.target?.toString(), Date.now());
const args = JSON.parse(decodeURIComponent(link.target!.query));
await vscode.commands.executeCommand(link.target!.path, args);
- console.log('executedLink', vscode.window.activeTextEditor?.document.toString(), Date.now());
+ debugLog('executedLink', vscode.window.activeTextEditor?.document.toString(), Date.now());
}
diff --git a/extensions/markdown-language-features/tsconfig.json b/extensions/markdown-language-features/tsconfig.json
index ecbf24dde1e..fcd79775de5 100644
--- a/extensions/markdown-language-features/tsconfig.json
+++ b/extensions/markdown-language-features/tsconfig.json
@@ -5,7 +5,6 @@
},
"include": [
"src/**/*",
- "../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json
index ef97ae07a9b..33e5eb749fc 100644
--- a/extensions/microsoft-authentication/package.json
+++ b/extensions/microsoft-authentication/package.json
@@ -12,7 +12,6 @@
"categories": [
"Other"
],
- "enableProposedApi": true,
"activationEvents": [
"onAuthenticationRequest:microsoft"
],
diff --git a/extensions/microsoft-authentication/tsconfig.json b/extensions/microsoft-authentication/tsconfig.json
index c340ac241e9..51edc522bc6 100644
--- a/extensions/microsoft-authentication/tsconfig.json
+++ b/extensions/microsoft-authentication/tsconfig.json
@@ -18,7 +18,6 @@
],
"include": [
"src/**/*",
- "../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/npm/package.json b/extensions/npm/package.json
index 3e85fc13ae1..e3baafd8bfe 100644
--- a/extensions/npm/package.json
+++ b/extensions/npm/package.json
@@ -8,7 +8,6 @@
"engines": {
"vscode": "0.10.x"
},
- "enableProposedApi": true,
"icon": "images/npm_icon.png",
"categories": [
"Other"
@@ -73,7 +72,8 @@
"name": "%view.name%",
"when": "npm:showScriptExplorer",
"icon": "$(json)",
- "visibility": "hidden"
+ "visibility": "hidden",
+ "contextualTitle": "%view.name%"
}
]
},
@@ -281,6 +281,15 @@
"scope": "window",
"default": "open"
},
+ "npm.scriptExplorerExclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "markdownDescription": "%config.npm.scriptExplorerExclude%",
+ "scope": "resource",
+ "default": []
+ },
"npm.fetchOnlinePackageInfo": {
"type": "boolean",
"description": "%config.npm.fetchOnlinePackageInfo%",
diff --git a/extensions/npm/package.nls.json b/extensions/npm/package.nls.json
index b3ff9a4d229..b0a4f06c01f 100644
--- a/extensions/npm/package.nls.json
+++ b/extensions/npm/package.nls.json
@@ -12,6 +12,7 @@
"config.npm.exclude": "Configure glob patterns for folders that should be excluded from automatic script detection.",
"config.npm.enableScriptExplorer": "Enable an explorer view for npm scripts when there is no top-level 'package.json' file.",
"config.npm.scriptExplorerAction": "The default click action used in the npm scripts explorer: `open` or `run`, the default is `open`.",
+ "config.npm.scriptExplorerExclude": "An array of regular expressions that indicate which scripts should be excluded from the NPM Scripts view.",
"config.npm.enableRunFromFolder": "Enable running npm scripts contained in a folder from the Explorer context menu.",
"config.npm.fetchOnlinePackageInfo": "Fetch data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies.",
"npm.parseError": "Npm task detection: failed to parse the file {0}",
diff --git a/extensions/npm/src/npmMain.ts b/extensions/npm/src/npmMain.ts
index 6969b7d63a6..3788c94ea45 100644
--- a/extensions/npm/src/npmMain.ts
+++ b/extensions/npm/src/npmMain.ts
@@ -38,7 +38,7 @@ export async function activate(context: vscode.ExtensionContext): Promise
treeDataProvider = registerExplorer(context);
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e) => {
- if (e.affectsConfiguration('npm.exclude') || e.affectsConfiguration('npm.autoDetect')) {
+ if (e.affectsConfiguration('npm.exclude') || e.affectsConfiguration('npm.autoDetect') || e.affectsConfiguration('npm.scriptExplorerExclude')) {
invalidateTasksCache();
if (treeDataProvider) {
treeDataProvider.refresh();
diff --git a/extensions/npm/src/npmView.ts b/extensions/npm/src/npmView.ts
index 7f06a994f70..47b43c8f74e 100644
--- a/extensions/npm/src/npmView.ts
+++ b/extensions/npm/src/npmView.ts
@@ -291,7 +291,14 @@ export class NpmScriptsTreeDataProvider implements TreeDataProvider {
let folder = null;
let packageJson = null;
+ const regularExpressionsSetting = workspace.getConfiguration('npm').get('scriptExplorerExclude', []);
+ const regularExpressions = regularExpressionsSetting?.map(value => RegExp(value));
+
tasks.forEach(each => {
+ if (regularExpressions.some((regularExpression) => (each.task.definition).script.match(regularExpression))) {
+ return;
+ }
+
if (isWorkspaceFolder(each.task.scope) && !this.isInstallTask(each.task)) {
folder = folders.get(each.task.scope.name);
if (!folder) {
diff --git a/extensions/npm/tsconfig.json b/extensions/npm/tsconfig.json
index 980445e09b2..7234fdfeb97 100644
--- a/extensions/npm/tsconfig.json
+++ b/extensions/npm/tsconfig.json
@@ -8,7 +8,6 @@
},
"include": [
"src/**/*",
- "../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/package.json b/extensions/package.json
index 22172c71c86..2c5746b4e73 100644
--- a/extensions/package.json
+++ b/extensions/package.json
@@ -4,7 +4,7 @@
"license": "MIT",
"description": "Dependencies shared by all extensions",
"dependencies": {
- "typescript": "^4.5.1-rc"
+ "typescript": "4.5"
},
"scripts": {
"postinstall": "node ./postinstall"
diff --git a/extensions/php-language-features/package.json b/extensions/php-language-features/package.json
index 8447f019786..03176a05573 100644
--- a/extensions/php-language-features/package.json
+++ b/extensions/php-language-features/package.json
@@ -9,7 +9,6 @@
"engines": {
"vscode": "0.10.x"
},
- "enableProposedApi": true,
"activationEvents": [
"onLanguage:php"
],
diff --git a/extensions/php-language-features/tsconfig.json b/extensions/php-language-features/tsconfig.json
index 980445e09b2..7234fdfeb97 100644
--- a/extensions/php-language-features/tsconfig.json
+++ b/extensions/php-language-features/tsconfig.json
@@ -8,7 +8,6 @@
},
"include": [
"src/**/*",
- "../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/search-result/package.json b/extensions/search-result/package.json
index d7f9aa4a138..747cde8e648 100644
--- a/extensions/search-result/package.json
+++ b/extensions/search-result/package.json
@@ -3,7 +3,6 @@
"displayName": "%displayName%",
"description": "%description%",
"version": "1.0.0",
- "enableProposedApi": true,
"publisher": "vscode",
"license": "MIT",
"icon": "images/icon.png",
@@ -28,6 +27,9 @@
"supported": true
}
},
+ "enabledApiProposals": [
+ "documentFiltersExclusive"
+ ],
"contributes": {
"configurationDefaults": {
"[search-result]": {
diff --git a/extensions/search-result/tsconfig.json b/extensions/search-result/tsconfig.json
index bd7e74d1d83..f0f7c00adf5 100644
--- a/extensions/search-result/tsconfig.json
+++ b/extensions/search-result/tsconfig.json
@@ -5,7 +5,6 @@
},
"include": [
"src/**/*",
- "../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/simple-browser/package.json b/extensions/simple-browser/package.json
index a1b2560bbc9..ea0fd90265b 100644
--- a/extensions/simple-browser/package.json
+++ b/extensions/simple-browser/package.json
@@ -2,7 +2,9 @@
"name": "simple-browser",
"displayName": "%displayName%",
"description": "%description%",
- "enableProposedApi": true,
+ "enabledApiProposals": [
+ "externalUriOpener"
+ ],
"version": "1.0.0",
"icon": "media/icon.png",
"publisher": "vscode",
diff --git a/extensions/simple-browser/tsconfig.json b/extensions/simple-browser/tsconfig.json
index c9980a21e38..bd370826678 100644
--- a/extensions/simple-browser/tsconfig.json
+++ b/extensions/simple-browser/tsconfig.json
@@ -7,6 +7,6 @@
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.proposed.externalUriOpener.d.ts",
]
}
diff --git a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json
index dfa65c9411a..cfb65d06c78 100644
--- a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json
+++ b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json
@@ -355,6 +355,7 @@
// "scrollbarSlider.hoverBackground": "",
// Editor
"editor.background": "#FDF6E3",
+ "notebook.cellEditorBackground": "#F7F0E0",
// "editor.foreground": "#6688cc",
"editorWidget.background": "#EEE8D5",
"editorCursor.foreground": "#657B83",
diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json
index 280a5fe744e..6651308b424 100644
--- a/extensions/typescript-language-features/package.json
+++ b/extensions/typescript-language-features/package.json
@@ -7,9 +7,12 @@
"publisher": "vscode",
"license": "MIT",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
- "enableProposedApi": true,
"enabledApiProposals": [
- "languageStatus"
+ "inlayHints",
+ "languageStatus",
+ "quickPickSeparators",
+ "resolvers",
+ "workspaceTrust"
],
"capabilities": {
"virtualWorkspaces": {
@@ -1113,16 +1116,16 @@
"markdownDescription": "%typescript.workspaceSymbols.scope%",
"scope": "window"
},
- "javascript.suggest.includeCompletionsWithClassMemberSnippets": {
+ "javascript.suggest.classMemberSnippets.enabled": {
"type": "boolean",
"default": true,
- "description": "%configuration.suggest.includeCompletionsWithClassMemberSnippets%",
+ "description": "%configuration.suggest.classMemberSnippets.enabled%",
"scope": "resource"
},
- "typescript.suggest.includeCompletionsWithClassMemberSnippets": {
+ "typescript.suggest.classMemberSnippets.enabled": {
"type": "boolean",
"default": true,
- "description": "%configuration.suggest.includeCompletionsWithClassMemberSnippets%",
+ "description": "%configuration.suggest.classMemberSnippets.enabled%",
"scope": "resource"
}
}
diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json
index 0014fe26992..4f76591ad37 100644
--- a/extensions/typescript-language-features/package.nls.json
+++ b/extensions/typescript-language-features/package.nls.json
@@ -184,5 +184,5 @@
"codeActions.refactor.rewrite.property.generateAccessors.description": "Generate 'get' and 'set' accessors",
"codeActions.source.organizeImports.title": "Organize imports",
"typescript.findAllFileReferences": "Find File References",
- "configuration.suggest.includeCompletionsWithClassMemberSnippets": "Enable/disable snippet completions for class members. Requires using TypeScript 4.5+ in the workspace"
+ "configuration.suggest.classMemberSnippets.enabled": "Enable/disable snippet completions for class members. Requires using TypeScript 4.5+ in the workspace"
}
diff --git a/extensions/typescript-language-features/src/languageFeatures/fileConfigurationManager.ts b/extensions/typescript-language-features/src/languageFeatures/fileConfigurationManager.ts
index 369136f378b..c79e44c63eb 100644
--- a/extensions/typescript-language-features/src/languageFeatures/fileConfigurationManager.ts
+++ b/extensions/typescript-language-features/src/languageFeatures/fileConfigurationManager.ts
@@ -186,7 +186,7 @@ export default class FileConfigurationManager extends Disposable {
generateReturnInDocTemplate: config.get('suggest.jsdoc.generateReturns', true),
includeCompletionsForImportStatements: config.get('suggest.includeCompletionsForImportStatements', true),
includeCompletionsWithSnippetText: config.get('suggest.includeCompletionsWithSnippetText', true),
- includeCompletionsWithClassMemberSnippets: config.get('suggest.includeCompletionsWithClassMemberSnippets', true),
+ includeCompletionsWithClassMemberSnippets: config.get('suggest.classMemberSnippets.enabled', true),
allowIncompleteCompletions: true,
displayPartsForJSDoc: true,
...getInlayHintsPreferences(config),
diff --git a/extensions/typescript-language-features/src/tsServer/spawner.ts b/extensions/typescript-language-features/src/tsServer/spawner.ts
index 6dcf81d929d..9a1e767bdbc 100644
--- a/extensions/typescript-language-features/src/tsServer/spawner.ts
+++ b/extensions/typescript-language-features/src/tsServer/spawner.ts
@@ -256,21 +256,15 @@ export class TypeScriptServerSpawner {
}
}
- if (configuration.npmLocation) {
+ if (configuration.npmLocation && !isWeb()) {
args.push('--npmLocation', `"${configuration.npmLocation}"`);
}
- if (apiVersion.gte(API.v260)) {
- args.push('--locale', TypeScriptServerSpawner.getTsLocale(configuration));
- }
+ args.push('--locale', TypeScriptServerSpawner.getTsLocale(configuration));
- if (apiVersion.gte(API.v291)) {
- args.push('--noGetErrOnBackgroundUpdate');
- }
+ args.push('--noGetErrOnBackgroundUpdate');
- if (apiVersion.gte(API.v345)) {
- args.push('--validateDefaultNpmLocation');
- }
+ args.push('--validateDefaultNpmLocation');
return { args, tsServerLogFile, tsServerTraceDirectory };
}
diff --git a/extensions/typescript-language-features/src/tsServer/versionManager.ts b/extensions/typescript-language-features/src/tsServer/versionManager.ts
index efd567148dd..7b8a3640660 100644
--- a/extensions/typescript-language-features/src/tsServer/versionManager.ts
+++ b/extensions/typescript-language-features/src/tsServer/versionManager.ts
@@ -82,6 +82,11 @@ export class TypeScriptVersionManager extends Disposable {
const selected = await vscode.window.showQuickPick([
this.getBundledPickItem(),
...this.getLocalPickItems(),
+ {
+ kind: vscode.QuickPickItemKind.Separator,
+ label: '',
+ run: () => { /* noop */ },
+ },
LearnMorePickItem,
], {
placeHolder: localize(
@@ -180,7 +185,7 @@ export class TypeScriptVersionManager extends Disposable {
}
const LearnMorePickItem: QuickPickItem = {
- label: localize('learnMore', 'Learn more about managing TypeScript versions'),
+ label: localize('learnMore', "Learn more about managing TypeScript versions"),
description: '',
run: () => {
vscode.env.openExternal(vscode.Uri.parse('https://go.microsoft.com/fwlink/?linkid=839919'));
diff --git a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts
index 41d06ed0576..f67db7f3858 100644
--- a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts
+++ b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts
@@ -62,7 +62,7 @@ export default class TypeScriptServiceClientHost extends Disposable {
constructor(
descriptions: LanguageDescription[],
context: vscode.ExtensionContext,
- onCaseInsenitiveFileSystem: boolean,
+ onCaseInsensitiveFileSystem: boolean,
services: {
pluginManager: PluginManager,
commandManager: CommandManager,
@@ -82,7 +82,7 @@ export default class TypeScriptServiceClientHost extends Disposable {
const allModeIds = this.getAllModeIds(descriptions, services.pluginManager);
this.client = this._register(new TypeScriptServiceClient(
context,
- onCaseInsenitiveFileSystem,
+ onCaseInsensitiveFileSystem,
services,
allModeIds));
@@ -99,7 +99,7 @@ export default class TypeScriptServiceClientHost extends Disposable {
this.typingsStatus = this._register(new TypingsStatus(this.client));
this._register(LargeProjectStatus.create(this.client));
- this.fileConfigurationManager = this._register(new FileConfigurationManager(this.client, onCaseInsenitiveFileSystem));
+ this.fileConfigurationManager = this._register(new FileConfigurationManager(this.client, onCaseInsensitiveFileSystem));
for (const description of descriptions) {
const manager = new LanguageProvider(this.client, description, this.commandManager, this.client.telemetryReporter, this.typingsStatus, this.fileConfigurationManager, onCompletionAccepted);
diff --git a/extensions/typescript-language-features/src/utils/previewer.ts b/extensions/typescript-language-features/src/utils/previewer.ts
index a443efba037..c6d1c942050 100644
--- a/extensions/typescript-language-features/src/utils/previewer.ts
+++ b/extensions/typescript-language-features/src/utils/previewer.ts
@@ -90,8 +90,7 @@ function getTagDocumentation(
if (!doc) {
return label;
}
- // allow-any-unicode-next-line
- return label + (doc.match(/\r\n|\n/g) ? ' \n' + processInlineTags(doc) : ` — ${processInlineTags(doc)}`);
+ return label + (doc.match(/\r\n|\n/g) ? ' \n' + processInlineTags(doc) : ` \u2014 ${processInlineTags(doc)}`);
}
}
@@ -101,8 +100,7 @@ function getTagDocumentation(
if (!text) {
return label;
}
- // allow-any-unicode-next-line
- return label + (text.match(/\r\n|\n/g) ? ' \n' + text : ` — ${text}`);
+ return label + (text.match(/\r\n|\n/g) ? ' \n' + text : ` \u2014 ${text}`);
}
export function plainWithLinks(
diff --git a/extensions/typescript-language-features/tsconfig.json b/extensions/typescript-language-features/tsconfig.json
index 9eac9f6421f..757f9ec5984 100644
--- a/extensions/typescript-language-features/tsconfig.json
+++ b/extensions/typescript-language-features/tsconfig.json
@@ -10,7 +10,10 @@
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
+ "../../src/vscode-dts/vscode.proposed.inlayHints.d.ts",
"../../src/vscode-dts/vscode.proposed.languageStatus.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.proposed.quickPickSeparators.d.ts",
+ "../../src/vscode-dts/vscode.proposed.resolvers.d.ts",
+ "../../src/vscode-dts/vscode.proposed.workspaceTrust.d.ts",
]
}
diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json
index dcdd8b608a9..45de8bf3b0a 100644
--- a/extensions/vscode-api-tests/package.json
+++ b/extensions/vscode-api-tests/package.json
@@ -4,7 +4,55 @@
"version": "0.0.1",
"publisher": "vscode",
"license": "MIT",
- "enableProposedApi": true,
+ "enabledApiProposals": [
+ "authSession",
+ "contribViewsRemote",
+ "customEditorMove",
+ "diffCommand",
+ "documentFiltersExclusive",
+ "editorInsets",
+ "extensionRuntime",
+ "externalUriOpener",
+ "fileSearchProvider",
+ "findTextInFiles",
+ "fsChunks",
+ "inlayHints",
+ "inlineCompletions",
+ "languageStatus",
+ "notebookCellExecutionState",
+ "notebookConcatTextDocument",
+ "notebookContentProvider",
+ "notebookControllerKind",
+ "notebookDebugOptions",
+ "notebookDeprecated",
+ "notebookEditor",
+ "notebookEditorDecorationType",
+ "notebookEditorEdit",
+ "notebookLiveShare",
+ "notebookMessaging",
+ "notebookMime",
+ "portsAttributes",
+ "quickPickSortByLabel",
+ "resolvers",
+ "scmActionButton",
+ "scmSelectedProvider",
+ "scmValidation",
+ "tabs",
+ "taskPresentationGroup",
+ "terminalDataWriteEvent",
+ "terminalDimensions",
+ "terminalLocation",
+ "terminalNameChangeEvent",
+ "testCoverage",
+ "testObserver",
+ "textDocumentNotebook",
+ "textSearchProvider",
+ "timeline",
+ "tokenInformation",
+ "treeViewDragAndDrop",
+ "treeViewReveal",
+ "workspaceTrust"
+ ],
"private": true,
"activationEvents": [],
"main": "./out/extension",
diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts
index ba7ce21e32f..bf0da5076b1 100644
--- a/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts
+++ b/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts
@@ -11,6 +11,7 @@ interface QuickPickExpected {
events: string[];
activeItems: string[][];
selectionItems: string[][];
+ values: string[];
acceptedItems: {
active: string[][];
selection: string[][];
@@ -18,6 +19,15 @@ interface QuickPickExpected {
};
}
+interface InputBoxExpected {
+ events: string[];
+ values: string[];
+ accepted: {
+ values: string[];
+ dispose: boolean[];
+ };
+}
+
suite('vscode API - quick input', function () {
teardown(async function () {
@@ -35,6 +45,7 @@ suite('vscode API - quick input', function () {
events: ['active', 'active', 'selection', 'accept', 'hide'],
activeItems: [['eins'], ['zwei']],
selectionItems: [['zwei']],
+ values: [],
acceptedItems: {
active: [['zwei']],
selection: [['zwei']],
@@ -61,6 +72,7 @@ suite('vscode API - quick input', function () {
events: ['active', 'selection', 'accept', 'hide'],
activeItems: [['zwei']],
selectionItems: [['zwei']],
+ values: [],
acceptedItems: {
active: [['zwei']],
selection: [['zwei']],
@@ -87,6 +99,7 @@ suite('vscode API - quick input', function () {
events: ['active', 'selection', 'active', 'selection', 'accept', 'hide'],
activeItems: [['eins'], ['zwei']],
selectionItems: [['eins'], ['eins', 'zwei']],
+ values: [],
acceptedItems: {
active: [['zwei']],
selection: [['eins', 'zwei']],
@@ -117,6 +130,7 @@ suite('vscode API - quick input', function () {
events: ['active', 'selection', 'accept', 'selection', 'accept', 'hide'],
activeItems: [['eins']],
selectionItems: [['zwei'], ['drei']],
+ values: [],
acceptedItems: {
active: [['eins'], ['eins']],
selection: [['zwei'], ['drei']],
@@ -142,6 +156,7 @@ suite('vscode API - quick input', function () {
events: ['active', 'selection', 'accept', 'active', 'selection', 'active', 'selection', 'accept', 'hide'],
activeItems: [['eins'], [], ['drei']],
selectionItems: [['eins'], [], ['drei']],
+ values: [],
acceptedItems: {
active: [['eins'], ['drei']],
selection: [['eins'], ['drei']],
@@ -163,6 +178,40 @@ suite('vscode API - quick input', function () {
.catch(err => done(err));
});
+ // NOTE: This test is currently accepting the wrong behavior of #135971
+ // so that we can test the fix for #137279.
+ test('createQuickPick, onDidChangeValue gets triggered', function (_done) {
+ let done = (err?: any) => {
+ done = () => { };
+ _done(err);
+ };
+
+ const quickPick = createQuickPick({
+ events: ['active', 'active', 'active', 'active', 'value', 'active', 'active', 'value', 'hide'],
+ activeItems: [['eins'], ['zwei'], [], ['zwei'], [], ['eins']],
+ selectionItems: [],
+ values: ['zwei', ''],
+ acceptedItems: {
+ active: [],
+ selection: [],
+ dispose: []
+ },
+ }, (err?: any) => done(err));
+ quickPick.items = ['eins', 'zwei'].map(label => ({ label }));
+ quickPick.show();
+
+ (async () => {
+ quickPick.value = 'zwei';
+ await timeout(async () => {
+ quickPick.value = '';
+ await timeout(async () => {
+ quickPick.hide();
+ }, 0);
+ }, 0);
+ })()
+ .catch(err => done(err));
+ });
+
test('createQuickPick, dispose in onDidHide', function (_done) {
let done = (err?: any) => {
done = () => { };
@@ -248,6 +297,34 @@ suite('vscode API - quick input', function () {
quickPick.hide();
await waitForHide(quickPick);
});
+
+ test('createInputBox, onDidChangeValue gets triggered', function (_done) {
+ let done = (err?: any) => {
+ done = () => { };
+ _done(err);
+ };
+
+ const quickPick = createInputBox({
+ events: ['value', 'accept', 'hide'],
+ values: ['zwei'],
+ accepted: {
+ values: ['zwei'],
+ dispose: [true]
+ },
+ }, (err?: any) => done(err));
+ quickPick.show();
+
+ (async () => {
+ quickPick.value = 'zwei';
+ await timeout(async () => {
+ await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem');
+ await timeout(async () => {
+ quickPick.hide();
+ }, 0);
+ }, 0);
+ })()
+ .catch(err => done(err));
+ });
});
function createQuickPick(expected: QuickPickExpected, done: (err?: any) => void, record = false) {
@@ -316,9 +393,78 @@ function createQuickPick(expected: QuickPickExpected, done: (err?: any) => void,
}
});
+ quickPick.onDidChangeValue(value => {
+ if (record) {
+ console.log('value');
+ return;
+ }
+
+ try {
+ eventIndex++;
+ assert.strictEqual('value', expected.events.shift(), `onDidChangeValue (event ${eventIndex})`);
+ const expectedValue = expected.values.shift();
+ assert.deepStrictEqual(value, expectedValue, `onDidChangeValue event value (event ${eventIndex})`);
+ } catch (err) {
+ done(err);
+ }
+ });
+
return quickPick;
}
+function createInputBox(expected: InputBoxExpected, done: (err?: any) => void, record = false) {
+ const inputBox = window.createInputBox();
+ let eventIndex = -1;
+ inputBox.onDidAccept(() => {
+ if (record) {
+ console.log('accept');
+ return;
+ }
+ try {
+ eventIndex++;
+ assert.strictEqual('accept', expected.events.shift(), `onDidAccept (event ${eventIndex})`);
+ const expectedValue = expected.accepted.values.shift();
+ assert.deepStrictEqual(inputBox.value, expectedValue, `onDidAccept event value (event ${eventIndex})`);
+ if (expected.accepted.dispose.shift()) {
+ inputBox.dispose();
+ }
+ } catch (err) {
+ done(err);
+ }
+ });
+ inputBox.onDidHide(() => {
+ if (record) {
+ console.log('hide');
+ done();
+ return;
+ }
+ try {
+ assert.strictEqual('hide', expected.events.shift());
+ done();
+ } catch (err) {
+ done(err);
+ }
+ });
+
+ inputBox.onDidChangeValue(value => {
+ if (record) {
+ console.log('value');
+ return;
+ }
+
+ try {
+ eventIndex++;
+ assert.strictEqual('value', expected.events.shift(), `onDidChangeValue (event ${eventIndex})`);
+ const expectedValue = expected.values.shift();
+ assert.deepStrictEqual(value, expectedValue, `onDidChangeValue event value (event ${eventIndex})`);
+ } catch (err) {
+ done(err);
+ }
+ });
+
+ return inputBox;
+}
+
async function timeout(run: () => Promise | T, ms: number): Promise {
return new Promise(resolve => setTimeout(() => resolve(run()), ms));
}
diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts
index c88fa9619d6..2bb71edea11 100644
--- a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts
+++ b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts
@@ -425,23 +425,24 @@ import { assertNoRpc } from '../utils';
});
suite('Extension pty terminals', () => {
- test('should fire onDidOpenTerminal and onDidCloseTerminal', (done) => {
- disposables.push(window.onDidOpenTerminal(term => {
- try {
- equal(term.name, 'c');
- } catch (e) {
- done(e);
- return;
- }
- disposables.push(window.onDidCloseTerminal(() => done()));
- term.dispose();
- }));
+ test('should fire onDidOpenTerminal and onDidCloseTerminal', async () => {
const pty: Pseudoterminal = {
onDidWrite: new EventEmitter().event,
open: () => { },
close: () => { }
};
- window.createTerminal({ name: 'c', pty });
+ const terminal = await new Promise(r => {
+ disposables.push(window.onDidOpenTerminal(t => {
+ if (t.name === 'c') {
+ r(t);
+ }
+ }));
+ window.createTerminal({ name: 'c', pty });
+ });
+ await new Promise(r => {
+ disposables.push(window.onDidCloseTerminal(() => r()));
+ terminal.dispose();
+ });
});
// The below tests depend on global UI state and each other
@@ -491,31 +492,8 @@ import { assertNoRpc } from '../utils';
// const terminal = window.createTerminal({ name: 'foo', pty });
// });
- test('should respect dimension overrides', (done) => {
- disposables.push(window.onDidOpenTerminal(term => {
- try {
- equal(terminal, term);
- } catch (e) {
- done(e);
- return;
- }
- term.show();
- disposables.push(window.onDidChangeTerminalDimensions(e => {
- // The default pty dimensions have a chance to appear here since override
- // dimensions happens after the terminal is created. If so just ignore and
- // wait for the right dimensions
- if (e.dimensions.columns === 10 || e.dimensions.rows === 5) {
- try {
- equal(e.terminal, terminal);
- } catch (e) {
- done(e);
- return;
- }
- disposables.push(window.onDidCloseTerminal(() => done()));
- terminal.dispose();
- }
- }));
- }));
+ // TODO: Fix test, flaky in CI (local and remote) https://github.com/microsoft/vscode/issues/137155
+ test.skip('should respect dimension overrides', async () => {
const writeEmitter = new EventEmitter();
const overrideDimensionsEmitter = new EventEmitter();
const pty: Pseudoterminal = {
@@ -524,29 +502,38 @@ import { assertNoRpc } from '../utils';
open: () => overrideDimensionsEmitter.fire({ columns: 10, rows: 5 }),
close: () => { }
};
- const terminal = window.createTerminal({ name: 'foo', pty });
+ const terminal = await new Promise(r => {
+ disposables.push(window.onDidOpenTerminal(t => {
+ if (t === created) {
+ r(t);
+ }
+ }));
+ const created = window.createTerminal({ name: 'foo', pty });
+ });
+ // Exit the test early if dimensions already match which may happen if the exthost
+ // has high latency
+ if (terminal.dimensions?.columns === 10 && terminal.dimensions?.rows === 5) {
+ return;
+ }
+ // TODO: Remove logs when the test is verified as non-flaky
+ await new Promise(r => {
+ // Does this never fire because it's already set to 10x5?
+ disposables.push(window.onDidChangeTerminalDimensions(e => {
+ console.log(`window.onDidChangeTerminalDimensions event, dimensions = ${e.dimensions?.columns}x${e.dimensions?.rows}`);
+ // The default pty dimensions have a chance to appear here since override
+ // dimensions happens after the terminal is created. If so just ignore and
+ // wait for the right dimensions
+ if (e.terminal === terminal && e.dimensions.columns === 10 && e.dimensions.rows === 5) {
+ disposables.push(window.onDidCloseTerminal(() => r()));
+ terminal.dispose();
+ }
+ }));
+ console.log(`listening for window.onDidChangeTerminalDimensions, current dimensions = ${terminal.dimensions?.columns}x${terminal.dimensions?.rows}`);
+ terminal.show();
+ });
});
- test('should change terminal name', (done) => {
- disposables.push(window.onDidOpenTerminal(term => {
- try {
- equal(terminal, term);
- equal(terminal.name, 'foo');
- } catch (e) {
- done(e);
- return;
- }
- disposables.push(window.onDidCloseTerminal(t => {
- try {
- equal(terminal, t);
- equal(terminal.name, 'bar');
- } catch (e) {
- done(e);
- return;
- }
- done();
- }));
- }));
+ test('should change terminal name', async () => {
const changeNameEmitter = new EventEmitter();
const closeEmitter = new EventEmitter();
const pty: Pseudoterminal = {
@@ -559,29 +546,22 @@ import { assertNoRpc } from '../utils';
},
close: () => { }
};
- const terminal = window.createTerminal({ name: 'foo', pty });
+ await new Promise(r => {
+ disposables.push(window.onDidOpenTerminal(t1 => {
+ if (t1 === created) {
+ disposables.push(window.onDidCloseTerminal(t2 => {
+ if (t2 === created) {
+ strictEqual(t1.name, 'bar');
+ r();
+ }
+ }));
+ }
+ }));
+ const created = window.createTerminal({ name: 'foo', pty });
+ });
});
- test('exitStatus.code should be set to the exit code (undefined)', (done) => {
- disposables.push(window.onDidOpenTerminal(term => {
- try {
- equal(terminal, term);
- equal(terminal.exitStatus, undefined);
- } catch (e) {
- done(e);
- return;
- }
- disposables.push(window.onDidCloseTerminal(t => {
- try {
- equal(terminal, t);
- deepEqual(terminal.exitStatus, { code: undefined });
- } catch (e) {
- done(e);
- return;
- }
- done();
- }));
- }));
+ test('exitStatus.code should be set to the exit code (undefined)', async () => {
const writeEmitter = new EventEmitter();
const closeEmitter = new EventEmitter();
const pty: Pseudoterminal = {
@@ -590,29 +570,23 @@ import { assertNoRpc } from '../utils';
open: () => closeEmitter.fire(undefined),
close: () => { }
};
- const terminal = window.createTerminal({ name: 'foo', pty });
+ await new Promise(r => {
+ disposables.push(window.onDidOpenTerminal(t1 => {
+ if (t1 === created) {
+ strictEqual(created.exitStatus, undefined);
+ disposables.push(window.onDidCloseTerminal(t2 => {
+ if (t2 === created) {
+ deepStrictEqual(created.exitStatus, { code: undefined });
+ r();
+ }
+ }));
+ }
+ }));
+ const created = window.createTerminal({ name: 'foo', pty });
+ });
});
- test('exitStatus.code should be set to the exit code (zero)', (done) => {
- disposables.push(window.onDidOpenTerminal(term => {
- try {
- equal(terminal, term);
- equal(terminal.exitStatus, undefined);
- } catch (e) {
- done(e);
- return;
- }
- disposables.push(window.onDidCloseTerminal(t => {
- try {
- equal(terminal, t);
- deepEqual(terminal.exitStatus, { code: 0 });
- } catch (e) {
- done(e);
- return;
- }
- done();
- }));
- }));
+ test('exitStatus.code should be set to the exit code (zero)', async () => {
const writeEmitter = new EventEmitter();
const closeEmitter = new EventEmitter();
const pty: Pseudoterminal = {
@@ -621,29 +595,23 @@ import { assertNoRpc } from '../utils';
open: () => closeEmitter.fire(0),
close: () => { }
};
- const terminal = window.createTerminal({ name: 'foo', pty });
+ await new Promise(r => {
+ disposables.push(window.onDidOpenTerminal(t1 => {
+ if (t1 === created) {
+ strictEqual(created.exitStatus, undefined);
+ disposables.push(window.onDidCloseTerminal(t2 => {
+ if (t2 === created) {
+ deepStrictEqual(created.exitStatus, { code: 0 });
+ r();
+ }
+ }));
+ }
+ }));
+ const created = window.createTerminal({ name: 'foo', pty });
+ });
});
- test('exitStatus.code should be set to the exit code (non-zero)', (done) => {
- disposables.push(window.onDidOpenTerminal(term => {
- try {
- equal(terminal, term);
- equal(terminal.exitStatus, undefined);
- } catch (e) {
- done(e);
- return;
- }
- disposables.push(window.onDidCloseTerminal(t => {
- try {
- equal(terminal, t);
- deepEqual(terminal.exitStatus, { code: 22 });
- } catch (e) {
- done(e);
- return;
- }
- done();
- }));
- }));
+ test('exitStatus.code should be set to the exit code (non-zero)', async () => {
const writeEmitter = new EventEmitter();
const closeEmitter = new EventEmitter();
const pty: Pseudoterminal = {
@@ -657,20 +625,23 @@ import { assertNoRpc } from '../utils';
},
close: () => { }
};
- const terminal = window.createTerminal({ name: 'foo', pty });
+ await new Promise(r => {
+ disposables.push(window.onDidOpenTerminal(t1 => {
+ if (t1 === created) {
+ strictEqual(created.exitStatus, undefined);
+ disposables.push(window.onDidCloseTerminal(t2 => {
+ if (t2 === created) {
+ deepStrictEqual(created.exitStatus, { code: 22 });
+ r();
+ }
+ }));
+ }
+ }));
+ const created = window.createTerminal({ name: 'foo', pty });
+ });
});
- test('creationOptions should be set and readonly for ExtensionTerminalOptions terminals', (done) => {
- disposables.push(window.onDidOpenTerminal(term => {
- try {
- equal(terminal, term);
- } catch (e) {
- done(e);
- return;
- }
- terminal.dispose();
- disposables.push(window.onDidCloseTerminal(() => done()));
- }));
+ test('creationOptions should be set and readonly for ExtensionTerminalOptions terminals', async () => {
const writeEmitter = new EventEmitter();
const pty: Pseudoterminal = {
onDidWrite: writeEmitter.event,
@@ -678,16 +649,20 @@ import { assertNoRpc } from '../utils';
close: () => { }
};
const options = { name: 'foo', pty };
- const terminal = window.createTerminal(options);
- try {
- equal(terminal.name, 'foo');
+ await new Promise(r => {
+ disposables.push(window.onDidOpenTerminal(term => {
+ if (term === terminal) {
+ terminal.dispose();
+ disposables.push(window.onDidCloseTerminal(() => r()));
+ }
+ }));
+ const terminal = window.createTerminal(options);
+ strictEqual(terminal.name, 'foo');
const terminalOptions = terminal.creationOptions as ExtensionTerminalOptions;
- equal(terminalOptions.name, 'foo');
- equal(terminalOptions.pty, pty);
+ strictEqual(terminalOptions.name, 'foo');
+ strictEqual(terminalOptions.pty, pty);
throws(() => terminalOptions.name = 'bad', 'creationOptions should be readonly at runtime');
- } catch (e) {
- done(e);
- }
+ });
});
});
diff --git a/extensions/vscode-api-tests/testWorkspace/image%.png b/extensions/vscode-api-tests/testWorkspace/image%.png
index 15b462975be..761522a3347 100644
Binary files a/extensions/vscode-api-tests/testWorkspace/image%.png and b/extensions/vscode-api-tests/testWorkspace/image%.png differ
diff --git a/extensions/vscode-api-tests/testWorkspace/image%02.png b/extensions/vscode-api-tests/testWorkspace/image%02.png
index 15b462975be..761522a3347 100644
Binary files a/extensions/vscode-api-tests/testWorkspace/image%02.png and b/extensions/vscode-api-tests/testWorkspace/image%02.png differ
diff --git a/extensions/vscode-api-tests/testWorkspace/image.png b/extensions/vscode-api-tests/testWorkspace/image.png
index 15b462975be..761522a3347 100644
Binary files a/extensions/vscode-api-tests/testWorkspace/image.png and b/extensions/vscode-api-tests/testWorkspace/image.png differ
diff --git a/extensions/vscode-api-tests/tsconfig.json b/extensions/vscode-api-tests/tsconfig.json
index 980445e09b2..3ef85d919ec 100644
--- a/extensions/vscode-api-tests/tsconfig.json
+++ b/extensions/vscode-api-tests/tsconfig.json
@@ -9,6 +9,6 @@
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.proposed.*.d.ts"
]
}
diff --git a/extensions/vscode-colorize-tests/package.json b/extensions/vscode-colorize-tests/package.json
index b2ce2e9d9cf..b27439bf8b6 100644
--- a/extensions/vscode-colorize-tests/package.json
+++ b/extensions/vscode-colorize-tests/package.json
@@ -9,7 +9,6 @@
"onLanguage:json"
],
"main": "./out/colorizerTestMain",
- "enableProposedApi": true,
"engines": {
"vscode": "*"
},
diff --git a/extensions/git/test/colorize-fixtures/COMMIT_EDITMSG b/extensions/vscode-colorize-tests/test/colorize-fixtures/COMMIT_EDITMSG
similarity index 100%
rename from extensions/git/test/colorize-fixtures/COMMIT_EDITMSG
rename to extensions/vscode-colorize-tests/test/colorize-fixtures/COMMIT_EDITMSG
diff --git a/extensions/git/test/colorize-fixtures/git-rebase-todo b/extensions/vscode-colorize-tests/test/colorize-fixtures/git-rebase-todo
similarity index 89%
rename from extensions/git/test/colorize-fixtures/git-rebase-todo
rename to extensions/vscode-colorize-tests/test/colorize-fixtures/git-rebase-todo
index 3b6df1cd4f7..3efe501eb98 100644
--- a/extensions/git/test/colorize-fixtures/git-rebase-todo
+++ b/extensions/vscode-colorize-tests/test/colorize-fixtures/git-rebase-todo
@@ -12,4 +12,4 @@ reword 4ca2acc i cant' typ goods
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
-# x, exec = run command (the rest of the line) using shell
\ No newline at end of file
+# x, exec = run command (the rest of the line) using shell
diff --git a/extensions/git/test/colorize-fixtures/example.diff b/extensions/vscode-colorize-tests/test/colorize-fixtures/test.diff
similarity index 100%
rename from extensions/git/test/colorize-fixtures/example.diff
rename to extensions/vscode-colorize-tests/test/colorize-fixtures/test.diff
diff --git a/extensions/git/test/colorize-results/COMMIT_EDITMSG.json b/extensions/vscode-colorize-tests/test/colorize-results/COMMIT_EDITMSG.json
similarity index 100%
rename from extensions/git/test/colorize-results/COMMIT_EDITMSG.json
rename to extensions/vscode-colorize-tests/test/colorize-results/COMMIT_EDITMSG.json
diff --git a/extensions/git/test/colorize-results/git-rebase-todo.json b/extensions/vscode-colorize-tests/test/colorize-results/git-rebase-todo.json
similarity index 100%
rename from extensions/git/test/colorize-results/git-rebase-todo.json
rename to extensions/vscode-colorize-tests/test/colorize-results/git-rebase-todo.json
diff --git a/extensions/git/test/colorize-results/example_diff.json b/extensions/vscode-colorize-tests/test/colorize-results/test_diff.json
similarity index 100%
rename from extensions/git/test/colorize-results/example_diff.json
rename to extensions/vscode-colorize-tests/test/colorize-results/test_diff.json
diff --git a/extensions/vscode-colorize-tests/tsconfig.json b/extensions/vscode-colorize-tests/tsconfig.json
index 980445e09b2..7234fdfeb97 100644
--- a/extensions/vscode-colorize-tests/tsconfig.json
+++ b/extensions/vscode-colorize-tests/tsconfig.json
@@ -8,7 +8,6 @@
},
"include": [
"src/**/*",
- "../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.d.ts"
]
}
diff --git a/extensions/vscode-custom-editor-tests/package.json b/extensions/vscode-custom-editor-tests/package.json
index acdd4adcb9e..778f5c56cf0 100644
--- a/extensions/vscode-custom-editor-tests/package.json
+++ b/extensions/vscode-custom-editor-tests/package.json
@@ -9,7 +9,6 @@
"onCustomEditor:testWebviewEditor.abc"
],
"main": "./out/extension",
- "enableProposedApi": true,
"engines": {
"vscode": "^1.48.0"
},
diff --git a/extensions/vscode-notebook-tests/package.json b/extensions/vscode-notebook-tests/package.json
index cc0264bb1a3..3cf93067634 100644
--- a/extensions/vscode-notebook-tests/package.json
+++ b/extensions/vscode-notebook-tests/package.json
@@ -9,7 +9,20 @@
"*"
],
"main": "./out/extension",
- "enableProposedApi": true,
+ "enabledApiProposals": [
+ "notebookCellExecutionState",
+ "notebookConcatTextDocument",
+ "notebookContentProvider",
+ "notebookControllerKind",
+ "notebookDebugOptions",
+ "notebookDeprecated",
+ "notebookEditor",
+ "notebookEditorDecorationType",
+ "notebookEditorEdit",
+ "notebookLiveShare",
+ "notebookMessaging",
+ "notebookMime"
+ ],
"engines": {
"vscode": "^1.25.0"
},
diff --git a/extensions/vscode-notebook-tests/tsconfig.json b/extensions/vscode-notebook-tests/tsconfig.json
index 980445e09b2..c9c35c63299 100644
--- a/extensions/vscode-notebook-tests/tsconfig.json
+++ b/extensions/vscode-notebook-tests/tsconfig.json
@@ -9,6 +9,6 @@
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.proposed.notebook*.d.ts"
]
}
diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json
index 99a836fd6c2..28cd1f1faef 100644
--- a/extensions/vscode-test-resolver/package.json
+++ b/extensions/vscode-test-resolver/package.json
@@ -5,6 +5,9 @@
"publisher": "vscode",
"license": "MIT",
"enableProposedApi": true,
+ "enabledApiProposals": [
+ "resolvers"
+ ],
"private": true,
"engines": {
"vscode": "^1.25.0"
diff --git a/extensions/vscode-test-resolver/tsconfig.json b/extensions/vscode-test-resolver/tsconfig.json
index 980445e09b2..f9a183ef9e1 100644
--- a/extensions/vscode-test-resolver/tsconfig.json
+++ b/extensions/vscode-test-resolver/tsconfig.json
@@ -9,6 +9,6 @@
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
- "../../src/vscode-dts/vscode.proposed.d.ts"
+ "../../src/vscode-dts/vscode.proposed.resolvers.d.ts"
]
}
diff --git a/extensions/yarn.lock b/extensions/yarn.lock
index 59cf0bcd5b8..a16a7bfc4b0 100644
--- a/extensions/yarn.lock
+++ b/extensions/yarn.lock
@@ -24,10 +24,10 @@ fast-plist@0.1.2:
resolved "https://registry.yarnpkg.com/fast-plist/-/fast-plist-0.1.2.tgz#a45aff345196006d406ca6cdcd05f69051ef35b8"
integrity sha1-pFr/NFGWAG1AbKbNzQX2kFHvNbg=
-typescript@^4.5.1-rc:
- version "4.5.1-rc"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.1-rc.tgz#02155eaa0579d11babb2a55dcbd796948a994bb3"
- integrity sha512-tQBWW1DCFqweyhSzsAUSFgssJ3uuRBh0zyOkRV4CaFF2rMBkGU0I+MqPMch0qhGCUGXjOW7FgMrbQLS6PE3Z6Q==
+typescript@4.5:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.2.tgz#8ac1fba9f52256fdb06fb89e4122fa6a346c2998"
+ integrity sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==
vscode-grammar-updater@^1.0.3:
version "1.0.3"
diff --git a/package.json b/package.json
index 368265d0742..0cd6378bac8 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.63.0",
- "distro": "cc8976e5470edb06e4b3abd29841ffe7bf5042d2",
+ "distro": "f5a2c7f01629f6d3c0dc65e3fbb3818033206bf2",
"author": {
"name": "Microsoft Corporation"
},
@@ -59,31 +59,31 @@
},
"dependencies": {
"@microsoft/applicationinsights-web": "^2.6.4",
- "@parcel/watcher": "2.0.1",
+ "@parcel/watcher": "2.0.2",
"@vscode/sqlite3": "4.0.12",
+ "@vscode/sudo-prompt": "9.3.1",
"@vscode/vscode-languagedetection": "1.0.21",
"applicationinsights": "1.0.8",
"graceful-fs": "4.2.8",
"http-proxy-agent": "^2.1.0",
"https-proxy-agent": "^2.2.3",
- "iconv-lite-umd": "0.6.8",
+ "iconv-lite-umd": "0.6.10",
"jschardet": "3.0.0",
"keytar": "7.2.0",
"minimist": "^1.2.5",
"native-is-elevated": "0.4.3",
"native-keymap": "3.0.1",
"native-watchdog": "1.3.0",
- "node-pty": "0.11.0-beta7",
+ "node-pty": "0.11.0-beta11",
"spdlog": "^0.13.0",
- "sudo-prompt": "9.2.1",
"tas-client-umd": "0.1.4",
"v8-inspect-profiler": "^0.0.22",
"vscode-nsfw": "2.1.8",
- "vscode-oniguruma": "1.5.1",
+ "vscode-oniguruma": "1.6.1",
"vscode-proxy-agent": "^0.11.0",
"vscode-regexpp": "^3.1.0",
"vscode-ripgrep": "^1.12.1",
- "vscode-textmate": "5.4.1",
+ "vscode-textmate": "5.5.0",
"xterm": "4.16.0-beta.2",
"xterm-addon-search": "0.9.0-beta.6",
"xterm-addon-serialize": "0.7.0-beta.3",
@@ -140,8 +140,8 @@
"file-loader": "^4.2.0",
"glob": "^5.0.13",
"gulp": "^4.0.0",
- "gulp-atom-electron": "1.32.0",
- "gulp-azure-storage": "^0.11.1",
+ "gulp-atom-electron": "^1.32.1",
+ "gulp-azure-storage": "^0.12.1",
"gulp-bom": "^3.0.0",
"gulp-buffer": "0.0.2",
"gulp-concat": "^2.6.1",
@@ -197,7 +197,7 @@
"style-loader": "^1.0.0",
"ts-loader": "^9.2.3",
"tsec": "0.1.4",
- "typescript": "^4.6.0-dev.20211108",
+ "typescript": "^4.6.0-dev.20211115",
"typescript-formatter": "7.1.0",
"underscore": "^1.12.1",
"util": "^0.12.4",
@@ -220,7 +220,7 @@
"url": "https://github.com/microsoft/vscode/issues"
},
"optionalDependencies": {
- "vscode-windows-registry": "1.0.3",
+ "vscode-windows-registry": "1.0.4",
"windows-foreground-love": "0.4.0",
"windows-mutex": "0.4.1",
"windows-process-tree": "^0.3.2"
diff --git a/remote/package.json b/remote/package.json
index 501827c3f79..27a382951c2 100644
--- a/remote/package.json
+++ b/remote/package.json
@@ -4,26 +4,26 @@
"private": true,
"dependencies": {
"@microsoft/applicationinsights-web": "^2.6.4",
- "@parcel/watcher": "2.0.1",
+ "@parcel/watcher": "2.0.2",
"@vscode/vscode-languagedetection": "1.0.21",
"applicationinsights": "1.0.8",
"cookie": "^0.4.0",
"graceful-fs": "4.2.8",
"http-proxy-agent": "^2.1.0",
"https-proxy-agent": "^2.2.3",
- "iconv-lite-umd": "0.6.8",
+ "iconv-lite-umd": "0.6.10",
"jschardet": "3.0.0",
"minimist": "^1.2.5",
"native-watchdog": "1.3.0",
- "node-pty": "0.11.0-beta7",
+ "node-pty": "0.11.0-beta11",
"spdlog": "^0.13.0",
"tas-client-umd": "0.1.4",
"vscode-nsfw": "2.1.8",
- "vscode-oniguruma": "1.5.1",
+ "vscode-oniguruma": "1.6.1",
"vscode-proxy-agent": "^0.11.0",
"vscode-regexpp": "^3.1.0",
"vscode-ripgrep": "^1.12.1",
- "vscode-textmate": "5.4.1",
+ "vscode-textmate": "5.5.0",
"xterm": "4.16.0-beta.2",
"xterm-addon-search": "0.9.0-beta.6",
"xterm-addon-serialize": "0.7.0-beta.3",
@@ -34,7 +34,7 @@
"yazl": "^2.4.3"
},
"optionalDependencies": {
- "vscode-windows-registry": "1.0.3",
+ "vscode-windows-registry": "1.0.4",
"windows-process-tree": "^0.3.2"
}
}
diff --git a/remote/web/package.json b/remote/web/package.json
index f69e0798f01..e44ba1550a4 100644
--- a/remote/web/package.json
+++ b/remote/web/package.json
@@ -5,11 +5,11 @@
"dependencies": {
"@microsoft/applicationinsights-web": "^2.6.4",
"@vscode/vscode-languagedetection": "1.0.21",
- "iconv-lite-umd": "0.6.8",
+ "iconv-lite-umd": "0.6.10",
"jschardet": "3.0.0",
"tas-client-umd": "0.1.4",
- "vscode-oniguruma": "1.5.1",
- "vscode-textmate": "5.4.1",
+ "vscode-oniguruma": "1.6.1",
+ "vscode-textmate": "5.5.0",
"xterm": "4.16.0-beta.2",
"xterm-addon-search": "0.9.0-beta.6",
"xterm-addon-unicode11": "0.4.0-beta.1",
diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock
index 4bf3abe60b5..4144af4392b 100644
--- a/remote/web/yarn.lock
+++ b/remote/web/yarn.lock
@@ -88,10 +88,10 @@
resolved "https://registry.yarnpkg.com/@vscode/vscode-languagedetection/-/vscode-languagedetection-1.0.21.tgz#89b48f293f6aa3341bb888c1118d16ff13b032d3"
integrity sha512-zSUH9HYCw5qsCtd7b31yqkpaCU6jhtkKLkvOOA8yTrIRfBSOFb8PPhgmMicD7B/m+t4PwOJXzU1XDtrM9Fd3/g==
-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==
+iconv-lite-umd@0.6.10:
+ version "0.6.10"
+ resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.10.tgz#faec47521e095b8e3a7175ae08e1b4ae0359a735"
+ integrity sha512-8NtgTa/m1jVq7vdywmD5+SqIlZsB59wtsjaylQuExyCojMq1tHVQxmHjeqVSYwKwnmQbH4mZ1Dxx1eqDkPgaqA==
jschardet@3.0.0:
version "3.0.0"
@@ -103,15 +103,15 @@ tas-client-umd@0.1.4:
resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.1.4.tgz#49db4130dd63a8342fabf77185a740fc6a7bea80"
integrity sha512-1hFqJeLD3ryNikniIaO7TItlXhS5vx7bJ+wbPDf8o+IifgwwOWK2ARisdEM9SnJd0ccfcwNPG6Po+RiKn5L2hg==
-vscode-oniguruma@1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.5.1.tgz#9ca10cd3ada128bd6380344ea28844243d11f695"
- integrity sha512-JrBZH8DCC262TEYcYdeyZusiETu0Vli0xFgdRwNJjDcObcRjbmJP+IFcA3ScBwIXwgFHYKbAgfxtM/Cl+3Spjw==
+vscode-oniguruma@1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz#2bf4dfcfe3dd2e56eb549a3068c8ee39e6c30ce5"
+ integrity sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==
-vscode-textmate@5.4.1:
- version "5.4.1"
- resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.4.1.tgz#09d566724fc76b60b3ad9791eebf1f0b50f29e5a"
- integrity sha512-4CvPHmfuZQaXrcCpathdh6jo7myuR+MU8BvscgQADuponpbqfmu2rwTOtCXhGwwEgStvJF8V4s9FwMKRVLNmKQ==
+vscode-textmate@5.5.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.5.0.tgz#d83776562c07d1e3181c2c7f1b3d5f20afcab483"
+ integrity sha512-jToQkPGMNKn0eyKyitYeINJF0NoD240aYyKPIWJv5W2jfPt++jIRg0OSergubtGhbw6SoefkvBYEpX7TsfoSUQ==
xterm-addon-search@0.9.0-beta.6:
version "0.9.0-beta.6"
diff --git a/remote/yarn.lock b/remote/yarn.lock
index 6eb9ea16e1b..5b1c1bd4b32 100644
--- a/remote/yarn.lock
+++ b/remote/yarn.lock
@@ -83,10 +83,10 @@
resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.4.tgz#40e1c0ad20743fcee1604a7df2c57faf0aa1af87"
integrity sha512-Ot53G927ykMF8cQ3/zq4foZtdk+Tt1YpX7aUTHxBU7UHNdkEiBvBfZSq+rnlUmKCJ19VatwPG4mNzvcGpBj4og==
-"@parcel/watcher@2.0.1":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.1.tgz#ec4bb6c43d9588a1ffd3d2abe6df5b501463c62d"
- integrity sha512-XegFF4L8sFn1RzU5KKOZxXUuzgOSwd6+X2ez3Cy6MVhYMbiLZ1moceMTqDhuT3N8DNbdumK3zP1wojsIsnX40w==
+"@parcel/watcher@2.0.2":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.2.tgz#46bef14584497147bad5247cfb41f80b24d24dfb"
+ integrity sha512-WGJY55/mTAGse2C9VVi2oo+p05oJ0kiSHmOjV33+ywgKgUkUh6B/qFQ5kBO/9mH686qqtV3k2zH1QNm+XX4+lw==
dependencies:
node-addon-api "^3.2.1"
node-gyp-build "^4.3.0"
@@ -305,10 +305,10 @@ https-proxy-agent@^5.0.0:
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==
+iconv-lite-umd@0.6.10:
+ version "0.6.10"
+ resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.10.tgz#faec47521e095b8e3a7175ae08e1b4ae0359a735"
+ integrity sha512-8NtgTa/m1jVq7vdywmD5+SqIlZsB59wtsjaylQuExyCojMq1tHVQxmHjeqVSYwKwnmQbH4mZ1Dxx1eqDkPgaqA==
inherits@~2.0.1:
version "2.0.4"
@@ -394,10 +394,10 @@ node-gyp-build@^4.3.0:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==
-node-pty@0.11.0-beta7:
- version "0.11.0-beta7"
- resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta7.tgz#aed0888b5032d96c54d8473455e6adfae3bbebbe"
- integrity sha512-uApPGLglZRiHQcUMWakbZOrBo8HVWvhzIqNnrWvBGJOvc6m/S5lCdbbg93BURyJqHFmBS0GV+4hwiMNDuGRbSA==
+node-pty@0.11.0-beta11:
+ version "0.11.0-beta11"
+ resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta11.tgz#10843516868129c26a97253903c46fe0e4520eb0"
+ integrity sha512-Gw58duqHle4k/BunssCE1CUKKWipRQZTUFhaTegkKC19fw3IXsvillblLUuD2bQL42+3mQCAFSgTDo+OsJzYCQ==
dependencies:
nan "^2.14.0"
@@ -479,10 +479,10 @@ vscode-nsfw@2.1.8:
dependencies:
node-addon-api "^4.2.0"
-vscode-oniguruma@1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.5.1.tgz#9ca10cd3ada128bd6380344ea28844243d11f695"
- integrity sha512-JrBZH8DCC262TEYcYdeyZusiETu0Vli0xFgdRwNJjDcObcRjbmJP+IFcA3ScBwIXwgFHYKbAgfxtM/Cl+3Spjw==
+vscode-oniguruma@1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz#2bf4dfcfe3dd2e56eb549a3068c8ee39e6c30ce5"
+ integrity sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==
vscode-proxy-agent@^0.11.0:
version "0.11.0"
@@ -512,10 +512,10 @@ vscode-ripgrep@^1.12.1:
https-proxy-agent "^4.0.0"
proxy-from-env "^1.1.0"
-vscode-textmate@5.4.1:
- version "5.4.1"
- resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.4.1.tgz#09d566724fc76b60b3ad9791eebf1f0b50f29e5a"
- integrity sha512-4CvPHmfuZQaXrcCpathdh6jo7myuR+MU8BvscgQADuponpbqfmu2rwTOtCXhGwwEgStvJF8V4s9FwMKRVLNmKQ==
+vscode-textmate@5.5.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.5.0.tgz#d83776562c07d1e3181c2c7f1b3d5f20afcab483"
+ integrity sha512-jToQkPGMNKn0eyKyitYeINJF0NoD240aYyKPIWJv5W2jfPt++jIRg0OSergubtGhbw6SoefkvBYEpX7TsfoSUQ==
vscode-windows-ca-certs@^0.3.0:
version "0.3.0"
@@ -524,10 +524,10 @@ vscode-windows-ca-certs@^0.3.0:
dependencies:
node-addon-api "^3.0.2"
-vscode-windows-registry@1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/vscode-windows-registry/-/vscode-windows-registry-1.0.3.tgz#377e9a8bf75c0acac81a188282a4f16f748ecd47"
- integrity sha512-IXCwNAm+H5yPCn6JBz89T9AAMgy5xEN2LxbxrvHPlErmyQqCYtpCCjvisfgT2dCuaJ2T9FfiqIeIrOpDm2Jc4Q==
+vscode-windows-registry@1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/vscode-windows-registry/-/vscode-windows-registry-1.0.4.tgz#9e565a497c84b6b82d200f88930baeff12912079"
+ integrity sha512-vjYaMzEygZrb8bN6I33XTajpF/gtDOk5CtQPPSaxanXg2kkrerEM9qovY6t6FtBGl3oLq6YHytYdYw4IpXgJdA==
windows-process-tree@^0.3.2:
version "0.3.2"
diff --git a/resources/server/bin-dev/code-web.js b/resources/server/bin-dev/code-web.js
index d5276fb41d0..0fdb7c76d2c 100644
--- a/resources/server/bin-dev/code-web.js
+++ b/resources/server/bin-dev/code-web.js
@@ -61,7 +61,7 @@ if (ENABLE_SYNC) {
}
// Connection Token
-serverArgs.push('--connectionToken', '00000');
+serverArgs.push('--connection-token', '00000');
// Server should really only listen from localhost
serverArgs.push('--host', '127.0.0.1');
diff --git a/resources/web/code-web.js b/resources/web/code-web.js
index 0625a848805..e2e23f9edec 100644
--- a/resources/web/code-web.js
+++ b/resources/web/code-web.js
@@ -37,7 +37,7 @@ const ALLOWED_CORS_ORIGINS = [
'http://127.0.0.1:8080',
];
-const WEB_PLAYGROUND_VERSION = '0.0.12';
+const WEB_PLAYGROUND_VERSION = '0.0.13';
const args = minimist(process.argv, {
boolean: [
diff --git a/scripts/test.bat b/scripts/test.bat
index 7232c26193c..d45505db8a7 100644
--- a/scripts/test.bat
+++ b/scripts/test.bat
@@ -17,7 +17,7 @@ if %errorlevel% neq 0 node .\node_modules\gulp\bin\gulp.js electron
:: Run tests
set ELECTRON_ENABLE_LOGGING=1
-%CODE% .\test\unit\electron\index.js %*
+%CODE% .\test\unit\electron\index.js --crash-reporter-directory=%~dp0\..\.build\crashes %*
popd
diff --git a/scripts/test.sh b/scripts/test.sh
index 10ffb97c71f..14a72e09cc3 100755
--- a/scripts/test.sh
+++ b/scripts/test.sh
@@ -21,6 +21,8 @@ else
CODE=".build/electron/$NAME"
fi
+VSCODECRASHDIR=$ROOT/.build/crashes
+
# Node modules
test -d node_modules || yarn
@@ -32,10 +34,10 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
cd $ROOT ; ulimit -n 4096 ; \
ELECTRON_ENABLE_LOGGING=1 \
"$CODE" \
- test/unit/electron/index.js "$@"
+ test/unit/electron/index.js --crash-reporter-directory=$VSCODECRASHDIR "$@"
else
cd $ROOT ; \
ELECTRON_ENABLE_LOGGING=1 \
"$CODE" \
- test/unit/electron/index.js $LINUX_EXTRA_ARGS "$@"
+ test/unit/electron/index.js --crash-reporter-directory=$VSCODECRASHDIR $LINUX_EXTRA_ARGS "$@"
fi
diff --git a/src/main.js b/src/main.js
index ad838aa245e..4f3e6ef6930 100644
--- a/src/main.js
+++ b/src/main.js
@@ -25,8 +25,6 @@ const { getUserDataPath } = require('./vs/platform/environment/node/userDataPath
const product = require('../product.json');
const { app, protocol, crashReporter } = require('electron');
-// Disable render process reuse, we still have
-// non-context aware native modules in the renderer.
app.allowRendererProcessReuse = false;
// Enable portable support
@@ -175,7 +173,10 @@ function configureCommandlineSwitchesSync(cliArgs) {
'enable-proposed-api',
// Log level to use. Default is 'info'. Allowed values are 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.
- 'log-level'
+ 'log-level',
+
+ // Enables render process reuse. Default value is 'false'. See https://github.com/electron/electron/issues/18397
+ 'enable-render-process-reuse'
];
// Read argv config
@@ -220,6 +221,12 @@ function configureCommandlineSwitchesSync(cliArgs) {
process.argv.push('--log', argvValue);
}
break;
+
+ case 'enable-render-process-reuse':
+ if (argvValue === true) {
+ app.allowRendererProcessReuse = true;
+ }
+ break;
}
}
});
diff --git a/src/tsconfig.json b/src/tsconfig.json
index 02e85647832..eaaa3fb52b8 100644
--- a/src/tsconfig.json
+++ b/src/tsconfig.json
@@ -26,7 +26,6 @@
"./typings",
"./vs",
"vscode-dts/vscode.proposed.*.d.ts",
- "vscode-dts/vscode.proposed.d.ts",
"vscode-dts/vscode.d.ts"
]
}
diff --git a/src/tsconfig.vscode-proposed-dts.json b/src/tsconfig.vscode-proposed-dts.json
index 802e37e567e..dd12f3bca28 100644
--- a/src/tsconfig.vscode-proposed-dts.json
+++ b/src/tsconfig.vscode-proposed-dts.json
@@ -2,6 +2,6 @@
"extends": "./tsconfig.vscode-dts.json",
"include": [
"vscode-dts/vscode.d.ts",
- "vscode-dts/vscode.proposed.d.ts",
+ "vscode-dts/vscode.proposed.*.d.ts",
]
}
diff --git a/src/tsec.exemptions.json b/src/tsec.exemptions.json
index fbb798ca0e3..7e7edeefd22 100644
--- a/src/tsec.exemptions.json
+++ b/src/tsec.exemptions.json
@@ -32,6 +32,7 @@
"vs/platform/sharedProcess/electron-browser/sharedProcessWorkerService.ts"
],
"ban-domparser-parsefromstring": [
+ "vs/base/browser/markdownRenderer.ts",
"vs/base/test/browser/markdownRenderer.test.ts"
]
}
diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
index de0524c037e..cff9352a148 100644
--- a/src/vs/base/browser/dom.ts
+++ b/src/vs/base/browser/dom.ts
@@ -908,7 +908,7 @@ export const EventHelper = {
export interface IFocusTracker extends Disposable {
onDidFocus: Event;
onDidBlur: Event;
- refreshState?(): void;
+ refreshState(): void;
}
export function saveParentsScrollTop(node: Element): number[] {
@@ -978,6 +978,8 @@ class FocusTracker extends Disposable implements IFocusTracker {
this._register(addDisposableListener(element, EventType.FOCUS, onFocus, true));
this._register(addDisposableListener(element, EventType.BLUR, onBlur, true));
+ this._register(addDisposableListener(element, EventType.FOCUS_IN, () => this._refreshStateHandler()));
+ this._register(addDisposableListener(element, EventType.FOCUS_OUT, () => this._refreshStateHandler()));
}
refreshState() {
diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts
index 70995984352..5d885f37ea3 100644
--- a/src/vs/base/browser/markdownRenderer.ts
+++ b/src/vs/base/browser/markdownRenderer.ts
@@ -71,20 +71,23 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
const _href = function (href: string, isDomUri: boolean): string {
const data = markdown.uris && markdown.uris[href];
- if (!data) {
- return href; // no uri exists
- }
let uri = URI.revive(data);
if (isDomUri) {
if (href.startsWith(Schemas.data + ':')) {
return href;
}
+ if (!uri) {
+ uri = URI.parse(href);
+ }
// this URI will end up as "src"-attribute of a dom node
// and because of that special rewriting needs to be done
// so that the URI uses a protocol that's understood by
// browsers (like http or https)
return FileAccess.asBrowserUri(uri).toString(true);
}
+ if (!uri) {
+ return href;
+ }
if (URI.parse(href).toString() === uri.toString()) {
return href; // no transformation performed
}
@@ -100,19 +103,12 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
const withInnerHTML = new Promise(c => signalInnerHTML = c);
const renderer = new marked.Renderer();
+
renderer.image = (href: string, title: string, text: string) => {
let dimensions: string[] = [];
let attributes: string[] = [];
if (href) {
({ href, dimensions } = parseHrefAndDimensions(href));
- href = _href(href, true);
- try {
- const hrefAsUri = URI.parse(href);
- if (options.baseUrl && hrefAsUri.scheme === Schemas.file) { // absolute or relative local path, or file: uri
- href = resolvePath(options.baseUrl, href).toString();
- }
- } catch (err) { }
-
attributes.push(`src="${href}"`);
}
if (text) {
@@ -250,7 +246,26 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
renderedMarkdown = elements.map(e => typeof e === 'string' ? e : e.outerHTML).join('');
}
- element.innerHTML = sanitizeRenderedMarkdown(markdown, renderedMarkdown) as unknown as string;
+ const htmlParser = new DOMParser();
+ const markdownHtmlDoc = htmlParser.parseFromString(sanitizeRenderedMarkdown(markdown, renderedMarkdown) as unknown as string, 'text/html');
+
+ markdownHtmlDoc.body.querySelectorAll('img')
+ .forEach(img => {
+ if (img.src) {
+ let href = _href(img.src, true);
+
+ try {
+ const hrefAsUri = URI.parse(href);
+ if (options.baseUrl && hrefAsUri.scheme === Schemas.file) { // absolute or relative local path, or file: uri
+ href = resolvePath(options.baseUrl, href).toString();
+ }
+ } catch (err) { }
+
+ img.src = href;
+ }
+ });
+
+ element.innerHTML = sanitizeRenderedMarkdown(markdown, markdownHtmlDoc.body.innerHTML) as unknown as string;
// signal that async code blocks can be now be inserted
signalInnerHTML!();
diff --git a/src/vs/base/browser/ui/checkbox/checkbox.css b/src/vs/base/browser/ui/checkbox/checkbox.css
index c754adc1518..706c9585e40 100644
--- a/src/vs/base/browser/ui/checkbox/checkbox.css
+++ b/src/vs/base/browser/ui/checkbox/checkbox.css
@@ -8,9 +8,9 @@
float: left;
cursor: pointer;
overflow: hidden;
- opacity: 0.7;
width: 20px;
height: 20px;
+ border-radius: 3px;
border: 1px solid transparent;
padding: 1px;
box-sizing: border-box;
@@ -19,9 +19,12 @@
-ms-user-select: none;
}
-.monaco-custom-checkbox:hover,
-.monaco-custom-checkbox.checked {
- opacity: 1;
+.monaco-custom-checkbox:hover {
+ background-color: var(--vscode-inputOption-hoverBackground);
+}
+
+.hc-black .monaco-custom-checkbox:hover {
+ border: 1px dashed var(--vscode-focusBorder);
}
.hc-black .monaco-custom-checkbox {
diff --git a/src/vs/base/browser/ui/checkbox/checkbox.ts b/src/vs/base/browser/ui/checkbox/checkbox.ts
index b66ce0497db..27b4c5875fa 100644
--- a/src/vs/base/browser/ui/checkbox/checkbox.ts
+++ b/src/vs/base/browser/ui/checkbox/checkbox.ts
@@ -191,9 +191,9 @@ export class Checkbox extends Widget {
protected applyStyles(): void {
if (this.domNode) {
- this.domNode.style.borderColor = this._checked && this._opts.inputActiveOptionBorder ? this._opts.inputActiveOptionBorder.toString() : 'transparent';
+ this.domNode.style.borderColor = this._checked && this._opts.inputActiveOptionBorder ? this._opts.inputActiveOptionBorder.toString() : '';
this.domNode.style.color = this._checked && this._opts.inputActiveOptionForeground ? this._opts.inputActiveOptionForeground.toString() : 'inherit';
- this.domNode.style.backgroundColor = this._checked && this._opts.inputActiveOptionBackground ? this._opts.inputActiveOptionBackground.toString() : 'transparent';
+ this.domNode.style.backgroundColor = this._checked && this._opts.inputActiveOptionBackground ? this._opts.inputActiveOptionBackground.toString() : '';
}
}
diff --git a/src/vs/base/browser/ui/grid/gridview.ts b/src/vs/base/browser/ui/grid/gridview.ts
index b80ffaecb29..113822bdffd 100644
--- a/src/vs/base/browser/ui/grid/gridview.ts
+++ b/src/vs/base/browser/ui/grid/gridview.ts
@@ -10,7 +10,7 @@ import { equals as arrayEquals, tail2 as tail } from 'vs/base/common/arrays';
import { Color } from 'vs/base/common/color';
import { Emitter, Event, Relay } from 'vs/base/common/event';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
-import { clamp } from 'vs/base/common/numbers';
+import { rot } from 'vs/base/common/numbers';
import { isUndefined } from 'vs/base/common/types';
import 'vs/css!./gridview';
@@ -235,6 +235,14 @@ function fromAbsoluteBoundarySashes(sashes: IBoundarySashes, orientation: Orient
}
}
+function validateIndex(index: number, numChildren: number): number {
+ if (Math.abs(index) > numChildren) {
+ throw new Error('Invalid index');
+ }
+
+ return rot(index, numChildren + 1);
+}
+
class BranchNode implements ISplitView, IDisposable {
readonly element: HTMLElement;
@@ -474,9 +482,7 @@ class BranchNode implements ISplitView, IDisposable {
}
addChild(node: Node, size: number | Sizing, index: number, skipLayout?: boolean): void {
- if (index < 0 || index > this.children.length) {
- throw new Error('Invalid index');
- }
+ index = validateIndex(index, this.children.length);
this.splitview.addView(node, size, index, skipLayout);
this._addChild(node, index);
@@ -511,9 +517,7 @@ class BranchNode implements ISplitView, IDisposable {
}
removeChild(index: number, sizing?: Sizing): void {
- if (index < 0 || index >= this.children.length) {
- throw new Error('Invalid index');
- }
+ index = validateIndex(index, this.children.length);
this.splitview.removeView(index, sizing);
this._removeChild(index);
@@ -543,16 +547,13 @@ class BranchNode implements ISplitView, IDisposable {
}
moveChild(from: number, to: number): void {
+ from = validateIndex(from, this.children.length);
+ to = validateIndex(to, this.children.length);
+
if (from === to) {
return;
}
- if (from < 0 || from >= this.children.length) {
- throw new Error('Invalid from index');
- }
-
- to = clamp(to, 0, this.children.length);
-
if (from < to) {
to--;
}
@@ -566,16 +567,13 @@ class BranchNode implements ISplitView, IDisposable {
}
swapChildren(from: number, to: number): void {
+ from = validateIndex(from, this.children.length);
+ to = validateIndex(to, this.children.length);
+
if (from === to) {
return;
}
- if (from < 0 || from >= this.children.length) {
- throw new Error('Invalid from index');
- }
-
- to = clamp(to, 0, this.children.length);
-
this.splitview.swapViews(from, to);
// swap boundary sashes
@@ -589,9 +587,7 @@ class BranchNode implements ISplitView, IDisposable {
}
resizeChild(index: number, size: number): void {
- if (index < 0 || index >= this.children.length) {
- throw new Error('Invalid index');
- }
+ index = validateIndex(index, this.children.length);
this.splitview.resizeView(index, size);
}
@@ -609,25 +605,19 @@ class BranchNode implements ISplitView, IDisposable {
}
getChildSize(index: number): number {
- if (index < 0 || index >= this.children.length) {
- throw new Error('Invalid index');
- }
+ index = validateIndex(index, this.children.length);
return this.splitview.getViewSize(index);
}
isChildVisible(index: number): boolean {
- if (index < 0 || index >= this.children.length) {
- throw new Error('Invalid index');
- }
+ index = validateIndex(index, this.children.length);
return this.splitview.isViewVisible(index);
}
setChildVisible(index: number, visible: boolean): void {
- if (index < 0 || index >= this.children.length) {
- throw new Error('Invalid index');
- }
+ index = validateIndex(index, this.children.length);
if (this.splitview.isViewVisible(index) === visible) {
return;
@@ -637,9 +627,7 @@ class BranchNode implements ISplitView, IDisposable {
}
getChildCachedVisibleSize(index: number): number | undefined {
- if (index < 0 || index >= this.children.length) {
- throw new Error('Invalid index');
- }
+ index = validateIndex(index, this.children.length);
return this.splitview.getViewCachedVisibleSize(index);
}
diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts
index a6ba042ad66..f04858f1545 100644
--- a/src/vs/base/browser/ui/inputbox/inputBox.ts
+++ b/src/vs/base/browser/ui/inputbox/inputBox.ts
@@ -363,11 +363,8 @@ export class InputBox extends Widget {
}
public set paddingRight(paddingRight: number) {
- if (this.options.flexibleHeight && this.options.flexibleWidth) {
- this.input.style.width = `calc(100% - ${paddingRight}px)`;
- } else {
- this.input.style.paddingRight = paddingRight + 'px';
- }
+ // Set width to avoid hint text overlapping buttons
+ this.input.style.width = `calc(100% - ${paddingRight}px)`;
if (this.mirror) {
this.mirror.style.paddingRight = paddingRight + 'px';
diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts
index dd3ec826f13..6469e3f3b45 100644
--- a/src/vs/base/browser/ui/menu/menu.ts
+++ b/src/vs/base/browser/ui/menu/menu.ts
@@ -59,6 +59,10 @@ export interface IMenuStyles {
selectionBackgroundColor?: Color;
selectionBorderColor?: Color;
separatorColor?: Color;
+ scrollbarShadow?: Color;
+ scrollbarSliderBackground?: Color;
+ scrollbarSliderHoverBackground?: Color;
+ scrollbarSliderActiveBackground?: Color;
}
interface ISubMenuData {
@@ -99,8 +103,6 @@ export class Menu extends ActionBar {
this.menuDisposables = this._register(new DisposableStore());
- this.initializeStyleSheet(container);
-
this._register(Gesture.addTarget(menuElement));
addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => {
@@ -262,23 +264,25 @@ export class Menu extends ActionBar {
});
}
- private initializeStyleSheet(container: HTMLElement): void {
- if (isInShadowDOM(container)) {
- this.styleSheet = createStyleSheet(container);
- this.styleSheet.textContent = MENU_WIDGET_CSS;
- } else {
- if (!Menu.globalStyleSheet) {
- Menu.globalStyleSheet = createStyleSheet();
- Menu.globalStyleSheet.textContent = MENU_WIDGET_CSS;
+ private initializeOrUpdateStyleSheet(container: HTMLElement, style: IMenuStyles): void {
+ if (!this.styleSheet) {
+ if (isInShadowDOM(container)) {
+ this.styleSheet = createStyleSheet(container);
+ } else {
+ if (!Menu.globalStyleSheet) {
+ Menu.globalStyleSheet = createStyleSheet();
+ }
+ this.styleSheet = Menu.globalStyleSheet;
}
-
- this.styleSheet = Menu.globalStyleSheet;
}
+ this.styleSheet.textContent = getMenuWidgetCSS(style);
}
style(style: IMenuStyles): void {
const container = this.getContainer();
+ this.initializeOrUpdateStyleSheet(container, style);
+
const fgColor = style.foregroundColor ? `${style.foregroundColor}` : '';
const bgColor = style.backgroundColor ? `${style.backgroundColor}` : '';
const border = style.borderColor ? `1px solid ${style.borderColor}` : '';
@@ -1016,7 +1020,8 @@ export function cleanMnemonic(label: string): string {
return label.replace(regex, mnemonicInText ? '$2$3' : '').trim();
}
-let MENU_WIDGET_CSS: string = /* css */`
+function getMenuWidgetCSS(style: IMenuStyles): string {
+ let result = /* css */`
.monaco-menu {
font-size: 13px;
@@ -1339,7 +1344,6 @@ ${formatRule(Codicon.menuSubmenu)}
left: 3px;
height: 3px;
width: 100%;
- box-shadow: #DDD 0 6px 6px -6px inset;
}
.monaco-scrollable-element > .shadow.left {
display: block;
@@ -1347,7 +1351,6 @@ ${formatRule(Codicon.menuSubmenu)}
left: 0;
height: 100%;
width: 3px;
- box-shadow: #DDD 6px 0 6px -6px inset;
}
.monaco-scrollable-element > .shadow.top-left-corner {
display: block;
@@ -1356,60 +1359,52 @@ ${formatRule(Codicon.menuSubmenu)}
height: 3px;
width: 3px;
}
-.monaco-scrollable-element > .shadow.top.left {
- box-shadow: #DDD 6px 6px 6px -6px inset;
-}
-
-/* ---------- Default Style ---------- */
-
-:host-context(.vs) .monaco-scrollable-element > .scrollbar > .slider {
- background: rgba(100, 100, 100, .4);
-}
-:host-context(.vs-dark) .monaco-scrollable-element > .scrollbar > .slider {
- background: rgba(121, 121, 121, .4);
-}
-:host-context(.hc-black) .monaco-scrollable-element > .scrollbar > .slider {
- background: rgba(111, 195, 223, .6);
-}
-
-.monaco-scrollable-element > .scrollbar > .slider:hover {
- background: rgba(100, 100, 100, .7);
-}
-:host-context(.hc-black) .monaco-scrollable-element > .scrollbar > .slider:hover {
- background: rgba(111, 195, 223, .8);
-}
-
-.monaco-scrollable-element > .scrollbar > .slider.active {
- background: rgba(0, 0, 0, .6);
-}
-:host-context(.vs-dark) .monaco-scrollable-element > .scrollbar > .slider.active {
- background: rgba(191, 191, 191, .4);
-}
-:host-context(.hc-black) .monaco-scrollable-element > .scrollbar > .slider.active {
- background: rgba(111, 195, 223, 1);
-}
-
-:host-context(.vs-dark) .monaco-scrollable-element .shadow.top {
- box-shadow: none;
-}
-
-:host-context(.vs-dark) .monaco-scrollable-element .shadow.left {
- box-shadow: #000 6px 0 6px -6px inset;
-}
-
-:host-context(.vs-dark) .monaco-scrollable-element .shadow.top.left {
- box-shadow: #000 6px 6px 6px -6px inset;
-}
-
-:host-context(.hc-black) .monaco-scrollable-element .shadow.top {
- box-shadow: none;
-}
-
-:host-context(.hc-black) .monaco-scrollable-element .shadow.left {
- box-shadow: none;
-}
-
-:host-context(.hc-black) .monaco-scrollable-element .shadow.top.left {
- box-shadow: none;
-}
`;
+
+ // Scrollbars
+ const scrollbarShadowColor = style.scrollbarShadow;
+ if (scrollbarShadowColor) {
+ result += `
+ .monaco-scrollable-element > .shadow.top {
+ box-shadow: ${scrollbarShadowColor} 0 6px 6px -6px inset;
+ }
+
+ .monaco-scrollable-element > .shadow.left {
+ box-shadow: ${scrollbarShadowColor} 6px 0 6px -6px inset;
+ }
+
+ .monaco-scrollable-element > .shadow.top.left {
+ box-shadow: ${scrollbarShadowColor} 6px 6px 6px -6px inset;
+ }
+ `;
+ }
+
+ const scrollbarSliderBackgroundColor = style.scrollbarSliderBackground;
+ if (scrollbarSliderBackgroundColor) {
+ result += `
+ .monaco-scrollable-element > .scrollbar > .slider {
+ background: ${scrollbarSliderBackgroundColor};
+ }
+ `;
+ }
+
+ const scrollbarSliderHoverBackgroundColor = style.scrollbarSliderHoverBackground;
+ if (scrollbarSliderHoverBackgroundColor) {
+ result += `
+ .monaco-scrollable-element > .scrollbar > .slider:hover {
+ background: ${scrollbarSliderHoverBackgroundColor};
+ }
+ `;
+ }
+
+ const scrollbarSliderActiveBackgroundColor = style.scrollbarSliderActiveBackground;
+ if (scrollbarSliderActiveBackgroundColor) {
+ result += `
+ .monaco-scrollable-element > .scrollbar > .slider.active {
+ background: ${scrollbarSliderActiveBackgroundColor};
+ }
+ `;
+ }
+
+ return result;
+}
diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts
index 0972e6f8bf1..f2f264f747c 100644
--- a/src/vs/base/common/async.ts
+++ b/src/vs/base/common/async.ts
@@ -9,6 +9,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { extUri as defaultExtUri, IExtUri } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
+import { setTimeout0 } from 'vs/base/common/platform';
export function isThenable(obj: unknown): obj is Promise {
return !!obj && typeof (obj as unknown as Promise).then === 'function';
@@ -968,6 +969,7 @@ export interface IdleDeadline {
readonly didTimeout: boolean;
timeRemaining(): number;
}
+
/**
* Execute the callback the next time the browser is idle
*/
@@ -979,8 +981,11 @@ declare function cancelIdleCallback(handle: number): void;
(function () {
if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') {
runWhenIdle = (runner) => {
- const handle = setTimeout(() => {
- const end = Date.now() + 15; // one frame at 64fps
+ setTimeout0(() => {
+ if (disposed) {
+ return;
+ }
+ const end = Date.now() + 3; // yield often
runner(Object.freeze({
didTimeout: true,
timeRemaining() {
@@ -995,7 +1000,6 @@ declare function cancelIdleCallback(handle: number): void;
return;
}
disposed = true;
- clearTimeout(handle);
}
};
};
diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts
index 100ec15f577..26792a1bd03 100644
--- a/src/vs/base/common/codicons.ts
+++ b/src/vs/base/common/codicons.ts
@@ -598,9 +598,9 @@ export interface CSSIcon {
export namespace CSSIcon {
export const iconNameSegment = '[A-Za-z0-9]+';
- export const iconNameExpression = '[A-Za-z0-9\\-]+';
+ export const iconNameExpression = '[A-Za-z0-9-]+';
export const iconModifierExpression = '~[A-Za-z]+';
- export const iconNameCharacter = '[A-Za-z0-9\\-~]';
+ export const iconNameCharacter = '[A-Za-z0-9~-]';
const cssIconIdRegex = new RegExp(`^(${iconNameExpression})(${iconModifierExpression})?$`);
diff --git a/src/vs/base/common/keybindingLabels.ts b/src/vs/base/common/keybindingLabels.ts
index c4857834c88..62e905a4bb4 100644
--- a/src/vs/base/common/keybindingLabels.ts
+++ b/src/vs/base/common/keybindingLabels.ts
@@ -54,8 +54,7 @@ export class ModifierLabelProvider {
*/
export const UILabelProvider = new ModifierLabelProvider(
{
- // allow-any-unicode-next-line
- ctrlKey: '⌃',
+ ctrlKey: '\u2303',
shiftKey: '⇧',
altKey: '⌥',
metaKey: '⌘',
@@ -84,7 +83,7 @@ export const AriaLabelProvider = new ModifierLabelProvider(
{
ctrlKey: nls.localize({ key: 'ctrlKey.long', comment: ['This is the long form for the Control key on the keyboard'] }, "Control"),
shiftKey: nls.localize({ key: 'shiftKey.long', comment: ['This is the long form for the Shift key on the keyboard'] }, "Shift"),
- altKey: nls.localize({ key: 'altKey.long', comment: ['This is the long form for the Alt key on the keyboard'] }, "Alt"),
+ altKey: nls.localize({ key: 'optKey.long', comment: ['This is the long form for the Alt/Option key on the keyboard'] }, "Option"),
metaKey: nls.localize({ key: 'cmdKey.long', comment: ['This is the long form for the Command key on the keyboard'] }, "Command"),
separator: '+',
},
diff --git a/src/vs/base/common/marked/marked.js b/src/vs/base/common/marked/marked.js
index b7a725a1bca..3a3f975c922 100644
--- a/src/vs/base/common/marked/marked.js
+++ b/src/vs/base/common/marked/marked.js
@@ -2980,14 +2980,14 @@
// ESM-uncomment-begin
// })();
-// export var marked = __marked_exports;
-// export var Parser = __marked_exports.Parser;
-// export var parser = __marked_exports.parser;
-// export var Renderer = __marked_exports.Renderer;
-// export var TextRenderer = __marked_exports.TextRenderer;
-// export var Lexer = __marked_exports.Lexer;
-// export var lexer = __marked_exports.lexer;
-// export var Tokenizer = __marked_exports.Tokenizer;
-// export var Slugger = __marked_exports.Slugger;
-// export var parse = __marked_exports.parse;
+// export var marked = (__marked_exports || exports);
+// export var Parser = (__marked_exports || exports).Parser;
+// export var parser = (__marked_exports || exports).parser;
+// export var Renderer = (__marked_exports || exports).Renderer;
+// export var TextRenderer = (__marked_exports || exports).TextRenderer;
+// export var Lexer = (__marked_exports || exports).Lexer;
+// export var lexer = (__marked_exports || exports).lexer;
+// export var Tokenizer = (__marked_exports || exports).Tokenizer;
+// export var Slugger = (__marked_exports || exports).Slugger;
+// export var parse = (__marked_exports || exports).parse;
// ESM-uncomment-end
diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js
index d15367be8b2..15eab308bf2 100644
--- a/src/vs/base/common/performance.js
+++ b/src/vs/base/common/performance.js
@@ -40,7 +40,9 @@
*/
function _define() {
- if (typeof performance === 'object' && typeof performance.mark === 'function') {
+ // Identify browser environment when following property is not present
+ // https://nodejs.org/dist/latest-v16.x/docs/api/perf_hooks.html#performancenodetiming
+ if (typeof performance === 'object' && typeof performance.mark === 'function' && !performance.nodeTiming) {
// in a browser context, reuse performance-util
if (typeof performance.timeOrigin !== 'number' && !performance.timing) {
diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts
index 1a571e41337..973ac98d615 100644
--- a/src/vs/base/common/platform.ts
+++ b/src/vs/base/common/platform.ts
@@ -190,10 +190,13 @@ interface ISetImmediate {
(callback: (...args: unknown[]) => void): void;
}
-export const setImmediate: ISetImmediate = (function defineSetImmediate() {
- if (globals.setImmediate) {
- return globals.setImmediate.bind(globals);
- }
+/**
+ * See https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#:~:text=than%204%2C%20then-,set%20timeout%20to%204,-.
+ *
+ * Works similarly to `setTimeout(0)` but doesn't suffer from the 4ms artificial delay
+ * that browsers set when the nesting level is > 5.
+ */
+export const setTimeout0 = (() => {
if (typeof globals.postMessage === 'function' && !globals.importScripts) {
interface IQueueElement {
id: number;
@@ -201,10 +204,10 @@ export const setImmediate: ISetImmediate = (function defineSetImmediate() {
}
let pending: IQueueElement[] = [];
globals.addEventListener('message', (e: MessageEvent) => {
- if (e.data && e.data.vscodeSetImmediateId) {
+ if (e.data && e.data.vscodeScheduleAsyncWork) {
for (let i = 0, len = pending.length; i < len; i++) {
const candidate = pending[i];
- if (candidate.id === e.data.vscodeSetImmediateId) {
+ if (candidate.id === e.data.vscodeScheduleAsyncWork) {
pending.splice(i, 1);
candidate.callback();
return;
@@ -219,9 +222,19 @@ export const setImmediate: ISetImmediate = (function defineSetImmediate() {
id: myId,
callback: callback
});
- globals.postMessage({ vscodeSetImmediateId: myId }, '*');
+ globals.postMessage({ vscodeScheduleAsyncWork: myId }, '*');
};
}
+ return (callback: () => void) => setTimeout(callback);
+})();
+
+export const setImmediate: ISetImmediate = (function defineSetImmediate() {
+ if (globals.setImmediate) {
+ return globals.setImmediate.bind(globals);
+ }
+ if (typeof globals.postMessage === 'function' && !globals.importScripts) {
+ return setTimeout0;
+ }
if (typeof nodeProcess?.nextTick === 'function') {
return nodeProcess.nextTick.bind(nodeProcess);
}
diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts
index e5a0af70bb2..ac67491f049 100644
--- a/src/vs/base/common/strings.ts
+++ b/src/vs/base/common/strings.ts
@@ -549,9 +549,9 @@ export function getCharContainingOffset(str: string, offset: number): [number, n
}
/**
- * Generated using https://github.com/alexdima/unicode-utils/blob/master/generate-rtl-test.js
+ * Generated using https://github.com/alexdima/unicode-utils/blob/main/rtl-test.js
*/
-const CONTAINS_RTL = /(?:[\u05BE\u05C0\u05C3\u05C6\u05D0-\u05F4\u0608\u060B\u060D\u061B-\u064A\u066D-\u066F\u0671-\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u0710\u0712-\u072F\u074D-\u07A5\u07B1-\u07EA\u07F4\u07F5\u07FA-\u0815\u081A\u0824\u0828\u0830-\u0858\u085E-\u08BD\u200F\uFB1D\uFB1F-\uFB28\uFB2A-\uFD3D\uFD50-\uFDFC\uFE70-\uFEFC]|\uD802[\uDC00-\uDD1B\uDD20-\uDE00\uDE10-\uDE33\uDE40-\uDEE4\uDEEB-\uDF35\uDF40-\uDFFF]|\uD803[\uDC00-\uDCFF]|\uD83A[\uDC00-\uDCCF\uDD00-\uDD43\uDD50-\uDFFF]|\uD83B[\uDC00-\uDEBB])/;
+const CONTAINS_RTL = /(?:[\u05BE\u05C0\u05C3\u05C6\u05D0-\u05F4\u0608\u060B\u060D\u061B-\u064A\u066D-\u066F\u0671-\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u0710\u0712-\u072F\u074D-\u07A5\u07B1-\u07EA\u07F4\u07F5\u07FA\u07FE-\u0815\u081A\u0824\u0828\u0830-\u0858\u085E-\u088E\u08A0-\u08C9\u200F\uFB1D\uFB1F-\uFB28\uFB2A-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFC\uFE70-\uFEFC]|\uD802[\uDC00-\uDD1B\uDD20-\uDE00\uDE10-\uDE35\uDE40-\uDEE4\uDEEB-\uDF35\uDF40-\uDFFF]|\uD803[\uDC00-\uDD23\uDE80-\uDEA9\uDEAD-\uDF45\uDF51-\uDF81\uDF86-\uDFF6]|\uD83A[\uDC00-\uDCCF\uDD00-\uDD43\uDD4B-\uDFFF]|\uD83B[\uDC00-\uDEBB])/;
/**
* Returns true if `str` contains any Unicode character that is classified as "R" or "AL".
@@ -561,9 +561,9 @@ export function containsRTL(str: string): boolean {
}
/**
- * Generated using https://github.com/alexdima/unicode-utils/blob/master/generate-emoji-test.js
+ * Generated using https://github.com/alexdima/unicode-utils/blob/main/emoji-test.js
*/
-const CONTAINS_EMOJI = /(?:[\u231A\u231B\u23F0\u23F3\u2600-\u27BF\u2B50\u2B55]|\uD83C[\uDDE6-\uDDFF\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F\uDE80-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD00-\uDDFF\uDE70-\uDED6])/;
+const CONTAINS_EMOJI = /(?:[\u231A\u231B\u23F0\u23F3\u2600-\u27BF\u2B50\u2B55]|\uD83C[\uDDE6-\uDDFF\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F\uDE80-\uDEFC\uDFE0-\uDFF0]|\uD83E[\uDD00-\uDDFF\uDE70-\uDEF6])/;
export function containsEmoji(str: string): boolean {
return CONTAINS_EMOJI.test(str);
@@ -642,15 +642,15 @@ export function isFullWidthCharacter(charCode: number): boolean {
/**
* A fast function (therefore imprecise) to check if code points are emojis.
- * Generated using https://github.com/alexdima/unicode-utils/blob/master/generate-emoji-test.js
+ * Generated using https://github.com/alexdima/unicode-utils/blob/main/emoji-test.js
*/
export function isEmojiImprecise(x: number): boolean {
return (
(x >= 0x1F1E6 && x <= 0x1F1FF) || (x === 8986) || (x === 8987) || (x === 9200)
|| (x === 9203) || (x >= 9728 && x <= 10175) || (x === 11088) || (x === 11093)
|| (x >= 127744 && x <= 128591) || (x >= 128640 && x <= 128764)
- || (x >= 128992 && x <= 129003) || (x >= 129280 && x <= 129535)
- || (x >= 129648 && x <= 129750)
+ || (x >= 128992 && x <= 129008) || (x >= 129280 && x <= 129535)
+ || (x >= 129648 && x <= 129782)
);
}
@@ -948,8 +948,8 @@ class GraphemeBreakTree {
}
function getGraphemeBreakRawData(): number[] {
- // generated using https://github.com/alexdima/unicode-utils/blob/master/generate-grapheme-break.js
- return JSON.parse('[0,0,0,51592,51592,11,44424,44424,11,72251,72254,5,7150,7150,7,48008,48008,11,55176,55176,11,128420,128420,14,3276,3277,5,9979,9980,14,46216,46216,11,49800,49800,11,53384,53384,11,70726,70726,5,122915,122916,5,129320,129327,14,2558,2558,5,5906,5908,5,9762,9763,14,43360,43388,8,45320,45320,11,47112,47112,11,48904,48904,11,50696,50696,11,52488,52488,11,54280,54280,11,70082,70083,1,71350,71350,7,73111,73111,5,127892,127893,14,128726,128727,14,129473,129474,14,2027,2035,5,2901,2902,5,3784,3789,5,6754,6754,5,8418,8420,5,9877,9877,14,11088,11088,14,44008,44008,5,44872,44872,11,45768,45768,11,46664,46664,11,47560,47560,11,48456,48456,11,49352,49352,11,50248,50248,11,51144,51144,11,52040,52040,11,52936,52936,11,53832,53832,11,54728,54728,11,69811,69814,5,70459,70460,5,71096,71099,7,71998,71998,5,72874,72880,5,119149,119149,7,127374,127374,14,128335,128335,14,128482,128482,14,128765,128767,14,129399,129400,14,129680,129685,14,1476,1477,5,2377,2380,7,2759,2760,5,3137,3140,7,3458,3459,7,4153,4154,5,6432,6434,5,6978,6978,5,7675,7679,5,9723,9726,14,9823,9823,14,9919,9923,14,10035,10036,14,42736,42737,5,43596,43596,5,44200,44200,11,44648,44648,11,45096,45096,11,45544,45544,11,45992,45992,11,46440,46440,11,46888,46888,11,47336,47336,11,47784,47784,11,48232,48232,11,48680,48680,11,49128,49128,11,49576,49576,11,50024,50024,11,50472,50472,11,50920,50920,11,51368,51368,11,51816,51816,11,52264,52264,11,52712,52712,11,53160,53160,11,53608,53608,11,54056,54056,11,54504,54504,11,54952,54952,11,68108,68111,5,69933,69940,5,70197,70197,7,70498,70499,7,70845,70845,5,71229,71229,5,71727,71735,5,72154,72155,5,72344,72345,5,73023,73029,5,94095,94098,5,121403,121452,5,126981,127182,14,127538,127546,14,127990,127990,14,128391,128391,14,128445,128449,14,128500,128505,14,128752,128752,14,129160,129167,14,129356,129356,14,129432,129442,14,129648,129651,14,129751,131069,14,173,173,4,1757,1757,1,2274,2274,1,2494,2494,5,2641,2641,5,2876,2876,5,3014,3016,7,3262,3262,7,3393,3396,5,3570,3571,7,3968,3972,5,4228,4228,7,6086,6086,5,6679,6680,5,6912,6915,5,7080,7081,5,7380,7392,5,8252,8252,14,9096,9096,14,9748,9749,14,9784,9786,14,9833,9850,14,9890,9894,14,9938,9938,14,9999,9999,14,10085,10087,14,12349,12349,14,43136,43137,7,43454,43456,7,43755,43755,7,44088,44088,11,44312,44312,11,44536,44536,11,44760,44760,11,44984,44984,11,45208,45208,11,45432,45432,11,45656,45656,11,45880,45880,11,46104,46104,11,46328,46328,11,46552,46552,11,46776,46776,11,47000,47000,11,47224,47224,11,47448,47448,11,47672,47672,11,47896,47896,11,48120,48120,11,48344,48344,11,48568,48568,11,48792,48792,11,49016,49016,11,49240,49240,11,49464,49464,11,49688,49688,11,49912,49912,11,50136,50136,11,50360,50360,11,50584,50584,11,50808,50808,11,51032,51032,11,51256,51256,11,51480,51480,11,51704,51704,11,51928,51928,11,52152,52152,11,52376,52376,11,52600,52600,11,52824,52824,11,53048,53048,11,53272,53272,11,53496,53496,11,53720,53720,11,53944,53944,11,54168,54168,11,54392,54392,11,54616,54616,11,54840,54840,11,55064,55064,11,65438,65439,5,69633,69633,5,69837,69837,1,70018,70018,7,70188,70190,7,70368,70370,7,70465,70468,7,70712,70719,5,70835,70840,5,70850,70851,5,71132,71133,5,71340,71340,7,71458,71461,5,71985,71989,7,72002,72002,7,72193,72202,5,72281,72283,5,72766,72766,7,72885,72886,5,73104,73105,5,92912,92916,5,113824,113827,4,119173,119179,5,121505,121519,5,125136,125142,5,127279,127279,14,127489,127490,14,127570,127743,14,127900,127901,14,128254,128254,14,128369,128370,14,128400,128400,14,128425,128432,14,128468,128475,14,128489,128494,14,128715,128720,14,128745,128745,14,128759,128760,14,129004,129023,14,129296,129304,14,129340,129342,14,129388,129392,14,129404,129407,14,129454,129455,14,129485,129487,14,129659,129663,14,129719,129727,14,917536,917631,5,13,13,2,1160,1161,5,1564,1564,4,1807,1807,1,2085,2087,5,2363,2363,7,2402,2403,5,2507,2508,7,2622,2624,7,2691,2691,7,2786,2787,5,2881,2884,5,3006,3006,5,3072,3072,5,3170,3171,5,3267,3268,7,3330,3331,7,3406,3406,1,3538,3540,5,3655,3662,5,3897,3897,5,4038,4038,5,4184,4185,5,4352,4447,8,6068,6069,5,6155,6157,5,6448,6449,7,6742,6742,5,6783,6783,5,6966,6970,5,7042,7042,7,7143,7143,7,7212,7219,5,7412,7412,5,8206,8207,4,8294,8303,4,8596,8601,14,9410,9410,14,9742,9742,14,9757,9757,14,9770,9770,14,9794,9794,14,9828,9828,14,9855,9855,14,9882,9882,14,9900,9903,14,9929,9933,14,9963,9967,14,9987,9988,14,10006,10006,14,10062,10062,14,10175,10175,14,11744,11775,5,42607,42607,5,43043,43044,7,43263,43263,5,43444,43445,7,43569,43570,5,43698,43700,5,43766,43766,5,44032,44032,11,44144,44144,11,44256,44256,11,44368,44368,11,44480,44480,11,44592,44592,11,44704,44704,11,44816,44816,11,44928,44928,11,45040,45040,11,45152,45152,11,45264,45264,11,45376,45376,11,45488,45488,11,45600,45600,11,45712,45712,11,45824,45824,11,45936,45936,11,46048,46048,11,46160,46160,11,46272,46272,11,46384,46384,11,46496,46496,11,46608,46608,11,46720,46720,11,46832,46832,11,46944,46944,11,47056,47056,11,47168,47168,11,47280,47280,11,47392,47392,11,47504,47504,11,47616,47616,11,47728,47728,11,47840,47840,11,47952,47952,11,48064,48064,11,48176,48176,11,48288,48288,11,48400,48400,11,48512,48512,11,48624,48624,11,48736,48736,11,48848,48848,11,48960,48960,11,49072,49072,11,49184,49184,11,49296,49296,11,49408,49408,11,49520,49520,11,49632,49632,11,49744,49744,11,49856,49856,11,49968,49968,11,50080,50080,11,50192,50192,11,50304,50304,11,50416,50416,11,50528,50528,11,50640,50640,11,50752,50752,11,50864,50864,11,50976,50976,11,51088,51088,11,51200,51200,11,51312,51312,11,51424,51424,11,51536,51536,11,51648,51648,11,51760,51760,11,51872,51872,11,51984,51984,11,52096,52096,11,52208,52208,11,52320,52320,11,52432,52432,11,52544,52544,11,52656,52656,11,52768,52768,11,52880,52880,11,52992,52992,11,53104,53104,11,53216,53216,11,53328,53328,11,53440,53440,11,53552,53552,11,53664,53664,11,53776,53776,11,53888,53888,11,54000,54000,11,54112,54112,11,54224,54224,11,54336,54336,11,54448,54448,11,54560,54560,11,54672,54672,11,54784,54784,11,54896,54896,11,55008,55008,11,55120,55120,11,64286,64286,5,66272,66272,5,68900,68903,5,69762,69762,7,69817,69818,5,69927,69931,5,70003,70003,5,70070,70078,5,70094,70094,7,70194,70195,7,70206,70206,5,70400,70401,5,70463,70463,7,70475,70477,7,70512,70516,5,70722,70724,5,70832,70832,5,70842,70842,5,70847,70848,5,71088,71089,7,71102,71102,7,71219,71226,5,71231,71232,5,71342,71343,7,71453,71455,5,71463,71467,5,71737,71738,5,71995,71996,5,72000,72000,7,72145,72147,7,72160,72160,5,72249,72249,7,72273,72278,5,72330,72342,5,72752,72758,5,72850,72871,5,72882,72883,5,73018,73018,5,73031,73031,5,73109,73109,5,73461,73462,7,94031,94031,5,94192,94193,7,119142,119142,7,119155,119162,4,119362,119364,5,121476,121476,5,122888,122904,5,123184,123190,5,126976,126979,14,127184,127231,14,127344,127345,14,127405,127461,14,127514,127514,14,127561,127567,14,127778,127779,14,127896,127896,14,127985,127986,14,127995,127999,5,128326,128328,14,128360,128366,14,128378,128378,14,128394,128397,14,128405,128406,14,128422,128423,14,128435,128443,14,128453,128464,14,128479,128480,14,128484,128487,14,128496,128498,14,128640,128709,14,128723,128724,14,128736,128741,14,128747,128748,14,128755,128755,14,128762,128762,14,128981,128991,14,129096,129103,14,129292,129292,14,129311,129311,14,129329,129330,14,129344,129349,14,129360,129374,14,129394,129394,14,129402,129402,14,129413,129425,14,129445,129450,14,129466,129471,14,129483,129483,14,129511,129535,14,129653,129655,14,129667,129670,14,129705,129711,14,129731,129743,14,917505,917505,4,917760,917999,5,10,10,3,127,159,4,768,879,5,1471,1471,5,1536,1541,1,1648,1648,5,1767,1768,5,1840,1866,5,2070,2073,5,2137,2139,5,2307,2307,7,2366,2368,7,2382,2383,7,2434,2435,7,2497,2500,5,2519,2519,5,2563,2563,7,2631,2632,5,2677,2677,5,2750,2752,7,2763,2764,7,2817,2817,5,2879,2879,5,2891,2892,7,2914,2915,5,3008,3008,5,3021,3021,5,3076,3076,5,3146,3149,5,3202,3203,7,3264,3265,7,3271,3272,7,3298,3299,5,3390,3390,5,3402,3404,7,3426,3427,5,3535,3535,5,3544,3550,7,3635,3635,7,3763,3763,7,3893,3893,5,3953,3966,5,3981,3991,5,4145,4145,7,4157,4158,5,4209,4212,5,4237,4237,5,4520,4607,10,5970,5971,5,6071,6077,5,6089,6099,5,6277,6278,5,6439,6440,5,6451,6456,7,6683,6683,5,6744,6750,5,6765,6770,7,6846,6846,5,6964,6964,5,6972,6972,5,7019,7027,5,7074,7077,5,7083,7085,5,7146,7148,7,7154,7155,7,7222,7223,5,7394,7400,5,7416,7417,5,8204,8204,5,8233,8233,4,8288,8292,4,8413,8416,5,8482,8482,14,8986,8987,14,9193,9203,14,9654,9654,14,9733,9733,14,9745,9745,14,9752,9752,14,9760,9760,14,9766,9766,14,9774,9775,14,9792,9792,14,9800,9811,14,9825,9826,14,9831,9831,14,9852,9853,14,9872,9873,14,9880,9880,14,9885,9887,14,9896,9897,14,9906,9916,14,9926,9927,14,9936,9936,14,9941,9960,14,9974,9974,14,9982,9985,14,9992,9997,14,10002,10002,14,10017,10017,14,10055,10055,14,10071,10071,14,10145,10145,14,11013,11015,14,11503,11505,5,12334,12335,5,12951,12951,14,42612,42621,5,43014,43014,5,43047,43047,7,43204,43205,5,43335,43345,5,43395,43395,7,43450,43451,7,43561,43566,5,43573,43574,5,43644,43644,5,43710,43711,5,43758,43759,7,44005,44005,5,44012,44012,7,44060,44060,11,44116,44116,11,44172,44172,11,44228,44228,11,44284,44284,11,44340,44340,11,44396,44396,11,44452,44452,11,44508,44508,11,44564,44564,11,44620,44620,11,44676,44676,11,44732,44732,11,44788,44788,11,44844,44844,11,44900,44900,11,44956,44956,11,45012,45012,11,45068,45068,11,45124,45124,11,45180,45180,11,45236,45236,11,45292,45292,11,45348,45348,11,45404,45404,11,45460,45460,11,45516,45516,11,45572,45572,11,45628,45628,11,45684,45684,11,45740,45740,11,45796,45796,11,45852,45852,11,45908,45908,11,45964,45964,11,46020,46020,11,46076,46076,11,46132,46132,11,46188,46188,11,46244,46244,11,46300,46300,11,46356,46356,11,46412,46412,11,46468,46468,11,46524,46524,11,46580,46580,11,46636,46636,11,46692,46692,11,46748,46748,11,46804,46804,11,46860,46860,11,46916,46916,11,46972,46972,11,47028,47028,11,47084,47084,11,47140,47140,11,47196,47196,11,47252,47252,11,47308,47308,11,47364,47364,11,47420,47420,11,47476,47476,11,47532,47532,11,47588,47588,11,47644,47644,11,47700,47700,11,47756,47756,11,47812,47812,11,47868,47868,11,47924,47924,11,47980,47980,11,48036,48036,11,48092,48092,11,48148,48148,11,48204,48204,11,48260,48260,11,48316,48316,11,48372,48372,11,48428,48428,11,48484,48484,11,48540,48540,11,48596,48596,11,48652,48652,11,48708,48708,11,48764,48764,11,48820,48820,11,48876,48876,11,48932,48932,11,48988,48988,11,49044,49044,11,49100,49100,11,49156,49156,11,49212,49212,11,49268,49268,11,49324,49324,11,49380,49380,11,49436,49436,11,49492,49492,11,49548,49548,11,49604,49604,11,49660,49660,11,49716,49716,11,49772,49772,11,49828,49828,11,49884,49884,11,49940,49940,11,49996,49996,11,50052,50052,11,50108,50108,11,50164,50164,11,50220,50220,11,50276,50276,11,50332,50332,11,50388,50388,11,50444,50444,11,50500,50500,11,50556,50556,11,50612,50612,11,50668,50668,11,50724,50724,11,50780,50780,11,50836,50836,11,50892,50892,11,50948,50948,11,51004,51004,11,51060,51060,11,51116,51116,11,51172,51172,11,51228,51228,11,51284,51284,11,51340,51340,11,51396,51396,11,51452,51452,11,51508,51508,11,51564,51564,11,51620,51620,11,51676,51676,11,51732,51732,11,51788,51788,11,51844,51844,11,51900,51900,11,51956,51956,11,52012,52012,11,52068,52068,11,52124,52124,11,52180,52180,11,52236,52236,11,52292,52292,11,52348,52348,11,52404,52404,11,52460,52460,11,52516,52516,11,52572,52572,11,52628,52628,11,52684,52684,11,52740,52740,11,52796,52796,11,52852,52852,11,52908,52908,11,52964,52964,11,53020,53020,11,53076,53076,11,53132,53132,11,53188,53188,11,53244,53244,11,53300,53300,11,53356,53356,11,53412,53412,11,53468,53468,11,53524,53524,11,53580,53580,11,53636,53636,11,53692,53692,11,53748,53748,11,53804,53804,11,53860,53860,11,53916,53916,11,53972,53972,11,54028,54028,11,54084,54084,11,54140,54140,11,54196,54196,11,54252,54252,11,54308,54308,11,54364,54364,11,54420,54420,11,54476,54476,11,54532,54532,11,54588,54588,11,54644,54644,11,54700,54700,11,54756,54756,11,54812,54812,11,54868,54868,11,54924,54924,11,54980,54980,11,55036,55036,11,55092,55092,11,55148,55148,11,55216,55238,9,65056,65071,5,65529,65531,4,68097,68099,5,68159,68159,5,69446,69456,5,69688,69702,5,69808,69810,7,69815,69816,7,69821,69821,1,69888,69890,5,69932,69932,7,69957,69958,7,70016,70017,5,70067,70069,7,70079,70080,7,70089,70092,5,70095,70095,5,70191,70193,5,70196,70196,5,70198,70199,5,70367,70367,5,70371,70378,5,70402,70403,7,70462,70462,5,70464,70464,5,70471,70472,7,70487,70487,5,70502,70508,5,70709,70711,7,70720,70721,7,70725,70725,7,70750,70750,5,70833,70834,7,70841,70841,7,70843,70844,7,70846,70846,7,70849,70849,7,71087,71087,5,71090,71093,5,71100,71101,5,71103,71104,5,71216,71218,7,71227,71228,7,71230,71230,7,71339,71339,5,71341,71341,5,71344,71349,5,71351,71351,5,71456,71457,7,71462,71462,7,71724,71726,7,71736,71736,7,71984,71984,5,71991,71992,7,71997,71997,7,71999,71999,1,72001,72001,1,72003,72003,5,72148,72151,5,72156,72159,7,72164,72164,7,72243,72248,5,72250,72250,1,72263,72263,5,72279,72280,7,72324,72329,1,72343,72343,7,72751,72751,7,72760,72765,5,72767,72767,5,72873,72873,7,72881,72881,7,72884,72884,7,73009,73014,5,73020,73021,5,73030,73030,1,73098,73102,7,73107,73108,7,73110,73110,7,73459,73460,5,78896,78904,4,92976,92982,5,94033,94087,7,94180,94180,5,113821,113822,5,119141,119141,5,119143,119145,5,119150,119154,5,119163,119170,5,119210,119213,5,121344,121398,5,121461,121461,5,121499,121503,5,122880,122886,5,122907,122913,5,122918,122922,5,123628,123631,5,125252,125258,5,126980,126980,14,127183,127183,14,127245,127247,14,127340,127343,14,127358,127359,14,127377,127386,14,127462,127487,6,127491,127503,14,127535,127535,14,127548,127551,14,127568,127569,14,127744,127777,14,127780,127891,14,127894,127895,14,127897,127899,14,127902,127984,14,127987,127989,14,127991,127994,14,128000,128253,14,128255,128317,14,128329,128334,14,128336,128359,14,128367,128368,14,128371,128377,14,128379,128390,14,128392,128393,14,128398,128399,14,128401,128404,14,128407,128419,14,128421,128421,14,128424,128424,14,128433,128434,14,128444,128444,14,128450,128452,14,128465,128467,14,128476,128478,14,128481,128481,14,128483,128483,14,128488,128488,14,128495,128495,14,128499,128499,14,128506,128591,14,128710,128714,14,128721,128722,14,128725,128725,14,128728,128735,14,128742,128744,14,128746,128746,14,128749,128751,14,128753,128754,14,128756,128758,14,128761,128761,14,128763,128764,14,128884,128895,14,128992,129003,14,129036,129039,14,129114,129119,14,129198,129279,14,129293,129295,14,129305,129310,14,129312,129319,14,129328,129328,14,129331,129338,14,129343,129343,14,129351,129355,14,129357,129359,14,129375,129387,14,129393,129393,14,129395,129398,14,129401,129401,14,129403,129403,14,129408,129412,14,129426,129431,14,129443,129444,14,129451,129453,14,129456,129465,14,129472,129472,14,129475,129482,14,129484,129484,14,129488,129510,14,129536,129647,14,129652,129652,14,129656,129658,14,129664,129666,14,129671,129679,14,129686,129704,14,129712,129718,14,129728,129730,14,129744,129750,14,917504,917504,4,917506,917535,4,917632,917759,4,918000,921599,4,0,9,4,11,12,4,14,31,4,169,169,14,174,174,14,1155,1159,5,1425,1469,5,1473,1474,5,1479,1479,5,1552,1562,5,1611,1631,5,1750,1756,5,1759,1764,5,1770,1773,5,1809,1809,5,1958,1968,5,2045,2045,5,2075,2083,5,2089,2093,5,2259,2273,5,2275,2306,5,2362,2362,5,2364,2364,5,2369,2376,5,2381,2381,5,2385,2391,5,2433,2433,5,2492,2492,5,2495,2496,7,2503,2504,7,2509,2509,5,2530,2531,5,2561,2562,5,2620,2620,5,2625,2626,5,2635,2637,5,2672,2673,5,2689,2690,5,2748,2748,5,2753,2757,5,2761,2761,7,2765,2765,5,2810,2815,5,2818,2819,7,2878,2878,5,2880,2880,7,2887,2888,7,2893,2893,5,2903,2903,5,2946,2946,5,3007,3007,7,3009,3010,7,3018,3020,7,3031,3031,5,3073,3075,7,3134,3136,5,3142,3144,5,3157,3158,5,3201,3201,5,3260,3260,5,3263,3263,5,3266,3266,5,3270,3270,5,3274,3275,7,3285,3286,5,3328,3329,5,3387,3388,5,3391,3392,7,3398,3400,7,3405,3405,5,3415,3415,5,3457,3457,5,3530,3530,5,3536,3537,7,3542,3542,5,3551,3551,5,3633,3633,5,3636,3642,5,3761,3761,5,3764,3772,5,3864,3865,5,3895,3895,5,3902,3903,7,3967,3967,7,3974,3975,5,3993,4028,5,4141,4144,5,4146,4151,5,4155,4156,7,4182,4183,7,4190,4192,5,4226,4226,5,4229,4230,5,4253,4253,5,4448,4519,9,4957,4959,5,5938,5940,5,6002,6003,5,6070,6070,7,6078,6085,7,6087,6088,7,6109,6109,5,6158,6158,4,6313,6313,5,6435,6438,7,6441,6443,7,6450,6450,5,6457,6459,5,6681,6682,7,6741,6741,7,6743,6743,7,6752,6752,5,6757,6764,5,6771,6780,5,6832,6845,5,6847,6848,5,6916,6916,7,6965,6965,5,6971,6971,7,6973,6977,7,6979,6980,7,7040,7041,5,7073,7073,7,7078,7079,7,7082,7082,7,7142,7142,5,7144,7145,5,7149,7149,5,7151,7153,5,7204,7211,7,7220,7221,7,7376,7378,5,7393,7393,7,7405,7405,5,7415,7415,7,7616,7673,5,8203,8203,4,8205,8205,13,8232,8232,4,8234,8238,4,8265,8265,14,8293,8293,4,8400,8412,5,8417,8417,5,8421,8432,5,8505,8505,14,8617,8618,14,9000,9000,14,9167,9167,14,9208,9210,14,9642,9643,14,9664,9664,14,9728,9732,14,9735,9741,14,9743,9744,14,9746,9746,14,9750,9751,14,9753,9756,14,9758,9759,14,9761,9761,14,9764,9765,14,9767,9769,14,9771,9773,14,9776,9783,14,9787,9791,14,9793,9793,14,9795,9799,14,9812,9822,14,9824,9824,14,9827,9827,14,9829,9830,14,9832,9832,14,9851,9851,14,9854,9854,14,9856,9861,14,9874,9876,14,9878,9879,14,9881,9881,14,9883,9884,14,9888,9889,14,9895,9895,14,9898,9899,14,9904,9905,14,9917,9918,14,9924,9925,14,9928,9928,14,9934,9935,14,9937,9937,14,9939,9940,14,9961,9962,14,9968,9973,14,9975,9978,14,9981,9981,14,9986,9986,14,9989,9989,14,9998,9998,14,10000,10001,14,10004,10004,14,10013,10013,14,10024,10024,14,10052,10052,14,10060,10060,14,10067,10069,14,10083,10084,14,10133,10135,14,10160,10160,14,10548,10549,14,11035,11036,14,11093,11093,14,11647,11647,5,12330,12333,5,12336,12336,14,12441,12442,5,12953,12953,14,42608,42610,5,42654,42655,5,43010,43010,5,43019,43019,5,43045,43046,5,43052,43052,5,43188,43203,7,43232,43249,5,43302,43309,5,43346,43347,7,43392,43394,5,43443,43443,5,43446,43449,5,43452,43453,5,43493,43493,5,43567,43568,7,43571,43572,7,43587,43587,5,43597,43597,7,43696,43696,5,43703,43704,5,43713,43713,5,43756,43757,5,43765,43765,7,44003,44004,7,44006,44007,7,44009,44010,7,44013,44013,5,44033,44059,12,44061,44087,12,44089,44115,12,44117,44143,12,44145,44171,12,44173,44199,12,44201,44227,12,44229,44255,12,44257,44283,12,44285,44311,12,44313,44339,12,44341,44367,12,44369,44395,12,44397,44423,12,44425,44451,12,44453,44479,12,44481,44507,12,44509,44535,12,44537,44563,12,44565,44591,12,44593,44619,12,44621,44647,12,44649,44675,12,44677,44703,12,44705,44731,12,44733,44759,12,44761,44787,12,44789,44815,12,44817,44843,12,44845,44871,12,44873,44899,12,44901,44927,12,44929,44955,12,44957,44983,12,44985,45011,12,45013,45039,12,45041,45067,12,45069,45095,12,45097,45123,12,45125,45151,12,45153,45179,12,45181,45207,12,45209,45235,12,45237,45263,12,45265,45291,12,45293,45319,12,45321,45347,12,45349,45375,12,45377,45403,12,45405,45431,12,45433,45459,12,45461,45487,12,45489,45515,12,45517,45543,12,45545,45571,12,45573,45599,12,45601,45627,12,45629,45655,12,45657,45683,12,45685,45711,12,45713,45739,12,45741,45767,12,45769,45795,12,45797,45823,12,45825,45851,12,45853,45879,12,45881,45907,12,45909,45935,12,45937,45963,12,45965,45991,12,45993,46019,12,46021,46047,12,46049,46075,12,46077,46103,12,46105,46131,12,46133,46159,12,46161,46187,12,46189,46215,12,46217,46243,12,46245,46271,12,46273,46299,12,46301,46327,12,46329,46355,12,46357,46383,12,46385,46411,12,46413,46439,12,46441,46467,12,46469,46495,12,46497,46523,12,46525,46551,12,46553,46579,12,46581,46607,12,46609,46635,12,46637,46663,12,46665,46691,12,46693,46719,12,46721,46747,12,46749,46775,12,46777,46803,12,46805,46831,12,46833,46859,12,46861,46887,12,46889,46915,12,46917,46943,12,46945,46971,12,46973,46999,12,47001,47027,12,47029,47055,12,47057,47083,12,47085,47111,12,47113,47139,12,47141,47167,12,47169,47195,12,47197,47223,12,47225,47251,12,47253,47279,12,47281,47307,12,47309,47335,12,47337,47363,12,47365,47391,12,47393,47419,12,47421,47447,12,47449,47475,12,47477,47503,12,47505,47531,12,47533,47559,12,47561,47587,12,47589,47615,12,47617,47643,12,47645,47671,12,47673,47699,12,47701,47727,12,47729,47755,12,47757,47783,12,47785,47811,12,47813,47839,12,47841,47867,12,47869,47895,12,47897,47923,12,47925,47951,12,47953,47979,12,47981,48007,12,48009,48035,12,48037,48063,12,48065,48091,12,48093,48119,12,48121,48147,12,48149,48175,12,48177,48203,12,48205,48231,12,48233,48259,12,48261,48287,12,48289,48315,12,48317,48343,12,48345,48371,12,48373,48399,12,48401,48427,12,48429,48455,12,48457,48483,12,48485,48511,12,48513,48539,12,48541,48567,12,48569,48595,12,48597,48623,12,48625,48651,12,48653,48679,12,48681,48707,12,48709,48735,12,48737,48763,12,48765,48791,12,48793,48819,12,48821,48847,12,48849,48875,12,48877,48903,12,48905,48931,12,48933,48959,12,48961,48987,12,48989,49015,12,49017,49043,12,49045,49071,12,49073,49099,12,49101,49127,12,49129,49155,12,49157,49183,12,49185,49211,12,49213,49239,12,49241,49267,12,49269,49295,12,49297,49323,12,49325,49351,12,49353,49379,12,49381,49407,12,49409,49435,12,49437,49463,12,49465,49491,12,49493,49519,12,49521,49547,12,49549,49575,12,49577,49603,12,49605,49631,12,49633,49659,12,49661,49687,12,49689,49715,12,49717,49743,12,49745,49771,12,49773,49799,12,49801,49827,12,49829,49855,12,49857,49883,12,49885,49911,12,49913,49939,12,49941,49967,12,49969,49995,12,49997,50023,12,50025,50051,12,50053,50079,12,50081,50107,12,50109,50135,12,50137,50163,12,50165,50191,12,50193,50219,12,50221,50247,12,50249,50275,12,50277,50303,12,50305,50331,12,50333,50359,12,50361,50387,12,50389,50415,12,50417,50443,12,50445,50471,12,50473,50499,12,50501,50527,12,50529,50555,12,50557,50583,12,50585,50611,12,50613,50639,12,50641,50667,12,50669,50695,12,50697,50723,12,50725,50751,12,50753,50779,12,50781,50807,12,50809,50835,12,50837,50863,12,50865,50891,12,50893,50919,12,50921,50947,12,50949,50975,12,50977,51003,12,51005,51031,12,51033,51059,12,51061,51087,12,51089,51115,12,51117,51143,12,51145,51171,12,51173,51199,12,51201,51227,12,51229,51255,12,51257,51283,12,51285,51311,12,51313,51339,12,51341,51367,12,51369,51395,12,51397,51423,12,51425,51451,12,51453,51479,12,51481,51507,12,51509,51535,12,51537,51563,12,51565,51591,12,51593,51619,12,51621,51647,12,51649,51675,12,51677,51703,12,51705,51731,12,51733,51759,12,51761,51787,12,51789,51815,12,51817,51843,12,51845,51871,12,51873,51899,12,51901,51927,12,51929,51955,12,51957,51983,12,51985,52011,12,52013,52039,12,52041,52067,12,52069,52095,12,52097,52123,12,52125,52151,12,52153,52179,12,52181,52207,12,52209,52235,12,52237,52263,12,52265,52291,12,52293,52319,12,52321,52347,12,52349,52375,12,52377,52403,12,52405,52431,12,52433,52459,12,52461,52487,12,52489,52515,12,52517,52543,12,52545,52571,12,52573,52599,12,52601,52627,12,52629,52655,12,52657,52683,12,52685,52711,12,52713,52739,12,52741,52767,12,52769,52795,12,52797,52823,12,52825,52851,12,52853,52879,12,52881,52907,12,52909,52935,12,52937,52963,12,52965,52991,12,52993,53019,12,53021,53047,12,53049,53075,12,53077,53103,12,53105,53131,12,53133,53159,12,53161,53187,12,53189,53215,12,53217,53243,12,53245,53271,12,53273,53299,12,53301,53327,12,53329,53355,12,53357,53383,12,53385,53411,12,53413,53439,12,53441,53467,12,53469,53495,12,53497,53523,12,53525,53551,12,53553,53579,12,53581,53607,12,53609,53635,12,53637,53663,12,53665,53691,12,53693,53719,12,53721,53747,12,53749,53775,12,53777,53803,12,53805,53831,12,53833,53859,12,53861,53887,12,53889,53915,12,53917,53943,12,53945,53971,12,53973,53999,12,54001,54027,12,54029,54055,12,54057,54083,12,54085,54111,12,54113,54139,12,54141,54167,12,54169,54195,12,54197,54223,12,54225,54251,12,54253,54279,12,54281,54307,12,54309,54335,12,54337,54363,12,54365,54391,12,54393,54419,12,54421,54447,12,54449,54475,12,54477,54503,12,54505,54531,12,54533,54559,12,54561,54587,12,54589,54615,12,54617,54643,12,54645,54671,12,54673,54699,12,54701,54727,12,54729,54755,12,54757,54783,12,54785,54811,12,54813,54839,12,54841,54867,12,54869,54895,12,54897,54923,12,54925,54951,12,54953,54979,12,54981,55007,12,55009,55035,12,55037,55063,12,55065,55091,12,55093,55119,12,55121,55147,12,55149,55175,12,55177,55203,12,55243,55291,10,65024,65039,5,65279,65279,4,65520,65528,4,66045,66045,5,66422,66426,5,68101,68102,5,68152,68154,5,68325,68326,5,69291,69292,5,69632,69632,7,69634,69634,7,69759,69761,5]');
+ // generated using https://github.com/alexdima/unicode-utils/blob/main/grapheme-break.js
+ return JSON.parse('[0,0,0,51229,51255,12,44061,44087,12,127462,127487,6,7083,7085,5,47645,47671,12,54813,54839,12,128678,128678,14,3270,3270,5,9919,9923,14,45853,45879,12,49437,49463,12,53021,53047,12,71216,71218,7,128398,128399,14,129360,129374,14,2519,2519,5,4448,4519,9,9742,9742,14,12336,12336,14,44957,44983,12,46749,46775,12,48541,48567,12,50333,50359,12,52125,52151,12,53917,53943,12,69888,69890,5,73018,73018,5,127990,127990,14,128558,128559,14,128759,128760,14,129653,129655,14,2027,2035,5,2891,2892,7,3761,3761,5,6683,6683,5,8293,8293,4,9825,9826,14,9999,9999,14,43452,43453,5,44509,44535,12,45405,45431,12,46301,46327,12,47197,47223,12,48093,48119,12,48989,49015,12,49885,49911,12,50781,50807,12,51677,51703,12,52573,52599,12,53469,53495,12,54365,54391,12,65279,65279,4,70471,70472,7,72145,72147,7,119173,119179,5,127799,127818,14,128240,128244,14,128512,128512,14,128652,128652,14,128721,128722,14,129292,129292,14,129445,129450,14,129734,129743,14,1476,1477,5,2366,2368,7,2750,2752,7,3076,3076,5,3415,3415,5,4141,4144,5,6109,6109,5,6964,6964,5,7394,7400,5,9197,9198,14,9770,9770,14,9877,9877,14,9968,9969,14,10084,10084,14,43052,43052,5,43713,43713,5,44285,44311,12,44733,44759,12,45181,45207,12,45629,45655,12,46077,46103,12,46525,46551,12,46973,46999,12,47421,47447,12,47869,47895,12,48317,48343,12,48765,48791,12,49213,49239,12,49661,49687,12,50109,50135,12,50557,50583,12,51005,51031,12,51453,51479,12,51901,51927,12,52349,52375,12,52797,52823,12,53245,53271,12,53693,53719,12,54141,54167,12,54589,54615,12,55037,55063,12,69506,69509,5,70191,70193,5,70841,70841,7,71463,71467,5,72330,72342,5,94031,94031,5,123628,123631,5,127763,127765,14,127941,127941,14,128043,128062,14,128302,128317,14,128465,128467,14,128539,128539,14,128640,128640,14,128662,128662,14,128703,128703,14,128745,128745,14,129004,129007,14,129329,129330,14,129402,129402,14,129483,129483,14,129686,129704,14,130048,131069,14,173,173,4,1757,1757,1,2200,2207,5,2434,2435,7,2631,2632,5,2817,2817,5,3008,3008,5,3201,3201,5,3387,3388,5,3542,3542,5,3902,3903,7,4190,4192,5,6002,6003,5,6439,6440,5,6765,6770,7,7019,7027,5,7154,7155,7,8205,8205,13,8505,8505,14,9654,9654,14,9757,9757,14,9792,9792,14,9852,9853,14,9890,9894,14,9937,9937,14,9981,9981,14,10035,10036,14,11035,11036,14,42654,42655,5,43346,43347,7,43587,43587,5,44006,44007,7,44173,44199,12,44397,44423,12,44621,44647,12,44845,44871,12,45069,45095,12,45293,45319,12,45517,45543,12,45741,45767,12,45965,45991,12,46189,46215,12,46413,46439,12,46637,46663,12,46861,46887,12,47085,47111,12,47309,47335,12,47533,47559,12,47757,47783,12,47981,48007,12,48205,48231,12,48429,48455,12,48653,48679,12,48877,48903,12,49101,49127,12,49325,49351,12,49549,49575,12,49773,49799,12,49997,50023,12,50221,50247,12,50445,50471,12,50669,50695,12,50893,50919,12,51117,51143,12,51341,51367,12,51565,51591,12,51789,51815,12,52013,52039,12,52237,52263,12,52461,52487,12,52685,52711,12,52909,52935,12,53133,53159,12,53357,53383,12,53581,53607,12,53805,53831,12,54029,54055,12,54253,54279,12,54477,54503,12,54701,54727,12,54925,54951,12,55149,55175,12,68101,68102,5,69762,69762,7,70067,70069,7,70371,70378,5,70720,70721,7,71087,71087,5,71341,71341,5,71995,71996,5,72249,72249,7,72850,72871,5,73109,73109,5,118576,118598,5,121505,121519,5,127245,127247,14,127568,127569,14,127777,127777,14,127872,127891,14,127956,127967,14,128015,128016,14,128110,128172,14,128259,128259,14,128367,128368,14,128424,128424,14,128488,128488,14,128530,128532,14,128550,128551,14,128566,128566,14,128647,128647,14,128656,128656,14,128667,128673,14,128691,128693,14,128715,128715,14,128728,128732,14,128752,128752,14,128765,128767,14,129096,129103,14,129311,129311,14,129344,129349,14,129394,129394,14,129413,129425,14,129466,129471,14,129511,129535,14,129664,129666,14,129719,129722,14,129760,129767,14,917536,917631,5,13,13,2,1160,1161,5,1564,1564,4,1807,1807,1,2085,2087,5,2307,2307,7,2382,2383,7,2497,2500,5,2563,2563,7,2677,2677,5,2763,2764,7,2879,2879,5,2914,2915,5,3021,3021,5,3142,3144,5,3263,3263,5,3285,3286,5,3398,3400,7,3530,3530,5,3633,3633,5,3864,3865,5,3974,3975,5,4155,4156,7,4229,4230,5,5909,5909,7,6078,6085,7,6277,6278,5,6451,6456,7,6744,6750,5,6846,6846,5,6972,6972,5,7074,7077,5,7146,7148,7,7222,7223,5,7416,7417,5,8234,8238,4,8417,8417,5,9000,9000,14,9203,9203,14,9730,9731,14,9748,9749,14,9762,9763,14,9776,9783,14,9800,9811,14,9831,9831,14,9872,9873,14,9882,9882,14,9900,9903,14,9929,9933,14,9941,9960,14,9974,9974,14,9989,9989,14,10006,10006,14,10062,10062,14,10160,10160,14,11647,11647,5,12953,12953,14,43019,43019,5,43232,43249,5,43443,43443,5,43567,43568,7,43696,43696,5,43765,43765,7,44013,44013,5,44117,44143,12,44229,44255,12,44341,44367,12,44453,44479,12,44565,44591,12,44677,44703,12,44789,44815,12,44901,44927,12,45013,45039,12,45125,45151,12,45237,45263,12,45349,45375,12,45461,45487,12,45573,45599,12,45685,45711,12,45797,45823,12,45909,45935,12,46021,46047,12,46133,46159,12,46245,46271,12,46357,46383,12,46469,46495,12,46581,46607,12,46693,46719,12,46805,46831,12,46917,46943,12,47029,47055,12,47141,47167,12,47253,47279,12,47365,47391,12,47477,47503,12,47589,47615,12,47701,47727,12,47813,47839,12,47925,47951,12,48037,48063,12,48149,48175,12,48261,48287,12,48373,48399,12,48485,48511,12,48597,48623,12,48709,48735,12,48821,48847,12,48933,48959,12,49045,49071,12,49157,49183,12,49269,49295,12,49381,49407,12,49493,49519,12,49605,49631,12,49717,49743,12,49829,49855,12,49941,49967,12,50053,50079,12,50165,50191,12,50277,50303,12,50389,50415,12,50501,50527,12,50613,50639,12,50725,50751,12,50837,50863,12,50949,50975,12,51061,51087,12,51173,51199,12,51285,51311,12,51397,51423,12,51509,51535,12,51621,51647,12,51733,51759,12,51845,51871,12,51957,51983,12,52069,52095,12,52181,52207,12,52293,52319,12,52405,52431,12,52517,52543,12,52629,52655,12,52741,52767,12,52853,52879,12,52965,52991,12,53077,53103,12,53189,53215,12,53301,53327,12,53413,53439,12,53525,53551,12,53637,53663,12,53749,53775,12,53861,53887,12,53973,53999,12,54085,54111,12,54197,54223,12,54309,54335,12,54421,54447,12,54533,54559,12,54645,54671,12,54757,54783,12,54869,54895,12,54981,55007,12,55093,55119,12,55243,55291,10,66045,66045,5,68325,68326,5,69688,69702,5,69817,69818,5,69957,69958,7,70089,70092,5,70198,70199,5,70462,70462,5,70502,70508,5,70750,70750,5,70846,70846,7,71100,71101,5,71230,71230,7,71351,71351,5,71737,71738,5,72000,72000,7,72160,72160,5,72273,72278,5,72752,72758,5,72882,72883,5,73031,73031,5,73461,73462,7,94192,94193,7,119149,119149,7,121403,121452,5,122915,122916,5,126980,126980,14,127358,127359,14,127535,127535,14,127759,127759,14,127771,127771,14,127792,127793,14,127825,127867,14,127897,127899,14,127945,127945,14,127985,127986,14,128000,128007,14,128021,128021,14,128066,128100,14,128184,128235,14,128249,128252,14,128266,128276,14,128335,128335,14,128379,128390,14,128407,128419,14,128444,128444,14,128481,128481,14,128499,128499,14,128526,128526,14,128536,128536,14,128543,128543,14,128556,128556,14,128564,128564,14,128577,128580,14,128643,128645,14,128649,128649,14,128654,128654,14,128660,128660,14,128664,128664,14,128675,128675,14,128686,128689,14,128695,128696,14,128705,128709,14,128717,128719,14,128725,128725,14,128736,128741,14,128747,128748,14,128755,128755,14,128762,128762,14,128981,128991,14,129009,129023,14,129160,129167,14,129296,129304,14,129320,129327,14,129340,129342,14,129356,129356,14,129388,129392,14,129399,129400,14,129404,129407,14,129432,129442,14,129454,129455,14,129473,129474,14,129485,129487,14,129648,129651,14,129659,129660,14,129671,129679,14,129709,129711,14,129728,129730,14,129751,129753,14,129776,129782,14,917505,917505,4,917760,917999,5,10,10,3,127,159,4,768,879,5,1471,1471,5,1536,1541,1,1648,1648,5,1767,1768,5,1840,1866,5,2070,2073,5,2137,2139,5,2274,2274,1,2363,2363,7,2377,2380,7,2402,2403,5,2494,2494,5,2507,2508,7,2558,2558,5,2622,2624,7,2641,2641,5,2691,2691,7,2759,2760,5,2786,2787,5,2876,2876,5,2881,2884,5,2901,2902,5,3006,3006,5,3014,3016,7,3072,3072,5,3134,3136,5,3157,3158,5,3260,3260,5,3266,3266,5,3274,3275,7,3328,3329,5,3391,3392,7,3405,3405,5,3457,3457,5,3536,3537,7,3551,3551,5,3636,3642,5,3764,3772,5,3895,3895,5,3967,3967,7,3993,4028,5,4146,4151,5,4182,4183,7,4226,4226,5,4253,4253,5,4957,4959,5,5940,5940,7,6070,6070,7,6087,6088,7,6158,6158,4,6432,6434,5,6448,6449,7,6679,6680,5,6742,6742,5,6754,6754,5,6783,6783,5,6912,6915,5,6966,6970,5,6978,6978,5,7042,7042,7,7080,7081,5,7143,7143,7,7150,7150,7,7212,7219,5,7380,7392,5,7412,7412,5,8203,8203,4,8232,8232,4,8265,8265,14,8400,8412,5,8421,8432,5,8617,8618,14,9167,9167,14,9200,9200,14,9410,9410,14,9723,9726,14,9733,9733,14,9745,9745,14,9752,9752,14,9760,9760,14,9766,9766,14,9774,9774,14,9786,9786,14,9794,9794,14,9823,9823,14,9828,9828,14,9833,9850,14,9855,9855,14,9875,9875,14,9880,9880,14,9885,9887,14,9896,9897,14,9906,9916,14,9926,9927,14,9935,9935,14,9939,9939,14,9962,9962,14,9972,9972,14,9978,9978,14,9986,9986,14,9997,9997,14,10002,10002,14,10017,10017,14,10055,10055,14,10071,10071,14,10133,10135,14,10548,10549,14,11093,11093,14,12330,12333,5,12441,12442,5,42608,42610,5,43010,43010,5,43045,43046,5,43188,43203,7,43302,43309,5,43392,43394,5,43446,43449,5,43493,43493,5,43571,43572,7,43597,43597,7,43703,43704,5,43756,43757,5,44003,44004,7,44009,44010,7,44033,44059,12,44089,44115,12,44145,44171,12,44201,44227,12,44257,44283,12,44313,44339,12,44369,44395,12,44425,44451,12,44481,44507,12,44537,44563,12,44593,44619,12,44649,44675,12,44705,44731,12,44761,44787,12,44817,44843,12,44873,44899,12,44929,44955,12,44985,45011,12,45041,45067,12,45097,45123,12,45153,45179,12,45209,45235,12,45265,45291,12,45321,45347,12,45377,45403,12,45433,45459,12,45489,45515,12,45545,45571,12,45601,45627,12,45657,45683,12,45713,45739,12,45769,45795,12,45825,45851,12,45881,45907,12,45937,45963,12,45993,46019,12,46049,46075,12,46105,46131,12,46161,46187,12,46217,46243,12,46273,46299,12,46329,46355,12,46385,46411,12,46441,46467,12,46497,46523,12,46553,46579,12,46609,46635,12,46665,46691,12,46721,46747,12,46777,46803,12,46833,46859,12,46889,46915,12,46945,46971,12,47001,47027,12,47057,47083,12,47113,47139,12,47169,47195,12,47225,47251,12,47281,47307,12,47337,47363,12,47393,47419,12,47449,47475,12,47505,47531,12,47561,47587,12,47617,47643,12,47673,47699,12,47729,47755,12,47785,47811,12,47841,47867,12,47897,47923,12,47953,47979,12,48009,48035,12,48065,48091,12,48121,48147,12,48177,48203,12,48233,48259,12,48289,48315,12,48345,48371,12,48401,48427,12,48457,48483,12,48513,48539,12,48569,48595,12,48625,48651,12,48681,48707,12,48737,48763,12,48793,48819,12,48849,48875,12,48905,48931,12,48961,48987,12,49017,49043,12,49073,49099,12,49129,49155,12,49185,49211,12,49241,49267,12,49297,49323,12,49353,49379,12,49409,49435,12,49465,49491,12,49521,49547,12,49577,49603,12,49633,49659,12,49689,49715,12,49745,49771,12,49801,49827,12,49857,49883,12,49913,49939,12,49969,49995,12,50025,50051,12,50081,50107,12,50137,50163,12,50193,50219,12,50249,50275,12,50305,50331,12,50361,50387,12,50417,50443,12,50473,50499,12,50529,50555,12,50585,50611,12,50641,50667,12,50697,50723,12,50753,50779,12,50809,50835,12,50865,50891,12,50921,50947,12,50977,51003,12,51033,51059,12,51089,51115,12,51145,51171,12,51201,51227,12,51257,51283,12,51313,51339,12,51369,51395,12,51425,51451,12,51481,51507,12,51537,51563,12,51593,51619,12,51649,51675,12,51705,51731,12,51761,51787,12,51817,51843,12,51873,51899,12,51929,51955,12,51985,52011,12,52041,52067,12,52097,52123,12,52153,52179,12,52209,52235,12,52265,52291,12,52321,52347,12,52377,52403,12,52433,52459,12,52489,52515,12,52545,52571,12,52601,52627,12,52657,52683,12,52713,52739,12,52769,52795,12,52825,52851,12,52881,52907,12,52937,52963,12,52993,53019,12,53049,53075,12,53105,53131,12,53161,53187,12,53217,53243,12,53273,53299,12,53329,53355,12,53385,53411,12,53441,53467,12,53497,53523,12,53553,53579,12,53609,53635,12,53665,53691,12,53721,53747,12,53777,53803,12,53833,53859,12,53889,53915,12,53945,53971,12,54001,54027,12,54057,54083,12,54113,54139,12,54169,54195,12,54225,54251,12,54281,54307,12,54337,54363,12,54393,54419,12,54449,54475,12,54505,54531,12,54561,54587,12,54617,54643,12,54673,54699,12,54729,54755,12,54785,54811,12,54841,54867,12,54897,54923,12,54953,54979,12,55009,55035,12,55065,55091,12,55121,55147,12,55177,55203,12,65024,65039,5,65520,65528,4,66422,66426,5,68152,68154,5,69291,69292,5,69633,69633,5,69747,69748,5,69811,69814,5,69826,69826,5,69932,69932,7,70016,70017,5,70079,70080,7,70095,70095,5,70196,70196,5,70367,70367,5,70402,70403,7,70464,70464,5,70487,70487,5,70709,70711,7,70725,70725,7,70833,70834,7,70843,70844,7,70849,70849,7,71090,71093,5,71103,71104,5,71227,71228,7,71339,71339,5,71344,71349,5,71458,71461,5,71727,71735,5,71985,71989,7,71998,71998,5,72002,72002,7,72154,72155,5,72193,72202,5,72251,72254,5,72281,72283,5,72344,72345,5,72766,72766,7,72874,72880,5,72885,72886,5,73023,73029,5,73104,73105,5,73111,73111,5,92912,92916,5,94095,94098,5,113824,113827,4,119142,119142,7,119155,119162,4,119362,119364,5,121476,121476,5,122888,122904,5,123184,123190,5,125252,125258,5,127183,127183,14,127340,127343,14,127377,127386,14,127491,127503,14,127548,127551,14,127744,127756,14,127761,127761,14,127769,127769,14,127773,127774,14,127780,127788,14,127796,127797,14,127820,127823,14,127869,127869,14,127894,127895,14,127902,127903,14,127943,127943,14,127947,127950,14,127972,127972,14,127988,127988,14,127992,127994,14,128009,128011,14,128019,128019,14,128023,128041,14,128064,128064,14,128102,128107,14,128174,128181,14,128238,128238,14,128246,128247,14,128254,128254,14,128264,128264,14,128278,128299,14,128329,128330,14,128348,128359,14,128371,128377,14,128392,128393,14,128401,128404,14,128421,128421,14,128433,128434,14,128450,128452,14,128476,128478,14,128483,128483,14,128495,128495,14,128506,128506,14,128519,128520,14,128528,128528,14,128534,128534,14,128538,128538,14,128540,128542,14,128544,128549,14,128552,128555,14,128557,128557,14,128560,128563,14,128565,128565,14,128567,128576,14,128581,128591,14,128641,128642,14,128646,128646,14,128648,128648,14,128650,128651,14,128653,128653,14,128655,128655,14,128657,128659,14,128661,128661,14,128663,128663,14,128665,128666,14,128674,128674,14,128676,128677,14,128679,128685,14,128690,128690,14,128694,128694,14,128697,128702,14,128704,128704,14,128710,128714,14,128716,128716,14,128720,128720,14,128723,128724,14,128726,128727,14,128733,128735,14,128742,128744,14,128746,128746,14,128749,128751,14,128753,128754,14,128756,128758,14,128761,128761,14,128763,128764,14,128884,128895,14,128992,129003,14,129008,129008,14,129036,129039,14,129114,129119,14,129198,129279,14,129293,129295,14,129305,129310,14,129312,129319,14,129328,129328,14,129331,129338,14,129343,129343,14,129351,129355,14,129357,129359,14,129375,129387,14,129393,129393,14,129395,129398,14,129401,129401,14,129403,129403,14,129408,129412,14,129426,129431,14,129443,129444,14,129451,129453,14,129456,129465,14,129472,129472,14,129475,129482,14,129484,129484,14,129488,129510,14,129536,129647,14,129652,129652,14,129656,129658,14,129661,129663,14,129667,129670,14,129680,129685,14,129705,129708,14,129712,129718,14,129723,129727,14,129731,129733,14,129744,129750,14,129754,129759,14,129768,129775,14,129783,129791,14,917504,917504,4,917506,917535,4,917632,917759,4,918000,921599,4,0,9,4,11,12,4,14,31,4,169,169,14,174,174,14,1155,1159,5,1425,1469,5,1473,1474,5,1479,1479,5,1552,1562,5,1611,1631,5,1750,1756,5,1759,1764,5,1770,1773,5,1809,1809,5,1958,1968,5,2045,2045,5,2075,2083,5,2089,2093,5,2192,2193,1,2250,2273,5,2275,2306,5,2362,2362,5,2364,2364,5,2369,2376,5,2381,2381,5,2385,2391,5,2433,2433,5,2492,2492,5,2495,2496,7,2503,2504,7,2509,2509,5,2530,2531,5,2561,2562,5,2620,2620,5,2625,2626,5,2635,2637,5,2672,2673,5,2689,2690,5,2748,2748,5,2753,2757,5,2761,2761,7,2765,2765,5,2810,2815,5,2818,2819,7,2878,2878,5,2880,2880,7,2887,2888,7,2893,2893,5,2903,2903,5,2946,2946,5,3007,3007,7,3009,3010,7,3018,3020,7,3031,3031,5,3073,3075,7,3132,3132,5,3137,3140,7,3146,3149,5,3170,3171,5,3202,3203,7,3262,3262,7,3264,3265,7,3267,3268,7,3271,3272,7,3276,3277,5,3298,3299,5,3330,3331,7,3390,3390,5,3393,3396,5,3402,3404,7,3406,3406,1,3426,3427,5,3458,3459,7,3535,3535,5,3538,3540,5,3544,3550,7,3570,3571,7,3635,3635,7,3655,3662,5,3763,3763,7,3784,3789,5,3893,3893,5,3897,3897,5,3953,3966,5,3968,3972,5,3981,3991,5,4038,4038,5,4145,4145,7,4153,4154,5,4157,4158,5,4184,4185,5,4209,4212,5,4228,4228,7,4237,4237,5,4352,4447,8,4520,4607,10,5906,5908,5,5938,5939,5,5970,5971,5,6068,6069,5,6071,6077,5,6086,6086,5,6089,6099,5,6155,6157,5,6159,6159,5,6313,6313,5,6435,6438,7,6441,6443,7,6450,6450,5,6457,6459,5,6681,6682,7,6741,6741,7,6743,6743,7,6752,6752,5,6757,6764,5,6771,6780,5,6832,6845,5,6847,6862,5,6916,6916,7,6965,6965,5,6971,6971,7,6973,6977,7,6979,6980,7,7040,7041,5,7073,7073,7,7078,7079,7,7082,7082,7,7142,7142,5,7144,7145,5,7149,7149,5,7151,7153,5,7204,7211,7,7220,7221,7,7376,7378,5,7393,7393,7,7405,7405,5,7415,7415,7,7616,7679,5,8204,8204,5,8206,8207,4,8233,8233,4,8252,8252,14,8288,8292,4,8294,8303,4,8413,8416,5,8418,8420,5,8482,8482,14,8596,8601,14,8986,8987,14,9096,9096,14,9193,9196,14,9199,9199,14,9201,9202,14,9208,9210,14,9642,9643,14,9664,9664,14,9728,9729,14,9732,9732,14,9735,9741,14,9743,9744,14,9746,9746,14,9750,9751,14,9753,9756,14,9758,9759,14,9761,9761,14,9764,9765,14,9767,9769,14,9771,9773,14,9775,9775,14,9784,9785,14,9787,9791,14,9793,9793,14,9795,9799,14,9812,9822,14,9824,9824,14,9827,9827,14,9829,9830,14,9832,9832,14,9851,9851,14,9854,9854,14,9856,9861,14,9874,9874,14,9876,9876,14,9878,9879,14,9881,9881,14,9883,9884,14,9888,9889,14,9895,9895,14,9898,9899,14,9904,9905,14,9917,9918,14,9924,9925,14,9928,9928,14,9934,9934,14,9936,9936,14,9938,9938,14,9940,9940,14,9961,9961,14,9963,9967,14,9970,9971,14,9973,9973,14,9975,9977,14,9979,9980,14,9982,9985,14,9987,9988,14,9992,9996,14,9998,9998,14,10000,10001,14,10004,10004,14,10013,10013,14,10024,10024,14,10052,10052,14,10060,10060,14,10067,10069,14,10083,10083,14,10085,10087,14,10145,10145,14,10175,10175,14,11013,11015,14,11088,11088,14,11503,11505,5,11744,11775,5,12334,12335,5,12349,12349,14,12951,12951,14,42607,42607,5,42612,42621,5,42736,42737,5,43014,43014,5,43043,43044,7,43047,43047,7,43136,43137,7,43204,43205,5,43263,43263,5,43335,43345,5,43360,43388,8,43395,43395,7,43444,43445,7,43450,43451,7,43454,43456,7,43561,43566,5,43569,43570,5,43573,43574,5,43596,43596,5,43644,43644,5,43698,43700,5,43710,43711,5,43755,43755,7,43758,43759,7,43766,43766,5,44005,44005,5,44008,44008,5,44012,44012,7,44032,44032,11,44060,44060,11,44088,44088,11,44116,44116,11,44144,44144,11,44172,44172,11,44200,44200,11,44228,44228,11,44256,44256,11,44284,44284,11,44312,44312,11,44340,44340,11,44368,44368,11,44396,44396,11,44424,44424,11,44452,44452,11,44480,44480,11,44508,44508,11,44536,44536,11,44564,44564,11,44592,44592,11,44620,44620,11,44648,44648,11,44676,44676,11,44704,44704,11,44732,44732,11,44760,44760,11,44788,44788,11,44816,44816,11,44844,44844,11,44872,44872,11,44900,44900,11,44928,44928,11,44956,44956,11,44984,44984,11,45012,45012,11,45040,45040,11,45068,45068,11,45096,45096,11,45124,45124,11,45152,45152,11,45180,45180,11,45208,45208,11,45236,45236,11,45264,45264,11,45292,45292,11,45320,45320,11,45348,45348,11,45376,45376,11,45404,45404,11,45432,45432,11,45460,45460,11,45488,45488,11,45516,45516,11,45544,45544,11,45572,45572,11,45600,45600,11,45628,45628,11,45656,45656,11,45684,45684,11,45712,45712,11,45740,45740,11,45768,45768,11,45796,45796,11,45824,45824,11,45852,45852,11,45880,45880,11,45908,45908,11,45936,45936,11,45964,45964,11,45992,45992,11,46020,46020,11,46048,46048,11,46076,46076,11,46104,46104,11,46132,46132,11,46160,46160,11,46188,46188,11,46216,46216,11,46244,46244,11,46272,46272,11,46300,46300,11,46328,46328,11,46356,46356,11,46384,46384,11,46412,46412,11,46440,46440,11,46468,46468,11,46496,46496,11,46524,46524,11,46552,46552,11,46580,46580,11,46608,46608,11,46636,46636,11,46664,46664,11,46692,46692,11,46720,46720,11,46748,46748,11,46776,46776,11,46804,46804,11,46832,46832,11,46860,46860,11,46888,46888,11,46916,46916,11,46944,46944,11,46972,46972,11,47000,47000,11,47028,47028,11,47056,47056,11,47084,47084,11,47112,47112,11,47140,47140,11,47168,47168,11,47196,47196,11,47224,47224,11,47252,47252,11,47280,47280,11,47308,47308,11,47336,47336,11,47364,47364,11,47392,47392,11,47420,47420,11,47448,47448,11,47476,47476,11,47504,47504,11,47532,47532,11,47560,47560,11,47588,47588,11,47616,47616,11,47644,47644,11,47672,47672,11,47700,47700,11,47728,47728,11,47756,47756,11,47784,47784,11,47812,47812,11,47840,47840,11,47868,47868,11,47896,47896,11,47924,47924,11,47952,47952,11,47980,47980,11,48008,48008,11,48036,48036,11,48064,48064,11,48092,48092,11,48120,48120,11,48148,48148,11,48176,48176,11,48204,48204,11,48232,48232,11,48260,48260,11,48288,48288,11,48316,48316,11,48344,48344,11,48372,48372,11,48400,48400,11,48428,48428,11,48456,48456,11,48484,48484,11,48512,48512,11,48540,48540,11,48568,48568,11,48596,48596,11,48624,48624,11,48652,48652,11,48680,48680,11,48708,48708,11,48736,48736,11,48764,48764,11,48792,48792,11,48820,48820,11,48848,48848,11,48876,48876,11,48904,48904,11,48932,48932,11,48960,48960,11,48988,48988,11,49016,49016,11,49044,49044,11,49072,49072,11,49100,49100,11,49128,49128,11,49156,49156,11,49184,49184,11,49212,49212,11,49240,49240,11,49268,49268,11,49296,49296,11,49324,49324,11,49352,49352,11,49380,49380,11,49408,49408,11,49436,49436,11,49464,49464,11,49492,49492,11,49520,49520,11,49548,49548,11,49576,49576,11,49604,49604,11,49632,49632,11,49660,49660,11,49688,49688,11,49716,49716,11,49744,49744,11,49772,49772,11,49800,49800,11,49828,49828,11,49856,49856,11,49884,49884,11,49912,49912,11,49940,49940,11,49968,49968,11,49996,49996,11,50024,50024,11,50052,50052,11,50080,50080,11,50108,50108,11,50136,50136,11,50164,50164,11,50192,50192,11,50220,50220,11,50248,50248,11,50276,50276,11,50304,50304,11,50332,50332,11,50360,50360,11,50388,50388,11,50416,50416,11,50444,50444,11,50472,50472,11,50500,50500,11,50528,50528,11,50556,50556,11,50584,50584,11,50612,50612,11,50640,50640,11,50668,50668,11,50696,50696,11,50724,50724,11,50752,50752,11,50780,50780,11,50808,50808,11,50836,50836,11,50864,50864,11,50892,50892,11,50920,50920,11,50948,50948,11,50976,50976,11,51004,51004,11,51032,51032,11,51060,51060,11,51088,51088,11,51116,51116,11,51144,51144,11,51172,51172,11,51200,51200,11,51228,51228,11,51256,51256,11,51284,51284,11,51312,51312,11,51340,51340,11,51368,51368,11,51396,51396,11,51424,51424,11,51452,51452,11,51480,51480,11,51508,51508,11,51536,51536,11,51564,51564,11,51592,51592,11,51620,51620,11,51648,51648,11,51676,51676,11,51704,51704,11,51732,51732,11,51760,51760,11,51788,51788,11,51816,51816,11,51844,51844,11,51872,51872,11,51900,51900,11,51928,51928,11,51956,51956,11,51984,51984,11,52012,52012,11,52040,52040,11,52068,52068,11,52096,52096,11,52124,52124,11,52152,52152,11,52180,52180,11,52208,52208,11,52236,52236,11,52264,52264,11,52292,52292,11,52320,52320,11,52348,52348,11,52376,52376,11,52404,52404,11,52432,52432,11,52460,52460,11,52488,52488,11,52516,52516,11,52544,52544,11,52572,52572,11,52600,52600,11,52628,52628,11,52656,52656,11,52684,52684,11,52712,52712,11,52740,52740,11,52768,52768,11,52796,52796,11,52824,52824,11,52852,52852,11,52880,52880,11,52908,52908,11,52936,52936,11,52964,52964,11,52992,52992,11,53020,53020,11,53048,53048,11,53076,53076,11,53104,53104,11,53132,53132,11,53160,53160,11,53188,53188,11,53216,53216,11,53244,53244,11,53272,53272,11,53300,53300,11,53328,53328,11,53356,53356,11,53384,53384,11,53412,53412,11,53440,53440,11,53468,53468,11,53496,53496,11,53524,53524,11,53552,53552,11,53580,53580,11,53608,53608,11,53636,53636,11,53664,53664,11,53692,53692,11,53720,53720,11,53748,53748,11,53776,53776,11,53804,53804,11,53832,53832,11,53860,53860,11,53888,53888,11,53916,53916,11,53944,53944,11,53972,53972,11,54000,54000,11,54028,54028,11,54056,54056,11,54084,54084,11,54112,54112,11,54140,54140,11,54168,54168,11,54196,54196,11,54224,54224,11,54252,54252,11,54280,54280,11,54308,54308,11,54336,54336,11,54364,54364,11,54392,54392,11,54420,54420,11,54448,54448,11,54476,54476,11,54504,54504,11,54532,54532,11,54560,54560,11,54588,54588,11,54616,54616,11,54644,54644,11,54672,54672,11,54700,54700,11,54728,54728,11,54756,54756,11,54784,54784,11,54812,54812,11,54840,54840,11,54868,54868,11,54896,54896,11,54924,54924,11,54952,54952,11,54980,54980,11,55008,55008,11,55036,55036,11,55064,55064,11,55092,55092,11,55120,55120,11,55148,55148,11,55176,55176,11,55216,55238,9,64286,64286,5,65056,65071,5,65438,65439,5,65529,65531,4,66272,66272,5,68097,68099,5,68108,68111,5,68159,68159,5,68900,68903,5,69446,69456,5,69632,69632,7,69634,69634,7,69744,69744,5,69759,69761,5,69808,69810,7,69815,69816,7,69821,69821,1,69837,69837,1,69927,69931,5,69933,69940,5,70003,70003,5,70018,70018,7,70070,70078,5,70082,70083,1,70094,70094,7,70188,70190,7,70194,70195,7,70197,70197,7,70206,70206,5,70368,70370,7,70400,70401,5,70459,70460,5,70463,70463,7,70465,70468,7,70475,70477,7,70498,70499,7,70512,70516,5,70712,70719,5,70722,70724,5,70726,70726,5,70832,70832,5,70835,70840,5,70842,70842,5,70845,70845,5,70847,70848,5,70850,70851,5,71088,71089,7,71096,71099,7,71102,71102,7,71132,71133,5,71219,71226,5,71229,71229,5,71231,71232,5,71340,71340,7,71342,71343,7,71350,71350,7,71453,71455,5,71462,71462,7,71724,71726,7,71736,71736,7,71984,71984,5,71991,71992,7,71997,71997,7,71999,71999,1,72001,72001,1,72003,72003,5,72148,72151,5,72156,72159,7,72164,72164,7,72243,72248,5,72250,72250,1,72263,72263,5,72279,72280,7,72324,72329,1,72343,72343,7,72751,72751,7,72760,72765,5,72767,72767,5,72873,72873,7,72881,72881,7,72884,72884,7,73009,73014,5,73020,73021,5,73030,73030,1,73098,73102,7,73107,73108,7,73110,73110,7,73459,73460,5,78896,78904,4,92976,92982,5,94033,94087,7,94180,94180,5,113821,113822,5,118528,118573,5,119141,119141,5,119143,119145,5,119150,119154,5,119163,119170,5,119210,119213,5,121344,121398,5,121461,121461,5,121499,121503,5,122880,122886,5,122907,122913,5,122918,122922,5,123566,123566,5,125136,125142,5,126976,126979,14,126981,127182,14,127184,127231,14,127279,127279,14,127344,127345,14,127374,127374,14,127405,127461,14,127489,127490,14,127514,127514,14,127538,127546,14,127561,127567,14,127570,127743,14,127757,127758,14,127760,127760,14,127762,127762,14,127766,127768,14,127770,127770,14,127772,127772,14,127775,127776,14,127778,127779,14,127789,127791,14,127794,127795,14,127798,127798,14,127819,127819,14,127824,127824,14,127868,127868,14,127870,127871,14,127892,127893,14,127896,127896,14,127900,127901,14,127904,127940,14,127942,127942,14,127944,127944,14,127946,127946,14,127951,127955,14,127968,127971,14,127973,127984,14,127987,127987,14,127989,127989,14,127991,127991,14,127995,127999,5,128008,128008,14,128012,128014,14,128017,128018,14,128020,128020,14,128022,128022,14,128042,128042,14,128063,128063,14,128065,128065,14,128101,128101,14,128108,128109,14,128173,128173,14,128182,128183,14,128236,128237,14,128239,128239,14,128245,128245,14,128248,128248,14,128253,128253,14,128255,128258,14,128260,128263,14,128265,128265,14,128277,128277,14,128300,128301,14,128326,128328,14,128331,128334,14,128336,128347,14,128360,128366,14,128369,128370,14,128378,128378,14,128391,128391,14,128394,128397,14,128400,128400,14,128405,128406,14,128420,128420,14,128422,128423,14,128425,128432,14,128435,128443,14,128445,128449,14,128453,128464,14,128468,128475,14,128479,128480,14,128482,128482,14,128484,128487,14,128489,128494,14,128496,128498,14,128500,128505,14,128507,128511,14,128513,128518,14,128521,128525,14,128527,128527,14,128529,128529,14,128533,128533,14,128535,128535,14,128537,128537,14]');
}
//#endregion
diff --git a/src/vs/base/node/ps.ts b/src/vs/base/node/ps.ts
index 786da64c247..0a4d82d0ae4 100644
--- a/src/vs/base/node/ps.ts
+++ b/src/vs/base/node/ps.ts
@@ -48,18 +48,15 @@ export function listProcesses(rootPid: number): Promise {
function findName(cmd: string): string {
- const SHARED_PROCESS_HINT = /--disable-blink-features=Auxclick/;
- const WINDOWS_WATCHER_HINT = /\\watcher\\win32\\CodeHelper\.exe/;
+ const SHARED_PROCESS_HINT = /--vscode-window-kind=shared-process/;
+ const ISSUE_REPORTER_HINT = /--vscode-window-kind=issue-reporter/;
+ const PROCESS_EXPLORER_HINT = /--vscode-window-kind=process-explorer/;
+ const UTILITY_NETWORK_HINT = /--utility-sub-type=network/;
const WINDOWS_CRASH_REPORTER = /--crashes-directory/;
const WINDOWS_PTY = /\\pipe\\winpty-control/;
const WINDOWS_CONSOLE_HOST = /conhost\.exe/;
const TYPE = /--type=([a-zA-Z-]+)/;
- // find windows file watcher
- if (WINDOWS_WATCHER_HINT.exec(cmd)) {
- return 'watcherService ';
- }
-
// find windows crash reporter
if (WINDOWS_CRASH_REPORTER.exec(cmd)) {
return 'electron-crash-reporter';
@@ -83,7 +80,19 @@ export function listProcesses(rootPid: number): Promise {
return 'shared-process';
}
+ if (ISSUE_REPORTER_HINT.exec(cmd)) {
+ return 'issue-reporter';
+ }
+
+ if (PROCESS_EXPLORER_HINT.exec(cmd)) {
+ return 'process-explorer';
+ }
+
return `window`;
+ } else if (matches[1] === 'utility') {
+ if (UTILITY_NETWORK_HINT.exec(cmd)) {
+ return 'utility-network-service';
+ }
}
return matches[1];
}
diff --git a/src/vs/base/parts/ipc/common/ipc.net.ts b/src/vs/base/parts/ipc/common/ipc.net.ts
index f72112c1522..6229c073c7a 100644
--- a/src/vs/base/parts/ipc/common/ipc.net.ts
+++ b/src/vs/base/parts/ipc/common/ipc.net.ts
@@ -7,7 +7,6 @@ import { VSBuffer } from 'vs/base/common/buffer';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
-import * as process from 'vs/base/common/process';
import { IIPCLogger, IMessagePassingProtocol, IPCClient } from 'vs/base/parts/ipc/common/ipc';
export const enum SocketCloseEventType {
@@ -484,7 +483,7 @@ export class BufferedEmitter {
// it is important to deliver these messages after this call, but before
// other messages have a chance to be received (to guarantee in order delivery)
// that's why we're using here nextTick and not other types of timeouts
- process.nextTick(() => this._deliverMessages());
+ queueMicrotask(() => this._deliverMessages());
},
onLastListenerRemove: () => {
this._hasListeners = false;
diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts
index 6b84d0aa6c3..9fbbf2ec5f6 100644
--- a/src/vs/base/parts/quickinput/browser/quickInput.ts
+++ b/src/vs/base/parts/quickinput/browser/quickInput.ts
@@ -490,6 +490,11 @@ class QuickPick extends QuickInput implements IQuickPi
if (this._value !== value) {
this._value = value || '';
this.update();
+ // TODO: Remove this duplicate code and have the updating of the input box handle this.
+ const didFilter = this.ui.list.filter(this.filterValue(this.ui.inputBox.value));
+ if (didFilter) {
+ this.trySelectFirst();
+ }
this.onDidChangeValueEmitter.fire(this._value);
}
}
@@ -1056,7 +1061,6 @@ class QuickPick extends QuickInput implements IQuickPi
}
class InputBox extends QuickInput implements IInputBox {
- private _value = '';
private _valueSelection: Readonly<[number, number]> | undefined;
private valueSelectionUpdated = true;
private _placeholder: string | undefined;
@@ -1066,12 +1070,11 @@ class InputBox extends QuickInput implements IInputBox {
private readonly onDidAcceptEmitter = this._register(new Emitter());
get value() {
- return this._value;
+ return this.ui.inputBox.value;
}
set value(value: string) {
- this._value = value || '';
- this.update();
+ this.ui.inputBox.value = value ?? '';
}
set valueSelection(valueSelection: Readonly<[number, number]>) {
@@ -1118,10 +1121,6 @@ class InputBox extends QuickInput implements IInputBox {
if (!this.visible) {
this.visibleDisposables.add(
this.ui.inputBox.onDidChange(value => {
- if (value === this.value) {
- return;
- }
- this._value = value;
this.onDidValueChangeEmitter.fire(value);
}));
this.visibleDisposables.add(this.ui.onDidAccept(() => this.onDidAcceptEmitter.fire()));
@@ -1141,9 +1140,6 @@ class InputBox extends QuickInput implements IInputBox {
};
this.ui.setVisibilities(visibilities);
super.update();
- if (this.ui.inputBox.value !== this.value) {
- this.ui.inputBox.value = this.value;
- }
if (this.valueSelectionUpdated) {
this.valueSelectionUpdated = false;
this.ui.inputBox.select(this._valueSelection && { start: this._valueSelection[0], end: this._valueSelection[1] });
@@ -1687,7 +1683,7 @@ export class QuickInputController extends Disposable {
while (currentElement && !currentElement.offsetParent) {
currentElement = withNullAsUndefined(currentElement.parentElement);
}
- if (currentElement?.offsetParent && !currentElement.parentElement?.classList.contains('monaco-editor')) {
+ if (currentElement?.offsetParent) {
currentElement.focus();
this.previousFocusElement = undefined;
} else {
diff --git a/src/vs/base/test/browser/markdownRenderer.test.ts b/src/vs/base/test/browser/markdownRenderer.test.ts
index befafc099b4..fc154b0f8d3 100644
--- a/src/vs/base/test/browser/markdownRenderer.test.ts
+++ b/src/vs/base/test/browser/markdownRenderer.test.ts
@@ -7,6 +7,7 @@ import * as assert from 'assert';
import { renderMarkdown, renderMarkdownAsPlaintext } from 'vs/base/browser/markdownRenderer';
import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent';
import { parse } from 'vs/base/common/marshalling';
+import { isWeb } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
function strToNode(str: string): HTMLElement {
@@ -56,6 +57,14 @@ suite('MarkdownRenderer', () => {
const result: HTMLElement = renderMarkdown({ value: `` }).element;
assertNodeEquals(result, ``);
});
+
+ test('image with file uri should render as same origin uri', () => {
+ if (isWeb) {
+ return;
+ }
+ const result: HTMLElement = renderMarkdown({ value: `` }).element;
+ assertNodeEquals(result, '');
+ });
});
suite('Code block renderer', () => {
@@ -139,7 +148,7 @@ suite('MarkdownRenderer', () => {
mds.appendMarkdown(`[$(zap)-link](#link)`);
let result: HTMLElement = renderMarkdown(mds).element;
- assert.strictEqual(result.innerHTML, `-link
`);
+ assert.strictEqual(result.innerHTML, `-link
`);
});
test('render icon in table', () => {
@@ -159,7 +168,7 @@ suite('MarkdownRenderer', () => {
|
--link |
+-link |
`);
@@ -251,5 +260,29 @@ suite('MarkdownRenderer', () => {
const result = renderMarkdown(mds).element;
assert.strictEqual(result.innerHTML, `a<b>b</b>c
`);
});
+
+ test('Should render html images', () => {
+ if (isWeb) {
+ return;
+ }
+
+ const mds = new MarkdownString(undefined, { supportHtml: true });
+ mds.appendMarkdown(`
`);
+
+ const result = renderMarkdown(mds).element;
+ assert.strictEqual(result.innerHTML, `
`);
+ });
+
+ test('Should render html images with file uri as same origin uri', () => {
+ if (isWeb) {
+ return;
+ }
+
+ const mds = new MarkdownString(undefined, { supportHtml: true });
+ mds.appendMarkdown(`
`);
+
+ const result = renderMarkdown(mds).element;
+ assert.strictEqual(result.innerHTML, `
`);
+ });
});
});
diff --git a/src/vs/base/test/node/keytar.test.ts b/src/vs/base/test/node/keytar.test.ts
deleted file mode 100644
index 4e187264b29..00000000000
--- a/src/vs/base/test/node/keytar.test.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
-import * as assert from 'assert';
-import { isLinux } from 'vs/base/common/platform';
-
-suite('Keytar', () => {
-
- (isLinux ? test.skip : test)('loads and is functional', async () => { // TODO@RMacfarlane test seems to fail on Linux (Error: Unknown or unsupported transport 'disabled' for address 'disabled:')
- const keytar = await import('keytar');
- const name = `VSCode Test ${Math.floor(Math.random() * 1e9)}`;
- try {
- await keytar.setPassword(name, 'foo', 'bar');
- assert.strictEqual(await keytar.findPassword(name), 'bar');
- assert.strictEqual((await keytar.findCredentials(name)).length, 1);
- assert.strictEqual(await keytar.getPassword(name, 'foo'), 'bar');
- await keytar.deletePassword(name, 'foo');
- assert.strictEqual(await keytar.getPassword(name, 'foo'), null);
- } catch (err) {
- // try to clean up
- try {
- await keytar.deletePassword(name, 'foo');
- } finally {
- // eslint-disable-next-line no-unsafe-finally
- throw err;
- }
- }
- });
-});
diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts b/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts
index 553304dc4cc..56eb3683002 100644
--- a/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts
+++ b/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts
@@ -17,6 +17,9 @@ export class StorageDataCleaner extends Disposable {
// Workspace/Folder storage names are MD5 hashes (128bits / 4 due to hex presentation)
private static readonly NON_EMPTY_WORKSPACE_ID_LENGTH = 128 / 4;
+ // Reserved empty window workspace storage name when in extension development
+ private static readonly EXTENSION_DEV_EMPTY_WINDOW_ID = 'ext-dev';
+
constructor(
private readonly backupWorkspacesPath: string,
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@@ -42,18 +45,20 @@ export class StorageDataCleaner extends Disposable {
const workspaces = JSON.parse(contents) as IBackupWorkspacesFormat;
const emptyWorkspaces = workspaces.emptyWorkspaceInfos.map(emptyWorkspace => emptyWorkspace.backupFolder);
- // Read all workspace storage folders that exist
- const storageFolders = await Promises.readdir(this.environmentService.workspaceStorageHome.fsPath);
- await Promise.all(storageFolders.map(async storageFolder => {
- if (storageFolder.length === StorageDataCleaner.NON_EMPTY_WORKSPACE_ID_LENGTH) {
+ // Read all workspace storage folders that exist & cleanup unused
+ const workspaceStorageFolders = await Promises.readdir(this.environmentService.workspaceStorageHome.fsPath);
+ await Promise.all(workspaceStorageFolders.map(async workspaceStorageFolder => {
+ if (
+ workspaceStorageFolder.length === StorageDataCleaner.NON_EMPTY_WORKSPACE_ID_LENGTH || // keep non-empty workspaces
+ workspaceStorageFolder === StorageDataCleaner.EXTENSION_DEV_EMPTY_WINDOW_ID || // keep empty extension dev workspaces
+ emptyWorkspaces.indexOf(workspaceStorageFolder) >= 0 // keep empty workspaces that are in use
+ ) {
return;
}
- if (emptyWorkspaces.indexOf(storageFolder) === -1) {
- this.logService.trace(`[storage cleanup]: Deleting storage folder ${storageFolder}.`);
+ this.logService.trace(`[storage cleanup]: Deleting workspace storage folder ${workspaceStorageFolder}.`);
- await Promises.rm(join(this.environmentService.workspaceStorageHome.fsPath, storageFolder));
- }
+ await Promises.rm(join(this.environmentService.workspaceStorageHome.fsPath, workspaceStorageFolder));
}));
} catch (error) {
onUnexpectedError(error);
diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts
index 80d479c2284..e3077d66510 100644
--- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts
+++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts
@@ -84,8 +84,6 @@ import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyn
import { UserDataSyncStoreManagementService, UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
import { UserDataAutoSyncService } from 'vs/platform/userDataSync/electron-sandbox/userDataAutoSyncService';
import { ActiveWindowManager } from 'vs/platform/windows/node/windowTracker';
-import { IExtensionHostStarter, ipcExtensionHostStarterChannelName } from 'vs/platform/extensions/common/extensionHostStarter';
-import { ExtensionHostStarter } from 'vs/platform/extensions/node/extensionHostStarter';
import { ISignService } from 'vs/platform/sign/common/sign';
import { SignService } from 'vs/platform/sign/node/signService';
import { ISharedTunnelsService } from 'vs/platform/remote/common/tunnel';
@@ -337,9 +335,6 @@ class SharedProcessMain extends Disposable {
// Terminal
services.set(ILocalPtyService, this._register(ptyHostService));
- // Extension Host
- services.set(IExtensionHostStarter, this._register(new ExtensionHostStarter(logService)));
-
// Signing
services.set(ISignService, new SyncDescriptor(SignService));
@@ -398,10 +393,6 @@ class SharedProcessMain extends Disposable {
const localPtyChannel = ProxyChannel.fromService(localPtyService);
this.server.registerChannel(TerminalIpcChannels.LocalPty, localPtyChannel);
- // Extension Host
- const extensionHostStarterChannel = ProxyChannel.fromService(accessor.get(IExtensionHostStarter));
- this.server.registerChannel(ipcExtensionHostStarterChannelName, extensionHostStarterChannel);
-
// Tunnel
const sharedProcessTunnelChannel = ProxyChannel.fromService(accessor.get(ISharedProcessTunnelService));
this.server.registerChannel(ipcSharedProcessTunnelChannelName, sharedProcessTunnelChannel);
diff --git a/src/vs/code/electron-sandbox/processExplorer/media/processExplorer.css b/src/vs/code/electron-sandbox/processExplorer/media/processExplorer.css
index 0129b721f77..3baf48ce1af 100644
--- a/src/vs/code/electron-sandbox/processExplorer/media/processExplorer.css
+++ b/src/vs/code/electron-sandbox/processExplorer/media/processExplorer.css
@@ -38,7 +38,7 @@ body {
}
.cpu {
- width: 45px;
+ width: 60px;
}
.pid {
diff --git a/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts b/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts
index f447d8e8645..5f2040266cf 100644
--- a/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts
+++ b/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts
@@ -115,7 +115,7 @@ class ProcessHeaderTreeRenderer implements ITreeRenderer, index: number, templateData: IProcessItemTemplateData, height: number | undefined): void {
templateData.name.textContent = localize('name', "Process Name");
- templateData.CPU.textContent = localize('cpu', "CPU %");
+ templateData.CPU.textContent = localize('cpu', "CPU (%)");
templateData.PID.textContent = localize('pid', "PID");
templateData.memory.textContent = localize('memory', "Memory (MB)");
@@ -181,12 +181,14 @@ class ProcessRenderer implements ITreeRenderer {
- const row = document.getElementById(pid.toString());
+ const row = document.getElementById(`pid-${pid}`);
if (row) {
this.nativeHostService.writeClipboardText(row.innerText);
}
diff --git a/src/vs/editor/browser/controller/textAreaState.ts b/src/vs/editor/browser/controller/textAreaState.ts
index 4c240bfd378..cf8846dbc02 100644
--- a/src/vs/editor/browser/controller/textAreaState.ts
+++ b/src/vs/editor/browser/controller/textAreaState.ts
@@ -172,8 +172,7 @@ export class TextAreaState {
if (potentialEmojiInput !== null && potentialEmojiInput.length > 0) {
// now we check that this is indeed an emoji
// emojis can grow quite long, so a length check is of no help
- // allow-any-unicode-next-line
- // e.g. 1F3F4 E0067 E0062 E0065 E006E E0067 E007F ; fully-qualified # 🏴 England
+ // e.g. 1F3F4 E0067 E0062 E0065 E006E E0067 E007F -- flag of England
// Oftentimes, emojis use Variation Selector-16 (U+FE0F), so that is a good hint
// http://emojipedia.org/variation-selector-16/
diff --git a/src/vs/editor/browser/view/domLineBreaksComputer.ts b/src/vs/editor/browser/view/domLineBreaksComputer.ts
index 68b9aab8b09..fbc84e86d86 100644
--- a/src/vs/editor/browser/view/domLineBreaksComputer.ts
+++ b/src/vs/editor/browser/view/domLineBreaksComputer.ts
@@ -25,9 +25,6 @@ export class DOMLineBreaksComputerFactory implements ILineBreaksComputerFactory
}
public createLineBreaksComputer(fontInfo: FontInfo, tabSize: number, wrappingColumn: number, wrappingIndent: WrappingIndent): ILineBreaksComputer {
- tabSize = tabSize | 0; //@perf
- wrappingColumn = +wrappingColumn; //@perf
-
let requests: string[] = [];
let injectedTexts: (LineInjectedText[] | null)[] = [];
return {
diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts
index 8560d1680a6..6e2b684002e 100644
--- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts
+++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts
@@ -230,6 +230,7 @@ class Widget {
this._renderData = null;
this.domNode.setPosition((this._fixedOverflowWidgets && this.allowEditorOverflow) ? 'fixed' : 'absolute');
+ this.domNode.setDisplay('none');
this.domNode.setVisibility('hidden');
this.domNode.setAttribute('widgetId', this.id);
this.domNode.setMaxWidth(this._maxWidth);
@@ -274,6 +275,15 @@ class Widget {
public setPosition(range: IRange | null, preference: ContentWidgetPositionPreference[] | null): void {
this._setPosition(range);
this._preference = preference;
+ if (this._viewRange && this._preference && this._preference.length > 0) {
+ // this content widget would like to be visible if possible
+ // we change it from `display:none` to `display:block` even if it
+ // might be outside the viewport such that we can measure its size
+ // in `prepareRender`
+ this.domNode.setDisplay('block');
+ } else {
+ this.domNode.setDisplay('none');
+ }
this._cachedDomNodeClientWidth = -1;
this._cachedDomNodeClientHeight = -1;
}
@@ -435,6 +445,10 @@ class Widget {
}
private _prepareRenderWidget(ctx: RenderingContext): IRenderData | null {
+ if (!this._preference || this._preference.length === 0) {
+ return null;
+ }
+
const [topLeft, bottomLeft] = this._getTopAndBottomLeft(ctx);
if (!topLeft || !bottomLeft) {
return null;
@@ -464,36 +478,35 @@ class Widget {
}
// Do two passes, first for perfect fit, second picks first option
- if (this._preference) {
- for (let pass = 1; pass <= 2; pass++) {
- for (const pref of this._preference) {
- // placement
- if (pref === ContentWidgetPositionPreference.ABOVE) {
- if (!placement) {
- // Widget outside of viewport
- return null;
- }
- if (pass === 2 || placement.fitsAbove) {
- return { coordinate: new Coordinate(placement.aboveTop, placement.aboveLeft), position: ContentWidgetPositionPreference.ABOVE };
- }
- } else if (pref === ContentWidgetPositionPreference.BELOW) {
- if (!placement) {
- // Widget outside of viewport
- return null;
- }
- if (pass === 2 || placement.fitsBelow) {
- return { coordinate: new Coordinate(placement.belowTop, placement.belowLeft), position: ContentWidgetPositionPreference.BELOW };
- }
+ for (let pass = 1; pass <= 2; pass++) {
+ for (const pref of this._preference) {
+ // placement
+ if (pref === ContentWidgetPositionPreference.ABOVE) {
+ if (!placement) {
+ // Widget outside of viewport
+ return null;
+ }
+ if (pass === 2 || placement.fitsAbove) {
+ return { coordinate: new Coordinate(placement.aboveTop, placement.aboveLeft), position: ContentWidgetPositionPreference.ABOVE };
+ }
+ } else if (pref === ContentWidgetPositionPreference.BELOW) {
+ if (!placement) {
+ // Widget outside of viewport
+ return null;
+ }
+ if (pass === 2 || placement.fitsBelow) {
+ return { coordinate: new Coordinate(placement.belowTop, placement.belowLeft), position: ContentWidgetPositionPreference.BELOW };
+ }
+ } else {
+ if (this.allowEditorOverflow) {
+ return { coordinate: this._prepareRenderWidgetAtExactPositionOverflowing(topLeft), position: ContentWidgetPositionPreference.EXACT };
} else {
- if (this.allowEditorOverflow) {
- return { coordinate: this._prepareRenderWidgetAtExactPositionOverflowing(topLeft), position: ContentWidgetPositionPreference.EXACT };
- } else {
- return { coordinate: topLeft, position: ContentWidgetPositionPreference.EXACT };
- }
+ return { coordinate: topLeft, position: ContentWidgetPositionPreference.EXACT };
}
}
}
}
+
return null;
}
diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts
index fcc405103f6..9148c986b73 100644
--- a/src/vs/editor/browser/viewParts/lines/viewLine.ts
+++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts
@@ -331,13 +331,11 @@ export class ViewLine implements IVisibleLine {
if (!this._renderedViewLine) {
return null;
}
- startColumn = startColumn | 0; // @perf
- endColumn = endColumn | 0; // @perf
startColumn = Math.min(this._renderedViewLine.input.lineContent.length + 1, Math.max(1, startColumn));
endColumn = Math.min(this._renderedViewLine.input.lineContent.length + 1, Math.max(1, endColumn));
- const stopRenderingLineAfter = this._renderedViewLine.input.stopRenderingLineAfter | 0; // @perf
+ const stopRenderingLineAfter = this._renderedViewLine.input.stopRenderingLineAfter;
let outsideRenderedLine = false;
if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter + 1 && endColumn > stopRenderingLineAfter + 1) {
diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts
index 09dbf3671cf..4f8a560a404 100644
--- a/src/vs/editor/common/controller/cursorTypeOperations.ts
+++ b/src/vs/editor/common/controller/cursorTypeOperations.ts
@@ -20,6 +20,7 @@ import { EnterAction, IndentAction, StandardAutoClosingPairConditional } from 'v
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
+import { createScopedLineTokens } from 'vs/editor/common/modes/supports';
export class TypeOperations {
@@ -502,89 +503,125 @@ export class TypeOperations {
return !isBeforeStartingBrace && isBeforeClosingBrace;
}
+ /**
+ * Determine if typing `ch` at all `positions` in the `model` results in an
+ * auto closing open sequence being typed.
+ *
+ * Auto closing open sequences can consist of multiple characters, which
+ * can lead to ambiguities. In such a case, the longest auto-closing open
+ * sequence is returned.
+ */
private static _findAutoClosingPairOpen(config: CursorConfiguration, model: ITextModel, positions: Position[], ch: string): StandardAutoClosingPairConditional | null {
- const autoClosingPairCandidates = config.autoClosingPairs.autoClosingPairsOpenByEnd.get(ch);
- if (!autoClosingPairCandidates) {
+ const candidates = config.autoClosingPairs.autoClosingPairsOpenByEnd.get(ch);
+ if (!candidates) {
return null;
}
// Determine which auto-closing pair it is
- let autoClosingPair: StandardAutoClosingPairConditional | null = null;
- for (const autoClosingPairCandidate of autoClosingPairCandidates) {
- if (autoClosingPair === null || autoClosingPairCandidate.open.length > autoClosingPair.open.length) {
+ let result: StandardAutoClosingPairConditional | null = null;
+ for (const candidate of candidates) {
+ if (result === null || candidate.open.length > result.open.length) {
let candidateIsMatch = true;
for (const position of positions) {
- const relevantText = model.getValueInRange(new Range(position.lineNumber, position.column - autoClosingPairCandidate.open.length + 1, position.lineNumber, position.column));
- if (relevantText + ch !== autoClosingPairCandidate.open) {
+ const relevantText = model.getValueInRange(new Range(position.lineNumber, position.column - candidate.open.length + 1, position.lineNumber, position.column));
+ if (relevantText + ch !== candidate.open) {
candidateIsMatch = false;
break;
}
}
if (candidateIsMatch) {
- autoClosingPair = autoClosingPairCandidate;
+ result = candidate;
}
}
}
- return autoClosingPair;
+ return result;
}
- private static _findSubAutoClosingPairClose(config: CursorConfiguration, autoClosingPair: StandardAutoClosingPairConditional): string {
- if (autoClosingPair.open.length <= 1) {
- return '';
+ /**
+ * Find another auto-closing pair that is contained by the one passed in.
+ *
+ * e.g. when having [(,)] and [(*,*)] as auto-closing pairs
+ * this method will find [(,)] as a containment pair for [(*,*)]
+ */
+ private static _findContainedAutoClosingPair(config: CursorConfiguration, pair: StandardAutoClosingPairConditional): StandardAutoClosingPairConditional | null {
+ if (pair.open.length <= 1) {
+ return null;
}
- const lastChar = autoClosingPair.close.charAt(autoClosingPair.close.length - 1);
+ const lastChar = pair.close.charAt(pair.close.length - 1);
// get candidates with the same last character as close
- const subPairCandidates = config.autoClosingPairs.autoClosingPairsCloseByEnd.get(lastChar) || [];
- let subPairMatch: StandardAutoClosingPairConditional | null = null;
- for (const x of subPairCandidates) {
- if (x.open !== autoClosingPair.open && autoClosingPair.open.includes(x.open) && autoClosingPair.close.endsWith(x.close)) {
- if (!subPairMatch || x.open.length > subPairMatch.open.length) {
- subPairMatch = x;
+ const candidates = config.autoClosingPairs.autoClosingPairsCloseByEnd.get(lastChar) || [];
+ let result: StandardAutoClosingPairConditional | null = null;
+ for (const candidate of candidates) {
+ if (candidate.open !== pair.open && pair.open.includes(candidate.open) && pair.close.endsWith(candidate.close)) {
+ if (!result || candidate.open.length > result.open.length) {
+ result = candidate;
}
}
}
- if (subPairMatch) {
- return subPairMatch.close;
- } else {
- return '';
- }
+ return result;
}
- private static _getAutoClosingPairClose(config: CursorConfiguration, model: ITextModel, selections: Selection[], ch: string, insertOpenCharacter: boolean): string | null {
+ private static _getAutoClosingPairClose(config: CursorConfiguration, model: ITextModel, selections: Selection[], ch: string, chIsAlreadyTyped: boolean): string | null {
const chIsQuote = isQuote(ch);
- const autoCloseConfig = chIsQuote ? config.autoClosingQuotes : config.autoClosingBrackets;
+ const autoCloseConfig = (chIsQuote ? config.autoClosingQuotes : config.autoClosingBrackets);
+ const shouldAutoCloseBefore = (chIsQuote ? config.shouldAutoCloseBefore.quote : config.shouldAutoCloseBefore.bracket);
+
if (autoCloseConfig === 'never') {
return null;
}
- const autoClosingPair = this._findAutoClosingPairOpen(config, model, selections.map(s => s.getPosition()), ch);
- if (!autoClosingPair) {
- return null;
- }
-
- const subAutoClosingPairClose = this._findSubAutoClosingPairClose(config, autoClosingPair);
- let isSubAutoClosingPairPresent = true;
-
- const shouldAutoCloseBefore = chIsQuote ? config.shouldAutoCloseBefore.quote : config.shouldAutoCloseBefore.bracket;
-
- for (let i = 0, len = selections.length; i < len; i++) {
- const selection = selections[i];
+ for (const selection of selections) {
if (!selection.isEmpty()) {
return null;
}
+ }
- const position = selection.getPosition();
- const lineText = model.getLineContent(position.lineNumber);
- const lineAfter = lineText.substring(position.column - 1);
+ // This method is called both when typing (regularly) and when composition ends
+ // This means that we need to work with a text buffer where sometimes `ch` is not
+ // there (it is being typed right now) or with a text buffer where `ch` has already been typed
+ //
+ // In order to avoid adding checks for `chIsAlreadyTyped` in all places, we will work
+ // with two conceptual positions, the position before `ch` and the position after `ch`
+ //
+ const positions: { lineNumber: number; beforeColumn: number; afterColumn: number; }[] = selections.map((s) => {
+ const position = s.getPosition();
+ if (chIsAlreadyTyped) {
+ return { lineNumber: position.lineNumber, beforeColumn: position.column - ch.length, afterColumn: position.column };
+ } else {
+ return { lineNumber: position.lineNumber, beforeColumn: position.column, afterColumn: position.column };
+ }
+ });
- if (!lineAfter.startsWith(subAutoClosingPairClose)) {
- isSubAutoClosingPairPresent = false;
+
+ // Find the longest auto-closing open pair in case of multiple ending in `ch`
+ // e.g. when having [f","] and [","], it picks [f","] if the character before is f
+ const pair = this._findAutoClosingPairOpen(config, model, positions.map(p => new Position(p.lineNumber, p.beforeColumn)), ch);
+ if (!pair) {
+ return null;
+ }
+
+ // Sometimes, it is possible to have two auto-closing pairs that have a containment relationship
+ // e.g. when having [(,)] and [(*,*)]
+ // - when typing (, the resulting state is (|)
+ // - when typing *, the desired resulting state is (*|*), not (*|*))
+ const containedPair = this._findContainedAutoClosingPair(config, pair);
+ const containedPairClose = containedPair ? containedPair.close : '';
+ let isContainedPairPresent = true;
+
+ for (const position of positions) {
+ const { lineNumber, beforeColumn, afterColumn } = position;
+ const lineText = model.getLineContent(lineNumber);
+ const lineBefore = lineText.substring(0, beforeColumn - 1);
+ const lineAfter = lineText.substring(afterColumn - 1);
+
+ if (!lineAfter.startsWith(containedPairClose)) {
+ isContainedPairPresent = false;
}
// Only consider auto closing the pair if an allowed character follows or if another autoclosed pair closing brace follows
- if (lineText.length > position.column - 1) {
- const characterAfter = lineText.charAt(position.column - 1);
+ if (lineAfter.length > 0) {
+ const characterAfter = lineAfter.charAt(0);
const isBeforeCloseBrace = TypeOperations._isBeforeClosingBrace(config, lineAfter);
if (!isBeforeCloseBrace && !shouldAutoCloseBefore(characterAfter)) {
@@ -592,49 +629,58 @@ export class TypeOperations {
}
}
- if (!model.isCheapToTokenize(position.lineNumber)) {
+ // Do not auto-close ' or " after a word character
+ if (pair.open.length === 1 && (ch === '\'' || ch === '"') && autoCloseConfig !== 'always') {
+ const wordSeparators = getMapForWordSeparators(config.wordSeparators);
+ if (lineBefore.length > 0) {
+ const characterBefore = lineBefore.charCodeAt(lineBefore.length - 1);
+ if (wordSeparators.get(characterBefore) === WordCharacterClass.Regular) {
+ return null;
+ }
+ }
+ }
+
+ if (!model.isCheapToTokenize(lineNumber)) {
// Do not force tokenization
return null;
}
- // Do not auto-close ' or " after a word character
- if (autoClosingPair.open.length === 1 && (ch === '\'' || ch === '"') && autoCloseConfig !== 'always') {
- const wordSeparators = getMapForWordSeparators(config.wordSeparators);
- if (insertOpenCharacter && position.column > 1 && wordSeparators.get(lineText.charCodeAt(position.column - 2)) === WordCharacterClass.Regular) {
- return null;
- }
- if (!insertOpenCharacter && position.column > 2 && wordSeparators.get(lineText.charCodeAt(position.column - 3)) === WordCharacterClass.Regular) {
- return null;
- }
- }
-
- model.forceTokenization(position.lineNumber);
- const lineTokens = model.getLineTokens(position.lineNumber);
-
- let shouldAutoClosePair = false;
- try {
- shouldAutoClosePair = LanguageConfigurationRegistry.shouldAutoClosePair(autoClosingPair, lineTokens, insertOpenCharacter ? position.column : position.column - 1);
- } catch (e) {
- onUnexpectedError(e);
- }
-
- if (!shouldAutoClosePair) {
+ model.forceTokenization(lineNumber);
+ const lineTokens = model.getLineTokens(lineNumber);
+ const scopedLineTokens = createScopedLineTokens(lineTokens, beforeColumn - 1);
+ if (!pair.shouldAutoClose(scopedLineTokens, beforeColumn - scopedLineTokens.firstCharOffset)) {
return null;
}
+
+ // Typing for example a quote could either start a new string, in which case auto-closing is desirable
+ // or it could end a previously started string, in which case auto-closing is not desirable
+ //
+ // In certain cases, it is really not possible to look at the previous token to determine
+ // what would happen. That's why we do something really unusual, we pretend to type a different
+ // character and ask the tokenizer what the outcome of doing that is: after typing a neutral
+ // character, are we in a string (i.e. the quote would most likely end a string) or not?
+ //
+ const neutralCharacter = pair.findNeutralCharacter();
+ if (neutralCharacter) {
+ const tokenType = model.getTokenTypeIfInsertingCharacter(lineNumber, beforeColumn, neutralCharacter);
+ if (!pair.isOK(tokenType)) {
+ return null;
+ }
+ }
}
- if (isSubAutoClosingPairPresent) {
- return autoClosingPair.close.substring(0, autoClosingPair.close.length - subAutoClosingPairClose.length);
+ if (isContainedPairPresent) {
+ return pair.close.substring(0, pair.close.length - containedPairClose.length);
} else {
- return autoClosingPair.close;
+ return pair.close;
}
}
- private static _runAutoClosingOpenCharType(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[], ch: string, insertOpenCharacter: boolean, autoClosingPairClose: string): EditOperationResult {
+ private static _runAutoClosingOpenCharType(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[], ch: string, chIsAlreadyTyped: boolean, autoClosingPairClose: string): EditOperationResult {
let commands: ICommand[] = [];
for (let i = 0, len = selections.length; i < len; i++) {
const selection = selections[i];
- commands[i] = new TypeWithAutoClosingCommand(selection, ch, insertOpenCharacter, autoClosingPairClose);
+ commands[i] = new TypeWithAutoClosingCommand(selection, ch, !chIsAlreadyTyped, autoClosingPairClose);
}
return new EditOperationResult(EditOperationType.TypingOther, commands, {
shouldPushStackElementBefore: true,
@@ -809,9 +855,9 @@ export class TypeOperations {
});
}
- const autoClosingPairClose = this._getAutoClosingPairClose(config, model, selections, ch, false);
+ const autoClosingPairClose = this._getAutoClosingPairClose(config, model, selections, ch, true);
if (autoClosingPairClose !== null) {
- return this._runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch, false, autoClosingPairClose);
+ return this._runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch, true, autoClosingPairClose);
}
return null;
@@ -853,9 +899,9 @@ export class TypeOperations {
}
if (!isDoingComposition) {
- const autoClosingPairClose = this._getAutoClosingPairClose(config, model, selections, ch, true);
+ const autoClosingPairClose = this._getAutoClosingPairClose(config, model, selections, ch, false);
if (autoClosingPairClose) {
- return this._runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch, true, autoClosingPairClose);
+ return this._runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch, false, autoClosingPairClose);
}
}
diff --git a/src/vs/editor/common/core/token.ts b/src/vs/editor/common/core/token.ts
index 9d7f3560197..083d7c29d15 100644
--- a/src/vs/editor/common/core/token.ts
+++ b/src/vs/editor/common/core/token.ts
@@ -13,7 +13,7 @@ export class Token {
public readonly language: string;
constructor(offset: number, type: string, language: string) {
- this.offset = offset | 0;// @perf
+ this.offset = offset;
this.type = type;
this.language = language;
}
diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts
index a6905eb8491..33b0669d37e 100644
--- a/src/vs/editor/common/model.ts
+++ b/src/vs/editor/common/model.ts
@@ -13,7 +13,7 @@ import { IRange, Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { IModelContentChange, IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelTokensChangedEvent, ModelInjectedTextChangedEvent, ModelRawContentChangedEvent } from 'vs/editor/common/model/textModelEvents';
import { SearchData } from 'vs/editor/common/model/textModelSearch';
-import { FormattingOptions } from 'vs/editor/common/modes';
+import { FormattingOptions, StandardTokenType } from 'vs/editor/common/modes';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { MultilineTokens, MultilineTokens2 } from 'vs/editor/common/model/tokensStore';
import { TextChange } from 'vs/editor/common/model/textChange';
@@ -950,6 +950,13 @@ export interface ITextModel {
*/
getLanguageIdAtPosition(lineNumber: number, column: number): string;
+ /**
+ * Returns the standard token type for a character if the character were to be inserted at
+ * the given position. If the result cannot be accurate, it returns null.
+ * @internal
+ */
+ getTokenTypeIfInsertingCharacter(lineNumber: number, column: number, character: string): StandardTokenType;
+
/**
* Get the word under or besides `position`.
* @param position The position to look for a word.
diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts
index 53020b43e01..c1763b1af7a 100644
--- a/src/vs/editor/common/model/textModel.ts
+++ b/src/vs/editor/common/model/textModel.ts
@@ -24,7 +24,7 @@ import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguag
import { SearchData, SearchParams, TextModelSearch } from 'vs/editor/common/model/textModelSearch';
import { TextModelTokenization } from 'vs/editor/common/model/textModelTokens';
import { getWordAtText } from 'vs/editor/common/model/wordHelper';
-import { FormattingOptions } from 'vs/editor/common/modes';
+import { FormattingOptions, StandardTokenType } from 'vs/editor/common/modes';
import { ILanguageConfigurationService, ResolvedLanguageConfiguration } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { NULL_MODE_ID } from 'vs/editor/common/modes/nullMode';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
@@ -2126,6 +2126,11 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
return lineTokens.getLanguageId(lineTokens.findTokenIndexAtOffset(position.column - 1));
}
+ public getTokenTypeIfInsertingCharacter(lineNumber: number, column: number, character: string): StandardTokenType {
+ const position = this.validatePosition(new Position(lineNumber, column));
+ return this._tokenization.getTokenTypeIfInsertingCharacter(position, character);
+ }
+
private getLanguageConfiguration(languageId: string): ResolvedLanguageConfiguration {
return this._languageConfigurationService.getLanguageConfiguration(languageId);
}
diff --git a/src/vs/editor/common/model/textModelTokens.ts b/src/vs/editor/common/model/textModelTokens.ts
index 04aa75a2096..cabbec32642 100644
--- a/src/vs/editor/common/model/textModelTokens.ts
+++ b/src/vs/editor/common/model/textModelTokens.ts
@@ -9,13 +9,13 @@ import { LineTokens } from 'vs/editor/common/core/lineTokens';
import { Position } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { TokenizationResult2 } from 'vs/editor/common/core/token';
-import { ILanguageIdCodec, IState, ITokenizationSupport, TokenizationRegistry } from 'vs/editor/common/modes';
+import { ILanguageIdCodec, IState, ITokenizationSupport, StandardTokenType, TokenizationRegistry } from 'vs/editor/common/modes';
import { nullTokenize2 } from 'vs/editor/common/modes/nullMode';
import { TextModel } from 'vs/editor/common/model/textModel';
import { Disposable } from 'vs/base/common/lifecycle';
import { StopWatch } from 'vs/base/common/stopwatch';
import { MultilineTokensBuilder, countEOL } from 'vs/editor/common/model/tokensStore';
-import * as platform from 'vs/base/common/platform';
+import { runWhenIdle, IdleDeadline } from 'vs/base/common/async';
const enum Constants {
CHEAP_TOKENIZATION_LENGTH_LIMIT = 2048
@@ -255,19 +255,26 @@ export class TextModelTokenization extends Disposable {
this._beginBackgroundTokenization();
}
+ private _isScheduled = false;
private _beginBackgroundTokenization(): void {
- if (this._textModel.isAttachedToEditor() && this._hasLinesToTokenize()) {
- platform.setImmediate(() => {
- if (this._isDisposed) {
- // disposed in the meantime
- return;
- }
- this._revalidateTokensNow();
- });
+ if (this._isScheduled || !this._textModel.isAttachedToEditor() || !this._hasLinesToTokenize()) {
+ return;
}
+
+ this._isScheduled = true;
+ runWhenIdle((deadline) => {
+ this._isScheduled = false;
+
+ if (this._isDisposed) {
+ // disposed in the meantime
+ return;
+ }
+
+ this._revalidateTokensNow(deadline);
+ });
}
- private _revalidateTokensNow(): void {
+ private _revalidateTokensNow(deadline: IdleDeadline): void {
const textModelLastLineNumber = this._textModel.getLineCount();
const MAX_ALLOWED_TIME = 1;
@@ -275,7 +282,7 @@ export class TextModelTokenization extends Disposable {
const sw = StopWatch.create(false);
let tokenizedLineNumber = -1;
- while (this._hasLinesToTokenize()) {
+ do {
if (sw.elapsed() > MAX_ALLOWED_TIME) {
// Stop if MAX_ALLOWED_TIME is reached
break;
@@ -286,7 +293,7 @@ export class TextModelTokenization extends Disposable {
if (tokenizedLineNumber >= textModelLastLineNumber) {
break;
}
- }
+ } while (this._hasLinesToTokenize() && deadline.timeRemaining() > 0);
this._beginBackgroundTokenization();
this._textModel.setTokens(builder.tokens, !this._hasLinesToTokenize());
@@ -309,6 +316,37 @@ export class TextModelTokenization extends Disposable {
this._textModel.setTokens(builder.tokens, !this._hasLinesToTokenize());
}
+ public getTokenTypeIfInsertingCharacter(position: Position, character: string): StandardTokenType {
+ if (!this._tokenizationSupport) {
+ return StandardTokenType.Other;
+ }
+
+ this.forceTokenization(position.lineNumber);
+ const lineStartState = this._tokenizationStateStore.getBeginState(position.lineNumber - 1);
+ if (!lineStartState) {
+ return StandardTokenType.Other;
+ }
+
+ const languageId = this._textModel.getLanguageId();
+ const lineContent = this._textModel.getLineContent(position.lineNumber);
+
+ // Create the text as if `character` was inserted
+ const text = (
+ lineContent.substring(0, position.column - 1)
+ + character
+ + lineContent.substring(position.column - 1)
+ );
+
+ const r = safeTokenize(this._languageIdCodec, languageId, this._tokenizationSupport, text, true, lineStartState);
+ const lineTokens = new LineTokens(r.tokens, text, this._languageIdCodec);
+ if (lineTokens.getCount() === 0) {
+ return StandardTokenType.Other;
+ }
+
+ const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
+ return lineTokens.getStandardTokenType(tokenIndex);
+ }
+
public isCheapToTokenize(lineNumber: number): boolean {
if (!this._tokenizationSupport) {
return true;
diff --git a/src/vs/editor/common/modes/languageConfiguration.ts b/src/vs/editor/common/modes/languageConfiguration.ts
index c911ae318d0..3c8a5c22b45 100644
--- a/src/vs/editor/common/modes/languageConfiguration.ts
+++ b/src/vs/editor/common/modes/languageConfiguration.ts
@@ -3,7 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
+import { CharCode } from 'vs/base/common/charCode';
import { StandardTokenType } from 'vs/editor/common/modes';
+import { ScopedLineTokens } from 'vs/editor/common/modes/supports';
/**
* Describes how comments for a language work.
@@ -268,11 +270,12 @@ export interface CompleteEnterAction {
* @internal
*/
export class StandardAutoClosingPairConditional {
- _standardAutoClosingPairConditionalBrand: void = undefined;
readonly open: string;
readonly close: string;
private readonly _standardTokenMask: number;
+ private _neutralCharacter: string | null = null;
+ private _neutralCharacterSearched: boolean = false;
constructor(source: IAutoClosingPairConditional) {
this.open = source.open;
@@ -302,6 +305,46 @@ export class StandardAutoClosingPairConditional {
public isOK(standardToken: StandardTokenType): boolean {
return (this._standardTokenMask & standardToken) === 0;
}
+
+ public shouldAutoClose(context: ScopedLineTokens, column: number): boolean {
+ // Always complete on empty line
+ if (context.getTokenCount() === 0) {
+ return true;
+ }
+
+ const tokenIndex = context.findTokenIndexAtOffset(column - 2);
+ const standardTokenType = context.getStandardTokenType(tokenIndex);
+ return this.isOK(standardTokenType);
+ }
+
+ private _findNeutralCharacterInRange(fromCharCode: number, toCharCode: number): string | null {
+ for (let charCode = fromCharCode; charCode <= toCharCode; charCode++) {
+ const character = String.fromCharCode(charCode);
+ if (!this.open.includes(character) && !this.close.includes(character)) {
+ return character;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find a character in the range [0-9a-zA-Z] that does not appear in the open or close
+ */
+ public findNeutralCharacter(): string | null {
+ if (!this._neutralCharacterSearched) {
+ this._neutralCharacterSearched = true;
+ if (!this._neutralCharacter) {
+ this._neutralCharacter = this._findNeutralCharacterInRange(CharCode.Digit0, CharCode.Digit9);
+ }
+ if (!this._neutralCharacter) {
+ this._neutralCharacter = this._findNeutralCharacterInRange(CharCode.a, CharCode.z);
+ }
+ if (!this._neutralCharacter) {
+ this._neutralCharacter = this._findNeutralCharacterInRange(CharCode.A, CharCode.Z);
+ }
+ }
+ return this._neutralCharacter;
+ }
}
/**
diff --git a/src/vs/editor/common/modes/languageConfigurationRegistry.ts b/src/vs/editor/common/modes/languageConfigurationRegistry.ts
index b1b73e3d713..704e51f7866 100644
--- a/src/vs/editor/common/modes/languageConfigurationRegistry.ts
+++ b/src/vs/editor/common/modes/languageConfigurationRegistry.ts
@@ -10,7 +10,7 @@ import { LineTokens } from 'vs/editor/common/core/lineTokens';
import { Range } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
import { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper';
-import { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, StandardAutoClosingPairConditional, CompleteEnterAction, AutoClosingPairs, CharacterPair, ExplicitLanguageConfiguration } from 'vs/editor/common/modes/languageConfiguration';
+import { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, CompleteEnterAction, AutoClosingPairs, CharacterPair, ExplicitLanguageConfiguration } from 'vs/editor/common/modes/languageConfiguration';
import { createScopedLineTokens, ScopedLineTokens } from 'vs/editor/common/modes/supports';
import { CharacterPairSupport } from 'vs/editor/common/modes/supports/characterPair';
import { BracketElectricCharacterSupport, IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter';
@@ -280,11 +280,6 @@ export class LanguageConfigurationRegistryImpl {
return characterPairSupport.getSurroundingPairs();
}
- public shouldAutoClosePair(autoClosingPair: StandardAutoClosingPairConditional, context: LineTokens, column: number): boolean {
- const scopedLineTokens = createScopedLineTokens(context, column - 1);
- return CharacterPairSupport.shouldAutoClosePair(autoClosingPair, scopedLineTokens, column - scopedLineTokens.firstCharOffset);
- }
-
// end characterPair
public getWordDefinition(languageId: string): RegExp {
diff --git a/src/vs/editor/common/modes/supports/characterPair.ts b/src/vs/editor/common/modes/supports/characterPair.ts
index e1f8d13dcd8..61ff9873862 100644
--- a/src/vs/editor/common/modes/supports/characterPair.ts
+++ b/src/vs/editor/common/modes/supports/characterPair.ts
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import { IAutoClosingPair, StandardAutoClosingPairConditional, LanguageConfiguration, CharacterPair } from 'vs/editor/common/modes/languageConfiguration';
-import { ScopedLineTokens } from 'vs/editor/common/modes/supports';
export class CharacterPairSupport {
@@ -58,17 +57,6 @@ export class CharacterPairSupport {
return this._autoCloseBefore;
}
- public static shouldAutoClosePair(autoClosingPair: StandardAutoClosingPairConditional, context: ScopedLineTokens, column: number): boolean {
- // Always complete on empty line
- if (context.getTokenCount() === 0) {
- return true;
- }
-
- const tokenIndex = context.findTokenIndexAtOffset(column - 2);
- const standardTokenType = context.getStandardTokenType(tokenIndex);
- return autoClosingPair.isOK(standardTokenType);
- }
-
public getSurroundingPairs(): IAutoClosingPair[] {
return this._surroundingPairs;
}
diff --git a/src/vs/editor/common/modes/supports/electricCharacter.ts b/src/vs/editor/common/modes/supports/electricCharacter.ts
index ead8e6da3a6..1d3ba8ed9ed 100644
--- a/src/vs/editor/common/modes/supports/electricCharacter.ts
+++ b/src/vs/editor/common/modes/supports/electricCharacter.ts
@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
+import { distinct } from 'vs/base/common/arrays';
import { ScopedLineTokens, ignoreBracketsInToken } from 'vs/editor/common/modes/supports';
import { BracketsUtils, RichEditBrackets } from 'vs/editor/common/modes/supports/richEditBrackets';
@@ -36,12 +37,7 @@ export class BracketElectricCharacterSupport {
}
}
- // Filter duplicate entries
- result = result.filter((item, pos, array) => {
- return array.indexOf(item) === pos;
- });
-
- return result;
+ return distinct(result);
}
public onElectricCharacter(character: string, context: ScopedLineTokens, column: number): IElectricAction | null {
diff --git a/src/vs/editor/common/view/overviewZoneManager.ts b/src/vs/editor/common/view/overviewZoneManager.ts
index 2397cb12722..5952be0122d 100644
--- a/src/vs/editor/common/view/overviewZoneManager.ts
+++ b/src/vs/editor/common/view/overviewZoneManager.ts
@@ -175,9 +175,9 @@ export class OverviewZoneManager {
public resolveColorZones(): ColorZone[] {
const colorZonesInvalid = this._colorZonesInvalid;
- const lineHeight = Math.floor(this._lineHeight); // @perf
- const totalHeight = Math.floor(this.getCanvasHeight()); // @perf
- const outerHeight = Math.floor(this._outerHeight); // @perf
+ const lineHeight = Math.floor(this._lineHeight);
+ const totalHeight = Math.floor(this.getCanvasHeight());
+ const outerHeight = Math.floor(this._outerHeight);
const heightRatio = totalHeight / outerHeight;
const halfMinimumHeight = Math.floor(Constants.MINIMUM_HEIGHT * this._pixelRatio / 2);
diff --git a/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts b/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts
index 4c1cd5c4ad9..3479b1739da 100644
--- a/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts
+++ b/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts
@@ -27,9 +27,6 @@ export class MonospaceLineBreaksComputerFactory implements ILineBreaksComputerFa
}
public createLineBreaksComputer(fontInfo: FontInfo, tabSize: number, wrappingColumn: number, wrappingIndent: WrappingIndent): ILineBreaksComputer {
- tabSize = tabSize | 0; //@perf
- wrappingColumn = +wrappingColumn; //@perf
-
const requests: string[] = [];
const injectedTexts: (LineInjectedText[] | null)[] = [];
const previousBreakingData: (ModelLineProjectionData | null)[] = [];
@@ -40,7 +37,7 @@ export class MonospaceLineBreaksComputerFactory implements ILineBreaksComputerFa
previousBreakingData.push(previousLineBreakData);
},
finalize: () => {
- const columnsForFullWidthChar = fontInfo.typicalFullwidthCharacterWidth / fontInfo.typicalHalfwidthCharacterWidth; //@perf
+ const columnsForFullWidthChar = fontInfo.typicalFullwidthCharacterWidth / fontInfo.typicalHalfwidthCharacterWidth;
let result: (ModelLineProjectionData | null)[] = [];
for (let i = 0, len = requests.length; i < len; i++) {
const injectedText = injectedTexts[i];
diff --git a/src/vs/editor/common/viewModel/prefixSumComputer.ts b/src/vs/editor/common/viewModel/prefixSumComputer.ts
index 47ac2a2c65b..7c6eba5854e 100644
--- a/src/vs/editor/common/viewModel/prefixSumComputer.ts
+++ b/src/vs/editor/common/viewModel/prefixSumComputer.ts
@@ -151,7 +151,7 @@ export class PrefixSumComputer {
}
public getIndexOf(sum: number): PrefixSumIndexOfResult {
- sum = Math.floor(sum); //@perf
+ sum = Math.floor(sum);
// Compute all sums (to get a fully valid prefixSum)
this.getTotalSum();
diff --git a/src/vs/editor/contrib/codeAction/test/codeActionModel.test.ts b/src/vs/editor/contrib/codeAction/test/codeActionModel.test.ts
index 2d925dcb22a..b4dd20023c7 100644
--- a/src/vs/editor/contrib/codeAction/test/codeActionModel.test.ts
+++ b/src/vs/editor/contrib/codeAction/test/codeActionModel.test.ts
@@ -7,6 +7,7 @@ import * as assert from 'assert';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { assertType } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
+import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { Selection } from 'vs/editor/common/core/selection';
import { TextModel } from 'vs/editor/common/model/textModel';
@@ -27,10 +28,11 @@ const testProvider = {
};
}
};
+
suite('CodeActionModel', () => {
const languageId = 'foo-lang';
- let uri = URI.parse('untitled:path');
+ const uri = URI.parse('untitled:path');
let model: TextModel;
let markerService: MarkerService;
let editor: ICodeEditor;
@@ -51,51 +53,15 @@ suite('CodeActionModel', () => {
markerService.dispose();
});
- test('Orcale -> marker added', done => {
- const reg = modes.CodeActionProviderRegistry.register(languageId, testProvider);
- disposables.add(reg);
+ test('Oracle -> marker added', async () => {
+ let done: () => void;
+ const donePromise = new Promise(resolve => {
+ done = resolve;
+ });
+ await runWithFakedTimers({ useFakeTimers: true }, () => {
+ const reg = modes.CodeActionProviderRegistry.register(languageId, testProvider);
+ disposables.add(reg);
- const contextKeys = new MockContextKeyService();
- const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
- disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
- assertType(e.type === CodeActionsState.Type.Triggered);
-
- assert.strictEqual(e.trigger.type, modes.CodeActionTriggerType.Auto);
- assert.ok(e.actions);
-
- e.actions.then(fixes => {
- model.dispose();
- assert.strictEqual(fixes.validActions.length, 1);
- done();
- }, done);
- }));
-
- // start here
- markerService.changeOne('fake', uri, [{
- startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
- message: 'error',
- severity: 1,
- code: '',
- source: ''
- }]);
-
- });
-
- test('Orcale -> position changed', () => {
- const reg = modes.CodeActionProviderRegistry.register(languageId, testProvider);
- disposables.add(reg);
-
- markerService.changeOne('fake', uri, [{
- startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
- message: 'error',
- severity: 1,
- code: '',
- source: ''
- }]);
-
- editor.setPosition({ lineNumber: 2, column: 1 });
-
- return new Promise((resolve, reject) => {
const contextKeys = new MockContextKeyService();
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
@@ -103,18 +69,62 @@ suite('CodeActionModel', () => {
assert.strictEqual(e.trigger.type, modes.CodeActionTriggerType.Auto);
assert.ok(e.actions);
+
e.actions.then(fixes => {
model.dispose();
assert.strictEqual(fixes.validActions.length, 1);
- resolve(undefined);
- }, reject);
+ done();
+ }, done);
}));
+
// start here
- editor.setPosition({ lineNumber: 1, column: 1 });
+ markerService.changeOne('fake', uri, [{
+ startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
+ message: 'error',
+ severity: 1,
+ code: '',
+ source: ''
+ }]);
+ return donePromise;
});
});
- test('Lightbulb is in the wrong place, #29933', async function () {
+ test('Oracle -> position changed', async () => {
+ await runWithFakedTimers({ useFakeTimers: true }, () => {
+ const reg = modes.CodeActionProviderRegistry.register(languageId, testProvider);
+ disposables.add(reg);
+
+ markerService.changeOne('fake', uri, [{
+ startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
+ message: 'error',
+ severity: 1,
+ code: '',
+ source: ''
+ }]);
+
+ editor.setPosition({ lineNumber: 2, column: 1 });
+
+ return new Promise((resolve, reject) => {
+ const contextKeys = new MockContextKeyService();
+ const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
+ disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
+ assertType(e.type === CodeActionsState.Type.Triggered);
+
+ assert.strictEqual(e.trigger.type, modes.CodeActionTriggerType.Auto);
+ assert.ok(e.actions);
+ e.actions.then(fixes => {
+ model.dispose();
+ assert.strictEqual(fixes.validActions.length, 1);
+ resolve(undefined);
+ }, reject);
+ }));
+ // start here
+ editor.setPosition({ lineNumber: 1, column: 1 });
+ });
+ });
+ });
+
+ test('Lightbulb is in the wrong place, #29933', async () => {
const reg = modes.CodeActionProviderRegistry.register(languageId, {
provideCodeActions(_doc, _range): modes.CodeActionList {
return { actions: [], dispose() { /* noop*/ } };
@@ -122,68 +132,77 @@ suite('CodeActionModel', () => {
});
disposables.add(reg);
- editor.getModel()!.setValue('// @ts-check\n2\ncon\n');
+ await runWithFakedTimers({ useFakeTimers: true }, async () => {
+ editor.getModel()!.setValue('// @ts-check\n2\ncon\n');
- markerService.changeOne('fake', uri, [{
- startLineNumber: 3, startColumn: 1, endLineNumber: 3, endColumn: 4,
- message: 'error',
- severity: 1,
- code: '',
- source: ''
- }]);
+ markerService.changeOne('fake', uri, [{
+ startLineNumber: 3, startColumn: 1, endLineNumber: 3, endColumn: 4,
+ message: 'error',
+ severity: 1,
+ code: '',
+ source: ''
+ }]);
- // case 1 - drag selection over multiple lines -> range of enclosed marker, position or marker
- await new Promise(resolve => {
+ // case 1 - drag selection over multiple lines -> range of enclosed marker, position or marker
+ await new Promise(resolve => {
+ const contextKeys = new MockContextKeyService();
+ const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
+ disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
+ assertType(e.type === CodeActionsState.Type.Triggered);
+
+ assert.strictEqual(e.trigger.type, modes.CodeActionTriggerType.Auto);
+ const selection = e.rangeOrSelection;
+ assert.strictEqual(selection.selectionStartLineNumber, 1);
+ assert.strictEqual(selection.selectionStartColumn, 1);
+ assert.strictEqual(selection.endLineNumber, 4);
+ assert.strictEqual(selection.endColumn, 1);
+ assert.strictEqual(e.position.lineNumber, 3);
+ assert.strictEqual(e.position.column, 1);
+ model.dispose();
+ resolve(undefined);
+ }, 5));
+
+ editor.setSelection({ startLineNumber: 1, startColumn: 1, endLineNumber: 4, endColumn: 1 });
+ });
+ });
+ });
+
+ test('Oracle -> should only auto trigger once for cursor and marker update right after each other', async () => {
+ let done: () => void;
+ const donePromise = new Promise(resolve => { done = resolve; });
+
+ await runWithFakedTimers({ useFakeTimers: true }, () => {
+ const reg = modes.CodeActionProviderRegistry.register(languageId, testProvider);
+ disposables.add(reg);
+
+ let triggerCount = 0;
const contextKeys = new MockContextKeyService();
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
assertType(e.type === CodeActionsState.Type.Triggered);
assert.strictEqual(e.trigger.type, modes.CodeActionTriggerType.Auto);
- const selection = e.rangeOrSelection;
- assert.strictEqual(selection.selectionStartLineNumber, 1);
- assert.strictEqual(selection.selectionStartColumn, 1);
- assert.strictEqual(selection.endLineNumber, 4);
- assert.strictEqual(selection.endColumn, 1);
- assert.strictEqual(e.position.lineNumber, 3);
- assert.strictEqual(e.position.column, 1);
- model.dispose();
- resolve(undefined);
- }, 5));
+ ++triggerCount;
+
+ // give time for second trigger before completing test
+ setTimeout(() => {
+ model.dispose();
+ assert.strictEqual(triggerCount, 1);
+ done();
+ }, 0);
+ }, 5 /*delay*/));
+
+ markerService.changeOne('fake', uri, [{
+ startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
+ message: 'error',
+ severity: 1,
+ code: '',
+ source: ''
+ }]);
editor.setSelection({ startLineNumber: 1, startColumn: 1, endLineNumber: 4, endColumn: 1 });
+
+ return donePromise;
});
});
-
- test('Orcale -> should only auto trigger once for cursor and marker update right after each other', done => {
- const reg = modes.CodeActionProviderRegistry.register(languageId, testProvider);
- disposables.add(reg);
-
- let triggerCount = 0;
- const contextKeys = new MockContextKeyService();
- const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
- disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
- assertType(e.type === CodeActionsState.Type.Triggered);
-
- assert.strictEqual(e.trigger.type, modes.CodeActionTriggerType.Auto);
- ++triggerCount;
-
- // give time for second trigger before completing test
- setTimeout(() => {
- model.dispose();
- assert.strictEqual(triggerCount, 1);
- done();
- }, 50);
- }, 5 /*delay*/));
-
- markerService.changeOne('fake', uri, [{
- startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
- message: 'error',
- severity: 1,
- code: '',
- source: ''
- }]);
-
- editor.setSelection({ startLineNumber: 1, startColumn: 1, endLineNumber: 4, endColumn: 1 });
- });
});
diff --git a/src/vs/editor/contrib/multicursor/multicursor.ts b/src/vs/editor/contrib/multicursor/multicursor.ts
index 116308fbd83..9eebf15826b 100644
--- a/src/vs/editor/contrib/multicursor/multicursor.ts
+++ b/src/vs/editor/contrib/multicursor/multicursor.ts
@@ -817,34 +817,33 @@ export class CompatChangeAll extends MultiCursorSelectionControllerAction {
}
class SelectionHighlighterState {
- public readonly searchText: string;
- public readonly matchCase: boolean;
- public readonly wordSeparators: string | null;
- public readonly modelVersionId: number;
+ private readonly _modelVersionId: number = this._model.getVersionId();
+ private _cachedFindMatches: Range[] | null = null;
- constructor(searchText: string, matchCase: boolean, wordSeparators: string | null, modelVersionId: number) {
- this.searchText = searchText;
- this.matchCase = matchCase;
- this.wordSeparators = wordSeparators;
- this.modelVersionId = modelVersionId;
+ constructor(
+ private readonly _model: ITextModel,
+ private readonly _searchText: string,
+ private readonly _matchCase: boolean,
+ private readonly _wordSeparators: string | null,
+ prevState: SelectionHighlighterState | null
+ ) {
+ if (prevState
+ && this._model === prevState._model
+ && this._searchText === prevState._searchText
+ && this._matchCase === prevState._matchCase
+ && this._wordSeparators === prevState._wordSeparators
+ && this._modelVersionId === prevState._modelVersionId
+ ) {
+ this._cachedFindMatches = prevState._cachedFindMatches;
+ }
}
- /**
- * Everything equals except for `lastWordUnderCursor`
- */
- public static softEquals(a: SelectionHighlighterState | null, b: SelectionHighlighterState | null): boolean {
- if (!a && !b) {
- return true;
+ public findMatches(): Range[] {
+ if (this._cachedFindMatches === null) {
+ this._cachedFindMatches = this._model.findMatches(this._searchText, true, false, this._matchCase, this._wordSeparators, false).map(m => m.range);
+ this._cachedFindMatches.sort(Range.compareRangesUsingStarts);
}
- if (!a || !b) {
- return false;
- }
- return (
- a.searchText === b.searchText
- && a.matchCase === b.matchCase
- && a.wordSeparators === b.wordSeparators
- && a.modelVersionId === b.modelVersionId
- );
+ return this._cachedFindMatches;
}
}
@@ -904,10 +903,10 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut
}
private _update(): void {
- this._setState(SelectionHighlighter._createState(this._isEnabled, this.editor));
+ this._setState(SelectionHighlighter._createState(this.state, this._isEnabled, this.editor));
}
- private static _createState(isEnabled: boolean, editor: ICodeEditor): SelectionHighlighterState | null {
+ private static _createState(oldState: SelectionHighlighterState | null, isEnabled: boolean, editor: ICodeEditor): SelectionHighlighterState | null {
if (!isEnabled) {
return null;
}
@@ -980,15 +979,11 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut
}
}
- return new SelectionHighlighterState(r.searchText, r.matchCase, r.wholeWord ? editor.getOption(EditorOption.wordSeparators) : null, editor.getModel().getVersionId());
+ return new SelectionHighlighterState(editor.getModel(), r.searchText, r.matchCase, r.wholeWord ? editor.getOption(EditorOption.wordSeparators) : null, oldState);
}
- private _setState(state: SelectionHighlighterState | null): void {
- if (SelectionHighlighterState.softEquals(this.state, state)) {
- this.state = state;
- return;
- }
- this.state = state;
+ private _setState(newState: SelectionHighlighterState | null): void {
+ this.state = newState;
if (!this.state) {
this.decorations = this.editor.deltaDecorations(this.decorations, []);
@@ -1001,20 +996,17 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut
const model = this.editor.getModel();
if (model.isTooLargeForTokenization()) {
- // the file is too large, so searching word under cursor in the whole document takes is blocking the UI.
+ // the file is too large, so searching word under cursor in the whole document would be blocking the UI.
return;
}
- const hasFindOccurrences = DocumentHighlightProviderRegistry.has(model) && this.editor.getOption(EditorOption.occurrencesHighlight);
+ const allMatches = this.state.findMatches();
- let allMatches = model.findMatches(this.state.searchText, true, false, this.state.matchCase, this.state.wordSeparators, false).map(m => m.range);
- allMatches.sort(Range.compareRangesUsingStarts);
-
- let selections = this.editor.getSelections();
+ const selections = this.editor.getSelections();
selections.sort(Range.compareRangesUsingStarts);
// do not overlap with selection (issue #64 and #512)
- let matches: Range[] = [];
+ const matches: Range[] = [];
for (let i = 0, j = 0, len = allMatches.length, lenJ = selections.length; i < len;) {
const match = allMatches[i];
@@ -1041,6 +1033,7 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut
}
}
+ const hasFindOccurrences = DocumentHighlightProviderRegistry.has(model) && this.editor.getOption(EditorOption.occurrencesHighlight);
const decorations = matches.map(r => {
return {
range: r,
diff --git a/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts b/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts
index f935d89342f..99a1b20d6f1 100644
--- a/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts
+++ b/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts
@@ -7,6 +7,7 @@ import * as assert from 'assert';
import { CancellationToken } from 'vs/base/common/cancellation';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
+import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
import { Position } from 'vs/editor/common/core/position';
import { Handler } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
@@ -62,7 +63,10 @@ suite('ParameterHintsModel', () => {
return editor;
}
- test('Provider should get trigger character on type', (done) => {
+ test('Provider should get trigger character on type', async () => {
+ let done: () => void;
+ const donePromise = new Promise(resolve => { done = resolve; });
+
const triggerChar = '(';
const editor = createMockEditor('');
@@ -80,10 +84,16 @@ suite('ParameterHintsModel', () => {
}
}));
- editor.trigger('keyboard', Handler.Type, { text: triggerChar });
+ await runWithFakedTimers({ useFakeTimers: true }, async () => {
+ editor.trigger('keyboard', Handler.Type, { text: triggerChar });
+ await donePromise;
+ });
});
- test('Provider should be retriggered if already active', (done) => {
+ test('Provider should be retriggered if already active', async () => {
+ let done: () => void;
+ const donePromise = new Promise(resolve => { done = resolve; });
+
const triggerChar = '(';
const editor = createMockEditor('');
@@ -104,7 +114,7 @@ suite('ParameterHintsModel', () => {
assert.strictEqual(context.activeSignatureHelp, undefined);
// Retrigger
- setTimeout(() => editor.trigger('keyboard', Handler.Type, { text: triggerChar }), 50);
+ setTimeout(() => editor.trigger('keyboard', Handler.Type, { text: triggerChar }), 0);
} else {
assert.strictEqual(invokeCount, 2);
assert.strictEqual(context.triggerKind, modes.SignatureHelpTriggerKind.TriggerCharacter);
@@ -122,10 +132,16 @@ suite('ParameterHintsModel', () => {
}
}));
- editor.trigger('keyboard', Handler.Type, { text: triggerChar });
+ await runWithFakedTimers({ useFakeTimers: true }, async () => {
+ editor.trigger('keyboard', Handler.Type, { text: triggerChar });
+ await donePromise;
+ });
});
- test('Provider should not be retriggered if previous help is canceled first', (done) => {
+ test('Provider should not be retriggered if previous help is canceled first', async () => {
+ let done: () => void;
+ const donePromise = new Promise(resolve => { done = resolve; });
+
const triggerChar = '(';
const editor = createMockEditor('');
@@ -165,10 +181,16 @@ suite('ParameterHintsModel', () => {
}
}));
- editor.trigger('keyboard', Handler.Type, { text: triggerChar });
+ await runWithFakedTimers({ useFakeTimers: true }, () => {
+ editor.trigger('keyboard', Handler.Type, { text: triggerChar });
+ return donePromise;
+ });
});
- test('Provider should get last trigger character when triggered multiple times and only be invoked once', (done) => {
+ test('Provider should get last trigger character when triggered multiple times and only be invoked once', async () => {
+ let done: () => void;
+ const donePromise = new Promise(resolve => { done = resolve; });
+
const editor = createMockEditor('');
disposables.add(new ParameterHintsModel(editor, 5));
@@ -199,16 +221,24 @@ suite('ParameterHintsModel', () => {
}
}));
- editor.trigger('keyboard', Handler.Type, { text: 'a' });
- editor.trigger('keyboard', Handler.Type, { text: 'b' });
- editor.trigger('keyboard', Handler.Type, { text: 'c' });
+ await runWithFakedTimers({ useFakeTimers: true }, async () => {
+ editor.trigger('keyboard', Handler.Type, { text: 'a' });
+ editor.trigger('keyboard', Handler.Type, { text: 'b' });
+ editor.trigger('keyboard', Handler.Type, { text: 'c' });
+
+ await donePromise;
+ });
});
- test('Provider should be retriggered if already active', (done) => {
+ test('Provider should be retriggered if already active', async () => {
+ let done: () => void;
+ const donePromise = new Promise(resolve => { done = resolve; });
+
const editor = createMockEditor('');
disposables.add(new ParameterHintsModel(editor, 5));
let invokeCount = 0;
+
disposables.add(modes.SignatureHelpProviderRegistry.register(mockFileSelector, new class implements modes.SignatureHelpProvider {
signatureHelpTriggerCharacters = ['a', 'b'];
signatureHelpRetriggerCharacters = [];
@@ -239,10 +269,14 @@ suite('ParameterHintsModel', () => {
}
}));
- editor.trigger('keyboard', Handler.Type, { text: 'a' });
+ await runWithFakedTimers({ useFakeTimers: true }, () => {
+ editor.trigger('keyboard', Handler.Type, { text: 'a' });
+ return donePromise;
+ });
});
- test('Should cancel existing request when new request comes in', () => {
+ test('Should cancel existing request when new request comes in', async () => {
+
const editor = createMockEditor('abc def');
const hintsModel = new ParameterHintsModel(editor);
@@ -287,22 +321,28 @@ suite('ParameterHintsModel', () => {
disposables.add(modes.SignatureHelpProviderRegistry.register(mockFileSelector, longRunningProvider));
- hintsModel.trigger({ triggerKind: modes.SignatureHelpTriggerKind.Invoke }, 0);
- assert.strictEqual(-1, didRequestCancellationOf);
+ await runWithFakedTimers({ useFakeTimers: true }, async () => {
- return new Promise((resolve, reject) =>
- hintsModel.onChangedHints(newParamterHints => {
- try {
- assert.strictEqual(0, didRequestCancellationOf);
- assert.strictEqual('1', newParamterHints!.signatures[0].label);
- resolve();
- } catch (e) {
- reject(e);
- }
- }));
+ hintsModel.trigger({ triggerKind: modes.SignatureHelpTriggerKind.Invoke }, 0);
+ assert.strictEqual(-1, didRequestCancellationOf);
+
+ return new Promise((resolve, reject) =>
+ hintsModel.onChangedHints(newParamterHints => {
+ try {
+ assert.strictEqual(0, didRequestCancellationOf);
+ assert.strictEqual('1', newParamterHints!.signatures[0].label);
+ resolve();
+ } catch (e) {
+ reject(e);
+ }
+ }));
+ });
});
- test('Provider should be retriggered by retrigger character', (done) => {
+ test('Provider should be retriggered by retrigger character', async () => {
+ let done: () => void;
+ const donePromise = new Promise(resolve => { done = resolve; });
+
const triggerChar = 'a';
const retriggerChar = 'b';
@@ -340,11 +380,15 @@ suite('ParameterHintsModel', () => {
}
}));
- // This should not trigger anything
- editor.trigger('keyboard', Handler.Type, { text: retriggerChar });
+ await runWithFakedTimers({ useFakeTimers: true }, async () => {
+ // This should not trigger anything
+ editor.trigger('keyboard', Handler.Type, { text: retriggerChar });
- // But a trigger character should
- editor.trigger('keyboard', Handler.Type, { text: triggerChar });
+ // But a trigger character should
+ editor.trigger('keyboard', Handler.Type, { text: triggerChar });
+
+ return donePromise;
+ });
});
test('should use first result from multiple providers', async () => {
@@ -413,17 +457,19 @@ suite('ParameterHintsModel', () => {
}
}));
- editor.trigger('keyboard', Handler.Type, { text: triggerChar });
+ await runWithFakedTimers({ useFakeTimers: true }, async () => {
+ editor.trigger('keyboard', Handler.Type, { text: triggerChar });
- const firstHint = (await getNextHint(model))!.value;
- assert.strictEqual(firstHint.signatures[0].label, firstProviderId);
- assert.strictEqual(firstHint.activeSignature, 0);
- assert.strictEqual(firstHint.signatures[0].parameters[0].label, paramterLabel);
+ const firstHint = (await getNextHint(model))!.value;
+ assert.strictEqual(firstHint.signatures[0].label, firstProviderId);
+ assert.strictEqual(firstHint.activeSignature, 0);
+ assert.strictEqual(firstHint.signatures[0].parameters[0].label, paramterLabel);
- const secondHint = (await getNextHint(model))!.value;
- assert.strictEqual(secondHint.signatures[0].label, secondProviderId);
- assert.strictEqual(secondHint.activeSignature, 1);
- assert.strictEqual(secondHint.signatures[0].parameters[0].label, paramterLabel);
+ const secondHint = (await getNextHint(model))!.value;
+ assert.strictEqual(secondHint.signatures[0].label, secondProviderId);
+ assert.strictEqual(secondHint.activeSignature, 1);
+ assert.strictEqual(secondHint.signatures[0].parameters[0].label, paramterLabel);
+ });
});
test('Quick typing should use the first trigger character', async () => {
@@ -457,13 +503,18 @@ suite('ParameterHintsModel', () => {
}
}));
- editor.trigger('keyboard', Handler.Type, { text: triggerCharacter });
- editor.trigger('keyboard', Handler.Type, { text: 'x' });
+ await runWithFakedTimers({ useFakeTimers: true }, async () => {
+ editor.trigger('keyboard', Handler.Type, { text: triggerCharacter });
+ editor.trigger('keyboard', Handler.Type, { text: 'x' });
- await getNextHint(model);
+ await getNextHint(model);
+ });
});
- test('Retrigger while a pending resolve is still going on should preserve last active signature #96702', (done) => {
+ test('Retrigger while a pending resolve is still going on should preserve last active signature #96702', async () => {
+ let done: (r?: any) => void;
+ const donePromise = new Promise(resolve => { done = resolve; });
+
const editor = createMockEditor('');
const model = new ParameterHintsModel(editor, 50);
disposables.add(model);
@@ -505,10 +556,15 @@ suite('ParameterHintsModel', () => {
}
}));
- editor.trigger('keyboard', Handler.Type, { text: triggerCharacter });
+ await runWithFakedTimers({ useFakeTimers: true }, async () => {
- getNextHint(model)
- .then(() => getNextHint(model));
+ editor.trigger('keyboard', Handler.Type, { text: triggerCharacter });
+
+ await getNextHint(model);
+ await getNextHint(model);
+
+ await donePromise;
+ });
});
});
diff --git a/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts b/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts
index 0c82db5f0d8..ddc4b3e90af 100644
--- a/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts
+++ b/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts
@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
+import { DeferredPromise } from 'vs/base/common/async';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { Codicon } from 'vs/base/common/codicons';
import { IMatch } from 'vs/base/common/filters';
@@ -101,22 +102,21 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
return true;
}
- let symbolProviderRegistryPromiseResolve: (res: boolean) => void;
- const symbolProviderRegistryPromise = new Promise(resolve => symbolProviderRegistryPromiseResolve = resolve);
+ const symbolProviderRegistryPromise = new DeferredPromise();
// Resolve promise when registry knows model
const symbolProviderListener = disposables.add(DocumentSymbolProviderRegistry.onDidChange(() => {
if (DocumentSymbolProviderRegistry.has(model)) {
symbolProviderListener.dispose();
- symbolProviderRegistryPromiseResolve(true);
+ symbolProviderRegistryPromise.complete(true);
}
}));
// Resolve promise when we get disposed too
- disposables.add(toDisposable(() => symbolProviderRegistryPromiseResolve(false)));
+ disposables.add(toDisposable(() => symbolProviderRegistryPromise.complete(false)));
- return symbolProviderRegistryPromise;
+ return symbolProviderRegistryPromise.p;
}
private doProvideWithEditorSymbols(context: IQuickAccessTextEditorContext, model: ITextModel, picker: IQuickPick, token: CancellationToken): IDisposable {
diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts
index 6de2eb0900c..42e2561cef1 100644
--- a/src/vs/editor/contrib/suggest/suggestController.ts
+++ b/src/vs/editor/contrib/suggest/suggestController.ts
@@ -43,6 +43,9 @@ import { CommitCharacterController } from './suggestCommitCharacters';
import { State, SuggestModel } from './suggestModel';
import { OvertypingCapturer } from './suggestOvertypingCapturer';
import { ISelectedSuggestion, SuggestWidget } from './suggestWidget';
+import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
+import { basename, extname } from 'vs/base/common/resources';
+import { hash } from 'vs/base/common/hash';
// sticky suggest widget which doesn't disappear on focus out and such
let _sticky = false;
@@ -122,6 +125,7 @@ export class SuggestController implements IEditorContribution {
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ILogService private readonly _logService: ILogService,
+ @ITelemetryService private readonly _telemetryService: ITelemetryService,
) {
this.editor = editor;
this.model = _instantiationService.createInstance(SuggestModel, this.editor,);
@@ -427,11 +431,37 @@ export class SuggestController implements IEditorContribution {
// clear only now - after all tasks are done
Promise.all(tasks).finally(() => {
+ this._reportSuggestionAcceptedTelemetry(model, event);
+
this.model.clear();
cts.dispose();
});
}
+ private _telemetryGate: number = 0;
+ private _reportSuggestionAcceptedTelemetry(model: ITextModel, acceptedSuggestion: ISelectedSuggestion) {
+ if (this._telemetryGate++ % 100 !== 0) {
+ return;
+ }
+
+ type AcceptedSuggestion = { providerId: string; fileExtension: string; languageId: string; basenameHash: string; };
+ type AcceptedSuggestionClassification = {
+ providerId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; };
+ basenameHash: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; };
+ fileExtension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; };
+ languageId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; };
+ };
+ // _debugDisplayName looks like `vscode.css-language-features(/-:)`, where the last bit is the trigger chars
+ // normalize it to just the extension ID and lowercase
+ const providerId = (acceptedSuggestion.item.provider._debugDisplayName ?? 'unknown').split('(', 1)[0].toLowerCase();
+ this._telemetryService.publicLog2('suggest.acceptedSuggestion', {
+ providerId,
+ basenameHash: hash(basename(model.uri)).toString(16),
+ languageId: model.getLanguageId(),
+ fileExtension: extname(model.uri),
+ });
+ }
+
getOverwriteInfo(item: CompletionItem, toggleMode: boolean): { overwriteBefore: number, overwriteAfter: number } {
assertType(this.editor.hasModel());
diff --git a/src/vs/editor/contrib/suggest/suggestWidgetDetails.ts b/src/vs/editor/contrib/suggest/suggestWidgetDetails.ts
index b5e9cad6a46..e12163c1035 100644
--- a/src/vs/editor/contrib/suggest/suggestWidgetDetails.ts
+++ b/src/vs/editor/contrib/suggest/suggestWidgetDetails.ts
@@ -363,7 +363,7 @@ export class SuggestDetailsOverlay implements IOverlayWidget {
}
placeAtAnchor(anchor: HTMLElement, preferAlignAtTop: boolean) {
- const anchorBox = dom.getDomNodePagePosition(anchor);
+ const anchorBox = anchor.getBoundingClientRect();
this._anchorBox = anchorBox;
this._preferAlignAtTop = preferAlignAtTop;
this._placeAtAnchor(this._anchorBox, this._userSize ?? this.widget.size, preferAlignAtTop);
diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts
index aa6af2cf6bb..8a1dc5e697c 100644
--- a/src/vs/editor/test/browser/controller/cursor.test.ts
+++ b/src/vs/editor/test/browser/controller/cursor.test.ts
@@ -14,16 +14,18 @@ import { TokenizationResult2 } from 'vs/editor/common/core/token';
import { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';
import { EndOfLinePreference, EndOfLineSequence, ITextModel } from 'vs/editor/common/model';
import { TextModel } from 'vs/editor/common/model/textModel';
-import { IState, ITokenizationSupport, TokenizationRegistry } from 'vs/editor/common/modes';
+import { IState, ITokenizationSupport, MetadataConsts, StandardTokenType, TokenizationRegistry } from 'vs/editor/common/modes';
import { IndentAction, IndentationRule } from 'vs/editor/common/modes/languageConfiguration';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { NULL_STATE } from 'vs/editor/common/modes/nullMode';
-import { withTestCodeEditor, TestCodeEditorCreationOptions, ITestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
-import { IRelaxedTextModelCreationOptions, createTextModel } from 'vs/editor/test/common/editorTestUtils';
+import { withTestCodeEditor, TestCodeEditorCreationOptions, ITestCodeEditor, createCodeEditorServices } from 'vs/editor/test/browser/testCodeEditor';
+import { IRelaxedTextModelCreationOptions, createTextModel, createTextModel2 } from 'vs/editor/test/common/editorTestUtils';
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
import { OutgoingViewModelEventKind } from 'vs/editor/common/viewModel/viewModelEventDispatcher';
+import { IModeService } from 'vs/editor/common/services/modeService';
+import { DisposableStore } from 'vs/base/common/lifecycle';
// --------- utils
@@ -4810,7 +4812,7 @@ suite('autoClosingPairs', () => {
private static readonly _id = 'autoClosingMode';
- constructor() {
+ constructor(modeService: IModeService | null = null) {
super(AutoClosingMode._id);
this._register(LanguageConfigurationRegistry.register(this.languageId, {
autoClosingPairs: [
@@ -4827,6 +4829,129 @@ suite('autoClosingPairs', () => {
docComment: { open: '/**', close: ' */' }
}
}));
+ class BaseState implements IState {
+ constructor(
+ public readonly parent: State | null = null
+ ) { }
+ clone(): IState { return this; }
+ equals(other: IState): boolean {
+ if (!(other instanceof BaseState)) {
+ return false;
+ }
+ if (!this.parent && !other.parent) {
+ return true;
+ }
+ if (!this.parent || !other.parent) {
+ return false;
+ }
+ return this.parent.equals(other.parent);
+ }
+ }
+ class StringState implements IState {
+ constructor(
+ public readonly char: string,
+ public readonly parentState: State
+ ) { }
+ clone(): IState { return this; }
+ equals(other: IState): boolean { return other instanceof StringState && this.char === other.char && this.parentState.equals(other.parentState); }
+ }
+ class BlockCommentState implements IState {
+ constructor(
+ public readonly parentState: State
+ ) { }
+ clone(): IState { return this; }
+ equals(other: IState): boolean { return other instanceof StringState && this.parentState.equals(other.parentState); }
+ }
+ type State = BaseState | StringState | BlockCommentState;
+
+ if (modeService) {
+ const encodedLanguageId = modeService.languageIdCodec.encodeLanguageId(this.languageId);
+ this._register(TokenizationRegistry.register(this.languageId, {
+ getInitialState: () => new BaseState(),
+ tokenize: undefined!,
+ tokenize2: function (line: string, hasEOL: boolean, _state: IState, offsetDelta: number): TokenizationResult2 {
+ let state = _state;
+ const tokens: { length: number; type: StandardTokenType; }[] = [];
+ const generateToken = (length: number, type: StandardTokenType, newState?: State) => {
+ if (tokens.length > 0 && tokens[tokens.length - 1].type === type) {
+ // grow last tokens
+ tokens[tokens.length - 1].length += length;
+ } else {
+ tokens.push({ length, type });
+ }
+ line = line.substring(length);
+ if (newState) {
+ state = newState;
+ }
+ };
+ while (line.length > 0) {
+ advance();
+ }
+ let result = new Uint32Array(tokens.length * 2);
+ let startIndex = 0;
+ for (let i = 0; i < tokens.length; i++) {
+ result[2 * i] = startIndex;
+ result[2 * i + 1] = (
+ (encodedLanguageId << MetadataConsts.LANGUAGEID_OFFSET)
+ | (tokens[i].type << MetadataConsts.TOKEN_TYPE_OFFSET)
+ );
+ startIndex += tokens[i].length;
+ }
+ return new TokenizationResult2(result, state);
+
+ function advance(): void {
+ if (state instanceof BaseState) {
+ const m1 = line.match(/^[^'"`{}/]+/g);
+ if (m1) {
+ return generateToken(m1[0].length, StandardTokenType.Other);
+ }
+ if (/^['"`]/.test(line)) {
+ return generateToken(1, StandardTokenType.String, new StringState(line.charAt(0), state));
+ }
+ if (/^{/.test(line)) {
+ return generateToken(1, StandardTokenType.Other, new BaseState(state));
+ }
+ if (/^}/.test(line)) {
+ return generateToken(1, StandardTokenType.Other, state.parent || new BaseState());
+ }
+ if (/^\/\//.test(line)) {
+ return generateToken(line.length, StandardTokenType.Comment, state);
+ }
+ if (/^\/\*/.test(line)) {
+ return generateToken(2, StandardTokenType.Comment, new BlockCommentState(state));
+ }
+ return generateToken(1, StandardTokenType.Other, state);
+ } else if (state instanceof StringState) {
+ const m1 = line.match(/^[^\\'"`\$]+/g);
+ if (m1) {
+ return generateToken(m1[0].length, StandardTokenType.String);
+ }
+ if (/^\\/.test(line)) {
+ return generateToken(2, StandardTokenType.String);
+ }
+ if (line.charAt(0) === state.char) {
+ return generateToken(1, StandardTokenType.String, state.parentState);
+ }
+ if (/^\$\{/.test(line)) {
+ return generateToken(2, StandardTokenType.Other, new BaseState(state));
+ }
+ return generateToken(1, StandardTokenType.Other, state);
+ } else if (state instanceof BlockCommentState) {
+ const m1 = line.match(/^[^*]+/g);
+ if (m1) {
+ return generateToken(m1[0].length, StandardTokenType.String);
+ }
+ if (/^\*\//.test(line)) {
+ return generateToken(2, StandardTokenType.Comment, state.parentState);
+ }
+ return generateToken(1, StandardTokenType.Other, state);
+ } else {
+ throw new Error(`unknown state`);
+ }
+ }
+ }
+ }));
+ }
}
public setAutocloseEnabledSet(chars: string) {
@@ -4869,7 +4994,7 @@ suite('autoClosingPairs', () => {
return result;
}
- function assertType(editor: ITestCodeEditor, model: TextModel, viewModel: ViewModel, lineNumber: number, column: number, chr: string, expectedInsert: string, message: string): void {
+ function assertType(editor: ITestCodeEditor, model: ITextModel, viewModel: ViewModel, lineNumber: number, column: number, chr: string, expectedInsert: string, message: string): void {
let lineContent = model.getLineContent(lineNumber);
let expected = lineContent.substr(0, column - 1) + expectedInsert + lineContent.substr(column - 1);
moveTo(editor, viewModel, lineNumber, column);
@@ -4890,6 +5015,25 @@ suite('autoClosingPairs', () => {
mode.dispose();
});
+ test('issue #132912: quotes should not auto-close if they are closing a string', () => {
+ const disposables = new DisposableStore();
+ const instantiationService = createCodeEditorServices(disposables);
+ const modeService = instantiationService.invokeFunction((accessor) => accessor.get(IModeService));
+ const mode = disposables.add(new AutoClosingMode(modeService));
+ withTestCodeEditor(
+ null,
+ {
+ model: disposables.add(createTextModel2(instantiationService, 'const t2 = `something ${t1}', undefined, mode.languageId))
+ },
+ (editor, viewModel) => {
+ const model = viewModel.model;
+ model.forceTokenization(1);
+ assertType(editor, model, viewModel, 1, 28, '`', '`', `does not auto close \` @ (1, 28)`);
+ }
+ );
+ disposables.dispose();
+ });
+
test('open parens: default', () => {
let mode = new AutoClosingMode();
usingCursor({
diff --git a/src/vs/editor/test/common/modes/supports/characterPair.test.ts b/src/vs/editor/test/common/modes/supports/characterPair.test.ts
index ce1c31ee92d..5d799f478de 100644
--- a/src/vs/editor/test/common/modes/supports/characterPair.test.ts
+++ b/src/vs/editor/test/common/modes/supports/characterPair.test.ts
@@ -53,78 +53,71 @@ suite('CharacterPairSupport', () => {
assert.deepStrictEqual(characaterPairSupport.getSurroundingPairs(), []);
});
- function findAutoClosingPair(characterPairSupport: CharacterPairSupport, character: string): StandardAutoClosingPairConditional | undefined {
- return characterPairSupport.getAutoClosingPairs().find(autoClosingPair => autoClosingPair.open === character);
- }
-
- function testShouldAutoClose(characterPairSupport: CharacterPairSupport, line: TokenText[], character: string, column: number): boolean {
- const autoClosingPair = findAutoClosingPair(characterPairSupport, character);
- if (!autoClosingPair) {
- return false;
- }
- return CharacterPairSupport.shouldAutoClosePair(autoClosingPair, createFakeScopedLineTokens(line), column);
+ function testShouldAutoClose(characterPairSupport: CharacterPairSupport, line: TokenText[], column: number): boolean {
+ const autoClosingPair = characterPairSupport.getAutoClosingPairs()[0];
+ return autoClosingPair.shouldAutoClose(createFakeScopedLineTokens(line), column);
}
test('shouldAutoClosePair in empty line', () => {
- let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
- assert.strictEqual(testShouldAutoClose(sup, [], 'a', 1), false);
- assert.strictEqual(testShouldAutoClose(sup, [], '{', 1), true);
+ const sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
+ const tokenText: TokenText[] = [];
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 1), true);
});
test('shouldAutoClosePair in not interesting line 1', () => {
- let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.Other }], '{', 3), true);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.Other }], 'a', 3), false);
+ const sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
+ const tokenText: TokenText[] = [
+ { text: 'do', type: StandardTokenType.Other }
+ ];
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 3), true);
});
test('shouldAutoClosePair in not interesting line 2', () => {
- let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}' }] });
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.String }], '{', 3), true);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'do', type: StandardTokenType.String }], 'a', 3), false);
+ const sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}' }] });
+ const tokenText: TokenText[] = [
+ { text: 'do', type: StandardTokenType.String }
+ ];
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 3), true);
});
test('shouldAutoClosePair in interesting line 1', () => {
- let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
- assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 1), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 1), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 2), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 2), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 3), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 3), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], '{', 4), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: '"a"', type: StandardTokenType.String }], 'a', 4), false);
+ const sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
+ const tokenText: TokenText[] = [
+ { text: '"a"', type: StandardTokenType.String }
+ ];
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 1), false);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 2), false);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 3), false);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 4), false);
});
test('shouldAutoClosePair in interesting line 2', () => {
- let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 1), true);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 1), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 2), true);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 2), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 3), true);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 3), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 4), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 4), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 5), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 5), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 6), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 6), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], '{', 7), true);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: 'x=', type: StandardTokenType.Other }, { text: '"a"', type: StandardTokenType.String }, { text: ';', type: StandardTokenType.Other }], 'a', 7), false);
+ const sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
+ const tokenText: TokenText[] = [
+ { text: 'x=', type: StandardTokenType.Other },
+ { text: '"a"', type: StandardTokenType.String },
+ { text: ';', type: StandardTokenType.Other }
+ ];
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 1), true);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 2), true);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 3), true);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 4), false);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 5), false);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 6), false);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 7), true);
});
test('shouldAutoClosePair in interesting line 3', () => {
- let sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 1), true);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 1), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 2), true);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 2), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 3), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 3), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 4), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 4), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], '{', 5), false);
- assert.strictEqual(testShouldAutoClose(sup, [{ text: ' ', type: StandardTokenType.Other }, { text: '//a', type: StandardTokenType.Comment }], 'a', 5), false);
+ const sup = new CharacterPairSupport({ autoClosingPairs: [{ open: '{', close: '}', notIn: ['string', 'comment'] }] });
+ const tokenText: TokenText[] = [
+ { text: ' ', type: StandardTokenType.Other },
+ { text: '//a', type: StandardTokenType.Comment }
+ ];
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 1), true);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 2), true);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 3), false);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 4), false);
+ assert.strictEqual(testShouldAutoClose(sup, tokenText, 5), false);
});
});
diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts
index 2711e370a19..7716e2b73dd 100644
--- a/src/vs/platform/configuration/common/configuration.ts
+++ b/src/vs/platform/configuration/common/configuration.ts
@@ -3,12 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { IStringDictionary } from 'vs/base/common/collections';
import { Event } from 'vs/base/common/event';
-import * as objects from 'vs/base/common/objects';
import * as types from 'vs/base/common/types';
import { URI, UriComponents } from 'vs/base/common/uri';
-import { Extensions, IConfigurationRegistry, overrideIdentifierFromKey, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry';
+import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
@@ -27,6 +25,16 @@ export interface IConfigurationOverrides {
resource?: URI | null;
}
+export function isConfigurationUpdateOverrides(thing: any): thing is IConfigurationUpdateOverrides {
+ return thing
+ && typeof thing === 'object'
+ && (!thing.overrideIdentifiers || types.isArray(thing.overrideIdentifiers))
+ && !thing.overrideIdentifier
+ && (!thing.resource || thing.resource instanceof URI);
+}
+
+export type IConfigurationUpdateOverrides = Omit & { overrideIdentifiers?: string[] | null; };
+
export const enum ConfigurationTarget {
USER = 1,
USER_LOCAL,
@@ -108,9 +116,9 @@ export interface IConfigurationService {
getValue(section: string, overrides: IConfigurationOverrides): T;
updateValue(key: string, value: any): Promise;
- updateValue(key: string, value: any, overrides: IConfigurationOverrides): Promise;
+ updateValue(key: string, value: any, overrides: IConfigurationOverrides | IConfigurationUpdateOverrides): Promise;
updateValue(key: string, value: any, target: ConfigurationTarget): Promise;
- updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget, donotNotifyError?: boolean): Promise;
+ updateValue(key: string, value: any, overrides: IConfigurationOverrides | IConfigurationUpdateOverrides, target: ConfigurationTarget, donotNotifyError?: boolean): Promise;
inspect(key: string, overrides?: IConfigurationOverrides): IConfigurationValue>;
@@ -151,89 +159,6 @@ export interface IConfigurationCompareResult {
overrides: [string, string[]][];
}
-export function compare(from: IConfigurationModel | undefined, to: IConfigurationModel | undefined): IConfigurationCompareResult {
- const added = to
- ? from ? to.keys.filter(key => from.keys.indexOf(key) === -1) : [...to.keys]
- : [];
- const removed = from
- ? to ? from.keys.filter(key => to.keys.indexOf(key) === -1) : [...from.keys]
- : [];
- const updated: string[] = [];
-
- if (to && from) {
- for (const key of from.keys) {
- if (to.keys.indexOf(key) !== -1) {
- const value1 = getConfigurationValue(from.contents, key);
- const value2 = getConfigurationValue(to.contents, key);
- if (!objects.equals(value1, value2)) {
- updated.push(key);
- }
- }
- }
- }
-
- const overrides: [string, string[]][] = [];
- const byOverrideIdentifier = (overrides: IOverrides[]): IStringDictionary => {
- const result: IStringDictionary = {};
- for (const override of overrides) {
- for (const identifier of override.identifiers) {
- result[keyFromOverrideIdentifier(identifier)] = override;
- }
- }
- return result;
- };
- const toOverridesByIdentifier: IStringDictionary = to ? byOverrideIdentifier(to.overrides) : {};
- const fromOverridesByIdentifier: IStringDictionary = from ? byOverrideIdentifier(from.overrides) : {};
-
- if (Object.keys(toOverridesByIdentifier).length) {
- for (const key of added) {
- const override = toOverridesByIdentifier[key];
- if (override) {
- overrides.push([overrideIdentifierFromKey(key), override.keys]);
- }
- }
- }
- if (Object.keys(fromOverridesByIdentifier).length) {
- for (const key of removed) {
- const override = fromOverridesByIdentifier[key];
- if (override) {
- overrides.push([overrideIdentifierFromKey(key), override.keys]);
- }
- }
- }
-
- if (Object.keys(toOverridesByIdentifier).length && Object.keys(fromOverridesByIdentifier).length) {
- for (const key of updated) {
- const fromOverride = fromOverridesByIdentifier[key];
- const toOverride = toOverridesByIdentifier[key];
- if (fromOverride && toOverride) {
- const result = compare({ contents: fromOverride.contents, keys: fromOverride.keys, overrides: [] }, { contents: toOverride.contents, keys: toOverride.keys, overrides: [] });
- overrides.push([overrideIdentifierFromKey(key), [...result.added, ...result.removed, ...result.updated]]);
- }
- }
- }
-
- return { added, removed, updated, overrides };
-}
-
-export function toOverrides(raw: any, conflictReporter: (message: string) => void): IOverrides[] {
- const overrides: IOverrides[] = [];
- for (const key of Object.keys(raw)) {
- if (OVERRIDE_PROPERTY_PATTERN.test(key)) {
- const overrideRaw: any = {};
- for (const keyInOverrideRaw in raw[key]) {
- overrideRaw[keyInOverrideRaw] = raw[key][keyInOverrideRaw];
- }
- overrides.push({
- identifiers: [overrideIdentifierFromKey(key).trim()],
- keys: Object.keys(overrideRaw),
- contents: toValuesTree(overrideRaw, conflictReporter)
- });
- }
- }
- return overrides;
-}
-
export function toValuesTree(properties: { [qualifiedKey: string]: any }, conflictReporter: (message: string) => void): any {
const root = Object.create(null);
@@ -354,10 +279,6 @@ export function getDefaultValues(): any {
return valueTreeRoot;
}
-export function keyFromOverrideIdentifier(overrideIdentifier: string): string {
- return `[${overrideIdentifier}]`;
-}
-
export function getMigratedSettingValue(configurationService: IConfigurationService, currentSettingName: string, legacySettingName: string): T {
const setting = configurationService.inspect(currentSettingName);
const legacySetting = configurationService.inspect(legacySettingName);
diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts
index ae155ae126f..f41d440c4f9 100644
--- a/src/vs/platform/configuration/common/configurationModels.ts
+++ b/src/vs/platform/configuration/common/configurationModels.ts
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as arrays from 'vs/base/common/arrays';
+import { IStringDictionary } from 'vs/base/common/collections';
import { Emitter, Event } from 'vs/base/common/event';
import * as json from 'vs/base/common/json';
import { Disposable } from 'vs/base/common/lifecycle';
@@ -12,8 +13,8 @@ import * as objects from 'vs/base/common/objects';
import { IExtUri } from 'vs/base/common/resources';
import * as types from 'vs/base/common/types';
import { URI, UriComponents } from 'vs/base/common/uri';
-import { addToValueTree, compare, ConfigurationTarget, getConfigurationKeys, getConfigurationValue, getDefaultValues, IConfigurationChange, IConfigurationChangeEvent, IConfigurationData, IConfigurationModel, IConfigurationOverrides, IConfigurationValue, IOverrides, removeFromValueTree, toOverrides, toValuesTree } from 'vs/platform/configuration/common/configuration';
-import { ConfigurationScope, Extensions, IConfigurationPropertySchema, IConfigurationRegistry, overrideIdentifierFromKey, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry';
+import { addToValueTree, ConfigurationTarget, getConfigurationKeys, getConfigurationValue, getDefaultValues, IConfigurationChange, IConfigurationChangeEvent, IConfigurationCompareResult, IConfigurationData, IConfigurationModel, IConfigurationOverrides, IConfigurationUpdateOverrides, IConfigurationValue, IOverrides, removeFromValueTree, toValuesTree } from 'vs/platform/configuration/common/configuration';
+import { ConfigurationScope, Extensions, IConfigurationPropertySchema, IConfigurationRegistry, overrideIdentifiersFromKey, OVERRIDE_PROPERTY_REGEX } from 'vs/platform/configuration/common/configurationRegistry';
import { IFileService } from 'vs/platform/files/common/files';
import { Registry } from 'vs/platform/registry/common/platform';
import { Workspace } from 'vs/platform/workspace/common/workspace';
@@ -58,12 +59,21 @@ export class ConfigurationModel implements IConfigurationModel {
}
getKeysForOverrideIdentifier(identifier: string): string[] {
+ const keys: string[] = [];
for (const override of this.overrides) {
- if (override.identifiers.indexOf(identifier) !== -1) {
- return override.keys;
+ if (override.identifiers.includes(identifier)) {
+ keys.push(...override.keys);
}
}
- return [];
+ return arrays.distinct(keys);
+ }
+
+ getAllOverrideIdentifiers(): string[] {
+ const result: string[] = [];
+ for (const override of this.overrides) {
+ result.push(...override.identifiers);
+ }
+ return arrays.distinct(result);
}
override(identifier: string): ConfigurationModel {
@@ -87,6 +97,8 @@ export class ConfigurationModel implements IConfigurationModel {
const [override] = overrides.filter(o => arrays.equals(o.identifiers, otherOverride.identifiers));
if (override) {
this.mergeContents(override.contents, otherOverride.contents);
+ override.keys.push(...otherOverride.keys);
+ override.keys = arrays.distinct(override.keys);
} else {
overrides.push(objects.deepClone(otherOverride));
}
@@ -156,12 +168,27 @@ export class ConfigurationModel implements IConfigurationModel {
}
private getContentsForOverrideIdentifer(identifier: string): any {
+ let contentsForIdentifierOnly: IStringDictionary | null = null;
+ let contents: IStringDictionary | null = null;
+ const mergeContents = (contentsToMerge: any) => {
+ if (contentsToMerge) {
+ if (contents) {
+ this.mergeContents(contents, contentsToMerge);
+ } else {
+ contents = objects.deepClone(contentsToMerge);
+ }
+ }
+ };
for (const override of this.overrides) {
- if (override.identifiers.indexOf(identifier) !== -1) {
- return override.contents;
+ if (arrays.equals(override.identifiers, [identifier])) {
+ contentsForIdentifierOnly = override.contents;
+ } else if (override.identifiers.includes(identifier)) {
+ mergeContents(override.contents);
}
}
- return null;
+ // Merge contents of the identifier only at the end to take precedence.
+ mergeContents(contentsForIdentifierOnly);
+ return contents;
}
toJSON(): IConfigurationModel {
@@ -212,9 +239,9 @@ export class DefaultConfigurationModel extends ConfigurationModel {
const keys = getConfigurationKeys();
const overrides: IOverrides[] = [];
for (const key of Object.keys(contents)) {
- if (OVERRIDE_PROPERTY_PATTERN.test(key)) {
+ if (OVERRIDE_PROPERTY_REGEX.test(key)) {
overrides.push({
- identifiers: [overrideIdentifierFromKey(key).trim()],
+ identifiers: overrideIdentifiersFromKey(key),
keys: Object.keys(contents[key]),
contents: toValuesTree(contents[key], message => console.error(`Conflict in default settings file: ${message}`)),
});
@@ -333,7 +360,7 @@ export class ConfigurationModelParser {
raw = filtered.raw;
const contents = toValuesTree(raw, message => console.error(`Conflict in settings file ${this._name}: ${message}`));
const keys = Object.keys(raw);
- const overrides: IOverrides[] = toOverrides(raw, message => console.error(`Conflict in settings file ${this._name}: ${message}`));
+ const overrides = this.toOverrides(raw, message => console.error(`Conflict in settings file ${this._name}: ${message}`));
return { contents, keys, overrides, restricted: filtered.restricted };
}
@@ -344,7 +371,7 @@ export class ConfigurationModelParser {
const raw: any = {};
const restricted: string[] = [];
for (let key in properties) {
- if (OVERRIDE_PROPERTY_PATTERN.test(key) && filterOverriddenProperties) {
+ if (OVERRIDE_PROPERTY_REGEX.test(key) && filterOverriddenProperties) {
const result = this.filter(properties[key], configurationProperties, false, options);
raw[key] = result.raw;
restricted.push(...result.restricted);
@@ -365,6 +392,24 @@ export class ConfigurationModelParser {
return { raw, restricted };
}
+ private toOverrides(raw: any, conflictReporter: (message: string) => void): IOverrides[] {
+ const overrides: IOverrides[] = [];
+ for (const key of Object.keys(raw)) {
+ if (OVERRIDE_PROPERTY_REGEX.test(key)) {
+ const overrideRaw: any = {};
+ for (const keyInOverrideRaw in raw[key]) {
+ overrideRaw[keyInOverrideRaw] = raw[key][keyInOverrideRaw];
+ }
+ overrides.push({
+ identifiers: overrideIdentifiersFromKey(key),
+ keys: Object.keys(overrideRaw),
+ contents: toValuesTree(overrideRaw, conflictReporter)
+ });
+ }
+ }
+ return overrides;
+ }
+
}
export class UserSettings extends Disposable {
@@ -431,7 +476,7 @@ export class Configuration {
return consolidateConfigurationModel.getValue(section);
}
- updateValue(key: string, value: any, overrides: IConfigurationOverrides = {}): void {
+ updateValue(key: string, value: any, overrides: IConfigurationUpdateOverrides = {}): void {
let memoryConfiguration: ConfigurationModel | undefined;
if (overrides.resource) {
memoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource);
@@ -543,10 +588,9 @@ export class Configuration {
}
compareAndUpdateDefaultConfiguration(defaults: ConfigurationModel, keys: string[]): IConfigurationChange {
- const overrides: [string, string[]][] = keys
- .filter(key => OVERRIDE_PROPERTY_PATTERN.test(key))
- .map(key => {
- const overrideIdentifier = overrideIdentifierFromKey(key);
+ const overrides: [string, string[]][] = [];
+ for (const key of keys) {
+ for (const overrideIdentifier of overrideIdentifiersFromKey(key)) {
const fromKeys = this._defaultConfiguration.getKeysForOverrideIdentifier(overrideIdentifier);
const toKeys = defaults.getKeysForOverrideIdentifier(overrideIdentifier);
const keys = [
@@ -554,8 +598,9 @@ export class Configuration {
...fromKeys.filter(key => toKeys.indexOf(key) === -1),
...fromKeys.filter(key => !objects.equals(this._defaultConfiguration.override(overrideIdentifier).getValue(key), defaults.override(overrideIdentifier).getValue(key)))
];
- return [overrideIdentifier, keys];
- });
+ overrides.push([overrideIdentifier, keys]);
+ }
+ }
this.updateDefaultConfiguration(defaults);
return { keys, overrides };
}
@@ -732,6 +777,15 @@ export class Configuration {
return [...keys.values()];
}
+ protected allOverrideIdentifiers(): string[] {
+ const keys: Set = new Set();
+ this._defaultConfiguration.freeze().getAllOverrideIdentifiers().forEach(key => keys.add(key));
+ this.userConfiguration.freeze().getAllOverrideIdentifiers().forEach(key => keys.add(key));
+ this._workspaceConfiguration.freeze().getAllOverrideIdentifiers().forEach(key => keys.add(key));
+ this._folderConfigurations.forEach(folderConfiguraiton => folderConfiguraiton.freeze().getAllOverrideIdentifiers().forEach(key => keys.add(key)));
+ return [...keys.values()];
+ }
+
protected getAllKeysForOverrideIdentifier(overrideIdentifier: string): string[] {
const keys: Set = new Set();
this._defaultConfiguration.getKeysForOverrideIdentifier(overrideIdentifier).forEach(key => keys.add(key));
@@ -839,3 +893,59 @@ export class AllKeysConfigurationChangeEvent extends ConfigurationChangeEvent {
this.sourceConfig = sourceConfig;
}
}
+
+function compare(from: ConfigurationModel | undefined, to: ConfigurationModel | undefined): IConfigurationCompareResult {
+ const { added, removed, updated } = compareConfigurationContents(to, from);
+ const overrides: [string, string[]][] = [];
+
+ const fromOverrideIdentifiers = from?.getAllOverrideIdentifiers() || [];
+ const toOverrideIdentifiers = to?.getAllOverrideIdentifiers() || [];
+
+ if (to) {
+ const addedOverrideIdentifiers = toOverrideIdentifiers.filter(key => !fromOverrideIdentifiers.includes(key));
+ for (const identifier of addedOverrideIdentifiers) {
+ overrides.push([identifier, to.getKeysForOverrideIdentifier(identifier)]);
+ }
+ }
+
+ if (from) {
+ const removedOverrideIdentifiers = fromOverrideIdentifiers.filter(key => !toOverrideIdentifiers.includes(key));
+ for (const identifier of removedOverrideIdentifiers) {
+ overrides.push([identifier, from.getKeysForOverrideIdentifier(identifier)]);
+ }
+ }
+
+ if (to && from) {
+ for (const identifier of fromOverrideIdentifiers) {
+ if (toOverrideIdentifiers.includes(identifier)) {
+ const result = compareConfigurationContents({ contents: from.getOverrideValue(undefined, identifier) || {}, keys: from.getKeysForOverrideIdentifier(identifier) }, { contents: to.getOverrideValue(undefined, identifier) || {}, keys: to.getKeysForOverrideIdentifier(identifier) });
+ overrides.push([identifier, [...result.added, ...result.removed, ...result.updated]]);
+ }
+ }
+ }
+
+ return { added, removed, updated, overrides };
+}
+
+function compareConfigurationContents(to: { keys: string[], contents: any } | undefined, from: { keys: string[], contents: any } | undefined) {
+ const added = to
+ ? from ? to.keys.filter(key => from.keys.indexOf(key) === -1) : [...to.keys]
+ : [];
+ const removed = from
+ ? to ? from.keys.filter(key => to.keys.indexOf(key) === -1) : [...from.keys]
+ : [];
+ const updated: string[] = [];
+
+ if (to && from) {
+ for (const key of from.keys) {
+ if (to.keys.indexOf(key) !== -1) {
+ const value1 = getConfigurationValue(from.contents, key);
+ const value2 = getConfigurationValue(to.contents, key);
+ if (!objects.equals(value1, value2)) {
+ updated.push(key);
+ }
+ }
+ }
+ }
+ return { added, removed, updated };
+}
diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts
index 16ae308adf1..6dc55505e20 100644
--- a/src/vs/platform/configuration/common/configurationRegistry.ts
+++ b/src/vs/platform/configuration/common/configurationRegistry.ts
@@ -217,6 +217,7 @@ class ConfigurationRegistry implements IConfigurationRegistry {
this.excludedConfigurationProperties = {};
contributionRegistry.registerSchema(resourceLanguageSettingsSchemaId, this.resourceLanguageSettingsSchema);
+ this.registerOverridePropertyPatternKey();
}
public registerConfiguration(configuration: IConfigurationNode, validate: boolean = true): void {
@@ -257,7 +258,7 @@ class ConfigurationRegistry implements IConfigurationRegistry {
for (const key in defaultConfiguration) {
properties.push(key);
- if (OVERRIDE_PROPERTY_PATTERN.test(key)) {
+ if (OVERRIDE_PROPERTY_REGEX.test(key)) {
this.defaultValues[key] = { ...(this.defaultValues[key] || {}), ...defaultConfiguration[key] };
const property: IConfigurationPropertySchema = {
type: 'object',
@@ -265,7 +266,7 @@ class ConfigurationRegistry implements IConfigurationRegistry {
description: nls.localize('defaultLanguageConfiguration.description', "Configure settings to be overridden for {0} language.", key),
$ref: resourceLanguageSettingsSchemaId
};
- overrideIdentifiers.push(overrideIdentifierFromKey(key));
+ overrideIdentifiers.push(...overrideIdentifiersFromKey(key));
this.configurationProperties[key] = property;
this.defaultLanguageConfigurationOverridesNode.properties![key] = property;
} else {
@@ -290,7 +291,7 @@ class ConfigurationRegistry implements IConfigurationRegistry {
for (const key in defaultConfiguration) {
properties.push(key);
delete this.defaultValues[key];
- if (OVERRIDE_PROPERTY_PATTERN.test(key)) {
+ if (OVERRIDE_PROPERTY_REGEX.test(key)) {
delete this.configurationProperties[key];
delete this.defaultLanguageConfigurationOverridesNode.properties![key];
} else {
@@ -370,7 +371,7 @@ class ConfigurationRegistry implements IConfigurationRegistry {
this.updatePropertyDefaultValue(key, property);
// update scope
- if (OVERRIDE_PROPERTY_PATTERN.test(key)) {
+ if (OVERRIDE_PROPERTY_REGEX.test(key)) {
property.scope = undefined; // No scope for overridable properties `[${identifier}]`
} else {
property.scope = types.isUndefinedOrNull(property.scope) ? scope : property.scope;
@@ -499,6 +500,22 @@ class ConfigurationRegistry implements IConfigurationRegistry {
this._onDidSchemaChange.fire();
}
+ private registerOverridePropertyPatternKey(): void {
+ const resourceLanguagePropertiesSchema: IJSONSchema = {
+ type: 'object',
+ description: nls.localize('overrideSettings.defaultDescription', "Configure editor settings to be overridden for a language."),
+ errorMessage: nls.localize('overrideSettings.errorMessage', "This setting does not support per-language configuration."),
+ $ref: resourceLanguageSettingsSchemaId,
+ };
+ allSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
+ applicationSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
+ machineSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
+ machineOverridableSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
+ windowSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
+ resourceSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
+ this._onDidSchemaChange.fire();
+ }
+
private updatePropertyDefaultValue(key: string, property: IConfigurationPropertySchema): void {
let defaultValue = this.defaultValues[key];
if (types.isUndefined(defaultValue)) {
@@ -511,11 +528,28 @@ class ConfigurationRegistry implements IConfigurationRegistry {
}
}
-const OVERRIDE_PROPERTY = '\\[.*\\]$';
-export const OVERRIDE_PROPERTY_PATTERN = new RegExp(OVERRIDE_PROPERTY);
+const OVERRIDE_IDENTIFIER_PATTERN = `\\[([^\\]]+)\\]`;
+const OVERRIDE_IDENTIFIER_REGEX = new RegExp(OVERRIDE_IDENTIFIER_PATTERN, 'g');
+export const OVERRIDE_PROPERTY_PATTERN = `^(${OVERRIDE_IDENTIFIER_PATTERN})+$`;
+export const OVERRIDE_PROPERTY_REGEX = new RegExp(OVERRIDE_PROPERTY_PATTERN);
-export function overrideIdentifierFromKey(key: string): string {
- return key.substring(1, key.length - 1);
+export function overrideIdentifiersFromKey(key: string): string[] {
+ const identifiers: string[] = [];
+ if (OVERRIDE_PROPERTY_REGEX.test(key)) {
+ let matches = OVERRIDE_IDENTIFIER_REGEX.exec(key);
+ while (matches?.length) {
+ const identifier = matches[1].trim();
+ if (identifier) {
+ identifiers.push(identifier);
+ }
+ matches = OVERRIDE_IDENTIFIER_REGEX.exec(key);
+ }
+ }
+ return distinct(identifiers);
+}
+
+export function keyFromOverrideIdentifiers(overrideIdentifiers: string[]): string {
+ return overrideIdentifiers.reduce((result, overrideIdentifier) => `${result}[${overrideIdentifier}]`, '');
}
export function getDefaultValue(type: string | string[] | undefined): any {
@@ -537,7 +571,6 @@ export function getDefaultValue(type: string | string[] | undefined): any {
}
}
-
const configurationRegistry = new ConfigurationRegistry();
Registry.add(Extensions.Configuration, configurationRegistry);
@@ -545,7 +578,7 @@ export function validateProperty(property: string): string | null {
if (!property.trim()) {
return nls.localize('config.property.empty', "Cannot register an empty property");
}
- if (OVERRIDE_PROPERTY_PATTERN.test(property)) {
+ if (OVERRIDE_PROPERTY_REGEX.test(property)) {
return nls.localize('config.property.languageDefault', "Cannot register '{0}'. This matches property pattern '\\\\[.*\\\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.", property);
}
if (configurationRegistry.getConfigurationProperties()[property] !== undefined) {
diff --git a/src/vs/platform/configuration/test/common/configurationModels.test.ts b/src/vs/platform/configuration/test/common/configurationModels.test.ts
index 0032a1e5b9f..406f48b8092 100644
--- a/src/vs/platform/configuration/test/common/configurationModels.test.ts
+++ b/src/vs/platform/configuration/test/common/configurationModels.test.ts
@@ -12,6 +12,35 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { Workspace } from 'vs/platform/workspace/test/common/testWorkspace';
+suite('ConfigurationModelParser', () => {
+
+ test('parse configuration model with single override identifier', () => {
+ const testObject = new ConfigurationModelParser('');
+
+ testObject.parse(JSON.stringify({ '[x]': { 'a': 1 } }));
+
+ assert.deepStrictEqual(JSON.stringify(testObject.configurationModel.overrides), JSON.stringify([{ identifiers: ['x'], keys: ['a'], contents: { 'a': 1 } }]));
+ });
+
+ test('parse configuration model with multiple override identifiers', () => {
+ const testObject = new ConfigurationModelParser('');
+
+ testObject.parse(JSON.stringify({ '[x][y]': { 'a': 1 } }));
+
+ assert.deepStrictEqual(JSON.stringify(testObject.configurationModel.overrides), JSON.stringify([{ identifiers: ['x', 'y'], keys: ['a'], contents: { 'a': 1 } }]));
+ });
+
+ test('parse configuration model with multiple duplicate override identifiers', () => {
+ const testObject = new ConfigurationModelParser('');
+
+ testObject.parse(JSON.stringify({ '[x][y][x][z]': { 'a': 1 } }));
+
+ assert.deepStrictEqual(JSON.stringify(testObject.configurationModel.overrides), JSON.stringify([{ identifiers: ['x', 'y', 'z'], keys: ['a'], contents: { 'a': 1 } }]));
+ });
+
+
+});
+
suite('ConfigurationModel', () => {
test('setValue for a key that has no sections and not defined', () => {
@@ -190,7 +219,7 @@ suite('ConfigurationModel', () => {
let result = base.merge(add);
assert.deepStrictEqual(result.contents, { 'a': { 'b': 2 } });
- assert.deepStrictEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': 2, 'b': 2 }, keys: ['a'] }]);
+ assert.deepStrictEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': 2, 'b': 2 }, keys: ['a', 'b'] }]);
assert.deepStrictEqual(result.override('c').contents, { 'a': 2, 'b': 2 });
assert.deepStrictEqual(result.keys, ['a.b']);
});
@@ -236,6 +265,45 @@ suite('ConfigurationModel', () => {
assert.deepStrictEqual(testObject.override('b').contents, { 'a': 2, 'c': 1 });
});
+
+ test('Test override when an override has multiple identifiers', () => {
+ const testObject = new ConfigurationModel({ 'a': 1, 'c': 1 }, ['a', 'c'], [{ identifiers: ['x', 'y'], contents: { 'a': 2 }, keys: ['a'] }]);
+
+ let actual = testObject.override('x');
+ assert.deepStrictEqual(actual.contents, { 'a': 2, 'c': 1 });
+ assert.deepStrictEqual(actual.keys, ['a', 'c']);
+ assert.deepStrictEqual(testObject.getKeysForOverrideIdentifier('x'), ['a']);
+
+ actual = testObject.override('y');
+ assert.deepStrictEqual(actual.contents, { 'a': 2, 'c': 1 });
+ assert.deepStrictEqual(actual.keys, ['a', 'c']);
+ assert.deepStrictEqual(testObject.getKeysForOverrideIdentifier('y'), ['a']);
+ });
+
+ test('Test override when an identifier is defined in multiple overrides', () => {
+ const testObject = new ConfigurationModel({ 'a': 1, 'c': 1 }, ['a', 'c'], [{ identifiers: ['x'], contents: { 'a': 3, 'b': 1 }, keys: ['a', 'b'] }, { identifiers: ['x', 'y'], contents: { 'a': 2 }, keys: ['a'] }]);
+
+ const actual = testObject.override('x');
+ assert.deepStrictEqual(actual.contents, { 'a': 3, 'c': 1, 'b': 1 });
+ assert.deepStrictEqual(actual.keys, ['a', 'c']);
+
+ assert.deepStrictEqual(testObject.getKeysForOverrideIdentifier('x'), ['a', 'b']);
+ });
+
+ test('Test merge when configuration models have multiple identifiers', () => {
+ const testObject = new ConfigurationModel({ 'a': 1, 'c': 1 }, ['a', 'c'], [{ identifiers: ['y'], contents: { 'c': 1 }, keys: ['c'] }, { identifiers: ['x', 'y'], contents: { 'a': 2 }, keys: ['a'] }]);
+ const target = new ConfigurationModel({ 'a': 2, 'b': 1 }, ['a', 'b'], [{ identifiers: ['x'], contents: { 'a': 3, 'b': 2 }, keys: ['a', 'b'] }, { identifiers: ['x', 'y'], contents: { 'b': 3 }, keys: ['b'] }]);
+
+ const actual = testObject.merge(target);
+
+ assert.deepStrictEqual(actual.contents, { 'a': 2, 'c': 1, 'b': 1 });
+ assert.deepStrictEqual(actual.keys, ['a', 'c', 'b']);
+ assert.deepStrictEqual(actual.overrides, [
+ { identifiers: ['y'], contents: { 'c': 1 }, keys: ['c'] },
+ { identifiers: ['x', 'y'], contents: { 'a': 2, 'b': 3 }, keys: ['a', 'b'] },
+ { identifiers: ['x'], contents: { 'a': 3, 'b': 2 }, keys: ['a', 'b'] },
+ ]);
+ });
});
suite('CustomConfigurationModel', () => {
@@ -582,11 +650,14 @@ suite('ConfigurationChangeEvent', () => {
'files.autoSave': 'off',
'[markdown]': {
'editor.wordWrap': 'off'
+ },
+ '[typescript][jsonc]': {
+ 'editor.lineNumbers': 'off'
}
}));
let testObject = new ConfigurationChangeEvent(change, undefined, configuration);
- assert.deepStrictEqual(testObject.affectedKeys, ['files.autoSave', '[markdown]', 'editor.wordWrap']);
+ assert.deepStrictEqual(testObject.affectedKeys, ['files.autoSave', '[markdown]', '[typescript][jsonc]', 'editor.wordWrap', 'editor.lineNumbers']);
assert.ok(testObject.affectsConfiguration('files'));
assert.ok(testObject.affectsConfiguration('files.autoSave'));
@@ -598,8 +669,16 @@ suite('ConfigurationChangeEvent', () => {
assert.ok(testObject.affectsConfiguration('editor'));
assert.ok(testObject.affectsConfiguration('editor.wordWrap'));
+ assert.ok(testObject.affectsConfiguration('editor.lineNumbers'));
assert.ok(testObject.affectsConfiguration('editor', { overrideIdentifier: 'markdown' }));
+ assert.ok(testObject.affectsConfiguration('editor', { overrideIdentifier: 'jsonc' }));
+ assert.ok(testObject.affectsConfiguration('editor', { overrideIdentifier: 'typescript' }));
assert.ok(testObject.affectsConfiguration('editor.wordWrap', { overrideIdentifier: 'markdown' }));
+ assert.ok(!testObject.affectsConfiguration('editor.wordWrap', { overrideIdentifier: 'jsonc' }));
+ assert.ok(!testObject.affectsConfiguration('editor.wordWrap', { overrideIdentifier: 'typescript' }));
+ assert.ok(!testObject.affectsConfiguration('editor.lineNumbers', { overrideIdentifier: 'markdown' }));
+ assert.ok(testObject.affectsConfiguration('editor.lineNumbers', { overrideIdentifier: 'typescript' }));
+ assert.ok(testObject.affectsConfiguration('editor.lineNumbers', { overrideIdentifier: 'jsonc' }));
assert.ok(!testObject.affectsConfiguration('editor', { overrideIdentifier: 'json' }));
assert.ok(!testObject.affectsConfiguration('editor.fontSize', { overrideIdentifier: 'markdown' }));
@@ -615,6 +694,10 @@ suite('ConfigurationChangeEvent', () => {
'editor.fontSize': 12,
'editor.wordWrap': 'off'
},
+ '[css][scss]': {
+ 'editor.lineNumbers': 'off',
+ 'css.lint.emptyRules': 'error'
+ },
'files.autoSave': 'off',
}));
const data = configuration.toData();
@@ -624,11 +707,15 @@ suite('ConfigurationChangeEvent', () => {
'editor.fontSize': 13,
'editor.wordWrap': 'off'
},
+ '[css][scss]': {
+ 'editor.lineNumbers': 'relative',
+ 'css.lint.emptyRules': 'error'
+ },
'window.zoomLevel': 1,
}));
let testObject = new ConfigurationChangeEvent(change, { data }, configuration);
- assert.deepStrictEqual(testObject.affectedKeys, ['window.zoomLevel', '[markdown]', 'workbench.editor.enablePreview', 'editor.fontSize']);
+ assert.deepStrictEqual(testObject.affectedKeys, ['window.zoomLevel', '[markdown]', '[css][scss]', 'workbench.editor.enablePreview', 'editor.fontSize', 'editor.lineNumbers']);
assert.ok(!testObject.affectsConfiguration('files'));
@@ -637,10 +724,18 @@ suite('ConfigurationChangeEvent', () => {
assert.ok(!testObject.affectsConfiguration('[markdown].editor.fontSize'));
assert.ok(!testObject.affectsConfiguration('[markdown].editor.wordWrap'));
assert.ok(!testObject.affectsConfiguration('[markdown].workbench'));
+ assert.ok(testObject.affectsConfiguration('[css][scss]'));
assert.ok(testObject.affectsConfiguration('editor'));
assert.ok(testObject.affectsConfiguration('editor', { overrideIdentifier: 'markdown' }));
+ assert.ok(testObject.affectsConfiguration('editor', { overrideIdentifier: 'css' }));
+ assert.ok(testObject.affectsConfiguration('editor', { overrideIdentifier: 'scss' }));
assert.ok(testObject.affectsConfiguration('editor.fontSize', { overrideIdentifier: 'markdown' }));
+ assert.ok(!testObject.affectsConfiguration('editor.fontSize', { overrideIdentifier: 'css' }));
+ assert.ok(!testObject.affectsConfiguration('editor.fontSize', { overrideIdentifier: 'scss' }));
+ assert.ok(testObject.affectsConfiguration('editor.lineNumbers', { overrideIdentifier: 'scss' }));
+ assert.ok(testObject.affectsConfiguration('editor.lineNumbers', { overrideIdentifier: 'css' }));
+ assert.ok(!testObject.affectsConfiguration('editor.lineNumbers', { overrideIdentifier: 'markdown' }));
assert.ok(!testObject.affectsConfiguration('editor.wordWrap'));
assert.ok(!testObject.affectsConfiguration('editor.wordWrap', { overrideIdentifier: 'markdown' }));
assert.ok(!testObject.affectsConfiguration('editor', { overrideIdentifier: 'json' }));
diff --git a/src/vs/platform/driver/browser/baseDriver.ts b/src/vs/platform/driver/browser/baseDriver.ts
index 90ef43a186a..40e5e2227ab 100644
--- a/src/vs/platform/driver/browser/baseDriver.ts
+++ b/src/vs/platform/driver/browser/baseDriver.ts
@@ -57,7 +57,6 @@ export abstract class BaseWindowDriver implements IWindowDriver {
async getElements(selector: string, recursive: boolean): Promise {
const query = document.querySelectorAll(selector);
const result: IElement[] = [];
-
for (let i = 0; i < query.length; i++) {
const element = query.item(i);
result.push(this.serializeElement(element, recursive));
@@ -139,9 +138,8 @@ export abstract class BaseWindowDriver implements IWindowDriver {
}
const lines: string[] = [];
-
- for (let i = 0; i < xterm.buffer.length; i++) {
- lines.push(xterm.buffer.getLine(i)!.translateToString(true));
+ for (let i = 0; i < xterm.buffer.active.length; i++) {
+ lines.push(xterm.buffer.active.getLine(i)!.translateToString(true));
}
return lines;
diff --git a/src/vs/platform/driver/common/driver.ts b/src/vs/platform/driver/common/driver.ts
index e447cee2532..41b7809f448 100644
--- a/src/vs/platform/driver/common/driver.ts
+++ b/src/vs/platform/driver/common/driver.ts
@@ -57,10 +57,6 @@ export interface IDriver {
getLocaleInfo(windowId: number): Promise;
getLocalizedStrings(windowId: number): Promise;
}
-//*END
-
-export const ID = 'driverService';
-export const IDriver = createDecorator(ID);
export interface IWindowDriver {
click(selector: string, xoffset?: number | undefined, yoffset?: number | undefined): Promise;
@@ -76,6 +72,10 @@ export interface IWindowDriver {
getLocaleInfo(): Promise;
getLocalizedStrings(): Promise
}
+//*END
+
+export const ID = 'driverService';
+export const IDriver = createDecorator(ID);
export interface IDriverOptions {
verbose: boolean;
diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts
index 821cbf257f6..763442884a9 100644
--- a/src/vs/platform/environment/node/argv.ts
+++ b/src/vs/platform/environment/node/argv.ts
@@ -290,14 +290,16 @@ function wrapText(text: string, columns: number): string[] {
return lines;
}
-export function buildHelpMessage(productName: string, executableName: string, version: string, options: OptionDescriptions, isPipeSupported = true): string {
+export function buildHelpMessage(productName: string, executableName: string, version: string, options: OptionDescriptions, capabilities?: { noPipe?: boolean, noInputFiles: boolean }): string {
const columns = (process.stdout).isTTY && (process.stdout).columns || 80;
- let help = [`${productName} ${version}`];
+ const inputFiles = capabilities?.noInputFiles !== true ? `[${localize('paths', 'paths')}...]` : '';
+
+ const help = [`${productName} ${version}`];
help.push('');
- help.push(`${localize('usage', "Usage")}: ${executableName} [${localize('options', "options")}][${localize('paths', 'paths')}...]`);
+ help.push(`${localize('usage', "Usage")}: ${executableName} [${localize('options', "options")}]${inputFiles}`);
help.push('');
- if (isPipeSupported) {
+ if (capabilities?.noPipe !== true) {
if (isWindows) {
help.push(localize('stdinWindows', "To read output from another program, append '-' (e.g. 'echo Hello World | {0} -')", executableName));
} else {
diff --git a/src/vs/platform/environment/test/node/nativeModules.test.ts b/src/vs/platform/environment/test/node/nativeModules.test.ts
index 130d0561679..f1379a6ff6f 100644
--- a/src/vs/platform/environment/test/node/nativeModules.test.ts
+++ b/src/vs/platform/environment/test/node/nativeModules.test.ts
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
-import { isWindows } from 'vs/base/common/platform';
+import { isLinux, isWindows } from 'vs/base/common/platform';
function testErrorMessage(module: string): string {
return `Unable to load "${module}" dependency. It was probably not compiled for the right operating system architecture or had missing build tools.`;
@@ -37,22 +37,39 @@ suite('Native Modules (all platforms)', () => {
assert.ok(typeof spdlog.createRotatingLogger === 'function', testErrorMessage('spdlog'));
});
- test('nsfw', async () => {
- const nsfWatcher = await import('vscode-nsfw');
- assert.ok(typeof nsfWatcher === 'function', testErrorMessage('nsfw'));
- });
-
- test('parcel', async () => {
+ test('@parcel/watcher', async () => {
const parcelWatcher = await import('@parcel/watcher');
assert.ok(typeof parcelWatcher.subscribe === 'function', testErrorMessage('parcel'));
});
- test('sqlite3', async () => {
+ test('@vscode/sqlite3', async () => {
const sqlite3 = await import('@vscode/sqlite3');
assert.ok(typeof sqlite3.Database === 'function', testErrorMessage('@vscode/sqlite3'));
});
});
+(isLinux ? suite.skip : suite)('Native Modules (Windows, macOS)', () => {
+
+ test('keytar', async () => {
+ const keytar = await import('keytar');
+ const name = `VSCode Test ${Math.floor(Math.random() * 1e9)}`;
+ try {
+ await keytar.setPassword(name, 'foo', 'bar');
+ assert.strictEqual(await keytar.findPassword(name), 'bar');
+ assert.strictEqual((await keytar.findCredentials(name)).length, 1);
+ assert.strictEqual(await keytar.getPassword(name, 'foo'), 'bar');
+ await keytar.deletePassword(name, 'foo');
+ assert.strictEqual(await keytar.getPassword(name, 'foo'), null);
+ } catch (err) {
+ try {
+ await keytar.deletePassword(name, 'foo'); // try to clean up
+ } catch { }
+
+ throw err;
+ }
+ });
+});
+
(!isWindows ? suite.skip : suite)('Native Modules (Windows)', () => {
test('windows-mutex', async () => {
@@ -77,7 +94,9 @@ suite('Native Modules (all platforms)', () => {
});
test('vscode-windows-ca-certs', async () => {
- // @ts-ignore Windows only
+ // @ts-ignore we do not directly depend on this module anymore
+ // but indirectly from our dependency to `vscode-proxy-agent`
+ // we still want to ensure this module can work properly.
const windowsCerts = await import('vscode-windows-ca-certs');
const store = new windowsCerts.Crypt32();
assert.ok(windowsCerts, testErrorMessage('vscode-windows-ca-certs'));
diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts
index 60e7e067f08..c4496b5a9f0 100644
--- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts
+++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts
@@ -584,12 +584,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi
return isEngineValid(engine, this.productService.version, this.productService.date);
}
- query(token: CancellationToken): Promise>;
- query(options: IQueryOptions, token: CancellationToken): Promise>;
- async query(arg1: any, arg2?: any): Promise> {
- const options: IQueryOptions = CancellationToken.isCancellationToken(arg1) ? {} : arg1;
- const token: CancellationToken = CancellationToken.isCancellationToken(arg1) ? arg1 : arg2;
-
+ async query(options: IQueryOptions, token: CancellationToken): Promise> {
if (!this.isEnabled()) {
throw new Error('No extension gallery service configured.');
}
diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts
index 35707069f50..ba9e7cfe606 100644
--- a/src/vs/platform/extensionManagement/common/extensionManagement.ts
+++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts
@@ -323,7 +323,6 @@ export const IExtensionGalleryService = createDecorator>;
query(options: IQueryOptions, token: CancellationToken): Promise>;
getExtensions(identifiers: ReadonlyArray, token: CancellationToken): Promise;
download(extension: IGalleryExtension, location: URI, operation: InstallOperation): Promise;
diff --git a/src/vs/platform/extensions/electron-main/directMainProcessExtensionHostStarter.ts b/src/vs/platform/extensions/electron-main/directMainProcessExtensionHostStarter.ts
deleted file mode 100644
index a238332b86d..00000000000
--- a/src/vs/platform/extensions/electron-main/directMainProcessExtensionHostStarter.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
-import { ExtensionHostStarter, IPartialLogService } from 'vs/platform/extensions/node/extensionHostStarter';
-import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
-import { ILogService } from 'vs/platform/log/common/log';
-
-export class DirectMainProcessExtensionHostStarter extends ExtensionHostStarter {
-
- constructor(
- @ILogService logService: IPartialLogService,
- @ILifecycleMainService lifecycleMainService: ILifecycleMainService
- ) {
- super(logService);
-
- // Abnormal shutdown: terminate extension hosts asap
- lifecycleMainService.onWillKill(() => {
- this.killAllNow();
- });
-
- // Normal shutdown: gracefully await extension host shutdowns
- lifecycleMainService.onWillShutdown((e) => {
- e.join(this.waitForAllExit(6000));
- });
- }
-
-}
diff --git a/src/vs/platform/extensions/electron-main/workerMainProcessExtensionHostStarter.ts b/src/vs/platform/extensions/electron-main/workerMainProcessExtensionHostStarter.ts
index 2abb2eb9dfd..dfc7164026f 100644
--- a/src/vs/platform/extensions/electron-main/workerMainProcessExtensionHostStarter.ts
+++ b/src/vs/platform/extensions/electron-main/workerMainProcessExtensionHostStarter.ts
@@ -11,9 +11,8 @@ import { FileAccess } from 'vs/base/common/network';
import { ILogService } from 'vs/platform/log/common/log';
import { Worker } from 'worker_threads';
import { IWorker, IWorkerCallback, IWorkerFactory, SimpleWorkerClient } from 'vs/base/common/worker/simpleWorker';
-import { IExtensionHostStarterWorkerHost } from 'vs/platform/extensions/node/extensionHostStarterWorker';
+import type { ExtensionHostStarter, IExtensionHostStarterWorkerHost } from 'vs/platform/extensions/node/extensionHostStarterWorker';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
-import { ExtensionHostStarter } from 'vs/platform/extensions/node/extensionHostStarter';
class NodeWorker implements IWorker {
@@ -80,15 +79,7 @@ export class WorkerMainProcessExtensionHostStarter implements IDisposable, IExte
);
this._initialize();
- // Abnormal shutdown: terminate extension hosts asap
- lifecycleMainService.onWillKill(async () => {
- this._shutdown = true;
- if (this._proxy) {
- this._proxy.killAllNow();
- }
- });
-
- // Normal shutdown: gracefully await extension host shutdowns
+ // On shutdown: gracefully await extension host shutdowns
lifecycleMainService.onWillShutdown((e) => {
this._shutdown = true;
if (this._proxy) {
diff --git a/src/vs/platform/extensions/node/extensionHostStarter.ts b/src/vs/platform/extensions/node/extensionHostStarter.ts
deleted file mode 100644
index c71a39fb46d..00000000000
--- a/src/vs/platform/extensions/node/extensionHostStarter.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
-import { SerializedError, transformErrorForSerialization } from 'vs/base/common/errors';
-import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
-import { IExtensionHostProcessOptions, IExtensionHostStarter } from 'vs/platform/extensions/common/extensionHostStarter';
-import { Emitter, Event } from 'vs/base/common/event';
-import { ChildProcess, fork } from 'child_process';
-import { FileAccess } from 'vs/base/common/network';
-import { StringDecoder } from 'string_decoder';
-import * as platform from 'vs/base/common/platform';
-import { ILogService } from 'vs/platform/log/common/log';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
-import { mixin } from 'vs/base/common/objects';
-import { cwd } from 'vs/base/common/process';
-import { StopWatch } from 'vs/base/common/stopwatch';
-import { Promises, timeout } from 'vs/base/common/async';
-
-export interface IPartialLogService {
- readonly _serviceBrand: undefined;
- info(message: string): void;
-}
-
-class ExtensionHostProcess extends Disposable {
-
- readonly _onStdout = this._register(new Emitter());
- readonly onStdout = this._onStdout.event;
-
- readonly _onStderr = this._register(new Emitter());
- readonly onStderr = this._onStderr.event;
-
- readonly _onMessage = this._register(new Emitter());
- readonly onMessage = this._onMessage.event;
-
- readonly _onError = this._register(new Emitter<{ error: SerializedError; }>());
- readonly onError = this._onError.event;
-
- readonly _onExit = this._register(new Emitter<{ pid: number; code: number; signal: string }>());
- readonly onExit = this._onExit.event;
-
- private _process: ChildProcess | null = null;
- private _hasExited: boolean = false;
-
- constructor(
- public readonly id: string,
- @ILogService private readonly _logService: IPartialLogService
- ) {
- super();
- }
-
- start(opts: IExtensionHostProcessOptions): { pid: number; } {
- const sw = StopWatch.create(false);
- this._process = fork(
- FileAccess.asFileUri('bootstrap-fork', require).fsPath,
- ['--type=extensionHost', '--skipWorkspaceStorageLock'],
- mixin({ cwd: cwd() }, opts),
- );
- const forkTime = sw.elapsed();
- const pid = this._process.pid;
-
- this._logService.info(`Starting extension host with pid ${pid} (fork() took ${forkTime} ms).`);
-
- const stdoutDecoder = new StringDecoder('utf-8');
- this._process.stdout?.on('data', (chunk) => {
- const strChunk = typeof chunk === 'string' ? chunk : stdoutDecoder.write(chunk);
- this._onStdout.fire(strChunk);
- });
-
- const stderrDecoder = new StringDecoder('utf-8');
- this._process.stderr?.on('data', (chunk) => {
- const strChunk = typeof chunk === 'string' ? chunk : stderrDecoder.write(chunk);
- this._onStderr.fire(strChunk);
- });
-
- this._process.on('message', msg => {
- this._onMessage.fire(msg);
- });
-
- this._process.on('error', (err) => {
- this._onError.fire({ error: transformErrorForSerialization(err) });
- });
-
- this._process.on('exit', (code: number, signal: string) => {
- this._hasExited = true;
- this._onExit.fire({ pid, code, signal });
- });
-
- return { pid };
- }
-
- enableInspectPort(): boolean {
- if (!this._process) {
- return false;
- }
-
- this._logService.info(`Enabling inspect port on extension host with pid ${this._process.pid}.`);
-
- interface ProcessExt {
- _debugProcess?(n: number): any;
- }
-
- if (typeof (process)._debugProcess === 'function') {
- // use (undocumented) _debugProcess feature of node
- (process)._debugProcess!(this._process.pid);
- return true;
- } else if (!platform.isWindows) {
- // use KILL USR1 on non-windows platforms (fallback)
- this._process.kill('SIGUSR1');
- return true;
- } else {
- // not supported...
- return false;
- }
- }
-
- kill(): void {
- if (!this._process) {
- return;
- }
- this._logService.info(`Killing extension host with pid ${this._process.pid}.`);
- this._process.kill();
- }
-
- async waitForExit(maxWaitTimeMs: number): Promise {
- if (!this._process) {
- return;
- }
- const pid = this._process.pid;
- this._logService.info(`Waiting for extension host with pid ${pid} to exit.`);
- await Promise.race([Event.toPromise(this.onExit), timeout(maxWaitTimeMs)]);
-
- if (!this._hasExited) {
- // looks like we timed out
- this._logService.info(`Extension host with pid ${pid} did not exit within ${maxWaitTimeMs}ms.`);
- this._process.kill();
- }
- }
-}
-
-export class ExtensionHostStarter implements IDisposable, IExtensionHostStarter {
- _serviceBrand: undefined;
-
- private static _lastId: number = 0;
-
- protected readonly _extHosts: Map;
-
- constructor(
- @ILogService private readonly _logService: IPartialLogService
- ) {
- this._extHosts = new Map();
- }
-
- dispose(): void {
- // Intentionally not killing the extension host processes
- }
-
- private _getExtHost(id: string): ExtensionHostProcess {
- const extHostProcess = this._extHosts.get(id);
- if (!extHostProcess) {
- throw new Error(`Unknown extension host!`);
- }
- return extHostProcess;
- }
-
- onDynamicStdout(id: string): Event {
- return this._getExtHost(id).onStdout;
- }
-
- onDynamicStderr(id: string): Event {
- return this._getExtHost(id).onStderr;
- }
-
- onDynamicMessage(id: string): Event {
- return this._getExtHost(id).onMessage;
- }
-
- onDynamicError(id: string): Event<{ error: SerializedError; }> {
- return this._getExtHost(id).onError;
- }
-
- onDynamicExit(id: string): Event<{ code: number; signal: string; }> {
- return this._getExtHost(id).onExit;
- }
-
- async createExtensionHost(): Promise<{ id: string; }> {
- const id = String(++ExtensionHostStarter._lastId);
- const extHost = new ExtensionHostProcess(id, this._logService);
- this._extHosts.set(id, extHost);
- extHost.onExit(({ pid, code, signal }) => {
- this._logService.info(`Extension host with pid ${pid} exited with code: ${code}, signal: ${signal}.`);
- setTimeout(() => {
- extHost.dispose();
- this._extHosts.delete(id);
- });
- });
- return { id };
- }
-
- async start(id: string, opts: IExtensionHostProcessOptions): Promise<{ pid: number; }> {
- return this._getExtHost(id).start(opts);
- }
-
- async enableInspectPort(id: string): Promise {
- const extHostProcess = this._extHosts.get(id);
- if (!extHostProcess) {
- return false;
- }
- return extHostProcess.enableInspectPort();
- }
-
- async kill(id: string): Promise {
- const extHostProcess = this._extHosts.get(id);
- if (!extHostProcess) {
- // already gone!
- return;
- }
- extHostProcess.kill();
- }
-
- async killAllNow(): Promise {
- for (const [, extHost] of this._extHosts) {
- extHost.kill();
- }
- }
-
- async waitForAllExit(maxWaitTimeMs: number): Promise {
- const exitPromises: Promise[] = [];
- for (const [, extHost] of this._extHosts) {
- exitPromises.push(extHost.waitForExit(maxWaitTimeMs));
- }
- return Promises.settled(exitPromises).then(() => { });
- }
-}
-
-registerSingleton(IExtensionHostStarter, ExtensionHostStarter, true);
diff --git a/src/vs/platform/extensions/node/extensionHostStarterWorker.ts b/src/vs/platform/extensions/node/extensionHostStarterWorker.ts
index 6bd329425ab..9ea3bd7857a 100644
--- a/src/vs/platform/extensions/node/extensionHostStarterWorker.ts
+++ b/src/vs/platform/extensions/node/extensionHostStarterWorker.ts
@@ -3,22 +3,238 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { ExtensionHostStarter, IPartialLogService } from 'vs/platform/extensions/node/extensionHostStarter';
+import { SerializedError, transformErrorForSerialization } from 'vs/base/common/errors';
+import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
+import { IExtensionHostProcessOptions, IExtensionHostStarter } from 'vs/platform/extensions/common/extensionHostStarter';
+import { Emitter, Event } from 'vs/base/common/event';
+import { ChildProcess, fork } from 'child_process';
+import { FileAccess } from 'vs/base/common/network';
+import { StringDecoder } from 'string_decoder';
+import * as platform from 'vs/base/common/platform';
+import { mixin } from 'vs/base/common/objects';
+import { cwd } from 'vs/base/common/process';
+import { StopWatch } from 'vs/base/common/stopwatch';
+import { Promises, timeout } from 'vs/base/common/async';
export interface IExtensionHostStarterWorkerHost {
logInfo(message: string): Promise;
}
+class ExtensionHostProcess extends Disposable {
+
+ readonly _onStdout = this._register(new Emitter());
+ readonly onStdout = this._onStdout.event;
+
+ readonly _onStderr = this._register(new Emitter());
+ readonly onStderr = this._onStderr.event;
+
+ readonly _onMessage = this._register(new Emitter());
+ readonly onMessage = this._onMessage.event;
+
+ readonly _onError = this._register(new Emitter<{ error: SerializedError; }>());
+ readonly onError = this._onError.event;
+
+ readonly _onExit = this._register(new Emitter<{ pid: number; code: number; signal: string }>());
+ readonly onExit = this._onExit.event;
+
+ private _process: ChildProcess | null = null;
+ private _hasExited: boolean = false;
+
+ constructor(
+ public readonly id: string,
+ private readonly _host: IExtensionHostStarterWorkerHost
+ ) {
+ super();
+ }
+
+ start(opts: IExtensionHostProcessOptions): { pid: number; } {
+ const sw = StopWatch.create(false);
+ this._process = fork(
+ FileAccess.asFileUri('bootstrap-fork', require).fsPath,
+ ['--type=extensionHost', '--skipWorkspaceStorageLock'],
+ mixin({ cwd: cwd() }, opts),
+ );
+ const forkTime = sw.elapsed();
+ const pid = this._process.pid;
+
+ this._host.logInfo(`Starting extension host with pid ${pid} (fork() took ${forkTime} ms).`);
+
+ const stdoutDecoder = new StringDecoder('utf-8');
+ this._process.stdout?.on('data', (chunk) => {
+ const strChunk = typeof chunk === 'string' ? chunk : stdoutDecoder.write(chunk);
+ this._onStdout.fire(strChunk);
+ });
+
+ const stderrDecoder = new StringDecoder('utf-8');
+ this._process.stderr?.on('data', (chunk) => {
+ const strChunk = typeof chunk === 'string' ? chunk : stderrDecoder.write(chunk);
+ this._onStderr.fire(strChunk);
+ });
+
+ this._process.on('message', msg => {
+ this._onMessage.fire(msg);
+ });
+
+ this._process.on('error', (err) => {
+ this._onError.fire({ error: transformErrorForSerialization(err) });
+ });
+
+ this._process.on('exit', (code: number, signal: string) => {
+ this._hasExited = true;
+ this._onExit.fire({ pid, code, signal });
+ });
+
+ return { pid };
+ }
+
+ enableInspectPort(): boolean {
+ if (!this._process) {
+ return false;
+ }
+
+ this._host.logInfo(`Enabling inspect port on extension host with pid ${this._process.pid}.`);
+
+ interface ProcessExt {
+ _debugProcess?(n: number): any;
+ }
+
+ if (typeof (process)._debugProcess === 'function') {
+ // use (undocumented) _debugProcess feature of node
+ (process)._debugProcess!(this._process.pid);
+ return true;
+ } else if (!platform.isWindows) {
+ // use KILL USR1 on non-windows platforms (fallback)
+ this._process.kill('SIGUSR1');
+ return true;
+ } else {
+ // not supported...
+ return false;
+ }
+ }
+
+ kill(): void {
+ if (!this._process) {
+ return;
+ }
+ this._host.logInfo(`Killing extension host with pid ${this._process.pid}.`);
+ this._process.kill();
+ }
+
+ async waitForExit(maxWaitTimeMs: number): Promise {
+ if (!this._process) {
+ return;
+ }
+ const pid = this._process.pid;
+ this._host.logInfo(`Waiting for extension host with pid ${pid} to exit.`);
+ await Promise.race([Event.toPromise(this.onExit), timeout(maxWaitTimeMs)]);
+
+ if (!this._hasExited) {
+ // looks like we timed out
+ this._host.logInfo(`Extension host with pid ${pid} did not exit within ${maxWaitTimeMs}ms.`);
+ this._process.kill();
+ }
+ }
+}
+
+export class ExtensionHostStarter implements IDisposable, IExtensionHostStarter {
+ _serviceBrand: undefined;
+
+ private static _lastId: number = 0;
+
+ protected readonly _extHosts: Map;
+
+ constructor(
+ private readonly _host: IExtensionHostStarterWorkerHost
+ ) {
+ this._extHosts = new Map();
+ }
+
+ dispose(): void {
+ // Intentionally not killing the extension host processes
+ }
+
+ private _getExtHost(id: string): ExtensionHostProcess {
+ const extHostProcess = this._extHosts.get(id);
+ if (!extHostProcess) {
+ throw new Error(`Unknown extension host!`);
+ }
+ return extHostProcess;
+ }
+
+ onDynamicStdout(id: string): Event {
+ return this._getExtHost(id).onStdout;
+ }
+
+ onDynamicStderr(id: string): Event {
+ return this._getExtHost(id).onStderr;
+ }
+
+ onDynamicMessage(id: string): Event {
+ return this._getExtHost(id).onMessage;
+ }
+
+ onDynamicError(id: string): Event<{ error: SerializedError; }> {
+ return this._getExtHost(id).onError;
+ }
+
+ onDynamicExit(id: string): Event<{ code: number; signal: string; }> {
+ return this._getExtHost(id).onExit;
+ }
+
+ async createExtensionHost(): Promise<{ id: string; }> {
+ const id = String(++ExtensionHostStarter._lastId);
+ const extHost = new ExtensionHostProcess(id, this._host);
+ this._extHosts.set(id, extHost);
+ extHost.onExit(({ pid, code, signal }) => {
+ this._host.logInfo(`Extension host with pid ${pid} exited with code: ${code}, signal: ${signal}.`);
+ setTimeout(() => {
+ extHost.dispose();
+ this._extHosts.delete(id);
+ });
+ });
+ return { id };
+ }
+
+ async start(id: string, opts: IExtensionHostProcessOptions): Promise<{ pid: number; }> {
+ return this._getExtHost(id).start(opts);
+ }
+
+ async enableInspectPort(id: string): Promise {
+ const extHostProcess = this._extHosts.get(id);
+ if (!extHostProcess) {
+ return false;
+ }
+ return extHostProcess.enableInspectPort();
+ }
+
+ async kill(id: string): Promise {
+ const extHostProcess = this._extHosts.get(id);
+ if (!extHostProcess) {
+ // already gone!
+ return;
+ }
+ extHostProcess.kill();
+ }
+
+ async killAllNow(): Promise {
+ for (const [, extHost] of this._extHosts) {
+ extHost.kill();
+ }
+ }
+
+ async waitForAllExit(maxWaitTimeMs: number): Promise {
+ const exitPromises: Promise[] = [];
+ for (const [, extHost] of this._extHosts) {
+ exitPromises.push(extHost.waitForExit(maxWaitTimeMs));
+ }
+ return Promises.settled(exitPromises).then(() => { });
+ }
+}
+
/**
* The `create` function needs to be there by convention because
* we are loaded via the `vs/base/common/worker/simpleWorker` utility.
*/
export function create(host: IExtensionHostStarterWorkerHost) {
- const partialLogService: IPartialLogService = {
- _serviceBrand: undefined,
- info: (message: string): void => {
- host.logInfo(message);
- }
- };
- return new ExtensionHostStarter(partialLogService);
+ return new ExtensionHostStarter(host);
}
diff --git a/src/vs/platform/files/common/watcher.ts b/src/vs/platform/files/common/watcher.ts
index 4314712e66b..eb1d60df636 100644
--- a/src/vs/platform/files/common/watcher.ts
+++ b/src/vs/platform/files/common/watcher.ts
@@ -185,20 +185,20 @@ export function toFileChanges(changes: IDiskFileChange[]): IFileChange[] {
}));
}
-export function normalizeFileChanges(changes: IDiskFileChange[]): IDiskFileChange[] {
+export function coalesceEvents(changes: IDiskFileChange[]): IDiskFileChange[] {
// Build deltas
- const normalizer = new EventNormalizer();
+ const coalescer = new EventCoalescer();
for (const event of changes) {
- normalizer.processEvent(event);
+ coalescer.processEvent(event);
}
- return normalizer.normalize();
+ return coalescer.coalesce();
}
-class EventNormalizer {
+class EventCoalescer {
- private readonly normalized = new Set();
+ private readonly coalesced = new Set();
private readonly mapPathToChange = new Map();
private toKey(event: IDiskFileChange): string {
@@ -232,7 +232,7 @@ class EventNormalizer {
// Ignore CREATE followed by DELETE in one go
else if (currentChangeType === FileChangeType.ADDED && newChangeType === FileChangeType.DELETED) {
this.mapPathToChange.delete(this.toKey(event));
- this.normalized.delete(existingEvent);
+ this.coalesced.delete(existingEvent);
}
// Flatten DELETE followed by CREATE into CHANGE
@@ -255,12 +255,12 @@ class EventNormalizer {
}
if (keepEvent) {
- this.normalized.add(event);
+ this.coalesced.add(event);
this.mapPathToChange.set(this.toKey(event), event);
}
}
- normalize(): IDiskFileChange[] {
+ coalesce(): IDiskFileChange[] {
const addOrChangeEvents: IDiskFileChange[] = [];
const deletedPaths: string[] = [];
@@ -271,7 +271,7 @@ class EventNormalizer {
// 1.) split ADD/CHANGE and DELETED events
// 2.) sort short deleted paths to the top
// 3.) for each DELETE, check if there is a deleted parent and ignore the event in that case
- return Array.from(this.normalized).filter(e => {
+ return Array.from(this.coalesced).filter(e => {
if (e.type !== FileChangeType.DELETED) {
addOrChangeEvents.push(e);
diff --git a/src/vs/platform/files/node/watcher/nodejs/watcherService.ts b/src/vs/platform/files/node/watcher/nodejs/watcherService.ts
index 346cdb0b656..983b291e229 100644
--- a/src/vs/platform/files/node/watcher/nodejs/watcherService.ts
+++ b/src/vs/platform/files/node/watcher/nodejs/watcherService.ts
@@ -10,7 +10,7 @@ import { realpath } from 'vs/base/node/extpath';
import { SymlinkSupport } from 'vs/base/node/pfs';
import { CHANGE_BUFFER_DELAY, watchFile, watchFolder } from 'vs/base/node/watcher';
import { FileChangeType } from 'vs/platform/files/common/files';
-import { IDiskFileChange, ILogMessage, normalizeFileChanges } from 'vs/platform/files/common/watcher';
+import { IDiskFileChange, ILogMessage, coalesceEvents } from 'vs/platform/files/common/watcher';
export class FileWatcher extends Disposable {
private isDisposed: boolean | undefined;
@@ -95,19 +95,19 @@ export class FileWatcher extends Disposable {
const fileChanges = this.fileChangesBuffer;
this.fileChangesBuffer = [];
- // Event normalization
- const normalizedFileChanges = normalizeFileChanges(fileChanges);
+ // Event coalsecer
+ const coalescedFileChanges = coalesceEvents(fileChanges);
// Logging
if (this.verboseLogging) {
- for (const event of normalizedFileChanges) {
+ for (const event of coalescedFileChanges) {
this.onVerbose(`>> normalized ${event.type === FileChangeType.ADDED ? '[ADDED]' : event.type === FileChangeType.DELETED ? '[DELETED]' : '[CHANGED]'} ${event.path}`);
}
}
// Fire
- if (normalizedFileChanges.length > 0) {
- this.onDidFilesChange(normalizedFileChanges);
+ if (coalescedFileChanges.length > 0) {
+ this.onDidFilesChange(coalescedFileChanges);
}
});
}
diff --git a/src/vs/platform/files/node/watcher/nsfw/nsfwWatcherService.ts b/src/vs/platform/files/node/watcher/nsfw/nsfwWatcherService.ts
index 0b7bd2a804a..7b415d8b902 100644
--- a/src/vs/platform/files/node/watcher/nsfw/nsfwWatcherService.ts
+++ b/src/vs/platform/files/node/watcher/nsfw/nsfwWatcherService.ts
@@ -18,7 +18,7 @@ import { isMacintosh } from 'vs/base/common/platform';
import { realcaseSync, realpathSync } from 'vs/base/node/extpath';
import { FileChangeType } from 'vs/platform/files/common/files';
import { IWatcherService } from 'vs/platform/files/node/watcher/nsfw/watcher';
-import { IDiskFileChange, ILogMessage, normalizeFileChanges, IWatchRequest } from 'vs/platform/files/common/watcher';
+import { IDiskFileChange, ILogMessage, coalesceEvents, IWatchRequest } from 'vs/platform/files/common/watcher';
import { watchFolder } from 'vs/base/node/watcher';
interface IWatcher extends IDisposable {
@@ -192,7 +192,7 @@ export class NsfwWatcherService extends Disposable implements IWatcherService {
undeliveredFileEvents = [];
// Broadcast to clients normalized
- const normalizedEvents = normalizeFileChanges(this.normalizeEvents(undeliveredFileEventsToEmit, request, realBasePathDiffers, realBasePathLength));
+ const normalizedEvents = coalesceEvents(this.normalizeEvents(undeliveredFileEventsToEmit, request, realBasePathDiffers, realBasePathLength));
this.emitEvents(normalizedEvents);
}, this.getOptions(watcher)).then(async nsfwWatcher => {
diff --git a/src/vs/platform/files/node/watcher/parcel/parcelWatcherService.ts b/src/vs/platform/files/node/watcher/parcel/parcelWatcherService.ts
index a731395f51b..26963631571 100644
--- a/src/vs/platform/files/node/watcher/parcel/parcelWatcherService.ts
+++ b/src/vs/platform/files/node/watcher/parcel/parcelWatcherService.ts
@@ -6,7 +6,7 @@
import * as parcelWatcher from '@parcel/watcher';
import { existsSync, unlinkSync } from 'fs';
import { tmpdir } from 'os';
-import { RunOnceScheduler } from 'vs/base/common/async';
+import { DeferredPromise, RunOnceScheduler } from 'vs/base/common/async';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { Emitter } from 'vs/base/common/event';
@@ -22,7 +22,7 @@ import { generateUuid } from 'vs/base/common/uuid';
import { realcaseSync, realpathSync } from 'vs/base/node/extpath';
import { watchFolder } from 'vs/base/node/watcher';
import { FileChangeType } from 'vs/platform/files/common/files';
-import { IDiskFileChange, ILogMessage, normalizeFileChanges, IWatchRequest, IWatcherService } from 'vs/platform/files/common/watcher';
+import { IDiskFileChange, ILogMessage, coalesceEvents, IWatchRequest, IWatcherService } from 'vs/platform/files/common/watcher';
export interface IWatcher {
@@ -244,15 +244,14 @@ export class ParcelWatcherService extends Disposable implements IWatcherService
private startPolling(request: IWatchRequest, pollingInterval: number, restarts = 0): void {
const cts = new CancellationTokenSource();
- let parcelWatcherPromiseResolve: () => void;
- const instance = new Promise(resolve => parcelWatcherPromiseResolve = resolve);
+ const instance = new DeferredPromise();
const snapshotFile = join(tmpdir(), `vscode-watcher-snapshot-${generateUuid()}`);
// Remember as watcher instance
const watcher: IWatcher = {
request,
- ready: instance,
+ ready: instance.p,
restarts,
token: cts.token,
stop: async () => {
@@ -299,7 +298,7 @@ export class ParcelWatcherService extends Disposable implements IWatcherService
// Signal we are ready now when the first snapshot was written
if (counter === 1) {
- parcelWatcherPromiseResolve();
+ instance.complete();
}
if (cts.token.isCancellationRequested) {
@@ -315,19 +314,18 @@ export class ParcelWatcherService extends Disposable implements IWatcherService
private startWatching(request: IWatchRequest, restarts = 0): void {
const cts = new CancellationTokenSource();
- let parcelWatcherPromiseResolve: (watcher: parcelWatcher.AsyncSubscription | undefined) => void;
- const instance = new Promise(resolve => parcelWatcherPromiseResolve = resolve);
+ const instance = new DeferredPromise();
// Remember as watcher instance
const watcher: IWatcher = {
request,
- ready: instance,
+ ready: instance.p,
restarts,
token: cts.token,
stop: async () => {
cts.dispose(true);
- const watcherInstance = await instance;
+ const watcherInstance = await instance.p;
await watcherInstance?.unsubscribe();
}
};
@@ -361,11 +359,11 @@ export class ParcelWatcherService extends Disposable implements IWatcherService
}).then(parcelWatcher => {
this.debug(`Started watching: '${realPath}' with backend '${ParcelWatcherService.PARCEL_WATCHER_BACKEND}' and native excludes '${ignore?.join(', ')}'`);
- parcelWatcherPromiseResolve(parcelWatcher);
+ instance.complete(parcelWatcher);
}).catch(error => {
this.onUnexpectedError(error, watcher);
- parcelWatcherPromiseResolve(undefined);
+ instance.complete(undefined);
});
}
@@ -377,14 +375,19 @@ export class ParcelWatcherService extends Disposable implements IWatcherService
// Check for excludes
const rawEvents = this.handleExcludes(parcelEvents, excludes);
- // Normalize and detect root path deletes
+ // Normalize events: handle NFC normalization and symlinks
const { events: normalizedEvents, rootDeleted } = this.normalizeEvents(rawEvents, watcher.request, realPathDiffers, realPathLength);
- // Broadcast to clients coalesced
- const coalescedEvents = normalizeFileChanges(normalizedEvents);
- this.emitEvents(coalescedEvents);
+ // Coalesce events: merge events of same kind
+ const coalescedEvents = coalesceEvents(normalizedEvents);
- // Handle root path delete if confirmed from coalseced events
+ // Filter events: check for specific events we want to exclude
+ const filteredEvents = this.filterEvents(coalescedEvents, watcher.request, rootDeleted);
+
+ // Broadcast to clients
+ this.emitEvents(filteredEvents);
+
+ // Handle root path delete if confirmed from coalesced events
if (rootDeleted && coalescedEvents.some(event => event.path === watcher.request.path && event.type === FileChangeType.DELETED)) {
this.onWatchedPathDeleted(watcher);
}
@@ -485,6 +488,25 @@ export class ParcelWatcherService extends Disposable implements IWatcherService
return { events, rootDeleted };
}
+ private filterEvents(events: IDiskFileChange[], request: IWatchRequest, rootDeleted: boolean): IDiskFileChange[] {
+ if (!rootDeleted) {
+ return events;
+ }
+
+ return events.filter(event => {
+ if (event.path === request.path && event.type === FileChangeType.DELETED) {
+ // Explicitly exclude changes to root if we have any
+ // to avoid VS Code closing all opened editors which
+ // can happen e.g. in case of network connectivity
+ // issues
+ // (https://github.com/microsoft/vscode/issues/136673)
+ return false;
+ }
+
+ return true;
+ });
+ }
+
private onWatchedPathDeleted(watcher: IWatcher): void {
this.warn('Watcher shutdown because watched path got deleted', watcher);
@@ -502,9 +524,6 @@ export class ParcelWatcherService extends Disposable implements IWatcherService
// Stop watching that parent folder
disposable.dispose();
- // Send a manual event given we know the root got added again
- this.emitEvents([{ path: watcher.request.path, type: FileChangeType.ADDED }]);
-
// Restart the file watching
this.restartWatching(watcher);
}
diff --git a/src/vs/platform/files/test/node/recursiveWatcher.integrationTest.ts b/src/vs/platform/files/test/node/recursiveWatcher.integrationTest.ts
index ee26d0ec595..f415f587b33 100644
--- a/src/vs/platform/files/test/node/recursiveWatcher.integrationTest.ts
+++ b/src/vs/platform/files/test/node/recursiveWatcher.integrationTest.ts
@@ -122,6 +122,28 @@ flakySuite('Recursive Watcher (parcel)', () => {
}
});
});
+
+ // Unwind from the event call stack: we have seen crashes in Parcel
+ // when e.g. calling `unsubscribe` directly from the stack of a file
+ // change event
+ // Refs: https://github.com/microsoft/vscode/issues/137430
+ await timeout(1);
+ }
+
+ function awaitMessage(service: TestParcelWatcherService, type: 'trace' | 'warn' | 'error' | 'info' | 'debug'): Promise {
+ if (loggingEnabled) {
+ console.log(`Awaiting message of type ${type}`);
+ }
+
+ // Await the message
+ return new Promise(resolve => {
+ const disposable = service.onDidLogMessage(msg => {
+ if (msg.type === type) {
+ disposable.dispose();
+ resolve();
+ }
+ });
+ });
}
test('basics', async function () {
@@ -379,8 +401,6 @@ flakySuite('Recursive Watcher (parcel)', () => {
changeFuture = awaitEvent(service, newTextFilePath, FileChangeType.ADDED);
await Promises.writeFile(newTextFilePath, 'Hello World');
await changeFuture;
-
- return service.stop();
});
test('subsequent watch updates watchers (excludes)', async function () {
@@ -392,8 +412,6 @@ flakySuite('Recursive Watcher (parcel)', () => {
let changeFuture: Promise = awaitEvent(service, newTextFilePath, FileChangeType.ADDED);
await Promises.writeFile(newTextFilePath, 'Hello World');
await changeFuture;
-
- return service.stop();
});
(isWindows /* windows: cannot create file symbolic link without elevated context */ ? test.skip : test)('symlink support (root)', async function () {
@@ -447,22 +465,19 @@ flakySuite('Recursive Watcher (parcel)', () => {
await service.watch([{ path: watchedPath, excludes: [] }]);
- // Delete watched path
- let changeFuture: Promise = awaitEvent(service, watchedPath, FileChangeType.DELETED);
+ // Delete watched path and await
+ const warnFuture = awaitMessage(service, 'warn');
await Promises.rm(watchedPath, RimRafMode.UNLINK);
- await changeFuture;
+ await warnFuture;
// Restore watched path
- changeFuture = awaitEvent(service, watchedPath, FileChangeType.ADDED);
await Promises.mkdir(watchedPath);
- await changeFuture;
-
- await timeout(20); // restart is delayed
+ await timeout(1500); // restart is delayed
await service.whenReady();
// Verify events come in again
const newFilePath = join(watchedPath, 'newFile.txt');
- changeFuture = awaitEvent(service, newFilePath, FileChangeType.ADDED);
+ const changeFuture = awaitEvent(service, newFilePath, FileChangeType.ADDED);
await Promises.writeFile(newFilePath, 'Hello World');
await changeFuture;
});
diff --git a/src/vs/platform/files/test/node/watcherNormalizer.test.ts b/src/vs/platform/files/test/node/watcherCoalescer.test.ts
similarity index 92%
rename from src/vs/platform/files/test/node/watcherNormalizer.test.ts
rename to src/vs/platform/files/test/node/watcherCoalescer.test.ts
index 988be68c599..7853f6ce565 100644
--- a/src/vs/platform/files/test/node/watcherNormalizer.test.ts
+++ b/src/vs/platform/files/test/node/watcherCoalescer.test.ts
@@ -9,7 +9,7 @@ import { isLinux, isWindows } from 'vs/base/common/platform';
import { isEqual } from 'vs/base/common/resources';
import { URI as uri } from 'vs/base/common/uri';
import { FileChangesEvent, FileChangeType, IFileChange } from 'vs/platform/files/common/files';
-import { IDiskFileChange, normalizeFileChanges, toFileChanges } from 'vs/platform/files/common/watcher';
+import { IDiskFileChange, coalesceEvents, toFileChanges } from 'vs/platform/files/common/watcher';
class TestFileWatcher {
private readonly _onDidFilesChange: Emitter<{ raw: IFileChange[], event: FileChangesEvent }>;
@@ -28,12 +28,12 @@ class TestFileWatcher {
private onRawFileEvents(events: IDiskFileChange[]): void {
- // Normalize
- let normalizedEvents = normalizeFileChanges(events);
+ // Coalesce
+ let coalescedEvents = coalesceEvents(events);
// Emit through event emitter
- if (normalizedEvents.length > 0) {
- this._onDidFilesChange.fire({ raw: toFileChanges(normalizedEvents), event: this.toFileChangesEvent(normalizedEvents) });
+ if (coalescedEvents.length > 0) {
+ this._onDidFilesChange.fire({ raw: toFileChanges(coalescedEvents), event: this.toFileChangesEvent(coalescedEvents) });
}
}
@@ -118,7 +118,7 @@ suite('Watcher Events Normalizer', () => {
});
});
- test('event normalization: ignore CREATE followed by DELETE', done => {
+ test('event coalescer: ignore CREATE followed by DELETE', done => {
const watch = new TestFileWatcher();
const created = uri.file('/users/data/src/related');
@@ -143,7 +143,7 @@ suite('Watcher Events Normalizer', () => {
watch.report(raw);
});
- test('event normalization: flatten DELETE followed by CREATE into CHANGE', done => {
+ test('event coalescer: flatten DELETE followed by CREATE into CHANGE', done => {
const watch = new TestFileWatcher();
const deleted = uri.file('/users/data/src/related');
@@ -169,7 +169,7 @@ suite('Watcher Events Normalizer', () => {
watch.report(raw);
});
- test('event normalization: ignore UPDATE when CREATE received', done => {
+ test('event coalescer: ignore UPDATE when CREATE received', done => {
const watch = new TestFileWatcher();
const created = uri.file('/users/data/src/related');
@@ -196,7 +196,7 @@ suite('Watcher Events Normalizer', () => {
watch.report(raw);
});
- test('event normalization: apply DELETE', done => {
+ test('event coalescer: apply DELETE', done => {
const watch = new TestFileWatcher();
const updated = uri.file('/users/data/src/related');
@@ -225,7 +225,7 @@ suite('Watcher Events Normalizer', () => {
watch.report(raw);
});
- test('event normalization: track case renames', done => {
+ test('event coalescer: track case renames', done => {
const watch = new TestFileWatcher();
const oldPath = uri.file('/users/data/src/added');
diff --git a/src/vs/platform/issue/electron-main/issueMainService.ts b/src/vs/platform/issue/electron-main/issueMainService.ts
index 2fb91fc0a3b..1166a4ec7f3 100644
--- a/src/vs/platform/issue/electron-main/issueMainService.ts
+++ b/src/vs/platform/issue/electron-main/issueMainService.ts
@@ -212,7 +212,7 @@ export class IssueMainService implements ICommonIssueService {
title: localize('issueReporter', "Issue Reporter"),
zoomLevel: data.zoomLevel,
alwaysOnTop: false
- });
+ }, 'issue-reporter');
// Store into config object URL
issueReporterWindowConfigUrl.update({
@@ -267,7 +267,7 @@ export class IssueMainService implements ICommonIssueService {
title: localize('processExplorer', "Process Explorer"),
zoomLevel: data.zoomLevel,
alwaysOnTop: true
- });
+ }, 'process-explorer');
// Store into config object URL
processExplorerWindowConfigUrl.update({
@@ -301,7 +301,7 @@ export class IssueMainService implements ICommonIssueService {
this.processExplorerWindow?.focus();
}
- private createBrowserWindow(position: IWindowState, ipcObjectUrl: IIPCObjectUrl, options: IBrowserWindowOptions): BrowserWindow {
+ private createBrowserWindow(position: IWindowState, ipcObjectUrl: IIPCObjectUrl, options: IBrowserWindowOptions, windowKind: string): BrowserWindow {
const window = new BrowserWindow({
fullscreen: false,
skipTaskbar: true,
@@ -316,7 +316,7 @@ export class IssueMainService implements ICommonIssueService {
backgroundColor: options.backgroundColor || IssueMainService.DEFAULT_BACKGROUND_COLOR,
webPreferences: {
preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-browser/preload.js', require).fsPath,
- additionalArguments: [`--vscode-window-config=${ipcObjectUrl.resource.toString()}`],
+ additionalArguments: [`--vscode-window-config=${ipcObjectUrl.resource.toString()}`, `--vscode-window-kind=${windowKind}`],
v8CacheOptions: this.environmentMainService.useCodeCache ? 'bypassHeatCheck' : 'none',
enableWebSQL: false,
spellcheck: false,
diff --git a/src/vs/platform/keybinding/test/common/keybindingLabels.test.ts b/src/vs/platform/keybinding/test/common/keybindingLabels.test.ts
index 3e83d0f1478..833f82c709c 100644
--- a/src/vs/platform/keybinding/test/common/keybindingLabels.test.ts
+++ b/src/vs/platform/keybinding/test/common/keybindingLabels.test.ts
@@ -122,7 +122,7 @@ suite('KeybindingLabels', () => {
assertAriaLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KeyA, 'Control+Shift+Alt+Windows+A');
assertAriaLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KeyA, 'Control+Shift+Alt+Super+A');
- assertAriaLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KeyA, 'Control+Shift+Alt+Command+A');
+ assertAriaLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KeyA, 'Control+Shift+Option+Command+A');
});
test('Electron Accelerator label', () => {
diff --git a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts
index bfe95f931ef..fc9c0fe9e9a 100644
--- a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts
+++ b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts
@@ -20,13 +20,13 @@ import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platf
export const ILifecycleMainService = createDecorator('lifecycleMainService');
-export interface IWindowLoadEvent {
+export interface WindowLoadEvent {
window: ICodeWindow;
workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined;
reason: LoadReason;
}
-export interface IWindowUnloadEvent {
+export interface WindowUnloadEvent {
window: ICodeWindow;
reason: UnloadReason;
veto(value: boolean | Promise): void;
@@ -77,13 +77,13 @@ export interface ILifecycleMainService {
* An event that fires when a window is loading. This can either be a window opening for the
* first time or a window reloading or changing to another URL.
*/
- readonly onWillLoadWindow: Event;
+ readonly onWillLoadWindow: Event;
/**
* An event that fires before a window is about to unload. Listeners can veto this event to prevent
* the window from unloading.
*/
- readonly onBeforeUnloadWindow: Event;
+ readonly onBeforeUnloadWindow: Event;
/**
* An event that fires before a window closes. This event is fired after any veto has been dealt
@@ -91,13 +91,6 @@ export interface ILifecycleMainService {
*/
readonly onBeforeCloseWindow: Event;
- /**
- * An event that fires in the rare cases where `app.exit` is triggered
- * and thus we Forcefully shutdown the application. No other lifecycle
- * event handlers are triggered.
- */
- readonly onWillKill: Event;
-
/**
* Make a `ICodeWindow` known to the lifecycle main service.
*/
@@ -124,8 +117,16 @@ export interface ILifecycleMainService {
quit(willRestart?: boolean): Promise;
/**
- * Forcefully shutdown the application. The only lifecycle event handler
- * that is triggered is `onWillKill`.
+ * Forcefully shutdown the application and optionally set an exit code.
+ *
+ * This method should only be used in rare situations where it is important
+ * to set an exit code (e.g. running tests) or when the application is
+ * not in a healthy state and should terminate asap.
+ *
+ * This method does not fire the normal lifecycle events to the windows,
+ * that normally can be vetoed. Windows are destroyed without a chance
+ * of components to participate. The only lifecycle event handler that
+ * is triggered is `onWillShutdown` in the main process.
*/
kill(code?: number): Promise;
@@ -168,18 +169,15 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe
private readonly _onWillShutdown = this._register(new Emitter());
readonly onWillShutdown = this._onWillShutdown.event;
- private readonly _onWillLoadWindow = this._register(new Emitter());
+ private readonly _onWillLoadWindow = this._register(new Emitter());
readonly onWillLoadWindow = this._onWillLoadWindow.event;
private readonly _onBeforeCloseWindow = this._register(new Emitter());
readonly onBeforeCloseWindow = this._onBeforeCloseWindow.event;
- private readonly _onBeforeUnloadWindow = this._register(new Emitter());
+ private readonly _onBeforeUnloadWindow = this._register(new Emitter());
readonly onBeforeUnloadWindow = this._onBeforeUnloadWindow.event;
- private readonly _onWillKill = this._register(new Emitter());
- readonly onWillKill = this._onWillKill.event;
-
private _quitRequested = false;
get quitRequested(): boolean { return this._quitRequested; }
@@ -239,7 +237,7 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe
// the onWillShutdown() event directly because there is no veto
// to be expected.
if (isMacintosh && this.windowCounter === 0) {
- this.beginOnWillShutdown();
+ this.fireOnWillShutdown();
}
};
app.addListener('before-quit', beforeQuitListener);
@@ -267,7 +265,7 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe
e.preventDefault();
// Start shutdown sequence
- const shutdownPromise = this.beginOnWillShutdown();
+ const shutdownPromise = this.fireOnWillShutdown();
// Wait until shutdown is signaled to be complete
shutdownPromise.finally(() => {
@@ -285,7 +283,7 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe
});
}
- private beginOnWillShutdown(): Promise {
+ private fireOnWillShutdown(): Promise {
if (this.pendingWillShutdownPromise) {
return this.pendingWillShutdownPromise; // shutdown is already running
}
@@ -411,7 +409,7 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe
// we are on macOS where it is perfectly fine to close the last window and
// the application continues running (unless quit was actually requested)
if (this.windowCounter === 0 && (!isMacintosh || this._quitRequested)) {
- this.beginOnWillShutdown();
+ this.fireOnWillShutdown();
}
});
}
@@ -600,17 +598,13 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe
async kill(code?: number): Promise {
this.logService.trace('Lifecycle#kill()');
- // Event
- this._onWillKill.fire();
+ // Give main process participants a chance to oderly shutdown
+ await this.fireOnWillShutdown();
- // The kill() method is only used in 2 situations:
- // - when an instance fails to start at all
- // - when extension tests run from CLI to report proper exit code
- //
// From extension tests we have seen issues where calling app.exit()
- // with an opened window can lead to native crashes (Linux) when webviews
- // are involved. As such, we should make sure to destroy any opened
- // window before calling app.exit().
+ // with an opened window can lead to native crashes (Linux). As such,
+ // we should make sure to destroy any opened window before calling
+ // `app.exit()`.
//
// Note: Electron implements a similar logic here:
// https://github.com/electron/electron/blob/fe5318d753637c3903e23fc1ed1b263025887b6a/spec-main/window-helpers.ts#L5
diff --git a/src/vs/platform/log/node/spdlogLog.ts b/src/vs/platform/log/node/spdlogLog.ts
index 9c7bc2b69a0..e72d4db4a36 100644
--- a/src/vs/platform/log/node/spdlogLog.ts
+++ b/src/vs/platform/log/node/spdlogLog.ts
@@ -23,12 +23,6 @@ async function createSpdLogLogger(name: string, logfilePath: string, filesize: n
return null;
}
-export function createRotatingLogger(name: string, filename: string, filesize: number, filecount: number): Promise {
- const _spdlog: typeof spdlog = require.__$__nodeRequire('spdlog');
- _spdlog.setFlushOn(LogLevel.Trace);
- return _spdlog.createRotatingLogger(name, filename, filesize, filecount);
-}
-
interface ILog {
level: LogLevel;
message: string;
diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts
index 42522056520..bd4dc019b68 100644
--- a/src/vs/platform/native/electron-main/nativeHostMainService.ts
+++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts
@@ -509,7 +509,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
}
async writeElevated(windowId: number | undefined, source: URI, target: URI, options?: { unlock?: boolean }): Promise {
- const sudoPrompt = await import('sudo-prompt');
+ const sudoPrompt = await import('@vscode/sudo-prompt');
return new Promise((resolve, reject) => {
const sudoCommand: string[] = [`"${this.cliPath}"`];
diff --git a/src/vs/platform/quickinput/browser/quickAccess.ts b/src/vs/platform/quickinput/browser/quickAccess.ts
index a0d19728eac..cf29d5ae602 100644
--- a/src/vs/platform/quickinput/browser/quickAccess.ts
+++ b/src/vs/platform/quickinput/browser/quickAccess.ts
@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
+import { DeferredPromise } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { once } from 'vs/base/common/functional';
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
@@ -111,10 +112,9 @@ export class QuickAccessController extends Disposable implements IQuickAccessCon
// Pick mode: setup a promise that can be resolved
// with the selected items and prevent execution
- let pickPromise: Promise | undefined = undefined;
- let pickResolve: Function | undefined = undefined;
+ let pickPromise: DeferredPromise | undefined = undefined;
if (pick) {
- pickPromise = new Promise(resolve => pickResolve = resolve);
+ pickPromise = new DeferredPromise();
disposables.add(once(picker.onWillAccept)(e => {
e.veto();
picker.hide();
@@ -143,7 +143,7 @@ export class QuickAccessController extends Disposable implements IQuickAccessCon
disposables.dispose();
// Resolve pick promise with selected items
- pickResolve?.(picker.selectedItems);
+ pickPromise?.complete(picker.selectedItems.slice(0));
});
// Finally, show the picker. This is important because a provider
@@ -153,7 +153,7 @@ export class QuickAccessController extends Disposable implements IQuickAccessCon
// Pick mode: return with promise
if (pick) {
- return pickPromise;
+ return pickPromise?.p;
}
}
diff --git a/src/vs/platform/remote/browser/browserSocketFactory.ts b/src/vs/platform/remote/browser/browserSocketFactory.ts
index 5197724fb1d..d9a5d9b26de 100644
--- a/src/vs/platform/remote/browser/browserSocketFactory.ts
+++ b/src/vs/platform/remote/browser/browserSocketFactory.ts
@@ -240,7 +240,8 @@ export class BrowserSocketFactory implements ISocketFactory {
}
connect(host: string, port: number, query: string, callback: IConnectCallback): void {
- const socket = this._webSocketFactory.create(`ws://${/:/.test(host) ? `[${host}]` : host}:${port}/?${query}&skipWebSocketFrames=false`);
+ const webSocketSchema = (/^https:/.test(window.location.href) ? 'wss' : 'ws');
+ const socket = this._webSocketFactory.create(`${webSocketSchema}://${/:/.test(host) ? `[${host}]` : host}:${port}/?${query}&skipWebSocketFrames=false`);
const errorListener = socket.onError((err) => callback(err, undefined));
socket.onOpen(() => {
errorListener.dispose();
diff --git a/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts b/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
index 76bb55627fe..a50828715f2 100644
--- a/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
+++ b/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
@@ -63,7 +63,8 @@ export class RemoteAuthorityResolverService extends Disposable implements IRemot
const pieces = authority.split(':');
return { authority: { authority, host: pieces[0], port: parseInt(pieces[1], 10), connectionToken } };
}
- return { authority: { authority, host: authority, port: 80, connectionToken } };
+ const port = (/^https:/.test(window.location.href) ? 443 : 80);
+ return { authority: { authority, host: authority, port: port, connectionToken } };
}
_clearResolvedAuthority(authority: string): void {
diff --git a/src/vs/platform/remote/common/remoteAuthorityResolver.ts b/src/vs/platform/remote/common/remoteAuthorityResolver.ts
index ecf80672720..d5b97ca9121 100644
--- a/src/vs/platform/remote/common/remoteAuthorityResolver.ts
+++ b/src/vs/platform/remote/common/remoteAuthorityResolver.ts
@@ -19,6 +19,7 @@ export interface ResolvedAuthority {
export interface ResolvedOptions {
readonly extensionHostEnv?: { [key: string]: string | null };
readonly isTrusted?: boolean;
+ readonly authenticationSession?: { id: string, providerId: string };
}
export interface TunnelDescription {
diff --git a/src/vs/platform/sharedProcess/electron-browser/sharedProcessWorkerService.ts b/src/vs/platform/sharedProcess/electron-browser/sharedProcessWorkerService.ts
index 1137f76e556..39d09c554ca 100644
--- a/src/vs/platform/sharedProcess/electron-browser/sharedProcessWorkerService.ts
+++ b/src/vs/platform/sharedProcess/electron-browser/sharedProcessWorkerService.ts
@@ -5,6 +5,7 @@
import { CrashReporterStartOptions, ipcRenderer } from 'electron';
import { join } from 'path';
+import { DeferredPromise } from 'vs/base/common/async';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
@@ -176,8 +177,7 @@ class SharedProcessWebWorker extends Disposable {
}
private doInit(): Promise {
- let readyResolve: (result: Worker) => void;
- const readyPromise = new Promise(resolve => readyResolve = resolve);
+ const readyPromise = new DeferredPromise();
const worker = new Worker('../../../base/worker/workerMain.js', {
name: `Shared Process Worker (${this.type})`
@@ -198,7 +198,7 @@ class SharedProcessWebWorker extends Disposable {
// Lifecycle: Ready
case SharedProcessWorkerMessages.Ready:
- readyResolve(worker);
+ readyPromise.complete(worker);
break;
// Lifecycle: Ack
@@ -250,7 +250,7 @@ class SharedProcessWebWorker extends Disposable {
// First message triggers the load of the worker
worker.postMessage('vs/platform/sharedProcess/electron-browser/sharedProcessWorkerMain');
- return readyPromise;
+ return readyPromise.p;
}
private async send(message: ISharedProcessToWorkerMessage, token: CancellationToken, port?: MessagePort): Promise {
diff --git a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts
index 36cd750dc0c..1f75cf92d18 100644
--- a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts
+++ b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts
@@ -218,7 +218,7 @@ export class SharedProcess extends Disposable implements ISharedProcess {
backgroundColor: this.themeMainService.getBackgroundColor(),
webPreferences: {
preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-browser/preload.js', require).fsPath,
- additionalArguments: [`--vscode-window-config=${configObjectUrl.resource.toString()}`],
+ additionalArguments: [`--vscode-window-config=${configObjectUrl.resource.toString()}`, '--vscode-window-kind=shared-process'],
v8CacheOptions: this.environmentMainService.useCodeCache ? 'bypassHeatCheck' : 'none',
nodeIntegration: true,
nodeIntegrationInWorker: true,
@@ -227,8 +227,7 @@ export class SharedProcess extends Disposable implements ISharedProcess {
spellcheck: false,
nativeWindowOpen: true,
images: false,
- webgl: false,
- disableBlinkFeatures: 'Auxclick' // do NOT change, allows us to identify this window as shared-process in the process explorer
+ webgl: false
}
});
diff --git a/src/vs/platform/storage/electron-main/storageMain.ts b/src/vs/platform/storage/electron-main/storageMain.ts
index d81f4d0f096..e82e328647e 100644
--- a/src/vs/platform/storage/electron-main/storageMain.ts
+++ b/src/vs/platform/storage/electron-main/storageMain.ts
@@ -6,14 +6,13 @@
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { join } from 'vs/base/common/path';
-import { generateUuid } from 'vs/base/common/uuid';
import { Promises } from 'vs/base/node/pfs';
import { InMemoryStorageDatabase, IStorage, Storage, StorageHint } from 'vs/base/parts/storage/common/storage';
import { ISQLiteStorageDatabaseLoggingOptions, SQLiteStorageDatabase } from 'vs/base/parts/storage/node/storage';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
import { IS_NEW_KEY } from 'vs/platform/storage/common/storage';
-import { currentSessionDateStorageKey, firstSessionDateStorageKey, instanceStorageKey, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
+import { currentSessionDateStorageKey, firstSessionDateStorageKey, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
import { IEmptyWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
export interface IStorageMainOptions {
@@ -214,12 +213,6 @@ export class GlobalStorageMain extends BaseStorageMain implements IStorageMain {
private updateTelemetryState(storage: IStorage): void {
- // Instance UUID (once)
- const instanceId = storage.get(instanceStorageKey, undefined);
- if (instanceId === undefined) {
- storage.set(instanceStorageKey, generateUuid());
- }
-
// First session date (once)
const firstSessionDate = storage.get(firstSessionDateStorageKey, undefined);
if (firstSessionDate === undefined) {
diff --git a/src/vs/platform/storage/test/electron-main/storageMainService.test.ts b/src/vs/platform/storage/test/electron-main/storageMainService.test.ts
index 110a60eb77e..782140d4e99 100644
--- a/src/vs/platform/storage/test/electron-main/storageMainService.test.ts
+++ b/src/vs/platform/storage/test/electron-main/storageMainService.test.ts
@@ -17,7 +17,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
import { IS_NEW_KEY } from 'vs/platform/storage/common/storage';
import { IStorageChangeEvent, IStorageMain, IStorageMainOptions } from 'vs/platform/storage/electron-main/storageMain';
import { StorageMainService } from 'vs/platform/storage/electron-main/storageMainService';
-import { currentSessionDateStorageKey, firstSessionDateStorageKey, instanceStorageKey } from 'vs/platform/telemetry/common/telemetry';
+import { currentSessionDateStorageKey, firstSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
import { ICodeWindow, UnloadReason } from 'vs/platform/windows/electron-main/windows';
suite('StorageMainService', function () {
@@ -57,7 +57,6 @@ suite('StorageMainService', function () {
onWillLoadWindow = Event.None;
onBeforeCloseWindow = Event.None;
onBeforeUnloadWindow = Event.None;
- onWillKill = Event.None;
wasRestarted = false;
quitRequested = false;
@@ -78,9 +77,7 @@ suite('StorageMainService', function () {
// Telemetry: added after init
if (isGlobal) {
strictEqual(storage.items.size, 0);
- strictEqual(storage.get(instanceStorageKey), undefined);
await storage.init();
- strictEqual(typeof storage.get(instanceStorageKey), 'string');
strictEqual(typeof storage.get(firstSessionDateStorageKey), 'string');
strictEqual(typeof storage.get(currentSessionDateStorageKey), 'string');
} else {
diff --git a/src/vs/platform/telemetry/common/telemetry.ts b/src/vs/platform/telemetry/common/telemetry.ts
index 4f0dfa36049..be381cd790c 100644
--- a/src/vs/platform/telemetry/common/telemetry.ts
+++ b/src/vs/platform/telemetry/common/telemetry.ts
@@ -11,7 +11,6 @@ export const ITelemetryService = createDecorator('telemetrySe
export interface ITelemetryInfo {
sessionId: string;
machineId: string;
- instanceId: string;
firstSessionDate: string;
msftInternal?: boolean;
}
@@ -66,7 +65,6 @@ export interface ICustomEndpointTelemetryService {
}
// Keys
-export const instanceStorageKey = 'telemetry.instanceId';
export const currentSessionDateStorageKey = 'telemetry.currentSessionDate';
export const firstSessionDateStorageKey = 'telemetry.firstSessionDate';
export const lastSessionDateStorageKey = 'telemetry.lastSessionDate';
diff --git a/src/vs/platform/telemetry/common/telemetryService.ts b/src/vs/platform/telemetry/common/telemetryService.ts
index a3b17f5a821..c66501394a0 100644
--- a/src/vs/platform/telemetry/common/telemetryService.ts
+++ b/src/vs/platform/telemetry/common/telemetryService.ts
@@ -95,12 +95,11 @@ export class TelemetryService implements ITelemetryService {
// well known properties
let sessionId = values['sessionID'];
- let instanceId = values['common.instanceId'];
let machineId = values['common.machineId'];
let firstSessionDate = values['common.firstSessionDate'];
let msftInternal = values['common.msftInternal'];
- return { sessionId, instanceId, machineId, firstSessionDate, msftInternal };
+ return { sessionId, machineId, firstSessionDate, msftInternal };
}
dispose(): void {
diff --git a/src/vs/platform/telemetry/test/browser/telemetryService.test.ts b/src/vs/platform/telemetry/test/browser/telemetryService.test.ts
index a930891c50e..66cccfc61d7 100644
--- a/src/vs/platform/telemetry/test/browser/telemetryService.test.ts
+++ b/src/vs/platform/telemetry/test/browser/telemetryService.test.ts
@@ -185,14 +185,12 @@ suite('TelemetryService', () => {
appenders: [NullAppender],
commonProperties: Promise.resolve({
sessionID: 'one',
- ['common.instanceId']: 'two',
['common.machineId']: 'three',
})
}, new TestConfigurationService());
return service.getTelemetryInfo().then(info => {
assert.strictEqual(info.sessionId, 'one');
- assert.strictEqual(info.instanceId, 'two');
assert.strictEqual(info.machineId, 'three');
service.dispose();
diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts
index 71c62368b09..026521405f7 100644
--- a/src/vs/platform/terminal/common/terminal.ts
+++ b/src/vs/platform/terminal/common/terminal.ts
@@ -91,6 +91,7 @@ export const enum TerminalSettingId {
UnicodeVersion = 'terminal.integrated.unicodeVersion',
ExperimentalLinkProvider = 'terminal.integrated.experimentalLinkProvider',
LocalEchoLatencyThreshold = 'terminal.integrated.localEchoLatencyThreshold',
+ LocalEchoEnabled = 'terminal.integrated.localEchoEnabled',
LocalEchoExcludePrograms = 'terminal.integrated.localEchoExcludePrograms',
LocalEchoStyle = 'terminal.integrated.localEchoStyle',
EnablePersistentSessions = 'terminal.integrated.enablePersistentSessions',
diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts
index 2c3294935ab..1273db4f215 100644
--- a/src/vs/platform/terminal/node/ptyService.ts
+++ b/src/vs/platform/terminal/node/ptyService.ts
@@ -100,7 +100,8 @@ export class PtyService extends Disposable implements IPtyService {
async serializeTerminalState(ids: number[]): Promise {
const promises: Promise[] = [];
for (const [persistentProcessId, persistentProcess] of this._ptys.entries()) {
- if (ids.indexOf(persistentProcessId) !== -1) {
+ // Only serialize persistent processes that have had data written or performed a replay
+ if (persistentProcess.hasWrittenData && ids.indexOf(persistentProcessId) !== -1) {
promises.push(Promises.withAsyncBody