Merge branch 'master' into joh/continous-browser-tests

This commit is contained in:
Johannes Rieken 2020-02-07 14:48:21 +01:00 committed by GitHub
commit 37ef5e45af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 604 additions and 556 deletions

View file

@ -614,6 +614,13 @@
"*"
]
},
{
"target": "**/test/integration/**",
"restrictions": [
"**/test/integration/**",
"*"
]
},
{
"target": "{**/api/**.test.ts,}",
"restrictions": "{**/vs/**,assert,sinon,crypto,vscode}"

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

View file

@ -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

View file

@ -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 \

View file

@ -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',

View file

@ -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

View file

@ -69,17 +69,16 @@ suite('Debug', function () {
})
}));
const capabilitiesPromise = new Promise<void>(resolve => capabilitiesReceived = resolve);
const initializedPromise = new Promise<void>(resolve => initializedReceived = resolve);
const configurationDonePromise = new Promise<void>(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);

View file

@ -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",

View file

@ -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');

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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)) {

View file

@ -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');
}

View file

@ -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,
]);
});

View file

@ -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<ILastSyncUserData>({ ...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);

View file

@ -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');
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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<void> {
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 */

View file

@ -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, <UserDataSyncErrorCode>match[1], <SyncSource>match[2]);
}
return new UserDataSyncError(error.message, UserDataSyncErrorCode.Unknown);
}
}
@ -222,7 +235,7 @@ export interface IUserDataSyncService extends ISynchroniser {
export const IUserDataAutoSyncService = createDecorator<IUserDataAutoSyncService>('IUserDataAutoSyncService');
export interface IUserDataAutoSyncService {
_serviceBrand: any;
onError: Event<{ code: UserDataSyncErrorCode, source?: SyncSource }>;
readonly onError: Event<{ code: UserDataSyncErrorCode, source?: SyncSource }>;
triggerAutoSync(): Promise<void>;
}

View file

@ -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;

View file

@ -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<void>;
/**
* Fired when the list of tunnels has changed.
*/
export const onDidChangeTunnels: Event<void>;
}
export interface ResourceLabelFormatter {

View file

@ -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) => {

View file

@ -33,7 +33,7 @@ export interface IExtHostTunnelService extends ExtHostTunnelServiceShape {
readonly _serviceBrand: undefined;
openTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined>;
getTunnels(): Promise<vscode.TunnelDescription[]>;
onDidTunnelsChange: vscode.Event<void>;
onDidChangeTunnels: vscode.Event<void>;
setTunnelExtensionFunctions(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable>;
}
@ -41,7 +41,7 @@ export const IExtHostTunnelService = createDecorator<IExtHostTunnelService>('IEx
export class ExtHostTunnelService implements IExtHostTunnelService {
_serviceBrand: undefined;
onDidTunnelsChange: vscode.Event<void> = (new Emitter<void>()).event;
onDidChangeTunnels: vscode.Event<void> = (new Emitter<void>()).event;
async openTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
return undefined;

View file

@ -39,8 +39,8 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
private _forwardPortProvider: ((tunnelOptions: TunnelOptions) => Thenable<vscode.Tunnel> | undefined) | undefined;
private _showCandidatePort: (host: string, port: number, detail: string) => Thenable<boolean> = () => { return Promise.resolve(true); };
private _extensionTunnels: Map<string, Map<number, vscode.Tunnel>> = new Map();
private _onDidTunnelsChange: Emitter<void> = new Emitter<void>();
onDidTunnelsChange: vscode.Event<void> = this._onDidTunnelsChange.event;
private _onDidChangeTunnels: Emitter<void> = new Emitter<void>();
onDidChangeTunnels: vscode.Event<void> = this._onDidChangeTunnels.event;
constructor(
@IExtHostRpcService extHostRpc: IExtHostRpcService,
@ -107,7 +107,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
}
async $onDidTunnelsChange(): Promise<void> {
this._onDidTunnelsChange.fire();
this._onDidChangeTunnels.fire();
}
$forwardPort(tunnelOptions: TunnelOptions): Promise<TunnelDto> | undefined {

View file

@ -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

View file

@ -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 {

View file

@ -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<void> {
return this.configurationService.updateValue(UserDataSyncWorkbenchContribution.ENABLEMENT_SETTING, undefined, ConfigurationTarget.USER);
private disableSync(source?: SyncSource): Promise<void> {
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<void> {
@ -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);
}
}
}
}

View file

@ -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)) {

View file

@ -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 {

View file

@ -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;

View file

@ -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<T>(command: string, arg?: any, cancellationToken?: CancellationToken): Promise<T> {
return userDataSyncChannel.call(command, arg, cancellationToken)
.then(null, error => { throw UserDataSyncError.toUserDataSyncError(error); });
},
listen<T>(event: string, arg?: any): Event<T> {
return userDataSyncChannel.listen(event, arg);
}
};
this.channel.call<SyncStatus>('_getInitialStatus').then(status => {
this.updateStatus(status);
this._register(this.channel.listen<SyncStatus>('onDidChangeStatus')(status => this.updateStatus(status)));

View file

@ -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/');
});

5
test/integration/browser/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
.DS_Store
npm-debug.log
Thumbs.db
node_modules/
out/

View file

@ -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
```

View file

@ -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"
}
}

View file

@ -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<void> {
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<string> {
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);

View file

@ -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"
]
}

View file

@ -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=

View file

@ -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

View file

@ -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:

View file

@ -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 <pattern>').alias('grep', 'g').alias('grep', 'f').string('grep')
.describe('run', 'only run tests matching <file_pattern>').alias('run', 'glob').string('runGlob')
.describe('run', 'only run tests matching <relative_file_path>').string('run')
.describe('glob', 'only run tests matching <glob_pattern>').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;
})
})();

View file

@ -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
}
});

View file

@ -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');

View file

@ -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']) {

View file

@ -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();
}

49
test/unit/node/browser.js Normal file
View file

@ -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}/`);
});
});

View file

@ -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 @@
});
</script>
</body>
</html>
</html>

321
yarn.lock
View file

@ -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"