提交 3e0ded9c 编写于 作者: J Johannes Rieken

keep input (for toString) when using URI.parse, URI.file uses now URI.parse

Add tests that check our logic against Nodejs's pathToFileURL
上级 359c17a6
......@@ -74,8 +74,17 @@ function _referenceResolution(scheme: string, path: string): string {
const _empty = '';
const _slash = '/';
const _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
const enum MatchIndex {
scheme = 2,
authority = 4,
path = 5,
query = 7,
fragment = 9
}
/**
* Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.
* This class is a simple parser which creates the basic component parts
......@@ -262,15 +271,24 @@ export class URI implements UriComponents {
static parse(value: string): URI {
const match = _regexp.exec(value);
if (!match) {
return new _URI(_empty, _empty, _empty, _empty, _empty);
throw new Error(`[UriError]: Invalid input: ${value}`);
}
return new _URI(
match[2] || _empty,
percentDecode(match[4] || _empty),
percentDecode(match[5] || _empty),
percentDecode(match[7] || _empty),
percentDecode(match[9] || _empty)
const scheme = _schemeFix(match[MatchIndex.scheme]) || _empty;
const authority = match[MatchIndex.authority] || _empty;
const path = _referenceResolution(scheme, match[MatchIndex.path] || _empty);
const query = match[MatchIndex.query] || _empty;
const fragment = match[MatchIndex.fragment] || _empty;
const result = new _URI(
scheme,
percentDecode(authority),
percentDecode(path),
percentDecode(query),
percentDecode(fragment),
);
result._formatted = _toString(false, scheme, authority, path, query, fragment);
return result;
}
/**
......@@ -318,7 +336,15 @@ export class URI implements UriComponents {
}
}
return new _URI('file', authority, path, _empty, _empty);
if (path.charAt(0) !== _slash) {
path = _slash + path;
}
// escape some vital characters
authority = authority.replace(/%/g, '%25');
path = path.replace(/%/g, '%25');
return URI.parse('file://' + authority + path);
}
static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string; }): URI {
......
......@@ -5,7 +5,7 @@
import * as assert from 'assert';
import { URI, UriComponents } from 'vs/base/common/uri';
import { isWindows } from 'vs/base/common/platform';
import { pathToFileURL } from 'url';
suite('URI', () => {
test('file#toString', () => {
......@@ -427,21 +427,24 @@ suite('URI', () => {
});
test('Unable to open \'%A0.txt\': URI malformed #76506', function () {
let uri = URI.file('/foo/%A0.txt');
let uri2 = URI.parse(uri.toString());
assert.equal(uri.scheme, uri2.scheme);
assert.equal(uri.path, uri2.path);
uri = URI.file('/foo/%2e.txt');
uri2 = URI.parse(uri.toString());
assert.equal(uri.scheme, uri2.scheme);
assert.equal(uri.path, uri2.path);
let uriFromPath = URI.file('/foo/%A0.txt');
let uriFromStr = URI.parse(uriFromPath.toString());
assert.equal(uriFromPath.scheme, uriFromStr.scheme);
assert.equal(uriFromPath.path, uriFromStr.path);
assert.equal(uriFromPath.toString(), 'file:///foo/%25A0.txt');
assert.equal(uriFromStr.toString(), 'file:///foo/%25A0.txt');
});
test('Valid percent-encoded character in filename', function () {
let uriFromPath = URI.file('/foo/%2e.txt');
let uriFromStr = URI.parse(uriFromPath.toString());
assert.equal(uriFromPath.scheme, uriFromStr.scheme);
assert.equal(uriFromPath.path, uriFromStr.path);
assert.equal(uriFromPath.toString(), 'file:///foo/%252e.txt');
assert.equal(uriFromStr.toString(), 'file:///foo/%252e.txt');
});
test('Links in markdown are broken if url contains encoded parameters #79474', function () {
this.skip();
let strIn = 'https://myhost.com/Redirect?url=http%3A%2F%2Fwww.bing.com%3Fsearch%3Dtom';
let uri1 = URI.parse(strIn);
let strOut = uri1.toString();
......@@ -456,7 +459,6 @@ suite('URI', () => {
});
test('Uri#parse can break path-component #45515', function () {
this.skip();
let strIn = 'https://firebasestorage.googleapis.com/v0/b/brewlangerie.appspot.com/o/products%2FzVNZkudXJyq8bPGTXUxx%2FBetterave-Sesame.jpg?alt=media&token=0b2310c4-3ea6-4207-bbde-9c3710ba0437';
let uri1 = URI.parse(strIn);
let strOut = uri1.toString();
......@@ -499,4 +501,20 @@ suite('URI', () => {
// }
// console.profileEnd();
});
function assertFileUri(path: string): void {
// check that our uri aligns with nodejs
const actual = URI.file(path).toString();
const expected = pathToFileURL(path).href;
assert.equal(actual, expected);
}
test('URI.file vs pathToFileURL', function () {
assertFileUri('/foo/bar');
assertFileUri('/foo/%2e.txt'); // %2e -> .
assertFileUri('/foo/%A0.txt'); // %A0 -> invalid
assertFileUri('/foo/ü.txt');
assertFileUri('/foo/ß.txt');
// assertFileUri('foo'); nodejs resolves the path first
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册