url: performance improvement in URL implementation
Yields about a 25% average performance improvement PR-URL: https://github.com/nodejs/node/pull/10469 Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
parent
509ff1b9e4
commit
2213f3640a
391
lib/internal/url.js
Normal file → Executable file
391
lib/internal/url.js
Normal file → Executable file
@ -67,50 +67,151 @@ class TupleOrigin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toString(unicode = false) {
|
toString(unicode = false) {
|
||||||
var result = this.scheme;
|
var result = this[kScheme];
|
||||||
result += '://';
|
result += '://';
|
||||||
result += unicode ? URL.domainToUnicode(this.host) : this.host;
|
result += unicode ? URL.domainToUnicode(this[kHost]) : this[kHost];
|
||||||
if (this.port !== undefined && this.port !== null)
|
if (this[kPort] !== undefined && this[kPort] !== null)
|
||||||
result += `:${this.port}`;
|
result += `:${this[kPort]}`;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inspect() {
|
inspect() {
|
||||||
return `TupleOrigin {
|
return `TupleOrigin {
|
||||||
scheme: ${this.scheme},
|
scheme: ${this[kScheme]},
|
||||||
host: ${this.host},
|
host: ${this[kHost]},
|
||||||
port: ${this.port},
|
port: ${this[kPort]},
|
||||||
domain: ${this.domain}
|
domain: ${this[kDomain]}
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onParseComplete(flags, protocol, username, password,
|
||||||
|
host, port, path, query, fragment) {
|
||||||
|
if (flags & binding.URL_FLAGS_FAILED)
|
||||||
|
throw new TypeError('Invalid URL');
|
||||||
|
var ctx = this[context];
|
||||||
|
ctx.flags = flags;
|
||||||
|
ctx.scheme = protocol;
|
||||||
|
ctx.username = username;
|
||||||
|
ctx.password = password;
|
||||||
|
ctx.port = port;
|
||||||
|
ctx.path = path;
|
||||||
|
ctx.query = query;
|
||||||
|
ctx.fragment = fragment;
|
||||||
|
ctx.host = host;
|
||||||
|
if (this[searchParams]) { // invoked from href setter
|
||||||
|
initSearchParams(this[searchParams], query);
|
||||||
|
} else {
|
||||||
|
this[searchParams] = new URLSearchParams(query);
|
||||||
|
}
|
||||||
|
this[searchParams][context] = this;
|
||||||
|
}
|
||||||
|
|
||||||
// Reused by URL constructor and URL#href setter.
|
// Reused by URL constructor and URL#href setter.
|
||||||
function parse(url, input, base) {
|
function parse(url, input, base) {
|
||||||
input = String(input);
|
input = String(input);
|
||||||
const base_context = base ? base[context] : undefined;
|
const base_context = base ? base[context] : undefined;
|
||||||
url[context] = new StorageObject();
|
url[context] = new StorageObject();
|
||||||
binding.parse(input.trim(), -1, base_context, undefined,
|
binding.parse(input.trim(), -1,
|
||||||
(flags, protocol, username, password,
|
base_context, undefined,
|
||||||
host, port, path, query, fragment) => {
|
onParseComplete.bind(url));
|
||||||
if (flags & binding.URL_FLAGS_FAILED)
|
}
|
||||||
throw new TypeError('Invalid URL');
|
|
||||||
url[context].flags = flags;
|
function onParseProtocolComplete(flags, protocol, username, password,
|
||||||
url[context].scheme = protocol;
|
host, port, path, query, fragment) {
|
||||||
url[context].username = username;
|
if (flags & binding.URL_FLAGS_FAILED)
|
||||||
url[context].password = password;
|
return;
|
||||||
url[context].port = port;
|
const newIsSpecial = (flags & binding.URL_FLAGS_SPECIAL) !== 0;
|
||||||
url[context].path = path;
|
const s = this[special];
|
||||||
url[context].query = query;
|
const ctx = this[context];
|
||||||
url[context].fragment = fragment;
|
if ((s && !newIsSpecial) || (!s && newIsSpecial)) {
|
||||||
url[context].host = host;
|
return;
|
||||||
if (url[searchParams]) { // invoked from href setter
|
}
|
||||||
initSearchParams(url[searchParams], query);
|
if (newIsSpecial) {
|
||||||
} else {
|
ctx.flags |= binding.URL_FLAGS_SPECIAL;
|
||||||
url[searchParams] = new URLSearchParams(query);
|
} else {
|
||||||
|
ctx.flags &= ~binding.URL_FLAGS_SPECIAL;
|
||||||
|
}
|
||||||
|
if (protocol) {
|
||||||
|
ctx.scheme = protocol;
|
||||||
|
ctx.flags |= binding.URL_FLAGS_HAS_SCHEME;
|
||||||
|
} else {
|
||||||
|
ctx.flags &= ~binding.URL_FLAGS_HAS_SCHEME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onParseHostComplete(flags, protocol, username, password,
|
||||||
|
host, port, path, query, fragment) {
|
||||||
|
if (flags & binding.URL_FLAGS_FAILED)
|
||||||
|
return;
|
||||||
|
const ctx = this[context];
|
||||||
|
if (host) {
|
||||||
|
ctx.host = host;
|
||||||
|
ctx.flags |= binding.URL_FLAGS_HAS_HOST;
|
||||||
|
} else {
|
||||||
|
ctx.flags &= ~binding.URL_FLAGS_HAS_HOST;
|
||||||
|
}
|
||||||
|
if (port !== undefined)
|
||||||
|
ctx.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onParseHostnameComplete(flags, protocol, username, password,
|
||||||
|
host, port, path, query, fragment) {
|
||||||
|
if (flags & binding.URL_FLAGS_FAILED)
|
||||||
|
return;
|
||||||
|
const ctx = this[context];
|
||||||
|
if (host) {
|
||||||
|
ctx.host = host;
|
||||||
|
ctx.flags |= binding.URL_FLAGS_HAS_HOST;
|
||||||
|
} else {
|
||||||
|
ctx.flags &= ~binding.URL_FLAGS_HAS_HOST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onParsePortComplete(flags, protocol, username, password,
|
||||||
|
host, port, path, query, fragment) {
|
||||||
|
if (flags & binding.URL_FLAGS_FAILED)
|
||||||
|
return;
|
||||||
|
this[context].port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onParsePathComplete(flags, protocol, username, password,
|
||||||
|
host, port, path, query, fragment) {
|
||||||
|
if (flags & binding.URL_FLAGS_FAILED)
|
||||||
|
return;
|
||||||
|
const ctx = this[context];
|
||||||
|
if (path) {
|
||||||
|
ctx.path = path;
|
||||||
|
ctx.flags |= binding.URL_FLAGS_HAS_PATH;
|
||||||
|
} else {
|
||||||
|
ctx.flags &= ~binding.URL_FLAGS_HAS_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onParseSearchComplete(flags, protocol, username, password,
|
||||||
|
host, port, path, query, fragment) {
|
||||||
|
if (flags & binding.URL_FLAGS_FAILED)
|
||||||
|
return;
|
||||||
|
const ctx = this[context];
|
||||||
|
if (query) {
|
||||||
|
ctx.query = query;
|
||||||
|
ctx.flags |= binding.URL_FLAGS_HAS_QUERY;
|
||||||
|
} else {
|
||||||
|
ctx.flags &= ~binding.URL_FLAGS_HAS_QUERY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onParseHashComplete(flags, protocol, username, password,
|
||||||
|
host, port, path, query, fragment) {
|
||||||
|
if (flags & binding.URL_FLAGS_FAILED)
|
||||||
|
return;
|
||||||
|
const ctx = this[context];
|
||||||
|
if (fragment) {
|
||||||
|
ctx.fragment = fragment;
|
||||||
|
ctx.flags |= binding.URL_FLAGS_HAS_FRAGMENT;
|
||||||
|
} else {
|
||||||
|
ctx.flags &= ~binding.URL_FLAGS_HAS_FRAGMENT;
|
||||||
}
|
}
|
||||||
url[searchParams][context] = url;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class URL {
|
class URL {
|
||||||
@ -121,33 +222,34 @@ class URL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get [special]() {
|
get [special]() {
|
||||||
return (this[context].flags & binding.URL_FLAGS_SPECIAL) != 0;
|
return (this[context].flags & binding.URL_FLAGS_SPECIAL) !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
get [cannotBeBase]() {
|
get [cannotBeBase]() {
|
||||||
return (this[context].flags & binding.URL_FLAGS_CANNOT_BE_BASE) != 0;
|
return (this[context].flags & binding.URL_FLAGS_CANNOT_BE_BASE) !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inspect(depth, opts) {
|
inspect(depth, opts) {
|
||||||
|
const ctx = this[context];
|
||||||
var ret = 'URL {\n';
|
var ret = 'URL {\n';
|
||||||
ret += ` href: ${this.href}\n`;
|
ret += ` href: ${this.href}\n`;
|
||||||
if (this[context].scheme !== undefined)
|
if (ctx.scheme !== undefined)
|
||||||
ret += ` protocol: ${this.protocol}\n`;
|
ret += ` protocol: ${this.protocol}\n`;
|
||||||
if (this[context].username !== undefined)
|
if (ctx.username !== undefined)
|
||||||
ret += ` username: ${this.username}\n`;
|
ret += ` username: ${this.username}\n`;
|
||||||
if (this[context].password !== undefined) {
|
if (ctx.password !== undefined) {
|
||||||
const pwd = opts.showHidden ? this[context].password : '--------';
|
const pwd = opts.showHidden ? ctx.password : '--------';
|
||||||
ret += ` password: ${pwd}\n`;
|
ret += ` password: ${pwd}\n`;
|
||||||
}
|
}
|
||||||
if (this[context].host !== undefined)
|
if (ctx.host !== undefined)
|
||||||
ret += ` hostname: ${this.hostname}\n`;
|
ret += ` hostname: ${this.hostname}\n`;
|
||||||
if (this[context].port !== undefined)
|
if (ctx.port !== undefined)
|
||||||
ret += ` port: ${this.port}\n`;
|
ret += ` port: ${this.port}\n`;
|
||||||
if (this[context].path !== undefined)
|
if (ctx.path !== undefined)
|
||||||
ret += ` pathname: ${this.pathname}\n`;
|
ret += ` pathname: ${this.pathname}\n`;
|
||||||
if (this[context].query !== undefined)
|
if (ctx.query !== undefined)
|
||||||
ret += ` search: ${this.search}\n`;
|
ret += ` search: ${this.search}\n`;
|
||||||
if (this[context].fragment !== undefined)
|
if (ctx.fragment !== undefined)
|
||||||
ret += ` hash: ${this.hash}\n`;
|
ret += ` hash: ${this.hash}\n`;
|
||||||
if (opts.showHidden) {
|
if (opts.showHidden) {
|
||||||
ret += ` cannot-be-base: ${this[cannotBeBase]}\n`;
|
ret += ` cannot-be-base: ${this[cannotBeBase]}\n`;
|
||||||
@ -171,18 +273,19 @@ Object.defineProperties(URL.prototype, {
|
|||||||
options.fragment !== undefined ?
|
options.fragment !== undefined ?
|
||||||
!!options.fragment : true;
|
!!options.fragment : true;
|
||||||
const unicode = !!options.unicode;
|
const unicode = !!options.unicode;
|
||||||
|
const ctx = this[context];
|
||||||
var ret;
|
var ret;
|
||||||
if (this.protocol)
|
if (this.protocol)
|
||||||
ret = this.protocol;
|
ret = this.protocol;
|
||||||
if (this[context].host !== undefined) {
|
if (ctx.host !== undefined) {
|
||||||
ret += '//';
|
ret += '//';
|
||||||
const has_username = typeof this[context].username === 'string';
|
const has_username = typeof ctx.username === 'string';
|
||||||
const has_password = typeof this[context].password === 'string';
|
const has_password = typeof ctx.password === 'string';
|
||||||
if (has_username || has_password) {
|
if (has_username || has_password) {
|
||||||
if (has_username)
|
if (has_username)
|
||||||
ret += this[context].username;
|
ret += ctx.username;
|
||||||
if (has_password)
|
if (has_password)
|
||||||
ret += `:${this[context].password}`;
|
ret += `:${ctx.password}`;
|
||||||
ret += '@';
|
ret += '@';
|
||||||
}
|
}
|
||||||
if (unicode) {
|
if (unicode) {
|
||||||
@ -192,15 +295,15 @@ Object.defineProperties(URL.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
ret += this.host;
|
ret += this.host;
|
||||||
}
|
}
|
||||||
} else if (this[context].scheme === 'file:') {
|
} else if (ctx.scheme === 'file:') {
|
||||||
ret += '//';
|
ret += '//';
|
||||||
}
|
}
|
||||||
if (this.pathname)
|
if (this.pathname)
|
||||||
ret += this.pathname;
|
ret += this.pathname;
|
||||||
if (typeof this[context].query === 'string')
|
if (typeof ctx.query === 'string')
|
||||||
ret += `?${this[context].query}`;
|
ret += `?${ctx.query}`;
|
||||||
if (fragment & typeof this[context].fragment === 'string')
|
if (fragment & typeof ctx.fragment === 'string')
|
||||||
ret += `#${this[context].fragment}`;
|
ret += `#${ctx.fragment}`;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -231,33 +334,8 @@ Object.defineProperties(URL.prototype, {
|
|||||||
scheme = String(scheme);
|
scheme = String(scheme);
|
||||||
if (scheme.length === 0)
|
if (scheme.length === 0)
|
||||||
return;
|
return;
|
||||||
binding.parse(scheme,
|
binding.parse(scheme, binding.kSchemeStart, null, this[context],
|
||||||
binding.kSchemeStart,
|
onParseProtocolComplete.bind(this));
|
||||||
null,
|
|
||||||
this[context],
|
|
||||||
(flags, protocol, username, password,
|
|
||||||
host, port, path, query, fragment) => {
|
|
||||||
if (flags & binding.URL_FLAGS_FAILED)
|
|
||||||
return;
|
|
||||||
const newIsSpecial = (flags & binding.URL_FLAGS_SPECIAL) != 0;
|
|
||||||
if ((this[special] && !newIsSpecial) ||
|
|
||||||
(!this[special] && newIsSpecial) ||
|
|
||||||
(newIsSpecial && !this[special] &&
|
|
||||||
this[context].host === undefined)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (newIsSpecial) {
|
|
||||||
this[context].flags |= binding.URL_FLAGS_SPECIAL;
|
|
||||||
} else {
|
|
||||||
this[context].flags &= ~binding.URL_FLAGS_SPECIAL;
|
|
||||||
}
|
|
||||||
if (protocol) {
|
|
||||||
this[context].scheme = protocol;
|
|
||||||
this[context].flags |= binding.URL_FLAGS_HAS_SCHEME;
|
|
||||||
} else {
|
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_SCHEME;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
username: {
|
username: {
|
||||||
@ -270,13 +348,14 @@ Object.defineProperties(URL.prototype, {
|
|||||||
username = String(username);
|
username = String(username);
|
||||||
if (!this.hostname)
|
if (!this.hostname)
|
||||||
return;
|
return;
|
||||||
|
const ctx = this[context];
|
||||||
if (!username) {
|
if (!username) {
|
||||||
this[context].username = null;
|
ctx.username = null;
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_USERNAME;
|
ctx.flags &= ~binding.URL_FLAGS_HAS_USERNAME;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this[context].username = binding.encodeAuth(username);
|
ctx.username = binding.encodeAuth(username);
|
||||||
this[context].flags |= binding.URL_FLAGS_HAS_USERNAME;
|
ctx.flags |= binding.URL_FLAGS_HAS_USERNAME;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
password: {
|
password: {
|
||||||
@ -289,25 +368,28 @@ Object.defineProperties(URL.prototype, {
|
|||||||
password = String(password);
|
password = String(password);
|
||||||
if (!this.hostname)
|
if (!this.hostname)
|
||||||
return;
|
return;
|
||||||
|
const ctx = this[context];
|
||||||
if (!password) {
|
if (!password) {
|
||||||
this[context].password = null;
|
ctx.password = null;
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_PASSWORD;
|
ctx.flags &= ~binding.URL_FLAGS_HAS_PASSWORD;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this[context].password = binding.encodeAuth(password);
|
ctx.password = binding.encodeAuth(password);
|
||||||
this[context].flags |= binding.URL_FLAGS_HAS_PASSWORD;
|
ctx.flags |= binding.URL_FLAGS_HAS_PASSWORD;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
host: {
|
host: {
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get() {
|
get() {
|
||||||
var ret = this[context].host || '';
|
const ctx = this[context];
|
||||||
if (this[context].port !== undefined)
|
var ret = ctx.host || '';
|
||||||
ret += `:${this[context].port}`;
|
if (ctx.port !== undefined)
|
||||||
|
ret += `:${ctx.port}`;
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
set(host) {
|
set(host) {
|
||||||
|
const ctx = this[context];
|
||||||
host = String(host);
|
host = String(host);
|
||||||
if (this[cannotBeBase] ||
|
if (this[cannotBeBase] ||
|
||||||
(this[special] && host.length === 0)) {
|
(this[special] && host.length === 0)) {
|
||||||
@ -316,24 +398,12 @@ Object.defineProperties(URL.prototype, {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!host) {
|
if (!host) {
|
||||||
this[context].host = null;
|
ctx.host = null;
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_HOST;
|
ctx.flags &= ~binding.URL_FLAGS_HAS_HOST;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
binding.parse(host, binding.kHost, null, this[context],
|
binding.parse(host, binding.kHost, null, ctx,
|
||||||
(flags, protocol, username, password,
|
onParseHostComplete.bind(this));
|
||||||
host, port, path, query, fragment) => {
|
|
||||||
if (flags & binding.URL_FLAGS_FAILED)
|
|
||||||
return;
|
|
||||||
if (host) {
|
|
||||||
this[context].host = host;
|
|
||||||
this[context].flags |= binding.URL_FLAGS_HAS_HOST;
|
|
||||||
} else {
|
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_HOST;
|
|
||||||
}
|
|
||||||
if (port !== undefined)
|
|
||||||
this[context].port = port;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hostname: {
|
hostname: {
|
||||||
@ -343,6 +413,7 @@ Object.defineProperties(URL.prototype, {
|
|||||||
return this[context].host || '';
|
return this[context].host || '';
|
||||||
},
|
},
|
||||||
set(host) {
|
set(host) {
|
||||||
|
const ctx = this[context];
|
||||||
host = String(host);
|
host = String(host);
|
||||||
if (this[cannotBeBase] ||
|
if (this[cannotBeBase] ||
|
||||||
(this[special] && host.length === 0)) {
|
(this[special] && host.length === 0)) {
|
||||||
@ -351,25 +422,12 @@ Object.defineProperties(URL.prototype, {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!host) {
|
if (!host) {
|
||||||
this[context].host = null;
|
ctx.host = null;
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_HOST;
|
ctx.flags &= ~binding.URL_FLAGS_HAS_HOST;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
binding.parse(host,
|
binding.parse(host, binding.kHostname, null, ctx,
|
||||||
binding.kHostname,
|
onParseHostnameComplete.bind(this));
|
||||||
null,
|
|
||||||
this[context],
|
|
||||||
(flags, protocol, username, password,
|
|
||||||
host, port, path, query, fragment) => {
|
|
||||||
if (flags & binding.URL_FLAGS_FAILED)
|
|
||||||
return;
|
|
||||||
if (host) {
|
|
||||||
this[context].host = host;
|
|
||||||
this[context].flags |= binding.URL_FLAGS_HAS_HOST;
|
|
||||||
} else {
|
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_HOST;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
port: {
|
port: {
|
||||||
@ -380,7 +438,8 @@ Object.defineProperties(URL.prototype, {
|
|||||||
return port === undefined ? '' : String(port);
|
return port === undefined ? '' : String(port);
|
||||||
},
|
},
|
||||||
set(port) {
|
set(port) {
|
||||||
if (!this[context].host || this[cannotBeBase] ||
|
const ctx = this[context];
|
||||||
|
if (!ctx.host || this[cannotBeBase] ||
|
||||||
this.protocol === 'file:')
|
this.protocol === 'file:')
|
||||||
return;
|
return;
|
||||||
port = String(port);
|
port = String(port);
|
||||||
@ -389,76 +448,46 @@ Object.defineProperties(URL.prototype, {
|
|||||||
// TODO(jasnell): This might be changing in the spec
|
// TODO(jasnell): This might be changing in the spec
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
binding.parse(port, binding.kPort, null, this[context],
|
binding.parse(port, binding.kPort, null, ctx,
|
||||||
(flags, protocol, username, password,
|
onParsePortComplete.bind(this));
|
||||||
host, port, path, query, fragment) => {
|
|
||||||
if (flags & binding.URL_FLAGS_FAILED)
|
|
||||||
return;
|
|
||||||
this[context].port = port;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pathname: {
|
pathname: {
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get() {
|
get() {
|
||||||
|
const ctx = this[context];
|
||||||
if (this[cannotBeBase])
|
if (this[cannotBeBase])
|
||||||
return this[context].path[0];
|
return ctx.path[0];
|
||||||
return this[context].path !== undefined ?
|
return ctx.path !== undefined ? `/${ctx.path.join('/')}` : '';
|
||||||
`/${this[context].path.join('/')}` : '';
|
|
||||||
},
|
},
|
||||||
set(path) {
|
set(path) {
|
||||||
if (this[cannotBeBase])
|
if (this[cannotBeBase])
|
||||||
return;
|
return;
|
||||||
path = String(path);
|
binding.parse(String(path), binding.kPathStart, null, this[context],
|
||||||
binding.parse(path,
|
onParsePathComplete.bind(this));
|
||||||
binding.kPathStart,
|
|
||||||
null,
|
|
||||||
this[context],
|
|
||||||
(flags, protocol, username, password,
|
|
||||||
host, port, path, query, fragment) => {
|
|
||||||
if (flags & binding.URL_FLAGS_FAILED)
|
|
||||||
return;
|
|
||||||
if (path) {
|
|
||||||
this[context].path = path;
|
|
||||||
this[context].flags |= binding.URL_FLAGS_HAS_PATH;
|
|
||||||
} else {
|
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_PATH;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get() {
|
get() {
|
||||||
return !this[context].query ? '' : `?${this[context].query}`;
|
const ctx = this[context];
|
||||||
|
return !ctx.query ? '' : `?${ctx.query}`;
|
||||||
},
|
},
|
||||||
set(search) {
|
set(search) {
|
||||||
|
const ctx = this[context];
|
||||||
search = String(search);
|
search = String(search);
|
||||||
if (search[0] === '?') search = search.slice(1);
|
if (search[0] === '?') search = search.slice(1);
|
||||||
if (!search) {
|
if (!search) {
|
||||||
this[context].query = null;
|
ctx.query = null;
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_QUERY;
|
ctx.flags &= ~binding.URL_FLAGS_HAS_QUERY;
|
||||||
this[searchParams][searchParams] = {};
|
this[searchParams][searchParams] = {};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this[context].query = '';
|
ctx.query = '';
|
||||||
binding.parse(search,
|
binding.parse(search, binding.kQuery, null, ctx,
|
||||||
binding.kQuery,
|
onParseSearchComplete.bind(this));
|
||||||
null,
|
|
||||||
this[context],
|
|
||||||
(flags, protocol, username, password,
|
|
||||||
host, port, path, query, fragment) => {
|
|
||||||
if (flags & binding.URL_FLAGS_FAILED)
|
|
||||||
return;
|
|
||||||
if (query) {
|
|
||||||
this[context].query = query;
|
|
||||||
this[context].flags |= binding.URL_FLAGS_HAS_QUERY;
|
|
||||||
} else {
|
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_QUERY;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this[searchParams][searchParams] = querystring.parse(search);
|
this[searchParams][searchParams] = querystring.parse(search);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -473,39 +502,29 @@ Object.defineProperties(URL.prototype, {
|
|||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get() {
|
get() {
|
||||||
return !this[context].fragment ? '' : `#${this[context].fragment}`;
|
const ctx = this[context];
|
||||||
|
return !ctx.fragment ? '' : `#${ctx.fragment}`;
|
||||||
},
|
},
|
||||||
set(hash) {
|
set(hash) {
|
||||||
|
const ctx = this[context];
|
||||||
hash = String(hash);
|
hash = String(hash);
|
||||||
if (this.protocol === 'javascript:')
|
if (this.protocol === 'javascript:')
|
||||||
return;
|
return;
|
||||||
if (!hash) {
|
if (!hash) {
|
||||||
this[context].fragment = null;
|
ctx.fragment = null;
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_FRAGMENT;
|
ctx.flags &= ~binding.URL_FLAGS_HAS_FRAGMENT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hash[0] === '#') hash = hash.slice(1);
|
if (hash[0] === '#') hash = hash.slice(1);
|
||||||
this[context].fragment = '';
|
ctx.fragment = '';
|
||||||
binding.parse(hash,
|
binding.parse(hash, binding.kFragment, null, ctx,
|
||||||
binding.kFragment,
|
onParseHashComplete.bind(this));
|
||||||
null,
|
|
||||||
this[context],
|
|
||||||
(flags, protocol, username, password,
|
|
||||||
host, port, path, query, fragment) => {
|
|
||||||
if (flags & binding.URL_FLAGS_FAILED)
|
|
||||||
return;
|
|
||||||
if (fragment) {
|
|
||||||
this[context].fragment = fragment;
|
|
||||||
this[context].flags |= binding.URL_FLAGS_HAS_FRAGMENT;
|
|
||||||
} else {
|
|
||||||
this[context].flags &= ~binding.URL_FLAGS_HAS_FRAGMENT;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var hexTable = new Array(256);
|
const hexTable = new Array(256);
|
||||||
|
|
||||||
for (var i = 0; i < 256; ++i)
|
for (var i = 0; i < 256; ++i)
|
||||||
hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
|
hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
|
||||||
function encodeAuth(str) {
|
function encodeAuth(str) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user