Skip to content

Commit

Permalink
sync with latest from vscode itself
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed May 29, 2019
1 parent b1d3221 commit 7f15d24
Showing 1 changed file with 83 additions and 38 deletions.
121 changes: 83 additions & 38 deletions src/index.ts
Expand Up @@ -435,7 +435,28 @@ const _schemePattern = /^\w[\w\d+.-]*$/;
const _singleSlashStart = /^\//;
const _doubleSlashStart = /^\/\//;

function _validateUri(ret: URI): void {
let _throwOnMissingSchema: boolean = true;

This comment has been minimized.

Copy link
@paul-marechal

paul-marechal May 29, 2019

This seems like a breaking change. At the very least it broke my project as I initialize URIs using empty strings, which means no scheme either. Worked before, doesn't now.

This comment has been minimized.

Copy link
@trevor-scheer

/**
* @internal
*/
export function setUriThrowOnMissingScheme(value: boolean): boolean {
const old = _throwOnMissingSchema;
_throwOnMissingSchema = value;
return old;
}

function _validateUri(ret: URI, _strict?: boolean): void {

// scheme, must be set
if (!ret.scheme) {
if (_strict || _throwOnMissingSchema) {
throw new Error(`[UriError]: Scheme is missing: {scheme: "", authority: "${ret.authority}", path: "${ret.path}", query: "${ret.query}", fragment: "${ret.fragment}"}`);
// } else {
// console.warn(`[UriError]: Scheme is missing: {scheme: "", authority: "${ret.authority}", path: "${ret.path}", query: "${ret.query}", fragment: "${ret.fragment}"}`);
}
}

// scheme, https://tools.ietf.org/html/rfc3986#section-3.1
// ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
if (ret.scheme && !_schemePattern.test(ret.scheme)) {
Expand All @@ -460,6 +481,21 @@ function _validateUri(ret: URI): void {
}
}

// for a while we allowed uris *without* schemes and this is the migration
// for them, e.g. an uri without scheme and without strict-mode warns and falls
// back to the file-scheme. that should cause the least carnage and still be a
// clear warning
function _schemeFix(scheme: string, _strict: boolean): string {
if (_strict || _throwOnMissingSchema) {
return scheme || _empty;
}
if (!scheme) {
// console.trace('BAD uri lacks scheme, falling back to file-scheme.');
scheme = 'file';
}
return scheme;
}

// implements a bit of https://tools.ietf.org/html/rfc3986#section-5
function _referenceResolution(scheme: string, path: string): string {

Expand Down Expand Up @@ -499,7 +535,7 @@ const _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
* / \ / \
* urn:example:animal:ferret:nose
*/
export default class URI implements UriComponents {
export class URI implements UriComponents {

static isUri(thing: any): thing is URI {
if (thing instanceof URI) {
Expand All @@ -512,7 +548,10 @@ export default class URI implements UriComponents {
&& typeof (<URI>thing).fragment === 'string'
&& typeof (<URI>thing).path === 'string'
&& typeof (<URI>thing).query === 'string'
&& typeof (<URI>thing).scheme === 'string';
&& typeof (<URI>thing).scheme === 'string'
&& typeof (<URI>thing).fsPath === 'function'
&& typeof (<URI>thing).with === 'function'
&& typeof (<URI>thing).toString === 'function';
}

/**
Expand Down Expand Up @@ -545,7 +584,7 @@ export default class URI implements UriComponents {
/**
* @internal
*/
protected constructor(scheme: string, authority: string, path: string, query: string, fragment: string);
protected constructor(scheme: string, authority?: string, path?: string, query?: string, fragment?: string, _strict?: boolean);

/**
* @internal
Expand All @@ -555,7 +594,7 @@ export default class URI implements UriComponents {
/**
* @internal
*/
protected constructor(schemeOrData: string | UriComponents, authority?: string, path?: string, query?: string, fragment?: string) {
protected constructor(schemeOrData: string | UriComponents, authority?: string, path?: string, query?: string, fragment?: string, _strict: boolean = false) {

if (typeof schemeOrData === 'object') {
this.scheme = schemeOrData.scheme || _empty;
Expand All @@ -567,13 +606,13 @@ export default class URI implements UriComponents {
// that creates uri components.
// _validateUri(this);
} else {
this.scheme = schemeOrData || _empty;
this.scheme = _schemeFix(schemeOrData, _strict);
this.authority = authority || _empty;
this.path = _referenceResolution(this.scheme, path || _empty);
this.query = query || _empty;
this.fragment = fragment || _empty;

_validateUri(this);
_validateUri(this, _strict);
}
}

Expand Down Expand Up @@ -612,34 +651,34 @@ export default class URI implements UriComponents {

// ---- modify to new -------------------------

public with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI {
with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI {

if (!change) {
return this;
}

let { scheme, authority, path, query, fragment } = change;
if (scheme === void 0) {
if (scheme === undefined) {
scheme = this.scheme;
} else if (scheme === null) {
scheme = _empty;
}
if (authority === void 0) {
if (authority === undefined) {
authority = this.authority;
} else if (authority === null) {
authority = _empty;
}
if (path === void 0) {
if (path === undefined) {
path = this.path;
} else if (path === null) {
path = _empty;
}
if (query === void 0) {
if (query === undefined) {
query = this.query;
} else if (query === null) {
query = _empty;
}
if (fragment === void 0) {
if (fragment === undefined) {
fragment = this.fragment;
} else if (fragment === null) {
fragment = _empty;
Expand All @@ -665,7 +704,7 @@ export default class URI implements UriComponents {
*
* @param value A string which represents an URI (see `URI#toString`).
*/
public static parse(value: string): URI {
static parse(value: string, _strict: boolean = false): URI {
const match = _regexp.exec(value);
if (!match) {
return new _URI(_empty, _empty, _empty, _empty, _empty);
Expand All @@ -676,6 +715,7 @@ export default class URI implements UriComponents {
decodeURIComponent(match[5] || _empty),
decodeURIComponent(match[7] || _empty),
decodeURIComponent(match[9] || _empty),
_strict
);
}

Expand All @@ -692,7 +732,6 @@ export default class URI implements UriComponents {
good.scheme === 'file';
good.path === '/coding/c#/project1';
good.fragment === '';
const bad = URI.parse('file://' + '/coding/c#/project1');
bad.scheme === 'file';
bad.path === '/coding/c'; // path is now broken
Expand All @@ -701,7 +740,7 @@ export default class URI implements UriComponents {
*
* @param path A file system path (see `URI#fsPath`)
*/
public static file(path: string): URI {
static file(path: string): URI {

let authority = _empty;

Expand All @@ -715,7 +754,7 @@ export default class URI implements UriComponents {
// check for authority as used in UNC shares
// or use the path as given
if (path[0] === _slash && path[1] === _slash) {
let idx = path.indexOf(_slash, 2);
const idx = path.indexOf(_slash, 2);
if (idx === -1) {
authority = path.substring(2);
path = _slash;
Expand All @@ -728,7 +767,7 @@ export default class URI implements UriComponents {
return new _URI('file', authority, path, _empty, _empty);
}

public static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
return new _URI(
components.scheme,
components.authority,
Expand All @@ -741,7 +780,7 @@ export default class URI implements UriComponents {
// ---- printing/externalize ---------------------------

/**
* Creates a string presentation for this URI. It's guardeed that calling
* Creates a string representation for this URI. It's guaranteed that calling
* `URI.parse` with the result of this function creates an URI which is equal
* to this URI.
*
Expand All @@ -751,23 +790,27 @@ export default class URI implements UriComponents {
*
* @param skipEncoding Do not encode the result, default is `false`
*/
public toString(skipEncoding: boolean = false): string {
toString(skipEncoding: boolean = false): string {
return _asFormatted(this, skipEncoding);
}

public toJSON(): object {
toJSON(): UriComponents {
return this;
}

static revive(data: UriComponents | any): URI {
static revive(data: UriComponents | URI): URI;
static revive(data: UriComponents | URI | undefined): URI | undefined;
static revive(data: UriComponents | URI | null): URI | null;
static revive(data: UriComponents | URI | undefined | null): URI | undefined | null;
static revive(data: UriComponents | URI | undefined | null): URI | undefined | null {
if (!data) {
return data;
return <any>data;
} else if (data instanceof URI) {
return data;
} else {
let result = new _URI(data);
result._fsPath = (<UriState>data).fsPath;
const result = new _URI(data);
result._formatted = (<UriState>data).external;
result._fsPath = (<UriState>data)._sep === _pathSepMarker ? (<UriState>data).fsPath : null;
return result;
}
}
Expand All @@ -783,16 +826,18 @@ export interface UriComponents {

interface UriState extends UriComponents {
$mid: number;
fsPath: string;
external: string;
fsPath: string;
_sep: 1 | undefined;
}

const _pathSepMarker = isWindows ? 1 : undefined;

// tslint:disable-next-line:class-name
class _URI extends URI {

_formatted: string = null;
_fsPath: string = null;
_formatted: string | null = null;
_fsPath: string | null = null;

get fsPath(): string {
if (!this._fsPath) {
Expand All @@ -801,7 +846,7 @@ class _URI extends URI {
return this._fsPath;
}

public toString(skipEncoding: boolean = false): string {
toString(skipEncoding: boolean = false): string {
if (!skipEncoding) {
if (!this._formatted) {
this._formatted = _asFormatted(this, false);
Expand All @@ -813,13 +858,14 @@ class _URI extends URI {
}
}

toJSON(): object {
toJSON(): UriComponents {
const res = <UriState>{
$mid: 1
};
// cached state
if (this._fsPath) {
res.fsPath = this._fsPath;
res._sep = _pathSepMarker;
}
if (this._formatted) {
res.external = this._formatted;
Expand Down Expand Up @@ -870,11 +916,11 @@ const encodeTable: { [ch: number]: string } = {
};

function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): string {
let res: string = undefined;
let res: string | undefined = undefined;
let nativeEncodePos = -1;

for (let pos = 0; pos < uriComponent.length; pos++) {
let code = uriComponent.charCodeAt(pos);
const code = uriComponent.charCodeAt(pos);

// unreserved characters: https://tools.ietf.org/html/rfc3986#section-2.3
if (
Expand Down Expand Up @@ -904,7 +950,7 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): stri
}

// check with default table first
let escaped = encodeTable[code];
const escaped = encodeTable[code];
if (escaped !== undefined) {

// check if we are delaying native encode
Expand All @@ -931,9 +977,9 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): stri
}

function encodeURIComponentMinimal(path: string): string {
let res: string = undefined;
let res: string | undefined = undefined;
for (let pos = 0; pos < path.length; pos++) {
let code = path.charCodeAt(pos);
const code = path.charCodeAt(pos);
if (code === CharCode.Hash || code === CharCode.QuestionMark) {
if (res === undefined) {
res = path.substr(0, pos);
Expand All @@ -950,7 +996,6 @@ function encodeURIComponentMinimal(path: string): string {

/**
* Compute `fsPath` for the given uri
* @param uri
*/
function _makeFsPath(uri: URI): string {

Expand Down Expand Up @@ -1024,12 +1069,12 @@ function _asFormatted(uri: URI, skipEncoding: boolean): string {
if (path) {
// lower-case windows drive letters in /C:/fff or C:/fff
if (path.length >= 3 && path.charCodeAt(0) === CharCode.Slash && path.charCodeAt(2) === CharCode.Colon) {
let code = path.charCodeAt(1);
const code = path.charCodeAt(1);
if (code >= CharCode.A && code <= CharCode.Z) {
path = `/${String.fromCharCode(code + 32)}:${path.substr(3)}`; // "/c:".length === 3
}
} else if (path.length >= 2 && path.charCodeAt(1) === CharCode.Colon) {
let code = path.charCodeAt(0);
const code = path.charCodeAt(0);
if (code >= CharCode.A && code <= CharCode.Z) {
path = `${String.fromCharCode(code + 32)}:${path.substr(2)}`; // "/c:".length === 3
}
Expand Down

0 comments on commit 7f15d24

Please sign in to comment.