Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
url: Passing additional WHATWG tests and marking failures.
  • Loading branch information
STRML committed Feb 7, 2016
commit 566b4b82f39d455fd1a1890177f1ddabe7c35dac
37 changes: 29 additions & 8 deletions lib/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function Url() {
this.path = null;
this.href = null;
this._prependSlash = false;
this._errored = false;
}

// Reference: RFC 3986, RFC 1808, RFC 2396
Expand All @@ -38,7 +39,8 @@ const _protocolCharacters = makeAsciiTable([
// RFC 2396: characters not allowed for various reasons.
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
const _autoEscape = [
'<', '>', '\'', '`', ' ', '\r', '\n', '\t', '{', '}', '|', '\\', '^', '`', '"'
'<', '>', '\'', '`', ' ', '\r', '\n', '\t', '{', '}', '|', '\\',
'^', '`', '"'
];

const _autoEscapeMap = new Array(128);
Expand Down Expand Up @@ -81,13 +83,12 @@ const _autoEscapeCharacters = makeAsciiTable(_autoEscape.map(function(v) {
// Note that any invalid chars are also handled, but these
// are the ones that are *expected* to be seen, so we fast-path them.
const _hostEndingCharacters = makeAsciiTable(
['#', '?', '/', '\\'].map(function(v) {
['#', '?', '/', '\\', ';'].map(function(v) {
return v.charCodeAt(0);
}));
// If these characters end a host name, the path will not be prepended a /.
const _hostEndingCharactersNoPrependSlash = makeAsciiTable([
'<', '>', '"', '`', ' ', '\r', '\n', '\t', '{', '}', '|', '^', '`', '\'', '%',
';'
'<', '>', '"', '`', ' ', '\r', '\n', '\t', '{', '}', '|', '^', '`', '\'', '%'
].map(function(v) {
return v.charCodeAt(0);
}));
Expand All @@ -100,7 +101,14 @@ function urlParse(url, parseQueryString, slashesDenoteHost) {

var u = new Url();
u.parse(url, parseQueryString, slashesDenoteHost);
u.href = u.format();
// If we hit a parse error, return an empty object with the href only.
if (u._errored) {
u = new Url();
u.href = url;
u._errored = true;
} else {
u.href = u.format();
}
return u;
}

Expand Down Expand Up @@ -193,6 +201,9 @@ function urlFormat(obj) {
}

Url.prototype.format = function() {
if (this._errored)
return this.href;

var auth = this.auth || '';

if (auth) {
Expand Down Expand Up @@ -311,6 +322,11 @@ Url.prototype.resolveObject = function(relative) {
return this._resolveEmpty();
}

// If there was an error parsing the relative url,
// we just return it entirely.
if (relative._errored)
return relative;

var result = this._clone();

// Hash is always overridden, no matter what.
Expand Down Expand Up @@ -663,11 +679,12 @@ Url.prototype._parseHost = function(str,
var charsAfterDot = 0;
var authNeedsDecoding = false;

var i;
var j = -1;

// Find the last occurrence of an @-sign until hostending character is met
// also mark if decoding is needed for the auth portion.
for (var i = start; i <= end; ++i) {
for (i = start; i <= end; ++i) {
var ch = str.charCodeAt(i);
if (ch === 0x40 /*'@'*/)
j = i;
Expand Down Expand Up @@ -729,14 +746,19 @@ Url.prototype._parseHost = function(str,
return start;
}

for (let i = start; i <= end; ++i) {
for (i = start; i <= end; ++i) {
if (charsAfterDot > 62) {
this.hostname = this.host = str.slice(start, i);
return i;
}
const ch = str.charCodeAt(i);

if (ch === 0x3A /*':'*/) {
if (portStart !== -1) {
// Illegal character in port
this._errored = true;
return start;
}
portStart = i + 1;
} else if (ch < 0x61 /*'a'*/) {
if (ch === 0x2E /*'.'*/) {
Expand Down Expand Up @@ -879,7 +901,6 @@ Url.prototype._isEmpty = function(value) {
return value === null || value === '' || value === undefined;
};


// Search `char1` (integer code for a character) in `string`
// starting from `fromIndex` and ending at `string.length - 1`
// or when a stop character is found.
Expand Down
Loading