Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

whatwg-url

Package Overview
Dependencies
Maintainers
1
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

whatwg-url - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0

LICENSE.txt

681

lib/url.js

@@ -9,3 +9,3 @@ "use strict";

const relativeSchemas = {
const specialSchemas = {
"ftp": "21",

@@ -39,16 +39,17 @@ "file": null,

RELATIVE: 4,
RELATIVE_OR_AUTHORITY: 5,
AUTHORITY_FIRST_SLASH: 6,
SCHEME_DATA: 7,
SPECIAL_RELATIVE_OR_AUTHORITY: 5,
SPECIAL_AUTHORITY_SLASHES: 6,
NON_RELATIVE_PATH: 7,
QUERY: 8,
FRAGMENT: 9,
AUTHORITY_IGNORE_SLASHES: 10,
SPECIAL_AUTHORITY_IGNORE_SLASHES: 10,
RELATIVE_SLASH: 11,
RELATIVE_PATH: 12,
PATH: 12,
FILE_HOST: 13,
AUTHORITY: 14,
HOST: 15,
RELATIVE_PATH_START: 16,
PATH_START: 16,
HOST_NAME: 17,
PORT: 18
PORT: 18,
PATH_OR_AUTHORITY: 19
};

@@ -77,2 +78,11 @@

function percentEncode(c) {
let hex = c.toString(16).toUpperCase();
if (hex.length === 1) {
hex = "0" + hex;
}
return "%" + hex;
}
const invalidCodePoint = String.fromCodePoint(65533);

@@ -88,8 +98,3 @@ function utf8PercentEncode(c) {

for (let i = 0; i < buf.length; ++i) {
let hex = buf[i].toString(16).toUpperCase();
if (hex.length === 1) {
hex = "0" + hex;
}
str += "%" + hex;
str += percentEncode(buf[i]);
}

@@ -113,3 +118,4 @@

if (c <= 0x20 || c >= 0x7E || c_str === "\"" || c_str === "#" ||
c_str === "<" || c_str === ">" || c_str === "?" || c_str === "`") {
c_str === "<" || c_str === ">" || c_str === "?" || c_str === "`" ||
c_str === "{" || c_str === "}") {
return utf8PercentEncode(c_str);

@@ -125,2 +131,3 @@ } else {

c_str === "<" || c_str === ">" || c_str === "?" || c_str === "`" ||
c_str === "{" || c_str === "}" ||
c_str === "/" || c_str === "@" || c_str === "\\") {

@@ -137,2 +144,3 @@ return utf8PercentEncode(c_str);

c_str === "<" || c_str === ">" || c_str === "?" || c_str === "`" ||
c_str === "{" || c_str === "}" ||
c_str === "/" || c_str === "@" || c_str === "\\" || c_str === ":") {

@@ -145,2 +153,76 @@ return utf8PercentEncode(c_str);

function parseIPv4Number(input) {
let R = 10;
if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") {
input = input.substring(2);
R = 16;
} else if (input.length >= 1 && input.charAt(0) === "0") {
input = input.substring(1);
R = 8;
}
const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/);
if (regex.test(input)) {
return null;
}
return parseInt(input, R);
}
function parseIPv4(input) {
let parts = input.split(".");
if (parts[parts.length - 1] === "") {
parts.pop();
}
if (parts.length > 4) {
return input;
}
let numbers = [];
for (const part of parts) {
const n = parseIPv4Number(part);
if (n === null) {
return input;
}
numbers.push(n);
}
for (let i = 0; i < numbers.length - 1; ++i) {
if (numbers[i] > 255) {
throw new TypeError("Invalid Host");
}
}
if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) {
throw new TypeError("Invalid Host");
}
let ipv4 = numbers.pop();
let counter = 0;
for (const n of numbers) {
ipv4 += n * Math.pow(256, 3 - counter);
++counter;
}
return ipv4;
}
function serializeIPv4(address) {
let output = "";
let n = address;
for (let i = 0; i < 4; ++i) {
output = String(n % 256) + output;
if (i !== 3) {
output = "." + output;
}
n = Math.floor(n / 256);
}
return output;
}
function parseIPv6(input) {

@@ -247,3 +329,7 @@ const ip = [0, 0, 0, 0, 0, 0, 0, 0];

}
++pointer;
if (input[pointer] !== undefined) {
++pointer;
}
if (dotsSeen === 3 && input[pointer] !== undefined) {

@@ -273,7 +359,29 @@ throw new TypeError("Invalid Host");

function parseHost(input, isUnicode) {
if (input === "") {
throw new TypeError("Invalid Host");
function serializeIPv6(address) {
let output = "";
const seqResult = findLongestZeroSequence(address);
const compressPtr = seqResult.idx;
for (var i = 0; i < address.length; ++i) {
if (compressPtr === i) {
if (i === 0) {
output += "::";
} else {
output += ":";
}
i += seqResult.len - 1;
continue;
}
output += address[i].toString(16);
if (i !== address.length - 1) {
output += ":";
}
}
return output;
}
function parseHost(input, isUnicode) {
if (input[0] === "[") {

@@ -284,3 +392,3 @@ if (input[input.length - 1] !== "]") {

return serializeHost(parseIPv6(input.substr(1, input.length - 2)));
return parseIPv6(input.substring(1, input.length - 1));
}

@@ -304,2 +412,7 @@

let ipv4Host = parseIPv4(asciiDomain);
if (typeof ipv4Host === "number") {
return ipv4Host;
}
return isUnicode ? tr46.toUnicode(asciiDomain, false).domain : asciiDomain;

@@ -338,4 +451,4 @@ }

function serializeHost(host) {
if (host === null) {
return "";
if (typeof host === "number") {
return serializeIPv4(host);
}

@@ -345,25 +458,3 @@

if (host instanceof Array) {
let output = "";
const seqResult = findLongestZeroSequence(host);
const compressPtr = seqResult.idx;
for (var i = 0; i < host.length; ++i) {
if (compressPtr === i) {
if (i === 0) {
output += "::";
} else {
output += ":";
}
i += seqResult.len - 1;
continue;
}
output += host[i].toString(16);
if (i !== host.length - 1) {
output += ":";
}
}
return "[" + output + "]";
return "[" + serializeIPv6(host) + "]";
}

@@ -374,2 +465,6 @@

function trimControlChars(url) {
return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, "");
}
function URLStateMachine(input, base, encoding_override, url, state_override) {

@@ -386,3 +481,2 @@ this.pointer = 0;

scheme: "",
scheme_data: "",
username: "",

@@ -396,6 +490,6 @@ password: null,

isRelative: false
nonRelative: false
};
this.input = this.input.trim();
this.input = trimControlChars(this.input);
}

@@ -440,2 +534,10 @@

} else if (c_str === ":") {
if (this.state_override) {
// TODO: XOR
if (specialSchemas[this.url.scheme] !== undefined && !specialSchemas[this.buffer]) {
return false;
} else if (specialSchemas[this.url.scheme] === undefined && specialSchemas[this.buffer]) {
return false;
}
}
this.url.scheme = this.buffer;

@@ -446,13 +548,16 @@ this.buffer = "";

}
if (relativeSchemas[this.url.scheme] !== undefined) {
this.url.isRelative = true;
}
if (this.url.scheme === "file") {
this.state = STATES.RELATIVE;
} else if (this.url.isRelative && this.base !== null && this.base.scheme === this.url.scheme) {
this.state = STATES.RELATIVE_OR_AUTHORITY;
} else if (this.url.isRelative) {
this.state = STATES.AUTHORITY_FIRST_SLASH;
} else if (specialSchemas[this.url.scheme] !== undefined && this.base !== null &&
this.base.scheme === this.url.scheme) {
this.state = STATES.SPECIAL_RELATIVE_OR_AUTHORITY;
} else if (specialSchemas[this.url.scheme] !== undefined) {
this.state = STATES.SPECIAL_AUTHORITY_SLASHES;
} else if (at(this.input, this.pointer + 1) === "/") {
this.state = STATES.PATH_OR_AUTHORITY;
++this.pointer;
} else {
this.state = STATES.SCHEME_DATA;
this.url.nonRelative = true;
this.url.path.push("");
this.state = STATES.NON_RELATIVE_PATH;
}

@@ -463,4 +568,2 @@ } else if (!this.state_override) {

this.pointer = -1;
} else if (isNaN(c)) {
return false;
} else {

@@ -474,4 +577,11 @@ this.parse_error = true;

//jshint unused:false
if (this.base === null || relativeSchemas[this.base.scheme] === undefined) {
if (this.base === null || (this.base.nonRelative && c_str !== "#")) {
throw new TypeError("Invalid URL");
} else if (this.base.nonRelative && c_str === "#") {
this.url.scheme = this.base.scheme;
this.url.path = this.base.path.slice();
this.url.query = this.base.query;
this.url.fragment = "";
this.url.nonRelative = true;
this.state = STATES.FRAGMENT;
} else {

@@ -483,4 +593,23 @@ this.state = STATES.RELATIVE;

URLStateMachine.prototype["parse" + STATES.SPECIAL_RELATIVE_OR_AUTHORITY] = function parseScheme(c, c_str) {
if (c_str === "/" && at(this.input, this.pointer + 1) === "/") {
this.state = STATES.SPECIAL_AUTHORITY_IGNORE_SLASHES;
++this.pointer;
} else {
this.parse_error = true;
this.state = STATES.RELATIVE;
--this.pointer;
}
};
URLStateMachine.prototype["parse" + STATES.PATH_OR_AUTHORITY] = function parseScheme(c, c_str) {
if (c_str === "/") {
this.state = STATES.AUTHORITY;
} else {
this.state = STATES.PATH;
--this.pointer;
}
};
URLStateMachine.prototype["parse" + STATES.RELATIVE] = function parseScheme(c, c_str) {
this.url.isRelative = true;
if (this.url.scheme !== "file") {

@@ -490,2 +619,4 @@ this.url.scheme = this.base.scheme;

if (isNaN(c)) {
this.url.username = this.base.username;
this.url.password = this.base.password;
this.url.host = this.base.host;

@@ -495,8 +626,7 @@ this.url.port = this.base.port;

this.url.query = this.base.query;
} else if (c_str === "\\" || c_str === "/") {
if (c_str === "\\") {
this.parse_error = true;
}
} else if (c_str === "/") {
this.state = STATES.RELATIVE_SLASH;
} else if (c_str === "?") {
this.url.username = this.base.username;
this.url.password = this.base.password;
this.url.host = this.base.host;

@@ -508,2 +638,4 @@ this.url.port = this.base.port;

} else if (c_str === "#") {
this.url.username = this.base.username;
this.url.password = this.base.password;
this.url.host = this.base.host;

@@ -515,2 +647,5 @@ this.url.port = this.base.port;

this.state = STATES.FRAGMENT;
} else if (specialSchemas[this.url.scheme] !== undefined && c_str === "\\") {
this.parse_error = true;
this.state = STATES.RELATIVE_SLASH;
} else {

@@ -522,2 +657,4 @@ let nextChar = at(this.input, this.pointer + 1);

nextNextChar === "?" || nextNextChar === "#")) {
this.url.username = this.base.username;
this.url.password = this.base.password;
this.url.host = this.base.host;

@@ -528,3 +665,3 @@ this.url.port = this.base.port;

this.state = STATES.RELATIVE_PATH;
this.state = STATES.PATH;
--this.pointer;

@@ -534,96 +671,4 @@ }

URLStateMachine.prototype["parse" + STATES.RELATIVE_OR_AUTHORITY] = function parseScheme(c, c_str) {
if (c_str === "/" && at(this.input, this.pointer + 1) === "/") {
this.state = STATES.AUTHORITY_IGNORE_SLASHES;
++this.pointer;
} else {
this.parse_error = true;
this.state = STATES.RELATIVE;
--this.pointer;
}
};
URLStateMachine.prototype["parse" + STATES.AUTHORITY_FIRST_SLASH] = function parseScheme(c, c_str) {
if (c_str === "/" && at(this.input, this.pointer + 1) === "/") { // patching AUTHORITY_SECOND_SLASH out here
++this.pointer;
this.state = STATES.AUTHORITY_IGNORE_SLASHES;
} else {
this.parse_error = true;
this.state = STATES.AUTHORITY_IGNORE_SLASHES;
--this.pointer;
}
};
URLStateMachine.prototype["parse" + STATES.SCHEME_DATA] = function parseScheme(c, c_str) {
if (c_str === "?") {
this.url.query = "";
this.state = STATES.QUERY;
} else if (c_str === "#") {
this.url.fragment = "";
this.state = STATES.FRAGMENT;
} else {
//TODO: If c is not the EOF code point, not a URL code point, and not "%", parse error.
if (c_str === "%" &&
(!isASCIIHex(at(this.input, this.pointer + 1)) ||
!isASCIIHex(at(this.input, this.pointer + 2)))) {
this.parse_error = true;
} else if (c !== undefined && c !== 0x9 && c !== 0xA && c !== 0xD) {
this.url.scheme_data += simpleEncode(c);
}
}
};
URLStateMachine.prototype["parse" + STATES.QUERY] = function parseScheme(c, c_str) {
if (isNaN(c) || (!this.state_override && c_str === "#")) {
if (!this.url.isRelative || this.url.scheme === "ws" || this.url.scheme === "wss") {
this.encoding_override = "utf-8";
}
this.buffer = this.buffer; //TODO: Use encoding override instead
this.url.query += encodeURI(this.buffer);
this.buffer = "";
if (c_str === "#") {
this.url.fragment = "";
this.state = STATES.FRAGMENT;
}
} else if (c === 0x9 || c === 0xA || c === 0xD) {
this.parse_error = true;
} else {
//TODO: If c is not a URL code point and not "%", parse error.
if (c_str === "%" &&
(!isASCIIHex(at(this.input, this.pointer + 1)) ||
!isASCIIHex(at(this.input, this.pointer + 2)))) {
this.parse_error = true;
} else {
this.buffer += c_str;
}
}
};
URLStateMachine.prototype["parse" + STATES.FRAGMENT] = function parseScheme(c, c_str) {
if (isNaN(c)) { // do nothing
} else if (c === 0x0 || c === 0x9 || c === 0xA || c === 0xD) {
this.parse_error = true;
} else {
//TODO: If c is not a URL code point and not "%", parse error.
if (c_str === "%" &&
(!isASCIIHex(at(this.input, this.pointer + 1)) ||
!isASCIIHex(at(this.input, this.pointer + 2)))) {
this.parse_error = true;
} else {
this.url.fragment += c_str;
}
}
};
URLStateMachine.prototype["parse" + STATES.AUTHORITY_IGNORE_SLASHES] = function parseScheme(c, c_str) {
if (c_str !== "/" && c_str !== "\\") {
this.state = STATES.AUTHORITY;
--this.pointer;
} else {
this.parse_error = true;
}
};
URLStateMachine.prototype["parse" + STATES.RELATIVE_SLASH] = function parseScheme(c, c_str) {
if (c_str === "/" || c_str === "\\") {
if (c_str === "/" || (specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) {
if (c_str === "\\") {

@@ -635,10 +680,12 @@ this.parse_error = true;

} else {
this.state = STATES.AUTHORITY_IGNORE_SLASHES;
this.state = STATES.SPECIAL_AUTHORITY_IGNORE_SLASHES;
}
} else {
if (this.url.scheme !== "file") {
this.url.username = this.base.username;
this.url.password = this.base.password;
this.url.host = this.base.host;
this.url.port = this.base.port;
}
this.state = STATES.RELATIVE_PATH;
this.state = STATES.PATH;
--this.pointer;

@@ -648,65 +695,19 @@ }

URLStateMachine.prototype["parse" + STATES.RELATIVE_PATH] = function parseScheme(c, c_str) {
if (isNaN(c) || c_str === "/" || c_str === "\\" || (!this.state_override && (c_str === "?" || c_str === "#"))) {
if (c_str === "\\") {
this.parse_error = true;
}
this.buffer = bufferReplacement[this.buffer.toLowerCase()] || this.buffer;
if (this.buffer === "..") {
this.url.path.pop();
if (c_str !== "/" && c_str !== "\\") {
this.url.path.push("");
}
} else if (this.buffer === "." && c_str !== "/" && c_str !== "\\") {
this.url.path.push("");
} else if (this.buffer !== ".") {
if (this.url.scheme === "file" && this.url.path.length === 0 &&
this.buffer.length === 2 && isASCIIAlpha(this.buffer.codePointAt(0)) && this.buffer[1] === "|") {
this.buffer = this.buffer[0] + ":";
}
this.url.path.push(this.buffer);
}
this.buffer = "";
if (c_str === "?") {
this.url.query = "";
this.state = STATES.QUERY;
}
if (c_str === "#") {
this.url.fragment = "";
this.state = STATES.FRAGMENT;
}
} else if (c === 0x9 || c === 0xA || c === 0xD) {
URLStateMachine.prototype["parse" + STATES.SPECIAL_AUTHORITY_SLASHES] = function parseScheme(c, c_str) {
if (c_str === "/" && at(this.input, this.pointer + 1) === "/") {
this.state = STATES.SPECIAL_AUTHORITY_IGNORE_SLASHES;
++this.pointer;
} else {
this.parse_error = true;
} else {
//TODO:If c is not a URL code point and not "%", parse error.
if (c_str === "%" &&
(!isASCIIHex(at(this.input, this.pointer + 1)) ||
!isASCIIHex(at(this.input, this.pointer + 2)))) {
this.parse_error = true;
}
this.buffer += defaultEncode(c);
this.state = STATES.SPECIAL_AUTHORITY_IGNORE_SLASHES;
--this.pointer;
}
};
URLStateMachine.prototype["parse" + STATES.FILE_HOST] = function parseScheme(c, c_str) {
if (isNaN(c) || c_str === "/" || c_str === "\\" || c_str === "?" || c_str === "#") {
URLStateMachine.prototype["parse" + STATES.SPECIAL_AUTHORITY_IGNORE_SLASHES] = function parseScheme(c, c_str) {
if (c_str !== "/" && c_str !== "\\") {
this.state = STATES.AUTHORITY;
--this.pointer;
// don't need to count symbols here since we check ASCII values
if (this.buffer.length === 2 &&
isASCIIAlpha(this.buffer.codePointAt(0)) && (this.buffer[1] === ":" || this.buffer[1] === "|")) {
this.state = STATES.RELATIVE_PATH;
} else if (this.buffer === "") {
this.state = STATES.RELATIVE_PATH_START;
} else {
let host = parseHost(this.buffer);
this.url.host = host;
this.buffer = "";
this.state = STATES.RELATIVE_PATH_START;
}
} else if (c === 0x9 || c === 0xA || c === 0xD) {
} else {
this.parse_error = true;
} else {
this.buffer += c_str;
}

@@ -717,4 +718,4 @@ };

if (c_str === "@") {
this.parse_error = true;
if (this.at_flag) {
this.parse_error = true;
this.buffer = "%40" + this.buffer;

@@ -733,11 +734,5 @@ }

if (c === 0x9 || c === 0xA || c === 0xD) {
this.parse_error = true;
continue;
}
//TODO: If code point is not a URL code point and not "%", parse error.
if (c_str === "%" &&
(!isASCIIHex(this.buffer.codePointAt(pointer + 1)) ||
!isASCIIHex(this.buffer.codePointAt(pointer + 2)))) {
this.parse_error = true;
}
if (c_str === ":" && this.url.password === null) {

@@ -748,9 +743,10 @@ this.url.password = "";

if (this.url.password !== null) {
this.url.password += simpleEncode(c);
this.url.password += passwordEncode(c);
} else {
this.url.username += simpleEncode(c);
this.url.username += usernameEncode(c);
}
}
this.buffer = "";
} else if (isNaN(c) || c_str === "/" || c_str === "\\" || c_str === "?" || c_str === "#") {
} else if (isNaN(c) || c_str === "/" || c_str === "?" || c_str === "#" ||
(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) {
this.pointer -= countSymbols(this.buffer) + 1;

@@ -767,2 +763,6 @@ this.buffer = "";

if (c_str === ":" && !this.arr_flag) {
if (specialSchemas[this.url.scheme] !== undefined && this.buffer === "") {
throw new TypeError("Invalid URL");
}
let host = parseHost(this.buffer);

@@ -775,8 +775,13 @@ this.url.host = host;

}
} else if (isNaN(c) || c_str === "/" || c_str === "\\" || c_str === "?" || c_str === "#") {
} else if (isNaN(c) || c_str === "/" || c_str === "?" || c_str === "#" ||
(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) {
--this.pointer;
if (specialSchemas[this.url.scheme] !== undefined && this.buffer === "") {
throw new TypeError("Invalid URL");
}
let host = parseHost(this.buffer);
this.url.host = host;
this.buffer = "";
this.state = STATES.RELATIVE_PATH_START;
this.state = STATES.PATH_START;
if (this.state_override) {

@@ -797,10 +802,22 @@ return false;

URLStateMachine.prototype["parse" + STATES.RELATIVE_PATH_START] = function parseScheme(c, c_str) {
if (c_str === "\\") {
URLStateMachine.prototype["parse" + STATES.FILE_HOST] = function parseScheme(c, c_str) {
if (isNaN(c) || c_str === "/" || c_str === "\\" || c_str === "?" || c_str === "#") {
--this.pointer;
// don't need to count symbols here since we check ASCII values
if (this.buffer.length === 2 &&
isASCIIAlpha(this.buffer.codePointAt(0)) && (this.buffer[1] === ":" || this.buffer[1] === "|")) {
this.state = STATES.PATH;
} else if (this.buffer === "") {
this.state = STATES.PATH_START;
} else {
let host = parseHost(this.buffer);
this.url.host = host;
this.buffer = "";
this.state = STATES.PATH_START;
}
} else if (c === 0x9 || c === 0xA || c === 0xD) {
this.parse_error = true;
} else {
this.buffer += c_str;
}
this.state = STATES.RELATIVE_PATH;
if (c_str !== "\\" && c_str !== "/") {
--this.pointer;
}
};

@@ -811,7 +828,8 @@

this.buffer += c_str;
} else if (isNaN(c) || c_str === "/" || c_str === "\\" || c_str === "?" || c_str === "#") {
} else if (isNaN(c) || c_str === "/" || c_str === "?" || c_str === "#" ||
(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) {
while (this.buffer[0] === "0" && this.buffer.length > 1) {
this.buffer = this.buffer.substr(1);
}
if (this.buffer === relativeSchemas[this.url.scheme]) {
if (this.buffer === specialSchemas[this.url.scheme]) {
this.buffer = "";

@@ -824,3 +842,3 @@ }

this.buffer = "";
this.state = STATES.RELATIVE_PATH_START;
this.state = STATES.PATH_START;
--this.pointer;

@@ -835,5 +853,137 @@ } else if (c === 0x9 || c === 0xA || c === 0xD) {

URLStateMachine.prototype["parse" + STATES.PATH_START] = function parseScheme(c, c_str) {
if (specialSchemas[this.url.scheme] !== undefined && c_str === "\\") {
this.parse_error = true;
}
this.state = STATES.PATH;
if (c_str !== "/" && !(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) {
--this.pointer;
}
};
URLStateMachine.prototype["parse" + STATES.PATH] = function parseScheme(c, c_str) {
if (isNaN(c) || c_str === "/" || (specialSchemas[this.url.scheme] !== undefined && c_str === "\\") ||
(!this.state_override && (c_str === "?" || c_str === "#"))) {
if (specialSchemas[this.url.scheme] !== undefined && c_str === "\\") {
this.parse_error = true;
}
this.buffer = bufferReplacement[this.buffer.toLowerCase()] || this.buffer;
if (this.buffer === "..") {
this.url.path.pop();
if (c_str !== "/" && !(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) {
this.url.path.push("");
}
} else if (this.buffer === "." && c_str !== "/" &&
!(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) {
this.url.path.push("");
} else if (this.buffer !== ".") {
if (this.url.scheme === "file" && this.url.path.length === 0 &&
this.buffer.length === 2 && isASCIIAlpha(this.buffer.codePointAt(0)) && this.buffer[1] === "|") {
this.buffer = this.buffer[0] + ":";
}
this.url.path.push(this.buffer);
}
this.buffer = "";
if (c_str === "?") {
this.url.query = "";
this.state = STATES.QUERY;
}
if (c_str === "#") {
this.url.fragment = "";
this.state = STATES.FRAGMENT;
}
} else if (c === 0x9 || c === 0xA || c === 0xD) {
this.parse_error = true;
} else {
//TODO:If c is not a URL code point and not "%", parse error.
if (c_str === "%" &&
(!isASCIIHex(at(this.input, this.pointer + 1)) ||
!isASCIIHex(at(this.input, this.pointer + 2)))) {
this.parse_error = true;
}
this.buffer += defaultEncode(c);
}
};
URLStateMachine.prototype["parse" + STATES.NON_RELATIVE_PATH] = function parseScheme(c, c_str) {
if (c_str === "?") {
this.url.query = "";
this.state = STATES.QUERY;
} else if (c_str === "#") {
this.url.fragment = "";
this.state = STATES.FRAGMENT;
} else {
// TODO: Add: not a URL code point
if (!isNaN(c) && c_str !== "%") {
this.parse_error = true;
}
if (c_str === "%" &&
(!isASCIIHex(at(this.input, this.pointer + 1)) ||
!isASCIIHex(at(this.input, this.pointer + 2)))) {
this.parse_error = true;
}
if (!isNaN(c) && c !== 0x9 && c !== 0xA && c !== 0xD) {
this.url.path[0] = this.url.path[0] + simpleEncode(c);
}
}
};
URLStateMachine.prototype["parse" + STATES.QUERY] = function parseScheme(c, c_str) {
if (isNaN(c) || (!this.state_override && c_str === "#")) {
if (specialSchemas[this.url.scheme] === undefined || this.url.scheme === "ws" || this.url.scheme === "wss") {
this.encoding_override = "utf-8";
}
const buffer = new Buffer(this.buffer); //TODO: Use encoding override instead
for (let i = 0; i < buffer.length; ++i) {
if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 ||
buffer[i] === 0x3C || buffer[i] === 0x3E) {
this.url.query += percentEncode(buffer[i]);
} else {
this.url.query += String.fromCodePoint(buffer[i]);
}
}
this.buffer = "";
if (c_str === "#") {
this.url.fragment = "";
this.state = STATES.FRAGMENT;
}
} else if (c === 0x9 || c === 0xA || c === 0xD) {
this.parse_error = true;
} else {
//TODO: If c is not a URL code point and not "%", parse error.
if (c_str === "%" &&
(!isASCIIHex(at(this.input, this.pointer + 1)) ||
!isASCIIHex(at(this.input, this.pointer + 2)))) {
this.parse_error = true;
} else {
this.buffer += c_str;
}
}
};
URLStateMachine.prototype["parse" + STATES.FRAGMENT] = function parseScheme(c, c_str) {
if (isNaN(c)) { // do nothing
} else if (c === 0x0 || c === 0x9 || c === 0xA || c === 0xD) {
this.parse_error = true;
} else {
//TODO: If c is not a URL code point and not "%", parse error.
if (c_str === "%" &&
(!isASCIIHex(at(this.input, this.pointer + 1)) ||
!isASCIIHex(at(this.input, this.pointer + 2)))) {
this.parse_error = true;
} else {
this.url.fragment += c_str;
}
}
};
function serializeURL(url, excludeFragment) {
let output = url.scheme + ":";
if (url.isRelative) {
if (url.host !== null) {
output += "//" + url.username;

@@ -850,5 +1000,8 @@ if (url.password !== null) {

}
}
if (url.nonRelative) {
output += url.path[0];
} else {
output += "/" + url.path.join("/");
} else {
output += url.scheme_data;
}

@@ -871,10 +1024,10 @@

}
let result = tuple.scheme + "://";
result += tr46.toUnicode(tuple.host, false).domain;
if (relativeSchemas[tuple.scheme] && tuple.port !== relativeSchemas[tuple.scheme]) {
if (specialSchemas[tuple.scheme] && tuple.port !== specialSchemas[tuple.scheme]) {
result += ":" + tuple.port;
}
return result;

@@ -951,3 +1104,3 @@ }

}
const url = this[urlSymbol].url;

@@ -959,4 +1112,4 @@ switch (url.scheme) {

} catch (e) {
// Chrome behaviour
return "://";
// serializing an opaque identifier returns "null"
return "null";
}

@@ -973,3 +1126,3 @@ break;

host: url.host,
port: url.port === "" ? relativeSchemas[url.scheme] : url.port
port: url.port === "" ? specialSchemas[url.scheme] : url.port
});

@@ -980,4 +1133,4 @@ case "file":

default:
// Chrome behaviour, Firefox returns "null"
return this[urlSymbol].url.scheme + "://";
// serializing an opaque identifier returns "null"
return "null";
}

@@ -1003,3 +1156,3 @@ },

set username(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
if (this[urlSymbol] === null || this[urlSymbol].url.host === null || this[urlSymbol].url.nonRelative) {
return;

@@ -1019,3 +1172,3 @@ }

set password(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
if (this[urlSymbol] === null || this[urlSymbol].url.host === null || this[urlSymbol].url.nonRelative) {
return;

@@ -1032,3 +1185,3 @@ }

get host() {
if (this[urlSymbol] === null) {
if (this[urlSymbol] === null || this[urlSymbol].url.host === null) {
return "";

@@ -1040,3 +1193,3 @@ }

set host(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
if (this[urlSymbol] === null || this[urlSymbol].url.nonRelative) {
return;

@@ -1048,3 +1201,3 @@ }

get hostname() {
if (this[urlSymbol] === null) {
if (this[urlSymbol] === null || this[urlSymbol].url.host === null) {
return "";

@@ -1055,3 +1208,3 @@ }

set hostname(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
if (this[urlSymbol] === null || this[urlSymbol].url.nonRelative) {
return;

@@ -1069,3 +1222,3 @@ }

set port(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative || this[urlSymbol].url.scheme === "file") {
if (this[urlSymbol] === null || this[urlSymbol].url.nonRelative || this[urlSymbol].url.scheme === "file") {
return;

@@ -1080,4 +1233,4 @@ }

}
if (!this[urlSymbol].url.isRelative) {
return this[urlSymbol].url.scheme_data;
if (this[urlSymbol].url.nonRelative) {
return this[urlSymbol].url.path[0];
}

@@ -1088,7 +1241,7 @@

set pathname(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
if (this[urlSymbol] === null || this[urlSymbol].url.nonRelative) {
return;
}
this[urlSymbol].url.path = [];
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.RELATIVE_PATH_START);
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.PATH_START);
},

@@ -1199,4 +1352,4 @@

setTheInput(obj, null, null);
mixin(URLUtils, obj);
};
{
"name": "whatwg-url",
"version": "0.2.1",
"version": "0.3.0",
"description": "An implementation of the WHATWG URL algorithm",
"main": "lib/url.js",
"author": {
"name": "Sebastian Mayr",
"email": "Sebastian Mayr <github@smayr.name>"
},
"author": "Sebastian Mayr <github@smayr.name>",
"license": "MIT",
"repository": "jsdom/whatwg-url",
"dependencies": {

@@ -11,0 +10,0 @@ "tr46": "~0.0.1"

# WHATWG-URL
WHATWG-URL is a full implementation of the [WHATWG URL](https://url.spec.whatwg.org/) specification.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc