Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -42,8 +42,6 @@ function select(builder: Builder, selector: string, offdom?: boolean): MultiBuil
}
suite('Builder', () => {
test('Binding', function () {
});
});

View File

@@ -11,4 +11,32 @@ const $ = dom.$;
suite('dom', () => {
test('hasClass', () => {
});
suite('$', () => {
test('should build simple nodes', () => {
const div = $('div');
assert(div);
assert(div instanceof HTMLElement);
assert.equal(div.tagName, 'DIV');
assert(!div.firstChild);
});
test('should build nodes with attributes', () => {
let div = $('div', { class: 'test' });
assert.equal(div.className, 'test');
div = $('div', null);
assert.equal(div.className, '');
});
test('should build nodes with children', () => {
let div = $('div', null, $('span', { id: 'demospan' }));
let firstChild = div.firstChild as HTMLElement;
assert.equal(firstChild.tagName, 'SPAN');
assert.equal(firstChild.id, 'demospan');
div = $('div', null, 'hello');
assert.equal(div.firstChild.textContent, 'hello');
});
});
});

View File

@@ -52,9 +52,12 @@ suite('HtmlContent', () => {
test('action', () => {
var callbackCalled = false;
var result: HTMLElement = renderFormattedText('[[action]]', {
actionCallback(content) {
assert.strictEqual(content, '0');
callbackCalled = true;
actionHandler: {
callback(content) {
assert.strictEqual(content, '0');
callbackCalled = true;
},
disposeables: []
}
});
assert.strictEqual(result.innerHTML, '<a href="#">action</a>');
@@ -68,9 +71,12 @@ suite('HtmlContent', () => {
test('fancy action', () => {
var callbackCalled = false;
var result: HTMLElement = renderFormattedText('__**[[action]]**__', {
actionCallback(content) {
assert.strictEqual(content, '0');
callbackCalled = true;
actionHandler: {
callback(content) {
assert.strictEqual(content, '0');
callbackCalled = true;
},
disposeables: []
}
});
assert.strictEqual(result.innerHTML, '<i><b><a href="#">action</a></b></i>');

View File

@@ -63,232 +63,6 @@ function getSashes(splitview: SplitView): Sash[] {
}
suite('Splitview', () => {
let container: HTMLElement;
setup(() => {
container = document.createElement('div');
container.style.position = 'absolute';
container.style.width = `${200}px`;
container.style.height = `${200}px`;
});
teardown(() => {
container = null;
});
test('empty splitview has empty DOM', () => {
});
test('calls view methods on addView and removeView', () => {
const view = new TestView(20, 20);
const splitview = new SplitView(container);
let didLayout = false;
const layoutDisposable = view.onDidLayout(() => didLayout = true);
let didRender = false;
const renderDisposable = view.onDidRender(() => didRender = true);
splitview.addView(view, 20);
assert.equal(view.size, 20, 'view has right size');
assert(didLayout, 'layout is called');
assert(didLayout, 'render is called');
splitview.dispose();
layoutDisposable.dispose();
renderDisposable.dispose();
view.dispose();
});
test('stretches view to viewport', () => {
const view = new TestView(20, Number.POSITIVE_INFINITY);
const splitview = new SplitView(container);
splitview.layout(200);
splitview.addView(view, 20);
assert.equal(view.size, 200, 'view is stretched');
splitview.layout(200);
assert.equal(view.size, 200, 'view stayed the same');
splitview.layout(100);
assert.equal(view.size, 100, 'view is collapsed');
splitview.layout(20);
assert.equal(view.size, 20, 'view is collapsed');
splitview.layout(10);
assert.equal(view.size, 20, 'view is clamped');
splitview.layout(200);
assert.equal(view.size, 200, 'view is stretched');
splitview.dispose();
view.dispose();
});
test('can resize views', () => {
const view1 = new TestView(20, Number.POSITIVE_INFINITY);
const view2 = new TestView(20, Number.POSITIVE_INFINITY);
const view3 = new TestView(20, Number.POSITIVE_INFINITY);
const splitview = new SplitView(container);
splitview.layout(200);
splitview.addView(view1, 20);
splitview.addView(view2, 20);
splitview.addView(view3, 20);
assert.equal(view1.size, 160, 'view1 is stretched');
assert.equal(view2.size, 20, 'view2 size is 20');
assert.equal(view3.size, 20, 'view3 size is 20');
splitview.resizeView(1, 40);
assert.equal(view1.size, 140, 'view1 is collapsed');
assert.equal(view2.size, 40, 'view2 is stretched');
assert.equal(view3.size, 20, 'view3 stays the same');
splitview.resizeView(0, 70);
assert.equal(view1.size, 70, 'view1 is collapsed');
assert.equal(view2.size, 110, 'view2 is expanded');
assert.equal(view3.size, 20, 'view3 stays the same');
splitview.resizeView(2, 40);
assert.equal(view1.size, 70, 'view1 stays the same');
assert.equal(view2.size, 90, 'view2 is collapsed');
assert.equal(view3.size, 40, 'view3 is stretched');
splitview.dispose();
view3.dispose();
view2.dispose();
view1.dispose();
});
test('reacts to view changes', () => {
const view1 = new TestView(20, Number.POSITIVE_INFINITY);
const view2 = new TestView(20, Number.POSITIVE_INFINITY);
const view3 = new TestView(20, Number.POSITIVE_INFINITY);
const splitview = new SplitView(container);
splitview.layout(200);
splitview.addView(view1, 20);
splitview.addView(view2, 20);
splitview.addView(view3, 20);
assert.equal(view1.size, 160, 'view1 is stretched');
assert.equal(view2.size, 20, 'view2 size is 20');
assert.equal(view3.size, 20, 'view3 size is 20');
view1.maximumSize = 20;
assert.equal(view1.size, 20, 'view1 is collapsed');
assert.equal(view2.size, 20, 'view2 stays the same');
assert.equal(view3.size, 160, 'view3 is stretched');
view3.maximumSize = 40;
assert.equal(view1.size, 20, 'view1 stays the same');
assert.equal(view2.size, 140, 'view2 is stretched');
assert.equal(view3.size, 40, 'view3 is collapsed');
view2.maximumSize = 200;
assert.equal(view1.size, 20, 'view1 stays the same');
assert.equal(view2.size, 140, 'view2 stays the same');
assert.equal(view3.size, 40, 'view3 stays the same');
view3.maximumSize = Number.POSITIVE_INFINITY;
view3.minimumSize = 100;
assert.equal(view1.size, 20, 'view1 is collapsed');
assert.equal(view2.size, 80, 'view2 is collapsed');
assert.equal(view3.size, 100, 'view3 is stretched');
splitview.dispose();
view3.dispose();
view2.dispose();
view1.dispose();
});
test('sashes are properly enabled/disabled', () => {
const view1 = new TestView(20, Number.POSITIVE_INFINITY);
const view2 = new TestView(20, Number.POSITIVE_INFINITY);
const view3 = new TestView(20, Number.POSITIVE_INFINITY);
const splitview = new SplitView(container);
splitview.layout(200);
splitview.addView(view1, 20);
splitview.addView(view2, 20);
splitview.addView(view3, 20);
let sashes = getSashes(splitview);
assert.equal(sashes.length, 2, 'there are two sashes');
assert.equal(sashes[0].enabled, true, 'first sash is enabled');
assert.equal(sashes[1].enabled, true, 'second sash is enabled');
splitview.layout(60);
assert.equal(sashes[0].enabled, false, 'first sash is disabled');
assert.equal(sashes[1].enabled, false, 'second sash is disabled');
splitview.layout(20);
assert.equal(sashes[0].enabled, false, 'first sash is disabled');
assert.equal(sashes[1].enabled, false, 'second sash is disabled');
splitview.layout(200);
assert.equal(sashes[0].enabled, true, 'first sash is enabled');
assert.equal(sashes[1].enabled, true, 'second sash is enabled');
view1.maximumSize = 20;
assert.equal(sashes[0].enabled, false, 'first sash is disabled');
assert.equal(sashes[1].enabled, true, 'second sash is enabled');
view2.maximumSize = 20;
assert.equal(sashes[0].enabled, false, 'first sash is disabled');
assert.equal(sashes[1].enabled, false, 'second sash is disabled');
view1.maximumSize = 300;
assert.equal(sashes[0].enabled, true, 'first sash is enabled');
assert.equal(sashes[1].enabled, true, 'second sash is enabled');
view2.maximumSize = 200;
assert.equal(sashes[0].enabled, true, 'first sash is enabled');
assert.equal(sashes[1].enabled, true, 'second sash is enabled');
splitview.dispose();
view3.dispose();
view2.dispose();
view1.dispose();
});
test('issue #35497', () => {
const view1 = new TestView(160, Number.POSITIVE_INFINITY);
const view2 = new TestView(66, 66);
const splitview = new SplitView(container);
splitview.layout(986);
splitview.addView(view1, 142, 0);
assert.equal(view1.size, 986, 'first view is stretched');
view2.onDidRender(() => {
assert.throws(() => splitview.resizeView(1, 922));
assert.throws(() => splitview.resizeView(1, 922));
});
splitview.addView(view2, 66, 0);
assert.equal(view2.size, 66, 'second view is fixed');
assert.equal(view1.size, 986 - 66, 'first view is collapsed');
const viewContainers = container.querySelectorAll('.split-view-view');
assert.equal(viewContainers.length, 2, 'there are two view containers');
assert.equal((viewContainers.item(0) as HTMLElement).style.height, '66px', 'second view container is 66px');
assert.equal((viewContainers.item(1) as HTMLElement).style.height, `${986 - 66}px`, 'first view container is 66px');
splitview.dispose();
view2.dispose();
view1.dispose();
});
});

View File

@@ -7,6 +7,7 @@
import * as assert from 'assert';
import { TPromise } from 'vs/base/common/winjs.base';
import arrays = require('vs/base/common/arrays');
import { coalesce } from 'vs/base/common/arrays';
suite('Arrays', () => {
test('findFirst', function () {
@@ -269,5 +270,41 @@ suite('Arrays', () => {
});
});
}
test('coalesce', function () {
let a = coalesce([null, 1, null, 2, 3]);
assert.equal(a.length, 3);
assert.equal(a[0], 1);
assert.equal(a[1], 2);
assert.equal(a[2], 3);
coalesce([null, 1, null, void 0, undefined, 2, 3]);
assert.equal(a.length, 3);
assert.equal(a[0], 1);
assert.equal(a[1], 2);
assert.equal(a[2], 3);
let b = [];
b[10] = 1;
b[20] = 2;
b[30] = 3;
b = coalesce(b);
assert.equal(b.length, 3);
assert.equal(b[0], 1);
assert.equal(b[1], 2);
assert.equal(b[2], 3);
let sparse = [];
sparse[0] = 1;
sparse[1] = 1;
sparse[17] = 1;
sparse[1000] = 1;
sparse[1001] = 1;
assert.equal(sparse.length, 1002);
sparse = coalesce(sparse);
assert.equal(sparse.length, 5);
});
});

View File

@@ -7,7 +7,6 @@
import * as assert from 'assert';
import { LcsDiff, IDiffChange } from 'vs/base/common/diff/diff';
import { LcsDiff2 } from 'vs/base/common/diff/diff2';
class StringDiffSequence {
@@ -116,11 +115,6 @@ suite('Diff', () => {
this.timeout(10000);
lcsTests(LcsDiff);
});
test('LcsDiff2 - different strings tests', function () {
this.timeout(10000);
lcsTests(LcsDiff2);
});
});
suite('Diff - Ported from VS', () => {

View File

@@ -393,11 +393,11 @@ suite('Filters', () => {
// issue #17836
// assertTopScore(fuzzyScore, 'TEdit', 1, 'TextEditorDecorationType', 'TextEdit', 'TextEditor');
assertTopScore(fuzzyScore, 'p', 0, 'parse', 'posix', 'pafdsa', 'path', 'p');
assertTopScore(fuzzyScore, 'p', 4, 'parse', 'posix', 'pafdsa', 'path', 'p');
assertTopScore(fuzzyScore, 'pa', 0, 'parse', 'pafdsa', 'path');
// issue #14583
assertTopScore(fuzzyScore, 'log', 3, 'HTMLOptGroupElement', 'ScrollLogicalPosition', 'SVGFEMorphologyElement', 'log');
assertTopScore(fuzzyScore, 'log', 3, 'HTMLOptGroupElement', 'ScrollLogicalPosition', 'SVGFEMorphologyElement', 'log', 'logger');
assertTopScore(fuzzyScore, 'e', 2, 'AbstractWorker', 'ActiveXObject', 'else');
// issue #14446
@@ -415,6 +415,8 @@ suite('Filters', () => {
assertTopScore(fuzzyScore, 'is', 0, 'isValidViewletId', 'import statement');
assertTopScore(fuzzyScore, 'title', 1, 'files.trimTrailingWhitespace', 'window.title');
assertTopScore(fuzzyScore, 'const', 1, 'constructor', 'const', 'cuOnstrul');
});
test('Unexpected suggestion scoring, #28791', function () {

View File

@@ -83,11 +83,11 @@ suite('History Navigator', () => {
});
test('adding existing element changes the position', function () {
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 2);
let testObject = new HistoryNavigator(['1', '2', '3', '4'], 5);
testObject.add('2');
assert.deepEqual(['4', '2'], toArray(testObject));
assert.deepEqual(['1', '3', '4', '2'], toArray(testObject));
});
test('add resets the navigator to last', function () {

View File

@@ -0,0 +1,63 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { IMatch } from 'vs/base/common/filters';
import { matchesFuzzyOcticonAware, parseOcticons } from 'vs/base/common/octicon';
export interface IOcticonFilter {
// Returns null if word doesn't match.
(query: string, target: { text: string, octiconOffsets?: number[] }): IMatch[];
}
function filterOk(filter: IOcticonFilter, word: string, target: { text: string, octiconOffsets?: number[] }, highlights?: { start: number; end: number; }[]) {
let r = filter(word, target);
assert(r);
if (highlights) {
assert.deepEqual(r, highlights);
}
}
suite('Octicon', () => {
test('matchesFuzzzyOcticonAware', function () {
// Camel Case
filterOk(matchesFuzzyOcticonAware, 'ccr', parseOcticons('$(octicon)CamelCaseRocks$(octicon)'), [
{ start: 10, end: 11 },
{ start: 15, end: 16 },
{ start: 19, end: 20 }
]);
filterOk(matchesFuzzyOcticonAware, 'ccr', parseOcticons('$(octicon) CamelCaseRocks $(octicon)'), [
{ start: 11, end: 12 },
{ start: 16, end: 17 },
{ start: 20, end: 21 }
]);
filterOk(matchesFuzzyOcticonAware, 'iut', parseOcticons('$(octicon) Indent $(octico) Using $(octic) Tpaces'), [
{ start: 11, end: 12 },
{ start: 28, end: 29 },
{ start: 43, end: 44 },
]);
// Prefix
filterOk(matchesFuzzyOcticonAware, 'using', parseOcticons('$(octicon) Indent Using Spaces'), [
{ start: 18, end: 23 },
]);
// Broken Octicon
filterOk(matchesFuzzyOcticonAware, 'octicon', parseOcticons('This $(octicon Indent Using Spaces'), [
{ start: 7, end: 14 },
]);
filterOk(matchesFuzzyOcticonAware, 'indent', parseOcticons('This $octicon Indent Using Spaces'), [
{ start: 14, end: 20 },
]);
});
});

View File

@@ -0,0 +1,54 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import URI from 'vs/base/common/uri';
import { distinctParents, dirname } from 'vs/base/common/resources';
import { normalize } from 'vs/base/common/paths';
suite('Resources', () => {
test('distinctParents', () => {
// Basic
let resources = [
URI.file('/some/folderA/file.txt'),
URI.file('/some/folderB/file.txt'),
URI.file('/some/folderC/file.txt')
];
let distinct = distinctParents(resources, r => r);
assert.equal(distinct.length, 3);
assert.equal(distinct[0].toString(), resources[0].toString());
assert.equal(distinct[1].toString(), resources[1].toString());
assert.equal(distinct[2].toString(), resources[2].toString());
// Parent / Child
resources = [
URI.file('/some/folderA'),
URI.file('/some/folderA/file.txt'),
URI.file('/some/folderA/child/file.txt'),
URI.file('/some/folderA2/file.txt'),
URI.file('/some/file.txt')
];
distinct = distinctParents(resources, r => r);
assert.equal(distinct.length, 3);
assert.equal(distinct[0].toString(), resources[0].toString());
assert.equal(distinct[1].toString(), resources[3].toString());
assert.equal(distinct[2].toString(), resources[4].toString());
});
test('dirname', (done) => {
const f = URI.file('/some/file/test.txt');
const d = dirname(f);
assert.equal(d.fsPath, normalize('/some/file', true));
// does not explode (https://github.com/Microsoft/vscode/issues/41987)
dirname(URI.from({ scheme: 'file', authority: '/users/someone/portal.h' }));
done();
});
});

View File

@@ -348,4 +348,37 @@ suite('Strings', () => {
assert.equal(strings.stripUTF8BOM('abc'), 'abc');
assert.equal(strings.stripUTF8BOM(''), '');
});
test('containsUppercaseCharacter', () => {
[
[null, false],
['', false],
['foo', false],
['föö', false],
['ناك', false],
['מבוססת', false],
['😀', false],
['(#@()*&%()@*#&09827340982374}{:">?></\'\\~`', false],
['Foo', true],
['FOO', true],
['FöÖ', true],
['FöÖ', true],
['\\Foo', true],
].forEach(([str, result]) => {
assert.equal(strings.containsUppercaseCharacter(<string>str), result, `Wrong result for ${str}`);
});
});
test('containsUppercaseCharacter (ignoreEscapedChars)', () => {
[
['\\Woo', false],
['f\\S\\S', false],
['foo', false],
['Foo', true],
].forEach(([str, result]) => {
assert.equal(strings.containsUppercaseCharacter(<string>str, true), result, `Wrong result for ${str}`);
});
});
});

View File

@@ -86,5 +86,5 @@ export function onError(error: Error, done: () => void): void {
}
export function toResource(this: any, path: string) {
return URI.file(paths.join('C:\\', new Buffer(this.test.fullTitle()).toString('base64'), path));
return URI.file(paths.join('C:\\', Buffer.from(this.test.fullTitle()).toString('base64'), path));
}

View File

@@ -11,6 +11,169 @@ import { Promise as WinJSPromise } from 'vs/base/common/winjs.base';
suite('Polyfill Promise', function () {
test('sync-resolve, NativePromise', function () {
// native promise behaviour
const actual: string[] = [];
const promise = new Promise(resolve => {
actual.push('inCtor');
resolve(null);
}).then(() => actual.push('inThen'));
actual.push('afterCtor');
return promise.then(() => {
assert.deepEqual(actual, ['inCtor', 'afterCtor', 'inThen']);
});
});
test('sync-resolve, WinJSPromise', function () {
// winjs promise behaviour
const actual: string[] = [];
const promise = new WinJSPromise(resolve => {
actual.push('inCtor');
resolve(null);
}).then(() => actual.push('inThen'));
actual.push('afterCtor');
return promise.then(() => {
assert.deepEqual(actual, ['inCtor', 'inThen', 'afterCtor']);
});
});
test('sync-resolve, PolyfillPromise', function () {
// winjs promise behaviour
const actual: string[] = [];
const promise = new PolyfillPromise(resolve => {
actual.push('inCtor');
resolve(null);
}).then(() => actual.push('inThen'));
actual.push('afterCtor');
return promise.then(() => {
assert.deepEqual(actual, ['inCtor', 'afterCtor', 'inThen']);
});
});
test('sync-then, NativePromise', function () {
const actual: string[] = [];
const promise = Promise.resolve(123).then(() => actual.push('inThen'));
actual.push('afterThen');
return promise.then(() => {
assert.deepEqual(actual, ['afterThen', 'inThen']);
});
});
test('sync-then, WinJSPromise', function () {
const actual: string[] = [];
const promise = WinJSPromise.as(123).then(() => actual.push('inThen'));
actual.push('afterThen');
return promise.then(() => {
assert.deepEqual(actual, ['inThen', 'afterThen']);
});
});
test('sync-then, PolyfillPromise', function () {
const actual: string[] = [];
const promise = PolyfillPromise.resolve(123).then(() => actual.push('inThen'));
actual.push('afterThen');
return promise.then(() => {
assert.deepEqual(actual, ['afterThen', 'inThen']);
});
});
test('PolyfillPromise, executor has two params', function () {
return new PolyfillPromise(function () {
assert.equal(arguments.length, 2);
assert.equal(typeof arguments[0], 'function');
assert.equal(typeof arguments[1], 'function');
arguments[0]();
});
});
// run the same tests for the native and polyfill promise
(<any[]>[Promise, PolyfillPromise]).forEach(PromiseCtor => {
test(PromiseCtor.name + ', resolved value', function () {
return new PromiseCtor((resolve: Function) => resolve(1)).then((value: number) => assert.equal(value, 1));
});
test(PromiseCtor.name + ', rejected value', function () {
return new PromiseCtor((_: Function, reject: Function) => reject(1)).then(null, (value: number) => assert.equal(value, 1));
});
test(PromiseCtor.name + ', catch', function () {
return new PromiseCtor((_: Function, reject: Function) => reject(1)).catch((value: number) => assert.equal(value, 1));
});
test(PromiseCtor.name + ', static-resolve', function () {
return PromiseCtor.resolve(42).then((value: number) => assert.equal(value, 42));
});
test(PromiseCtor.name + ', static-reject', function () {
return PromiseCtor.reject(42).then(null, (value: number) => assert.equal(value, 42));
});
test(PromiseCtor.name + ', static-all, 1', function () {
return PromiseCtor.all([
PromiseCtor.resolve(1),
PromiseCtor.resolve(2)
]).then((values: number[]) => {
assert.deepEqual(values, [1, 2]);
});
});
test(PromiseCtor.name + ', static-all, 2', function () {
return PromiseCtor.all([
PromiseCtor.resolve(1),
3,
PromiseCtor.resolve(2)
]).then((values: number[]) => {
assert.deepEqual(values, [1, 3, 2]);
});
});
test(PromiseCtor.name + ', static-all, 3', function () {
return PromiseCtor.all([
PromiseCtor.resolve(1),
PromiseCtor.reject(13),
PromiseCtor.reject(12),
]).catch((values: number) => {
assert.deepEqual(values, 13);
});
});
test(PromiseCtor.name + ', static-race, 1', function () {
return PromiseCtor.race([
PromiseCtor.resolve(1),
PromiseCtor.resolve(2),
]).then((value: number) => {
assert.deepEqual(value, 1);
});
});
test(PromiseCtor.name + ', static-race, 2', function () {
return PromiseCtor.race([
PromiseCtor.reject(-1),
PromiseCtor.resolve(2),
]).catch((value: number) => {
assert.deepEqual(value, -1);
});
});
test(PromiseCtor.name + ', static-race, 3', function () {
return PromiseCtor.race([
PromiseCtor.resolve(1),
PromiseCtor.reject(2),
]).then((value: number) => {
assert.deepEqual(value, 1);
});
});
test(PromiseCtor.name + ', throw in ctor', function () {
return new PromiseCtor(() => {
throw new Error('sooo bad');
}).catch((err: Error) => {
assert.equal(err.message, 'sooo bad');
});
});
});
});

View File

@@ -12,10 +12,10 @@ suite('Decoder', () => {
test('decoding', function () {
const lineDecoder = new decoder.LineDecoder();
let res = lineDecoder.write(new Buffer('hello'));
let res = lineDecoder.write(Buffer.from('hello'));
assert.equal(res.length, 0);
res = lineDecoder.write(new Buffer('\nworld'));
res = lineDecoder.write(Buffer.from('\nworld'));
assert.equal(res[0], 'hello');
assert.equal(res.length, 1);

View File

@@ -25,12 +25,12 @@ h1, h2, h3, h4, h5, h6
margin: 0px;
}
textarea
textarea
{
font-family: Consolas
}
#results
#results
{
margin-top: 2em;
margin-left: 2em;

View File

@@ -25,12 +25,12 @@ h1, h2, h3, h4, h5, h6
margin: 0px;
}
textarea
textarea
{
font-family: Consolas
}
#results
#results
{
margin-top: 2em;
margin-left: 2em;

View File

@@ -15,6 +15,8 @@ import uuid = require('vs/base/common/uuid');
import strings = require('vs/base/common/strings');
import extfs = require('vs/base/node/extfs');
import { onError } from 'vs/base/test/common/utils';
import { Readable } from 'stream';
import { isLinux, isWindows } from 'vs/base/common/platform';
const ignore = () => { };
@@ -22,6 +24,38 @@ const mkdirp = (path: string, mode: number, callback: (error) => void) => {
extfs.mkdirp(path, mode).done(() => callback(null), error => callback(error));
};
const chunkSize = 64 * 1024;
const readError = 'Error while reading';
function toReadable(value: string, throwError?: boolean): Readable {
const totalChunks = Math.ceil(value.length / chunkSize);
const stringChunks: string[] = [];
for (let i = 0, j = 0; i < totalChunks; ++i, j += chunkSize) {
stringChunks[i] = value.substr(j, chunkSize);
}
let counter = 0;
return new Readable({
read: function () {
if (throwError) {
this.emit('error', new Error(readError));
}
let res: string;
let canPush = true;
while (canPush && (res = stringChunks[counter++])) {
canPush = this.push(res);
}
// EOS
if (!res) {
this.push(null);
}
},
encoding: 'utf8'
});
}
suite('Extfs', () => {
test('mkdirp', function (done: () => void) {
@@ -40,6 +74,46 @@ suite('Extfs', () => {
}); // 493 = 0755
});
test('stat link', function (done: () => void) {
if (isWindows) {
// Symlinks are not the same on win, and we can not create them programitically without admin privileges
return done();
}
const id1 = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id1);
const directory = path.join(parentDir, 'extfs', id1);
const id2 = uuid.generateUuid();
const symbolicLink = path.join(parentDir, 'extfs', id2);
mkdirp(directory, 493, error => {
if (error) {
return onError(error, done);
}
fs.symlinkSync(directory, symbolicLink);
extfs.statLink(directory, (error, statAndIsLink) => {
if (error) {
return onError(error, done);
}
assert.ok(!statAndIsLink.isSymbolicLink);
extfs.statLink(symbolicLink, (error, statAndIsLink) => {
if (error) {
return onError(error, done);
}
assert.ok(statAndIsLink.isSymbolicLink);
extfs.delSync(directory);
done();
});
});
});
});
test('delSync - swallows file not found error', function () {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
@@ -174,7 +248,7 @@ suite('Extfs', () => {
}
});
test('writeFileAndFlush', function (done: () => void) {
test('writeFileAndFlush (string)', function (done: () => void) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
@@ -209,6 +283,200 @@ suite('Extfs', () => {
});
});
test('writeFileAndFlush (stream)', function (done: () => void) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
assert.ok(fs.existsSync(newDir));
extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null, error => {
if (error) {
return onError(error, done);
}
assert.equal(fs.readFileSync(testFile), 'Hello World');
const largeString = (new Array(100 * 1024)).join('Large String\n');
extfs.writeFileAndFlush(testFile, toReadable(largeString), null, error => {
if (error) {
return onError(error, done);
}
assert.equal(fs.readFileSync(testFile), largeString);
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
});
test('writeFileAndFlush (file stream)', function (done: () => void) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const sourceFile = require.toUrl('./fixtures/index.html');
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
assert.ok(fs.existsSync(newDir));
extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null, error => {
if (error) {
return onError(error, done);
}
assert.equal(fs.readFileSync(testFile).toString(), fs.readFileSync(sourceFile).toString());
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (string, error handling)', function (done: () => void) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
assert.ok(fs.existsSync(newDir));
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
extfs.writeFileAndFlush(testFile, 'Hello World', null, error => {
if (!error) {
return onError(new Error('Expected error for writing to readonly file'), done);
}
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (stream, error handling EISDIR)', function (done: () => void) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
assert.ok(fs.existsSync(newDir));
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
const readable = toReadable('Hello World');
extfs.writeFileAndFlush(testFile, readable, null, error => {
if (!error || (<any>error).code !== 'EISDIR') {
return onError(new Error('Expected EISDIR error for writing to folder but got: ' + (error ? (<any>error).code : 'no error')), done);
}
// verify that the stream is still consumable (for https://github.com/Microsoft/vscode/issues/42542)
assert.equal(readable.read(), 'Hello World');
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (stream, error handling READERROR)', function (done: () => void) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
assert.ok(fs.existsSync(newDir));
extfs.writeFileAndFlush(testFile, toReadable('Hello World', true /* throw error */), null, error => {
if (!error || error.message !== readError) {
return onError(new Error('Expected error for writing to folder'), done);
}
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (stream, error handling EACCES)', function (done: () => void) {
if (isLinux) {
return done(); // somehow this test fails on Linux in our TFS builds
}
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
assert.ok(fs.existsSync(newDir));
fs.writeFileSync(testFile, '');
fs.chmodSync(testFile, 33060); // make readonly
extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null, error => {
if (!error || !((<any>error).code !== 'EACCES' || (<any>error).code !== 'EPERM')) {
return onError(new Error('Expected EACCES/EPERM error for writing to folder but got: ' + (error ? (<any>error).code : 'no error')), done);
}
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (file stream, error handling)', function (done: () => void) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const sourceFile = require.toUrl('./fixtures/index.html');
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
assert.ok(fs.existsSync(newDir));
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null, error => {
if (!error) {
return onError(new Error('Expected error for writing to folder'), done);
}
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlushSync', function (done: () => void) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
@@ -296,4 +564,4 @@ suite('Extfs', () => {
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
});

View File

@@ -25,12 +25,12 @@ h1, h2, h3, h4, h5, h6
margin: 0px;
}
textarea
textarea
{
font-family: Consolas
}
#results
#results
{
margin-top: 2em;
margin-left: 2em;

View File

@@ -301,6 +301,22 @@ suite('Glob', () => {
assert(!glob.match(p, '/xpackage.json'));
});
test('issue 41724', function () {
let p = 'some/**/*.js';
assert(glob.match(p, 'some/foo.js'));
assert(glob.match(p, 'some/folder/foo.js'));
assert(!glob.match(p, 'something/foo.js'));
assert(!glob.match(p, 'something/folder/foo.js'));
p = 'some/**/*';
assert(glob.match(p, 'some/foo.js'));
assert(glob.match(p, 'some/folder/foo.js'));
assert(!glob.match(p, 'something/foo.js'));
assert(!glob.match(p, 'something/folder/foo.js'));
});
test('brace expansion', function () {
let p = '*.{html,js}';

View File

@@ -25,12 +25,12 @@ h1, h2, h3, h4, h5, h6
margin: 0px;
}
textarea
textarea
{
font-family: Consolas
}
#results
#results
{
margin-top: 2em;
margin-left: 2em;