diff --git a/.eslintrc.json b/.eslintrc.json index e7506985bd3..fada4705598 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -614,6 +614,13 @@ "*" ] }, + { + "target": "**/test/integration/**", + "restrictions": [ + "**/test/integration/**", + "*" + ] + }, { "target": "{**/api/**.test.ts,}", "restrictions": "{**/vs/**,assert,sinon,crypto,vscode}" diff --git a/build/azure-pipelines/darwin/entitlements.plist b/build/azure-pipelines/darwin/entitlements.plist new file mode 100644 index 00000000000..46f67566114 --- /dev/null +++ b/build/azure-pipelines/darwin/entitlements.plist @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 50c85822a53..55f55e0eade 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -44,6 +44,13 @@ steps: git config user.email "vscode@microsoft.com" git config user.name "VSCode" + + security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain + security default-keychain -s $(agent.tempdirectory)/buildagent.keychain + security unlock-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain + echo "$(macos-developer-certificate)" | base64 -D > $(agent.tempdirectory)/cert.p12 + security import $(agent.tempdirectory)/cert.p12 -k $(agent.tempdirectory)/buildagent.keychain -P "$(macos-developer-certificate-key)" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain displayName: Prepare tooling - script: | @@ -127,7 +134,12 @@ steps: - script: | set -e - pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin.zip * && popd + codesign -s 99FM488X57 --deep --force --options runtime --entitlements build/azure-pipelines/darwin/entitlements.plist $(agent.builddirectory)/VSCode-darwin/*.app + displayName: Set Hardened Entitlements + +- script: | + set -e + pushd $(agent.builddirectory)/VSCode-darwin && zip -r -X -y $(agent.builddirectory)/VSCode-darwin.zip * && popd displayName: Archive build - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 @@ -141,13 +153,53 @@ steps: { "keyCode": "CP-401337-Apple", "operationSetCode": "MacAppDeveloperSign", - "parameters": [ ], + "parameters": [ + { + "parameterName": "Hardening", + "parameterValue": "--options=runtime" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + SessionTimeout: 60 + displayName: Codesign + +- script: | + zip -d $(agent.builddirectory)/VSCode-darwin.zip "*.pkg" + displayName: Clean Archive + +- script: | + APP_ROOT=$(agent.builddirectory)/VSCode-darwin + APP_NAME="`ls $APP_ROOT | head -n 1`" + BUNDLE_IDENTIFIER=$(node -p "require(\"$APP_ROOT/$APP_NAME/Contents/Resources/app/product.json\").darwinBundleIdentifier") + echo "##vso[task.setvariable variable=BundleIdentifier]$BUNDLE_IDENTIFIER" + displayName: Export bundle identifier + +- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + inputs: + ConnectedServiceName: 'ESRP CodeSign' + FolderPath: '$(agent.builddirectory)' + Pattern: 'VSCode-darwin.zip' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-401337-Apple", + "operationSetCode": "MacAppNotarize", + "parameters": [ + { + "parameterName": "BundleId", + "parameterValue": "$(BundleIdentifier)" + } + ], "toolName": "sign", "toolVersion": "1.0" } ] SessionTimeout: 120 - displayName: Codesign + displayName: Notarization - script: | set -e diff --git a/build/azure-pipelines/darwin/publish.sh b/build/azure-pipelines/darwin/publish.sh index a8067a5eefb..58f110c5df5 100755 --- a/build/azure-pipelines/darwin/publish.sh +++ b/build/azure-pipelines/darwin/publish.sh @@ -1,9 +1,6 @@ #!/usr/bin/env bash set -e -# remove pkg from archive -zip -d ../VSCode-darwin.zip "*.pkg" - # publish the build node build/azure-pipelines/common/createAsset.js \ darwin \ diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 9af81603c8a..c0b16af0ea7 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -53,7 +53,7 @@ const indentationFilter = [ '!src/vs/base/common/marked/marked.js', '!src/vs/base/node/terminateProcess.sh', '!src/vs/base/node/cpuUsage.sh', - '!test/assert.js', + '!test/unit/assert.js', // except specific folders '!test/automation/out/**', @@ -82,7 +82,7 @@ const indentationFilter = [ '!src/vs/*/**/*.d.ts', '!src/typings/**/*.d.ts', '!extensions/**/*.d.ts', - '!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe,ico,icns}', + '!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe,ico,icns,plist}', '!build/{lib,download}/**/*.js', '!build/**/*.sh', '!build/azure-pipelines/**/*.js', diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index 83e31e8b853..5a937a80bd8 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -72,4 +72,5 @@ runtime "${runtime}"`; yarnInstall(`build`); // node modules required for build yarnInstall('test/automation'); // node modules required for smoketest yarnInstall('test/smoke'); // node modules required for smoketest +yarnInstall('test/integration/browser'); // node modules required for integration yarnInstallBuildDependencies(); // node modules for watching, specific to host node version, not electron diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts index aba94541010..275ecf3003c 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts @@ -69,17 +69,16 @@ suite('Debug', function () { }) })); - const capabilitiesPromise = new Promise(resolve => capabilitiesReceived = resolve); const initializedPromise = new Promise(resolve => initializedReceived = resolve); const configurationDonePromise = new Promise(resolve => configurationDoneReceived = resolve); // Do not await debug start to return due to https://github.com/microsoft/vscode/issues/90134 debug.startDebugging(workspace.workspaceFolders![0], 'Launch debug.js'); - await capabilitiesPromise; await initializedPromise; await configurationDonePromise; - assert.notEqual(debug.activeDebugSession, undefined); - assert.equal(debug.activeDebugSession?.name, 'Launch debug.js'); + // Do not verify activeDebugSession due to same flakiness that sometimes start debugging does not return + // assert.notEqual(debug.activeDebugSession, undefined); + // assert.equal(debug.activeDebugSession?.name, 'Launch debug.js'); await firstVariablesRetrieved; assert.equal(stoppedEvents, 1); diff --git a/package.json b/package.json index 861d97d248f..e5da56c97a7 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,6 @@ "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", "event-stream": "3.3.4", - "express": "^4.13.1", "fancy-log": "^1.3.3", "fast-plist": "0.1.2", "glob": "^5.0.13", @@ -158,7 +157,8 @@ "vscode-nls-dev": "^3.3.1", "webpack": "^4.16.5", "webpack-cli": "^3.3.8", - "webpack-stream": "^5.1.1" + "webpack-stream": "^5.1.1", + "yaserver": "^0.2.0" }, "repository": { "type": "git", diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts index 6b35d6afc9c..495a1ddf636 100644 --- a/src/vs/base/test/common/uri.test.ts +++ b/src/vs/base/test/common/uri.test.ts @@ -404,7 +404,7 @@ suite('URI', () => { path = 'foo/bar'; assert.equal(URI.file(path).path, '/foo/bar'); path = './foo/bar'; - assert.equal(URI.file(path).path, '/./foo/bar'); // todo@joh missing normalization + assert.equal(URI.file(path).path, '/./foo/bar'); // missing normalization const fileUri1 = URI.parse(`file:foo/bar`); assert.equal(fileUri1.path, '/foo/bar'); diff --git a/src/vs/editor/browser/viewParts/minimap/minimapCharRenderer.ts b/src/vs/editor/browser/viewParts/minimap/minimapCharRenderer.ts index cc8a37fcf6b..6feeecc03ac 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimapCharRenderer.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimapCharRenderer.ts @@ -5,6 +5,7 @@ import { RGBA8 } from 'vs/editor/common/core/rgba'; import { Constants, getCharIndex } from './minimapCharSheet'; +import { toUint8 } from 'vs/base/common/uint'; export class MinimapCharRenderer { _minimapCharRendererBrand: void; @@ -20,7 +21,7 @@ export class MinimapCharRenderer { private static soften(input: Uint8ClampedArray, ratio: number): Uint8ClampedArray { let result = new Uint8ClampedArray(input.length); for (let i = 0, len = input.length; i < len; i++) { - result[i] = input[i] * ratio; + result[i] = toUint8(input[i] * ratio); } return result; } diff --git a/src/vs/editor/browser/viewParts/minimap/minimapCharRendererFactory.ts b/src/vs/editor/browser/viewParts/minimap/minimapCharRendererFactory.ts index 585f5d01509..46c6c8e27a9 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimapCharRendererFactory.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimapCharRendererFactory.ts @@ -7,6 +7,7 @@ import { MinimapCharRenderer } from 'vs/editor/browser/viewParts/minimap/minimap import { allCharCodes } from 'vs/editor/browser/viewParts/minimap/minimapCharSheet'; import { prebakedMiniMaps } from 'vs/editor/browser/viewParts/minimap/minimapPreBaked'; import { Constants } from './minimapCharSheet'; +import { toUint8 } from 'vs/base/common/uint'; /** * Creates character renderers. It takes a 'scale' that determines how large @@ -135,7 +136,7 @@ export class MinimapCharRendererFactory { const final = value / samples; brightest = Math.max(brightest, final); - dest[targetIndex++] = final; + dest[targetIndex++] = toUint8(final); } } diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index 1f2df5a96b7..0afaa0abca4 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -45,11 +45,13 @@ function canSyncModel(modelService: IModelService, resource: URI): boolean { } export class EditorWorkerServiceImpl extends Disposable implements IEditorWorkerService { - public _serviceBrand: undefined; + + _serviceBrand: undefined; private readonly _modelService: IModelService; private readonly _workerManager: WorkerManager; private readonly _logService: ILogService; + constructor( @IModelService modelService: IModelService, @ITextResourceConfigurationService configurationService: ITextResourceConfigurationService, @@ -60,7 +62,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker this._workerManager = this._register(new WorkerManager(this._modelService)); this._logService = logService; - // todo@joh make sure this happens only once + // register default link-provider and default completions-provider this._register(modes.LinkProviderRegistry.register('*', { provideLinks: (model, token) => { if (!canSyncModel(this._modelService, model.uri)) { diff --git a/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts index d61207f384e..1bb98526f71 100644 --- a/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts +++ b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts @@ -154,6 +154,7 @@ suite('Decoration Render Options', () => { sheet.indexOf('background: url(\'file:///c%3A/files/miles/more.png\') center center no-repeat;') > 0 || sheet.indexOf('background: url("file:///c%3A/files/miles/more.png") center center no-repeat;') > 0 || sheet.indexOf('background: url("file:///c:/files/miles/more.png") center center no-repeat;') > 0 + || sheet.indexOf('background-image: url("file:///c:/files/miles/more.png"); background-position: center center; background-repeat: no-repeat no-repeat;') > 0 ); s.removeDecorationType('example'); } diff --git a/src/vs/editor/test/browser/view/minimapCharRenderer.test.ts b/src/vs/editor/test/browser/view/minimapCharRenderer.test.ts index 56281b80706..b0b0762997c 100644 --- a/src/vs/editor/test/browser/view/minimapCharRenderer.test.ts +++ b/src/vs/editor/test/browser/view/minimapCharRenderer.test.ts @@ -10,22 +10,6 @@ import { MinimapCharRendererFactory } from 'vs/editor/browser/viewParts/minimap/ suite('MinimapCharRenderer', () => { - let sampleData: Uint8ClampedArray | null = null; - - suiteSetup(() => { - sampleData = new Uint8ClampedArray(Constants.SAMPLED_CHAR_HEIGHT * Constants.SAMPLED_CHAR_WIDTH * Constants.RGBA_CHANNELS_CNT * Constants.CHAR_COUNT); - }); - - suiteTeardown(() => { - sampleData = null; - }); - - setup(() => { - for (let i = 0; i < sampleData!.length; i++) { - sampleData![i] = 0; - } - }); - const sampleD = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0x00, 0x00, 0x00, 0x00, @@ -45,7 +29,13 @@ suite('MinimapCharRenderer', () => { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; - function setSampleData(charCode: number, data: number[]) { + function getSampleData() { + const charCode = 'd'.charCodeAt(0); + const result = new Uint8ClampedArray(Constants.SAMPLED_CHAR_HEIGHT * Constants.SAMPLED_CHAR_WIDTH * Constants.RGBA_CHANNELS_CNT * Constants.CHAR_COUNT); + for (let i = 0; i < result.length; i++) { + result[i] = 0; + } + const rowWidth = Constants.SAMPLED_CHAR_WIDTH * Constants.RGBA_CHANNELS_CNT * Constants.CHAR_COUNT; let chIndex = charCode - Constants.START_CH_CODE; @@ -55,13 +45,15 @@ suite('MinimapCharRenderer', () => { let outputOffset = globalOutputOffset; for (let j = 0; j < Constants.SAMPLED_CHAR_WIDTH; j++) { for (let channel = 0; channel < Constants.RGBA_CHANNELS_CNT; channel++) { - sampleData![outputOffset] = data[inputOffset]; + result[outputOffset] = sampleD[inputOffset]; inputOffset++; outputOffset++; } } globalOutputOffset += rowWidth; } + + return result; } function createFakeImageData(width: number, height: number): ImageData { @@ -73,8 +65,8 @@ suite('MinimapCharRenderer', () => { } test('letter d @ 2x', () => { - setSampleData('d'.charCodeAt(0), sampleD); - let renderer = MinimapCharRendererFactory.createFromSampleData(sampleData!, 2); + const sampleData = getSampleData(); + let renderer = MinimapCharRendererFactory.createFromSampleData(sampleData, 2); let background = new RGBA8(0, 0, 0, 255); let color = new RGBA8(255, 255, 255, 255); @@ -94,16 +86,16 @@ suite('MinimapCharRenderer', () => { } assert.deepEqual(actual, [ - 0x2E, 0x2E, 0x2E, 0xFF, 0xAD, 0xAD, 0xAD, 0xFF, + 0x2D, 0x2D, 0x2D, 0xFF, 0xAC, 0xAC, 0xAC, 0xFF, 0xC6, 0xC6, 0xC6, 0xFF, 0xC8, 0xC8, 0xC8, 0xFF, - 0xC1, 0xC1, 0xC1, 0xFF, 0xCC, 0xCC, 0xCC, 0xFF, + 0xC0, 0xC0, 0xC0, 0xFF, 0xCB, 0xCB, 0xCB, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, ]); }); test('letter d @ 1x', () => { - setSampleData('d'.charCodeAt(0), sampleD); - let renderer = MinimapCharRendererFactory.createFromSampleData(sampleData!, 1); + const sampleData = getSampleData(); + let renderer = MinimapCharRendererFactory.createFromSampleData(sampleData, 1); let background = new RGBA8(0, 0, 0, 255); let color = new RGBA8(255, 255, 255, 255); @@ -125,7 +117,7 @@ suite('MinimapCharRenderer', () => { assert.deepEqual(actual, [ 0xCB, 0xCB, 0xCB, 0xFF, - 0x82, 0x82, 0x82, 0xFF, + 0x81, 0x81, 0x81, 0xFF, ]); }); diff --git a/src/vs/platform/userDataSync/common/extensionsSync.ts b/src/vs/platform/userDataSync/common/extensionsSync.ts index 5724540aa1f..3cf230cb66f 100644 --- a/src/vs/platform/userDataSync/common/extensionsSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsSync.ts @@ -136,7 +136,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse this.setStatus(SyncStatus.Idle); if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.Rejected) { // Rejected as there is a new remote version. Syncing again, - this.logService.info('Extensions: Failed to synchronise extensions as there is a new remote version available. Synchronizing again...'); + this.logService.info('Extensions: Failed to synchronize extensions as there is a new remote version available. Synchronizing again...'); return this.sync(); } throw e; @@ -211,16 +211,18 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse if (remote) { // update remote - this.logService.info('Extensions: Updating remote extensions...'); + this.logService.trace('Extensions: Updating remote extensions...'); const content = JSON.stringify(remote); const ref = await this.updateRemoteUserData(content, forcePush ? null : remoteUserData.ref); remoteUserData = { ref, content }; + this.logService.info('Extensions: Updated remote extensions'); } if (lastSyncUserData?.ref !== remoteUserData.ref) { // update last sync - this.logService.info('Extensions: Updating last synchronised extensions...'); + this.logService.trace('Extensions: Updating last synchronized extensions...'); await this.updateLastSyncUserData({ ...remoteUserData, skippedExtensions }); + this.logService.info('Extensions: Updated last synchronized extensions'); } } @@ -232,8 +234,9 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse const installedExtensions = await this.extensionManagementService.getInstalled(ExtensionType.User); const extensionsToRemove = installedExtensions.filter(({ identifier }) => removed.some(r => areSameExtensions(identifier, r))); await Promise.all(extensionsToRemove.map(async extensionToRemove => { - this.logService.info('Extensions: Removing local extension.', extensionToRemove.identifier.id); + this.logService.trace('Extensions: Uninstalling local extension...', extensionToRemove.identifier.id); await this.extensionManagementService.uninstall(extensionToRemove); + this.logService.info('Extensions: Uninstalled local extension.', extensionToRemove.identifier.id); removeFromSkipped.push(extensionToRemove.identifier); })); } @@ -246,11 +249,13 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse // Builtin Extension: Sync only enablement state if (installedExtension && installedExtension.type === ExtensionType.System) { if (e.enabled) { - this.logService.info('Extensions: Enabling extension.', e.identifier.id); + this.logService.trace('Extensions: Enabling extension...', e.identifier.id); await this.extensionEnablementService.enableExtension(e.identifier); + this.logService.info('Extensions: Enabled extension', e.identifier.id); } else { - this.logService.info('Extensions: Disabling extension.', e.identifier.id); + this.logService.trace('Extensions: Disabling extension...', e.identifier.id); await this.extensionEnablementService.disableExtension(e.identifier); + this.logService.info('Extensions: Disabled extension.', e.identifier.id); } removeFromSkipped.push(e.identifier); return; @@ -260,22 +265,25 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse if (extension) { try { if (e.enabled) { - this.logService.info('Extensions: Enabling extension.', e.identifier.id, extension.version); + this.logService.trace('Extensions: Enabling extension...', e.identifier.id, extension.version); await this.extensionEnablementService.enableExtension(extension.identifier); + this.logService.info('Extensions: Enabled extension', e.identifier.id, extension.version); } else { - this.logService.info('Extensions: Disabling extension.', e.identifier.id, extension.version); + this.logService.trace('Extensions: Disabling extension...', e.identifier.id, extension.version); await this.extensionEnablementService.disableExtension(extension.identifier); + this.logService.info('Extensions: Disabled extension', e.identifier.id, extension.version); } // Install only if the extension does not exist if (!installedExtension || installedExtension.manifest.version !== extension.version) { - this.logService.info('Extensions: Installing extension.', e.identifier.id, extension.version); + this.logService.trace('Extensions: Installing extension...', e.identifier.id, extension.version); await this.extensionManagementService.installFromGallery(extension); + this.logService.info('Extensions: Installed extension.', e.identifier.id, extension.version); removeFromSkipped.push(extension.identifier); } } catch (error) { addToSkipped.push(e); this.logService.error(error); - this.logService.info(localize('skip extension', "Skipping synchronising extension {0}", extension.displayName || extension.identifier.id)); + this.logService.info(localize('skip extension', "Skipped synchronizing extension {0}", extension.displayName || extension.identifier.id)); } } else { addToSkipped.push(e); diff --git a/src/vs/platform/userDataSync/common/globalStateSync.ts b/src/vs/platform/userDataSync/common/globalStateSync.ts index c20024d1f20..bd125de964a 100644 --- a/src/vs/platform/userDataSync/common/globalStateSync.ts +++ b/src/vs/platform/userDataSync/common/globalStateSync.ts @@ -118,7 +118,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs this.setStatus(SyncStatus.Idle); if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.Rejected) { // Rejected as there is a new remote version. Syncing again, - this.logService.info('UI State: Failed to synchronise ui state as there is a new remote version available. Synchronizing again...'); + this.logService.info('UI State: Failed to synchronize ui state as there is a new remote version available. Synchronizing again...'); return this.sync(); } throw e; @@ -183,22 +183,25 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs if (local) { // update local - this.logService.info('UI State: Updating local ui state...'); + this.logService.trace('UI State: Updating local ui state...'); await this.writeLocalGlobalState(local); + this.logService.info('UI State: Updated local ui state'); } if (remote) { // update remote - this.logService.info('UI State: Updating remote ui state...'); + this.logService.trace('UI State: Updating remote ui state...'); const content = JSON.stringify(remote); const ref = await this.updateRemoteUserData(content, forcePush ? null : remoteUserData.ref); + this.logService.info('UI State: Updated remote ui state'); remoteUserData = { ref, content }; } if (lastSyncUserData?.ref !== remoteUserData.ref) { // update last sync - this.logService.info('UI State: Updating last synchronised ui state...'); + this.logService.trace('UI State: Updating last synchronized ui state...'); await this.updateLastSyncUserData(remoteUserData); + this.logService.info('UI State: Updated last synchronized ui state'); } } diff --git a/src/vs/platform/userDataSync/common/keybindingsSync.ts b/src/vs/platform/userDataSync/common/keybindingsSync.ts index 76083e2a537..464f50fc04d 100644 --- a/src/vs/platform/userDataSync/common/keybindingsSync.ts +++ b/src/vs/platform/userDataSync/common/keybindingsSync.ts @@ -176,10 +176,9 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements await this.apply(content, true); this.setStatus(SyncStatus.Idle); } catch (e) { - this.logService.error(e); if ((e instanceof FileSystemProviderError && e.code === FileSystemProviderErrorCode.FileExists) || (e instanceof FileOperationError && e.fileOperationResult === FileOperationResult.FILE_MODIFIED_SINCE)) { - throw new Error('Failed to resolve conflicts as there is a new local version available.'); + throw new UserDataSyncError('Failed to resolve conflicts as there is a new local version available.', UserDataSyncErrorCode.NewLocal); } throw e; } @@ -235,13 +234,13 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements this.setStatus(SyncStatus.Idle); if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.Rejected) { // Rejected as there is a new remote version. Syncing again, - this.logService.info('Keybindings: Failed to synchronise keybindings as there is a new remote version available. Synchronizing again...'); + this.logService.info('Keybindings: Failed to synchronize keybindings as there is a new remote version available. Synchronizing again...'); return this.sync(); } if ((e instanceof FileSystemProviderError && e.code === FileSystemProviderErrorCode.FileExists) || (e instanceof FileOperationError && e.fileOperationResult === FileOperationResult.FILE_MODIFIED_SINCE)) { // Rejected as there is a new local version. Syncing again. - this.logService.info('Keybindings: Failed to synchronise keybindings as there is a new local version available. Synchronizing again...'); + this.logService.info('Keybindings: Failed to synchronize keybindings as there is a new local version available. Synchronizing again...'); return this.sync(); } throw e; @@ -274,15 +273,17 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements } if (hasLocalChanged) { - this.logService.info('Keybindings: Updating local keybindings'); + this.logService.trace('Keybindings: Updating local keybindings...'); await this.updateLocalFileContent(content, fileContent); + this.logService.info('Keybindings: Updated local keybindings'); } if (hasRemoteChanged) { - this.logService.info('Keybindings: Updating remote keybindings'); + this.logService.trace('Keybindings: Updating remote keybindings...'); const remoteContents = this.updateSyncContent(content, remoteUserData.content); const ref = await this.updateRemoteUserData(remoteContents, forcePush ? null : remoteUserData.ref); remoteUserData = { ref, content: remoteContents }; + this.logService.info('Keybindings: Updated remote keybindings'); } // Delete the preview @@ -292,9 +293,10 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements } if (lastSyncUserData?.ref !== remoteUserData.ref && (content !== undefined || fileContent !== null)) { - this.logService.info('Keybindings: Updating last synchronised keybindings'); + this.logService.trace('Keybindings: Updating last synchronized keybindings...'); const lastSyncContent = this.updateSyncContent(content !== undefined ? content : fileContent!.value.toString(), null); await this.updateLastSyncUserData({ ref: remoteUserData.ref, content: lastSyncContent }); + this.logService.info('Keybindings: Updated last synchronized keybindings'); } this.syncPreviewResultPromise = null; diff --git a/src/vs/platform/userDataSync/common/settingsSync.ts b/src/vs/platform/userDataSync/common/settingsSync.ts index bd702546688..9b223976b9a 100644 --- a/src/vs/platform/userDataSync/common/settingsSync.ts +++ b/src/vs/platform/userDataSync/common/settingsSync.ts @@ -245,10 +245,9 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS await this.apply(true); this.setStatus(SyncStatus.Idle); } catch (e) { - this.logService.error(e); if ((e instanceof FileSystemProviderError && e.code === FileSystemProviderErrorCode.FileExists) || (e instanceof FileOperationError && e.fileOperationResult === FileOperationResult.FILE_MODIFIED_SINCE)) { - throw new Error('New local version available.'); + throw new UserDataSyncError('Failed to resolve conflicts as there is a new local version available.', UserDataSyncErrorCode.NewLocal); } throw e; } @@ -282,13 +281,13 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS this.setStatus(SyncStatus.Idle); if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.Rejected) { // Rejected as there is a new remote version. Syncing again, - this.logService.info('Settings: Failed to synchronise settings as there is a new remote version available. Synchronizing again...'); + this.logService.info('Settings: Failed to synchronize settings as there is a new remote version available. Synchronizing again...'); return this.sync(); } if ((e instanceof FileSystemProviderError && e.code === FileSystemProviderErrorCode.FileExists) || (e instanceof FileOperationError && e.fileOperationResult === FileOperationResult.FILE_MODIFIED_SINCE)) { // Rejected as there is a new local version. Syncing again. - this.logService.info('Settings: Failed to synchronise settings as there is a new local version available. Synchronizing again...'); + this.logService.info('Settings: Failed to synchronize settings as there is a new local version available. Synchronizing again...'); return this.sync(); } throw e; @@ -311,15 +310,17 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS } if (hasLocalChanged) { - this.logService.info('Settings: Updating local settings'); + this.logService.trace('Settings: Updating local settings...'); await this.updateLocalFileContent(content, fileContent); + this.logService.info('Settings: Updated local settings'); } if (hasRemoteChanged) { const formatUtils = await this.getFormattingOptions(); // Update ignored settings from remote content = updateIgnoredSettings(content, remoteUserData.content || '{}', getIgnoredSettings(this.configurationService, content), formatUtils); - this.logService.info('Settings: Updating remote settings'); + this.logService.trace('Settings: Updating remote settings...'); const ref = await this.updateRemoteUserData(content, forcePush ? null : remoteUserData.ref); + this.logService.info('Settings: Updated remote settings'); remoteUserData = { ref, content }; } @@ -330,8 +331,9 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS } if (lastSyncUserData?.ref !== remoteUserData.ref) { - this.logService.info('Settings: Updating last synchronised settings'); + this.logService.trace('Settings: Updating last synchronized settings...'); await this.updateLastSyncUserData(remoteUserData); + this.logService.info('Settings: Updated last synchronized settings'); } this.syncPreviewResultPromise = null; diff --git a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts index 0a169d45b34..e401fb270aa 100644 --- a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts @@ -84,7 +84,7 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto this.sync(loop, true); } } else { - this.logService.trace('Not syncing as it is disabled.'); + this.logService.trace('Auto Sync: Not syncing as it is disabled.'); } } @@ -107,7 +107,7 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto async triggerAutoSync(): Promise { if (this.enabled) { return this.syncDelayer.trigger(() => { - this.logService.info('Sync: Triggerred.'); + this.logService.info('Auto Sync: Triggerred.'); return this.sync(false, true); }, this.successiveFailures ? 1000 * 1 * Math.min(this.successiveFailures, 60) /* Delay by number of seconds as number of failures up to 1 minute */ diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index 68b16a286c9..60495654ccd 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -130,6 +130,7 @@ export enum UserDataSyncErrorCode { Rejected = 'Rejected', TooLarge = 'TooLarge', NoRef = 'NoRef', + NewLocal = 'NewLocal', Unknown = 'Unknown', } @@ -137,6 +138,18 @@ export class UserDataSyncError extends Error { constructor(message: string, public readonly code: UserDataSyncErrorCode, public readonly source?: SyncSource) { super(message); + this.name = `${this.code} (UserDataSyncError) ${this.source}`; + } + + static toUserDataSyncError(error: Error): UserDataSyncError { + if (error instanceof UserDataSyncStoreError) { + return error; + } + const match = /^(.+) \(UserDataSyncError\) (.+)?$/.exec(error.name); + if (match && match[1]) { + return new UserDataSyncError(error.message, match[1], match[2]); + } + return new UserDataSyncError(error.message, UserDataSyncErrorCode.Unknown); } } @@ -222,7 +235,7 @@ export interface IUserDataSyncService extends ISynchroniser { export const IUserDataAutoSyncService = createDecorator('IUserDataAutoSyncService'); export interface IUserDataAutoSyncService { _serviceBrand: any; - onError: Event<{ code: UserDataSyncErrorCode, source?: SyncSource }>; + readonly onError: Event<{ code: UserDataSyncErrorCode, source?: SyncSource }>; triggerAutoSync(): Promise; } diff --git a/src/vs/platform/userDataSync/common/userDataSyncService.ts b/src/vs/platform/userDataSync/common/userDataSyncService.ts index 9d67caea8bb..10a4c4599c7 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncService.ts @@ -3,10 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IUserDataSyncService, SyncStatus, ISynchroniser, IUserDataSyncStoreService, SyncSource, ISettingsSyncService, IUserDataSyncLogService, IUserDataAuthTokenService, IUserDataSynchroniser, UserDataSyncStoreError } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserDataSyncService, SyncStatus, IUserDataSyncStoreService, SyncSource, ISettingsSyncService, IUserDataSyncLogService, IUserDataAuthTokenService, IUserDataSynchroniser, UserDataSyncStoreError, UserDataSyncErrorCode } from 'vs/platform/userDataSync/common/userDataSync'; import { Disposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { SettingsSynchroniser } from 'vs/platform/userDataSync/common/settingsSync'; import { Emitter, Event } from 'vs/base/common/event'; import { ExtensionsSynchroniser } from 'vs/platform/userDataSync/common/extensionsSync'; import { KeybindingsSynchroniser } from 'vs/platform/userDataSync/common/keybindingsSync'; @@ -19,6 +18,10 @@ type SyncConflictsClassification = { source?: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; }; +type SyncErrorClassification = { + source: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; +}; + export class UserDataSyncService extends Disposable implements IUserDataSyncService { _serviceBrand: any; @@ -73,7 +76,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ try { await synchroniser.pull(); } catch (e) { - this.logService.error(`${this.getSyncSource(synchroniser)}: ${toErrorMessage(e)}`); + this.handleSyncError(e, synchroniser.source); } } } @@ -89,7 +92,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ try { await synchroniser.push(); } catch (e) { - this.logService.error(`${this.getSyncSource(synchroniser)}: ${toErrorMessage(e)}`); + this.handleSyncError(e, synchroniser.source); } } } @@ -114,10 +117,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ break; } } catch (e) { - if (e instanceof UserDataSyncStoreError) { - throw e; - } - this.logService.error(`${this.getSyncSource(synchroniser)}: ${toErrorMessage(e)}`); + this.handleSyncError(e, synchroniser.source); } } this.logService.trace(`Finished Syncing. Took ${new Date().getTime() - startTime}ms`); @@ -249,7 +249,8 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ try { await synchroniser.resetLocal(); } catch (e) { - this.logService.error(`${this.getSyncSource(synchroniser)}: ${toErrorMessage(e)}`); + this.logService.error(`${synchroniser.source}: ${toErrorMessage(e)}`); + this.logService.error(e); } } this.logService.info('Completed resetting local cache'); @@ -287,9 +288,21 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ return SyncStatus.Idle; } + private handleSyncError(e: Error, source: SyncSource): void { + if (e instanceof UserDataSyncStoreError) { + switch (e.code) { + case UserDataSyncErrorCode.TooLarge: + this.telemetryService.publicLog2<{ source: string }, SyncErrorClassification>('sync/errorTooLarge', { source }); + } + throw e; + } + this.logService.error(e); + this.logService.error(`${source}: ${toErrorMessage(e)}`); + } + private computeConflictsSource(): SyncSource | null { const synchroniser = this.synchronisers.filter(s => s.status === SyncStatus.HasConflicts)[0]; - return synchroniser ? this.getSyncSource(synchroniser) : null; + return synchroniser ? synchroniser.source : null; } private getSynchroniserInConflicts(): IUserDataSynchroniser | null { @@ -297,19 +310,6 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ return synchroniser || null; } - private getSyncSource(synchroniser: ISynchroniser): SyncSource { - if (synchroniser instanceof SettingsSynchroniser) { - return SyncSource.Settings; - } - if (synchroniser instanceof KeybindingsSynchroniser) { - return SyncSource.Keybindings; - } - if (synchroniser instanceof ExtensionsSynchroniser) { - return SyncSource.Extensions; - } - return SyncSource.GlobalState; - } - private getSynchroniser(source: SyncSource): IUserDataSynchroniser { switch (source) { case SyncSource.Settings: return this.settingsSynchroniser; diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index f4711ab88a4..3637da92959 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -170,10 +170,15 @@ declare module 'vscode' { /** * Fired when the list of tunnels has changed. + * @deprecated use onDidChangeTunnels instead */ // TODO@alexr // eslint-disable-next-line vscode-dts-event-naming export const onDidTunnelsChange: Event; + /** + * Fired when the list of tunnels has changed. + */ + export const onDidChangeTunnels: Event; } export interface ResourceLabelFormatter { diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 0ce895559ea..96b5fdbfb5e 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -757,9 +757,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I checkProposedApiEnabled(extension); return extHostTunnelService.getTunnels(); }, + onDidChangeTunnels: (listener, thisArg?, disposables?) => { + checkProposedApiEnabled(extension); + return extHostTunnelService.onDidChangeTunnels(listener, thisArg, disposables); + + }, onDidTunnelsChange: (listener, thisArg?, disposables?) => { checkProposedApiEnabled(extension); - return extHostTunnelService.onDidTunnelsChange(listener, thisArg, disposables); + return extHostTunnelService.onDidChangeTunnels(listener, thisArg, disposables); }, registerTimelineProvider: (scheme: string, provider: vscode.TimelineProvider) => { diff --git a/src/vs/workbench/api/common/extHostTunnelService.ts b/src/vs/workbench/api/common/extHostTunnelService.ts index b81fc443758..98436355eb8 100644 --- a/src/vs/workbench/api/common/extHostTunnelService.ts +++ b/src/vs/workbench/api/common/extHostTunnelService.ts @@ -33,7 +33,7 @@ export interface IExtHostTunnelService extends ExtHostTunnelServiceShape { readonly _serviceBrand: undefined; openTunnel(forward: TunnelOptions): Promise; getTunnels(): Promise; - onDidTunnelsChange: vscode.Event; + onDidChangeTunnels: vscode.Event; setTunnelExtensionFunctions(provider: vscode.RemoteAuthorityResolver | undefined): Promise; } @@ -41,7 +41,7 @@ export const IExtHostTunnelService = createDecorator('IEx export class ExtHostTunnelService implements IExtHostTunnelService { _serviceBrand: undefined; - onDidTunnelsChange: vscode.Event = (new Emitter()).event; + onDidChangeTunnels: vscode.Event = (new Emitter()).event; async openTunnel(forward: TunnelOptions): Promise { return undefined; diff --git a/src/vs/workbench/api/node/extHostTunnelService.ts b/src/vs/workbench/api/node/extHostTunnelService.ts index 8930d91e856..4138fd2192c 100644 --- a/src/vs/workbench/api/node/extHostTunnelService.ts +++ b/src/vs/workbench/api/node/extHostTunnelService.ts @@ -39,8 +39,8 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe private _forwardPortProvider: ((tunnelOptions: TunnelOptions) => Thenable | undefined) | undefined; private _showCandidatePort: (host: string, port: number, detail: string) => Thenable = () => { return Promise.resolve(true); }; private _extensionTunnels: Map> = new Map(); - private _onDidTunnelsChange: Emitter = new Emitter(); - onDidTunnelsChange: vscode.Event = this._onDidTunnelsChange.event; + private _onDidChangeTunnels: Emitter = new Emitter(); + onDidChangeTunnels: vscode.Event = this._onDidChangeTunnels.event; constructor( @IExtHostRpcService extHostRpc: IExtHostRpcService, @@ -107,7 +107,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe } async $onDidTunnelsChange(): Promise { - this._onDidTunnelsChange.fire(); + this._onDidChangeTunnels.fire(); } $forwardPort(tunnelOptions: TunnelOptions): Promise | undefined { diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditTree.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditTree.ts index d364ec671d2..37984510df1 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditTree.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditTree.ts @@ -447,17 +447,15 @@ class FileElementTemplate { })); if (element.edit.type & BulkFileOperationType.Rename && element.edit.newUri) { - // rename: NEW NAME (old name) - this._label.setFile(element.edit.newUri, { - matches: createMatches(score), - fileKind: FileKind.FILE, - fileDecorations: { colors: true, badges: false }, + // rename: oldName → newName + this._label.setResource({ + resource: element.edit.uri, + name: localize('rename.label', "{0} → {1}", this._labelService.getUriLabel(element.edit.uri, { relative: true }), this._labelService.getUriLabel(element.edit.newUri, { relative: true })), + }, { + fileDecorations: { colors: true, badges: false } }); - this._details.innerText = localize( - 'detail.rename', "(renaming from {0})", - this._labelService.getUriLabel(element.edit.uri, { relative: true }) - ); + this._details.innerText = localize('detail.rename', "(renaming)"); } else { // create, delete, edit: NAME diff --git a/src/vs/workbench/contrib/debug/browser/debugHover.ts b/src/vs/workbench/contrib/debug/browser/debugHover.ts index c45488e0464..323c3be37c8 100644 --- a/src/vs/workbench/contrib/debug/browser/debugHover.ts +++ b/src/vs/workbench/contrib/debug/browser/debugHover.ts @@ -273,11 +273,13 @@ export class DebugHoverWidget implements IContentWidget { return; } + if (dom.isAncestor(document.activeElement, this.domNode)) { + this.editor.focus(); + } this._isVisible = false; this.editor.deltaDecorations(this.highlightDecorations, []); this.highlightDecorations = []; this.editor.layoutContentWidget(this); - this.editor.focus(); } getPosition(): IContentWidgetPosition | null { diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 4ac7696f9b4..a572425da7c 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IUserDataSyncService, SyncStatus, SyncSource, CONTEXT_SYNC_STATE, IUserDataSyncStore, registerConfiguration, getUserDataSyncStore, ISyncConfiguration, IUserDataAuthTokenService, IUserDataAutoSyncService, USER_DATA_SYNC_SCHEME, toRemoteContentResource, getSyncSourceFromRemoteContentResource, UserDataSyncErrorCode } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserDataSyncService, SyncStatus, SyncSource, CONTEXT_SYNC_STATE, IUserDataSyncStore, registerConfiguration, getUserDataSyncStore, ISyncConfiguration, IUserDataAuthTokenService, IUserDataAutoSyncService, USER_DATA_SYNC_SCHEME, toRemoteContentResource, getSyncSourceFromRemoteContentResource, UserDataSyncErrorCode, UserDataSyncError } from 'vs/platform/userDataSync/common/userDataSync'; import { localize } from 'vs/nls'; import { Disposable, MutableDisposable, toDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -67,10 +67,6 @@ type FirstTimeSyncClassification = { action: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; }; -type SyncErrorClassification = { - source: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; -}; - export class UserDataSyncWorkbenchContribution extends Disposable implements IWorkbenchContribution { private static readonly ENABLEMENT_SETTING = 'sync.enable'; @@ -278,15 +274,13 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo private onAutoSyncError(code: UserDataSyncErrorCode, source?: SyncSource): void { switch (code) { case UserDataSyncErrorCode.TooLarge: - this.telemetryService.publicLog2<{ source: string }, SyncErrorClassification>('sync/errorTooLarge', { source: source! }); if (source === SyncSource.Keybindings || source === SyncSource.Settings) { const sourceArea = getSyncAreaLabel(source); - this.disableSync(); this.notificationService.notify({ severity: Severity.Error, - message: localize('too large', "Turned off sync because size of the {0} file to sync is larger than {1}. Please open the file and reduce the size and turn on sync", sourceArea, '1MB'), + message: localize('too large', "Disabled synchronizing {0} because size of the {1} file to sync is larger than {2}. Please open the file and reduce the size and enable sync", sourceArea, sourceArea, '100kb'), actions: { - primary: [new Action('open sync log', localize('open file', "Show {0} file", sourceArea), undefined, true, + primary: [new Action('open sync file', localize('open file', "Show {0} file", sourceArea), undefined, true, () => source === SyncSource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))] } }); @@ -472,8 +466,15 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo } } - private disableSync(): Promise { - return this.configurationService.updateValue(UserDataSyncWorkbenchContribution.ENABLEMENT_SETTING, undefined, ConfigurationTarget.USER); + private disableSync(source?: SyncSource): Promise { + let key: string = UserDataSyncWorkbenchContribution.ENABLEMENT_SETTING; + switch (source) { + case SyncSource.Settings: key = 'sync.enableSettings'; break; + case SyncSource.Keybindings: key = 'sync.enableKeybindings'; break; + case SyncSource.Extensions: key = 'sync.enableExtensions'; break; + case SyncSource.GlobalState: key = 'sync.enableUIState'; break; + } + return this.configurationService.updateValue(key, false, ConfigurationTarget.USER); } private async signIn(): Promise { @@ -787,11 +788,15 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio try { await this.userDataSyncService.accept(conflictsSource!, model.getValue()); } catch (e) { - this.userDataSyncService.restart().then(() => { - if (conflictsSource === this.userDataSyncService.conflictsSource) { - this.notificationService.warn(localize('update conflicts', "Could not resolve conflicts as there is new local version available. Please try again.")); - } - }); + if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.NewLocal) { + this.userDataSyncService.restart().then(() => { + if (conflictsSource === this.userDataSyncService.conflictsSource) { + this.notificationService.warn(localize('update conflicts', "Could not resolve conflicts as there is new local version available. Please try again.")); + } + }); + } else { + this.notificationService.error(e); + } } } } diff --git a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts index 2d103e7bf89..199f78af912 100644 --- a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts @@ -402,7 +402,6 @@ export class BulkEditService implements IBulkEditService { } // try to find code editor - // todo@joh, prefer editor that gets edited if (!codeEditor) { let candidate = this._editorService.activeTextEditorWidget; if (isCodeEditor(candidate)) { diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts index 748960c515e..4afc0cdea9e 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts @@ -13,9 +13,7 @@ import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService'; import 'vs/workbench/services/extensions/worker/extHost.services'; //#region --- Define, capture, and override some globals -//todo@joh do not allow extensions to call postMessage and other globals... -// declare WorkerSelf#postMessage declare function postMessage(data: any, transferables?: Transferable[]): void; declare namespace self { diff --git a/src/vs/workbench/services/timer/electron-browser/timerService.ts b/src/vs/workbench/services/timer/electron-browser/timerService.ts index f796d9d28b1..3b3d71f9eb0 100644 --- a/src/vs/workbench/services/timer/electron-browser/timerService.ts +++ b/src/vs/workbench/services/timer/electron-browser/timerService.ts @@ -227,8 +227,6 @@ export interface IStartupMetrics { * * Reading of package.json-files is avoided by caching them all in a single file (after the read, * until another extension is installed) * * Happens in parallel to other things, depends on async timing - * - * todo@joh/ramya this measures an artifical dealy we have added, see https://github.com/Microsoft/vscode/blob/2f07ddae8bf56e969e3f4ba1447258ebc999672f/src/vs/workbench/services/extensions/electron-browser/extensionService.ts#L311-L326 */ readonly ellapsedExtensions: number; @@ -264,8 +262,6 @@ export interface IStartupMetrics { * * Measured with the `willRestoreEditors` and `didRestoreEditors` performance marks. * * This should be looked at per editor and per editor type. * * Happens in parallel to other things, depends on async timing - * - * todo@joh/ramya We should probably measures each editor individually? */ readonly ellapsedEditorRestore: number; @@ -274,8 +270,6 @@ export interface IStartupMetrics { * * * Happens in the renderer-process * * Measured with the `willStartWorkbench` and `didStartWorkbench` performance marks. - * - * todo@joh/ramya Not sure if this is useful because this includes too much */ readonly ellapsedWorkbench: number; diff --git a/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts b/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts index 09f62bc9082..b1af7c97888 100644 --- a/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts +++ b/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts @@ -3,12 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SyncStatus, SyncSource, IUserDataSyncService } from 'vs/platform/userDataSync/common/userDataSync'; +import { SyncStatus, SyncSource, IUserDataSyncService, UserDataSyncError } from 'vs/platform/userDataSync/common/userDataSync'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; import { Disposable } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; import { IChannel } from 'vs/base/parts/ipc/common/ipc'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { CancellationToken } from 'vs/base/common/cancellation'; export class UserDataSyncService extends Disposable implements IUserDataSyncService { @@ -30,7 +31,16 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ @ISharedProcessService sharedProcessService: ISharedProcessService ) { super(); - this.channel = sharedProcessService.getChannel('userDataSync'); + const userDataSyncChannel = sharedProcessService.getChannel('userDataSync'); + this.channel = { + call(command: string, arg?: any, cancellationToken?: CancellationToken): Promise { + return userDataSyncChannel.call(command, arg, cancellationToken) + .then(null, error => { throw UserDataSyncError.toUserDataSyncError(error); }); + }, + listen(event: string, arg?: any): Event { + return userDataSyncChannel.listen(event, arg); + } + }; this.channel.call('_getInitialStatus').then(status => { this.updateStatus(status); this._register(this.channel.listen('onDidChangeStatus')(status => this.updateStatus(status))); diff --git a/test/browser.js b/test/browser.js deleted file mode 100644 index 6d90695a690..00000000000 --- a/test/browser.js +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -var express = require('express'); -var glob = require('glob'); -var path = require('path'); -var fs = require('fs'); - -var port = 8887; -var root = path.dirname(__dirname); - -function template(str, env) { - return str.replace(/{{\s*([\w_\-]+)\s*}}/g, function (all, part) { - return env[part]; - }); -} - -var app = express(); - -app.use('/out', express.static(path.join(root, 'out'))); -app.use('/test', express.static(path.join(root, 'test'))); -app.use('/node_modules', express.static(path.join(root, 'node_modules'))); - -app.get('/', function (req, res) { - glob('**/vs/{base,platform,editor}/**/test/{common,browser}/**/*.test.js', { - cwd: path.join(root, 'out'), - // ignore: ['**/test/{node,electron*}/**/*.js'] - }, function (err, files) { - if (err) { return res.sendStatus(500); } - - var modules = files - .map(function (file) { return file.replace(/\.js$/, ''); }); - - fs.readFile(path.join(__dirname, 'index.html'), 'utf8', function (err, templateString) { - if (err) { return res.sendStatus(500); } - - res.send(template(templateString, { - modules: JSON.stringify(modules) - })); - }); - }); -}); - -app.listen(port, function () { - console.log('http://localhost:8887/'); -}); \ No newline at end of file diff --git a/test/integration/browser/.gitignore b/test/integration/browser/.gitignore new file mode 100644 index 00000000000..e7d563c46ad --- /dev/null +++ b/test/integration/browser/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +npm-debug.log +Thumbs.db +node_modules/ +out/ diff --git a/test/integration/browser/README.md b/test/integration/browser/README.md new file mode 100644 index 00000000000..529130a7f7f --- /dev/null +++ b/test/integration/browser/README.md @@ -0,0 +1,13 @@ +# VS Code Integration test + +### Run + +```bash + +# Dev (Electron) +scripts/test-integration.sh + +# Dev (Web) +node test/integration/browser/out/index.js + +``` diff --git a/test/integration/browser/package.json b/test/integration/browser/package.json new file mode 100644 index 00000000000..ed4f447f681 --- /dev/null +++ b/test/integration/browser/package.json @@ -0,0 +1,17 @@ +{ + "name": "code-oss-dev-integration-test", + "version": "0.1.0", + "main": "./index.js", + "scripts": { + "postinstall": "npm run compile", + "compile": "yarn tsc" + }, + "devDependencies": { + "@types/mkdirp": "0.5.1", + "@types/node": "^12.11.7", + "@types/rimraf": "2.0.2", + "rimraf": "^2.6.1", + "tmp": "0.0.33", + "typescript": "3.7.5" + } +} diff --git a/test/integration/browser/index.js b/test/integration/browser/src/index.ts similarity index 62% rename from test/integration/browser/index.js rename to test/integration/browser/src/index.ts index 17508685fcb..11b1e49e73d 100644 --- a/test/integration/browser/index.js +++ b/test/integration/browser/src/index.ts @@ -3,23 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -//@ts-check +import * as path from 'path'; +import * as cp from 'child_process'; +import * as playwright from 'playwright'; +import * as url from 'url'; +import * as tmp from 'tmp'; +import * as rimraf from 'rimraf'; -const path = require('path'); -const cp = require('child_process'); -const playwright = require('playwright'); -const url = require('url'); - -// opts const optimist = require('optimist') .describe('debug', 'do not run browsers headless').boolean('debug') .describe('browser', 'browser in which integration tests should run').string('browser').default('browser', 'chromium') .describe('help', 'show the help').alias('help', 'h'); -// logic -const argv = optimist.argv; - -let serverProcess; +let serverProcess: cp.ChildProcess | undefined = undefined; function teardownServer() { if (serverProcess) { @@ -28,18 +24,17 @@ function teardownServer() { } } -/** - * @param {string} browserType - * @param {string} endpoint - */ -async function runTestsInBrowser(browserType, endpoint) { - const browser = await playwright[browserType].launch({ headless: !Boolean(argv.debug) }); +async function runTestsInBrowser(browserType: string, endpoint: string): Promise { + const browser = await playwright[browserType].launch({ headless: !Boolean(optimist.argv.debug) }); const page = (await browser.defaultContext().pages())[0]; - const integrationTestsPath = path.join(__dirname, '..', '..', '..', 'extensions', 'vscode-api-tests'); - const testWorkspaceUri = url.format({ pathname: path.join(integrationTestsPath, 'testWorkspace'), protocol: 'vscode-remote:', slashes: true, host: 'localhost:9888' }); - const testExtensionUri = url.format({ pathname: path.join(integrationTestsPath), protocol: 'vscode-remote:', slashes: true, host: 'localhost:9888' }); - const testFilesUri = url.format({ pathname: path.join(integrationTestsPath, 'out', 'singlefolder-tests'), protocol: 'vscode-remote:', slashes: true, host: 'localhost:9888' }); + const host = url.parse(endpoint).host; + const protocol = 'vscode-remote'; + + const integrationTestsPath = path.join(__dirname, '..', '..', '..', '..', 'extensions', 'vscode-api-tests'); + const testWorkspaceUri = url.format({ pathname: path.join(integrationTestsPath, 'testWorkspace'), protocol, host, slashes: true }); + const testExtensionUri = url.format({ pathname: path.join(integrationTestsPath), protocol, host, slashes: true }); + const testFilesUri = url.format({ pathname: path.join(integrationTestsPath, 'out', 'singlefolder-tests'), protocol, host, slashes: true }); const folderParam = testWorkspaceUri; const payloadParam = `[["extensionDevelopmentPath","${testExtensionUri}"],["extensionTestsPath","${testFilesUri}"]]`; @@ -51,7 +46,7 @@ async function runTestsInBrowser(browserType, endpoint) { // emitter.emit(type, data1, data2) // }); - page.on('console', async msg => { + page.on('console', async (msg: playwright.ConsoleMessage) => { const msgText = msg.text(); console[msg.type()](msgText, await Promise.all(msg.args().map(async arg => await arg.jsonValue()))); @@ -63,12 +58,15 @@ async function runTestsInBrowser(browserType, endpoint) { }); } -async function launch() { - // workspacePath = _workspacePath; - // const agentFolder = userDataDir; - // await promisify(mkdir)(agentFolder); +async function launchServer(): Promise { + const tmpDir = tmp.dirSync({ prefix: 't' }); + const testDataPath = tmpDir.name; + process.once('exit', () => rimraf.sync(testDataPath)); + + const userDataDir = path.join(testDataPath, 'd'); + const env = { - // VSCODE_AGENT_FOLDER: agentFolder, + VSCODE_AGENT_FOLDER: userDataDir, ...process.env }; @@ -76,7 +74,9 @@ async function launch() { if (process.env.VSCODE_REMOTE_SERVER_PATH) { serverLocation = path.join(process.env.VSCODE_REMOTE_SERVER_PATH, `server.${process.platform === 'win32' ? 'cmd' : 'sh'}`); } else { - serverLocation = path.join(__dirname, '..', '..', '..', `resources/server/web.${process.platform === 'win32' ? 'bat' : 'sh'}`); + serverLocation = path.join(__dirname, '..', '..', '..', '..', `resources/server/web.${process.platform === 'win32' ? 'bat' : 'sh'}`); + + process.env.VSCODE_DEV = '1'; } serverProcess = cp.spawn( @@ -85,15 +85,15 @@ async function launch() { { env } ); - serverProcess.stderr.on('data', e => console.log('Server stderr: ' + e)); - serverProcess.stdout.on('data', e => console.log('Server stdout: ' + e)); + serverProcess?.stderr?.on('data', e => console.log(`Server stderr: ${e}`)); + serverProcess?.stdout?.on('data', e => console.log(`Server stdout: ${e}`)); process.on('exit', teardownServer); process.on('SIGINT', teardownServer); process.on('SIGTERM', teardownServer); return new Promise(r => { - serverProcess.stdout.on('data', d => { + serverProcess?.stdout?.on('data', d => { const matches = d.toString('ascii').match(/Web UI available at (.+)/); if (matches !== null) { r(matches[1]); @@ -102,6 +102,6 @@ async function launch() { }); } -launch().then(async endpoint => { - return runTestsInBrowser(argv.browser, endpoint); +launchServer().then(async endpoint => { + return runTestsInBrowser(optimist.argv.browser, endpoint); }, console.error); diff --git a/test/integration/browser/tsconfig.json b/test/integration/browser/tsconfig.json new file mode 100644 index 00000000000..6f0b40e93e5 --- /dev/null +++ b/test/integration/browser/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "noImplicitAny": false, + "removeComments": false, + "preserveConstEnums": true, + "target": "es2017", + "strictNullChecks": true, + "noUnusedParameters": false, + "noUnusedLocals": true, + "outDir": "out", + "sourceMap": true, + "lib": [ + "es2016", + "dom" + ] + }, + "exclude": [ + "node_modules" + ] +} diff --git a/test/integration/browser/yarn.lock b/test/integration/browser/yarn.lock new file mode 100644 index 00000000000..059c3c8f3cf --- /dev/null +++ b/test/integration/browser/yarn.lock @@ -0,0 +1,143 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/glob@*": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/mkdirp@0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.1.tgz#ea887cd024f691c1ca67cce20b7606b053e43b0f" + integrity sha512-XA4vNO6GCBz8Smq0hqSRo4yRWMqr4FPQrWjhJt6nKskzly4/p87SfuJMFYGRyYb6jo2WNIQU2FDBsY5r1BibUA== + dependencies: + "@types/node" "*" + +"@types/node@*": + version "13.7.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.0.tgz#b417deda18cf8400f278733499ad5547ed1abec4" + integrity sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ== + +"@types/node@^12.11.7": + version "12.12.26" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.26.tgz#213e153babac0ed169d44a6d919501e68f59dea9" + integrity sha512-UmUm94/QZvU5xLcUlNR8hA7Ac+fGpO1EG/a8bcWVz0P0LqtxFmun9Y2bbtuckwGboWJIT70DoWq1r3hb56n3DA== + +"@types/rimraf@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" + integrity sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ== + dependencies: + "@types/glob" "*" + "@types/node" "*" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +rimraf@^2.6.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +typescript@3.7.5: + version "3.7.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" + integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= diff --git a/test/smoke/README.md b/test/smoke/README.md index 1060250f7fd..ddd05e7eb65 100644 --- a/test/smoke/README.md +++ b/test/smoke/README.md @@ -1,6 +1,6 @@ # VS Code Smoke Test -Make sure you are on **Node v10.x**. +Make sure you are on **Node v12.x**. ### Run diff --git a/test/unit/README.md b/test/unit/README.md index 96d866fe6ad..206f4baccf6 100644 --- a/test/unit/README.md +++ b/test/unit/README.md @@ -26,6 +26,10 @@ You can run tests inside a browser instance too: node test\unit\browser\index.js +## Run (with node) + + yarn run mocha --run src/vs/editor/test/browser/controller/cursor.test.ts + ## Debug To debug tests use `--debug` when running the test script. Also, the set of tests can be reduced with the `--run` and `--runGlob` flags. Both require a file path/pattern. Like so: diff --git a/test/assert.js b/test/unit/assert.js similarity index 100% rename from test/assert.js rename to test/unit/assert.js diff --git a/test/unit/browser/index.js b/test/unit/browser/index.js index 9464baee18e..64790c8245a 100644 --- a/test/unit/browser/index.js +++ b/test/unit/browser/index.js @@ -7,6 +7,7 @@ const path = require('path'); const glob = require('glob'); +const fs = require('fs'); const events = require('events'); const mocha = require('mocha'); const url = require('url'); @@ -17,7 +18,8 @@ const playwright = require('playwright'); const defaultReporterName = process.platform === 'win32' ? 'list' : 'spec'; const optimist = require('optimist') .describe('grep', 'only run tests matching ').alias('grep', 'g').alias('grep', 'f').string('grep') - .describe('run', 'only run tests matching ').alias('run', 'glob').string('runGlob') + .describe('run', 'only run tests matching ').string('run') + .describe('glob', 'only run tests matching ').string('glob') .describe('build', 'run with build output (out-build)').boolean('build') .describe('debug', 'do not run browsers headless').boolean('debug') .describe('browser', 'browsers in which tests should run').string('browser').default('browser', ['chromium']) @@ -59,35 +61,53 @@ const withReporter = (function () { const outdir = argv.build ? 'out-build' : 'out'; const out = path.join(__dirname, `../../../${outdir}`); +function ensureIsArray(a) { + return Array.isArray(a) ? a : [a]; +} + const testModules = (async function () { - const defaultGlob = '**/*.test.js'; const excludeGlob = '**/{node,electron-browser,electron-main}/**/*.test.js'; - const pattern = argv.glob || defaultGlob + let isDefaultModules = true; + let promise; - return new Promise((resolve, reject) => { - glob(pattern, { cwd: out }, (err, files) => { - if (err) { - reject(err); - return; - } + if (argv.run) { + // use file list (--run) + isDefaultModules = false; + promise = Promise.resolve(ensureIsArray(argv.run).map(file => { + file = file.replace(/^src/, 'out'); + file = file.replace(/\.ts$/, '.js'); + return path.relative(out, file); + })); - const modules = []; - const badFiles = []; + } else { + // glob patterns (--glob) + const defaultGlob = '**/*.test.js'; + const pattern = argv.glob || defaultGlob + isDefaultModules = argv.glob === defaultGlob; - for (let file of files) { - if (minimatch(file, excludeGlob)) { - badFiles.push(file); + promise = new Promise((resolve, reject) => { + glob(pattern, { cwd: out }, (err, files) => { + if (err) { + reject(err); } else { - modules.push(file.replace(/\.js$/, '')); + resolve(files) } - } - - if (badFiles.length > 0 && pattern !== defaultGlob) { - console.warn(`DROPPED ${badFiles.length} files because '${pattern}' includes files from invalid layers.${badFiles.map(file => `\n\t-${file}`)}`); - } - resolve(modules); + }); }); + } + + return promise.then(files => { + const modules = []; + for (let file of files) { + if (!minimatch(file, excludeGlob)) { + modules.push(file.replace(/\.js$/, '')); + + } else if (!isDefaultModules) { + console.warn(`DROPPONG ${file} because it cannot be run inside a browser`); + } + } + return modules; }) })(); diff --git a/test/unit/browser/renderer.html b/test/unit/browser/renderer.html index 52a512f26b0..2f46b408f41 100644 --- a/test/unit/browser/renderer.html +++ b/test/unit/browser/renderer.html @@ -46,7 +46,7 @@ baseUrl: new URL('../../../src', baseUrl).href, paths: { 'vs': new URL('../../../out/vs', baseUrl).href, - assert: new URL('../../assert.js', baseUrl).href, + assert: new URL('../assert.js', baseUrl).href, sinon: new URL('../../../node_modules/sinon/pkg/sinon-1.17.7.js', baseUrl).href } }); diff --git a/test/coverage.js b/test/unit/coverage.js similarity index 94% rename from test/coverage.js rename to test/unit/coverage.js index e01452047f5..e93f84c8c4f 100644 --- a/test/coverage.js +++ b/test/unit/coverage.js @@ -12,7 +12,7 @@ const iLibSourceMaps = require('istanbul-lib-source-maps'); const iLibReport = require('istanbul-lib-report'); const iReports = require('istanbul-reports'); -const REPO_PATH = toUpperDriveLetter(path.join(__dirname, '..')); +const REPO_PATH = toUpperDriveLetter(path.join(__dirname, '../../')); exports.initialize = function (loaderConfig) { const instrumenter = iLibInstrument.createInstrumenter(); @@ -47,7 +47,7 @@ exports.createReport = function (isSingle) { transformed.data = newData; const context = iLibReport.createContext({ - dir: path.join(__dirname, `../.build/coverage${isSingle ? '-single' : ''}`), + dir: path.join(REPO_PATH, `.build/coverage${isSingle ? '-single' : ''}`), coverageMap: transformed }); const tree = context.getTree('flat'); diff --git a/test/unit/electron/renderer.js b/test/unit/electron/renderer.js index 12c86ad8221..734c0837841 100644 --- a/test/unit/electron/renderer.js +++ b/test/unit/electron/renderer.js @@ -11,7 +11,7 @@ const path = require('path'); const glob = require('glob'); const util = require('util'); const bootstrap = require('../../../src/bootstrap'); -const coverage = require('../../coverage'); +const coverage = require('../coverage'); // Disabled custom inspect. See #38847 if (util.inspect && util.inspect['defaultOptions']) { diff --git a/test/unit/node/all.js b/test/unit/node/all.js index 6f1fb97a875..a1421c5c72c 100644 --- a/test/unit/node/all.js +++ b/test/unit/node/all.js @@ -11,7 +11,7 @@ const path = require('path'); const glob = require('glob'); const jsdom = require('jsdom-no-contextify'); const TEST_GLOB = '**/test/**/*.test.js'; -const coverage = require('../../coverage'); +const coverage = require('../coverage'); const optimist = require('optimist') .usage('Run the Code tests. All mocha options apply.') @@ -44,7 +44,7 @@ function main() { nodeMain: __filename, baseUrl: path.join(REPO_ROOT, 'src'), paths: { - 'vs/css': '../test/css.mock', + 'vs/css': '../test/unit/node/css.mock', 'vs': `../${out}/vs`, 'lib': `../${out}/lib`, 'bootstrap-fork': `../${out}/bootstrap-fork` @@ -166,7 +166,7 @@ function main() { } if (process.argv.some(function (a) { return /^--browser/.test(a); })) { - require('../../browser'); + require('./browser'); } else { main(); } diff --git a/test/unit/node/browser.js b/test/unit/node/browser.js new file mode 100644 index 00000000000..a564b7672e2 --- /dev/null +++ b/test/unit/node/browser.js @@ -0,0 +1,49 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const yaserver = require('yaserver'); +const http = require('http'); +const glob = require('glob'); +const path = require('path'); +const fs = require('fs'); + +const REPO_ROOT = path.join(__dirname, '../../../'); +const PORT = 8887; + +function template(str, env) { + return str.replace(/{{\s*([\w_\-]+)\s*}}/g, function (all, part) { + return env[part]; + }); +} + +yaserver.createServer({ rootDir: REPO_ROOT }).then((staticServer) => { + const server = http.createServer((req, res) => { + if (req.url === '' || req.url === '/') { + glob('**/vs/{base,platform,editor}/**/test/{common,browser}/**/*.test.js', { + cwd: path.join(REPO_ROOT, 'out'), + // ignore: ['**/test/{node,electron*}/**/*.js'] + }, function (err, files) { + if (err) { console.log(err); process.exit(0); } + + var modules = files + .map(function (file) { return file.replace(/\.js$/, ''); }); + + fs.readFile(path.join(__dirname, 'index.html'), 'utf8', function (err, templateString) { + if (err) { console.log(err); process.exit(0); } + + res.end(template(templateString, { + modules: JSON.stringify(modules) + })); + }); + }); + } else { + return staticServer.handle(req, res); + } + }); + + server.listen(PORT, () => { + console.log(`http://localhost:${PORT}/`); + }); +}); diff --git a/test/css.mock.js b/test/unit/node/css.mock.js similarity index 100% rename from test/css.mock.js rename to test/unit/node/css.mock.js diff --git a/test/index.html b/test/unit/node/index.html similarity index 92% rename from test/index.html rename to test/unit/node/index.html index 384c987fed1..55f9bb0f708 100644 --- a/test/index.html +++ b/test/unit/node/index.html @@ -16,7 +16,7 @@ require.config({ baseUrl: '/out', paths: { - assert: '/test/assert.js', + assert: '/test/unit/assert.js', sinon: '/node_modules/sinon/pkg/sinon-1.17.7.js' } }); @@ -26,4 +26,4 @@ }); - \ No newline at end of file + diff --git a/yarn.lock b/yarn.lock index 496cddcf29b..46a44ea74a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -556,14 +556,6 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" - integrity sha1-hiRnWMfdbSGmR0/whKR0DsBesh8= - dependencies: - mime-types "~2.1.16" - negotiator "0.6.1" - acorn-dynamic-import@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278" @@ -907,11 +899,6 @@ array-each@^1.0.0, array-each@^1.0.1: resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - array-initial@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" @@ -1256,22 +1243,6 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== -body-parser@1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" - integrity sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ= - dependencies: - bytes "3.0.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.1" - http-errors "~1.6.2" - iconv-lite "0.4.19" - on-finished "~2.3.0" - qs "6.5.1" - raw-body "2.3.2" - type-is "~1.6.15" - boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -1487,11 +1458,6 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - cacache@^10.0.4: version "10.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" @@ -2056,16 +2022,6 @@ constants-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - continuation-local-storage@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz#11f613f74e914fe9b34c92ad2d28fe6ae1db7ffb" @@ -2093,16 +2049,6 @@ convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= - copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -2524,11 +2470,6 @@ denodeify@^1.2.1: resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" integrity sha1-OjYof1A05pnnV3kBBSwubJQlFjE= -depd@1.1.1, depd@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" - integrity sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k= - des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" @@ -2537,11 +2478,6 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" @@ -2730,11 +2666,6 @@ editorconfig@^0.15.2: semver "^5.6.0" sigmund "^1.0.1" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - electron-to-chromium@^1.2.7: version "1.3.27" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz#78ecb8a399066187bb374eede35d9c70565a803d" @@ -2789,11 +2720,6 @@ encodeurl@^1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -encodeurl@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" - integrity sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA= - end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" @@ -2886,11 +2812,6 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.1" es6-symbol "^3.1.1" -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - escape-string-regexp@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" @@ -3096,11 +3017,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - event-stream@3.3.4, event-stream@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" @@ -3192,42 +3108,6 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -express@^4.13.1: - version "4.16.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" - integrity sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w= - dependencies: - accepts "~1.3.4" - array-flatten "1.1.1" - body-parser "1.18.2" - content-disposition "0.5.2" - content-type "~1.0.4" - cookie "0.3.1" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.1" - encodeurl "~1.0.1" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.1.0" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.2" - path-to-regexp "0.1.7" - proxy-addr "~2.0.2" - qs "6.5.1" - range-parser "~1.2.0" - safe-buffer "5.1.1" - send "0.16.1" - serve-static "1.13.1" - setprototypeof "1.1.0" - statuses "~1.3.1" - type-is "~1.6.15" - utils-merge "1.0.1" - vary "~1.1.2" - extend-shallow@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" @@ -3430,19 +3310,6 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" - integrity sha1-zgtoVbRYU+eRsvzGgARtiCU91/U= - dependencies: - debug "2.6.9" - encodeurl "~1.0.1" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.3.1" - unpipe "~1.0.0" - find-cache-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" @@ -3620,11 +3487,6 @@ formatio@1.1.1: dependencies: samsam "~1.1" -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -3632,11 +3494,6 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" @@ -4583,16 +4440,6 @@ http-cache-semantics@^4.0.0: resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== -http-errors@1.6.2, http-errors@~1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - integrity sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY= - dependencies: - depd "1.1.1" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" - http-proxy-agent@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" @@ -4650,11 +4497,6 @@ husky@^0.13.1: is-ci "^1.0.9" normalize-path "^1.0.0" -iconv-lite@0.4.19, iconv-lite@^0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" - integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ== - iconv-lite@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.0.tgz#59cdde0a2a297cc2aeb0c6445a195ee89f127550" @@ -4662,6 +4504,11 @@ iconv-lite@0.5.0: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ== + iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -4830,11 +4677,6 @@ ip@^1.1.5: resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= -ipaddr.js@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0" - integrity sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A= - is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" @@ -5925,11 +5767,6 @@ mdurl@^1.0.1: resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - mem@^4.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" @@ -5947,11 +5784,6 @@ memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: errno "^0.1.3" readable-stream "^2.0.1" -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - merge-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32" @@ -5966,11 +5798,6 @@ merge-stream@^1.0.0: dependencies: readable-stream "^2.0.1" -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - micromatch@^2.3.7: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -6027,7 +5854,7 @@ mime-db@~1.36.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw== -mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo= @@ -6041,7 +5868,7 @@ mime-types@~2.1.19: dependencies: mime-db "~1.36.0" -mime@1.4.1, mime@^1.3.4: +mime@^1.3.4: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== @@ -6321,11 +6148,6 @@ needle@^2.2.1: iconv-lite "^0.4.4" sax "^1.2.4" -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= - neo-async@^2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.1.tgz#acb909e327b1e87ec9ef15f41b8a269512ad41ee" @@ -6651,13 +6473,6 @@ object.reduce@^1.0.0: for-own "^1.0.0" make-iterator "^1.0.0" -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -6963,11 +6778,6 @@ parse5@^3.0.1: dependencies: "@types/node" "*" -parseurl@~1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= - pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -7032,11 +6842,6 @@ path-root@^0.1.1: dependencies: path-root-regex "^0.1.0" -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -7516,14 +7321,6 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= -proxy-addr@~2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec" - integrity sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew= - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.5.2" - proxy-from-env@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" @@ -7616,16 +7413,16 @@ q@^1.0.1, q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qs@6.5.1, qs@~6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== - qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" integrity sha1-51vV9uJoEioqDgvaYwslUMFmUCw= +qs@~6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== + qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -7693,21 +7490,6 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -range-parser@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= - -raw-body@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" - integrity sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k= - dependencies: - bytes "3.0.0" - http-errors "1.6.2" - iconv-lite "0.4.19" - unpipe "1.0.0" - rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -8223,7 +8005,7 @@ rxjs@^6.5.3: dependencies: tslib "^1.9.0" -safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== @@ -8327,25 +8109,6 @@ semver@^6.1.2, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -send@0.16.1: - version "0.16.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" - integrity sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A== - dependencies: - debug "2.6.9" - depd "~1.1.1" - destroy "~1.0.4" - encodeurl "~1.0.1" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.3.1" - serialize-error@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-5.0.0.tgz#a7ebbcdb03a5d71a6ed8461ffe0fc1a1afed62ac" @@ -8358,16 +8121,6 @@ serialize-javascript@^1.4.0: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.5.0.tgz#1aa336162c88a890ddad5384baebc93a655161fe" integrity sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ== -serve-static@1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" - integrity sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ== - dependencies: - encodeurl "~1.0.1" - escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.1" - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -8403,16 +8156,6 @@ setimmediate@^1.0.4: resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= -setprototypeof@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" - integrity sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" @@ -8716,16 +8459,6 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.3.1 < 2": - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== - -statuses@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - integrity sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4= - stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" @@ -9350,14 +9083,6 @@ type-fest@^0.8.0, type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.15: - version "1.6.15" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" - integrity sha1-yrEPtJCeRByChC6v4a1kbIGARBA= - dependencies: - media-typer "0.3.0" - mime-types "~2.1.15" - typed-rest-client@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/typed-rest-client/-/typed-rest-client-0.9.0.tgz#f768cc0dc3f4e950f06e04825c36b3e7834aa1f2" @@ -9505,11 +9230,6 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -9584,11 +9304,6 @@ util@^0.10.3: dependencies: inherits "2.0.3" -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - uuid@^3.0.0, uuid@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" @@ -9651,11 +9366,6 @@ value-or-function@^3.0.0: resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - vendors@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22" @@ -10274,6 +9984,11 @@ yargs@^7.1.0: y18n "^3.2.1" yargs-parser "^5.0.0" +yaserver@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/yaserver/-/yaserver-0.2.0.tgz#56393027dc13f3c1bb89d20e0bd17269aa927802" + integrity sha512-onsELrl7Y42M4P3T9R0N/ZJNJRu4cGwzhDyOWIFRMJvPUIrGKInYGh+DJBefrbr1qoyDu7DSCLl9BL5hSSVfDA== + yauzl@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005"