url: refactor binding imports in internal/url

PR-URL: https://github.com/nodejs/node/pull/12717
Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com
This commit is contained in:
James M Snell 2017-04-27 20:14:26 -07:00
parent b331ba6ca9
commit 97ec72b76d

View File

@ -5,20 +5,44 @@ const {
hexTable, hexTable,
isHexTable isHexTable
} = require('internal/querystring'); } = require('internal/querystring');
const { getConstructorOf } = require('internal/util'); const { getConstructorOf } = require('internal/util');
const errors = require('internal/errors'); const errors = require('internal/errors');
const binding = process.binding('url'); const querystring = require('querystring');
const { platform } = process;
const isWindows = platform === 'win32';
const {
domainToASCII: _domainToASCII,
domainToUnicode: _domainToUnicode,
encodeAuth,
toUSVString: _toUSVString,
parse: _parse,
setURLConstructor,
URL_FLAGS_CANNOT_BE_BASE,
URL_FLAGS_HAS_FRAGMENT,
URL_FLAGS_HAS_HOST,
URL_FLAGS_HAS_PASSWORD,
URL_FLAGS_HAS_PATH,
URL_FLAGS_HAS_QUERY,
URL_FLAGS_HAS_USERNAME,
URL_FLAGS_SPECIAL,
kFragment,
kHost,
kHostname,
kPathStart,
kPort,
kQuery,
kSchemeStart
} = process.binding('url');
const context = Symbol('context'); const context = Symbol('context');
const cannotBeBase = Symbol('cannot-be-base'); const cannotBeBase = Symbol('cannot-be-base');
const cannotHaveUsernamePasswordPort = const cannotHaveUsernamePasswordPort =
Symbol('cannot-have-username-password-port'); Symbol('cannot-have-username-password-port');
const special = Symbol('special'); const special = Symbol('special');
const searchParams = Symbol('query'); const searchParams = Symbol('query');
const querystring = require('querystring');
const { platform } = process;
const isWindows = platform === 'win32';
const kFormat = Symbol('format'); const kFormat = Symbol('format');
// https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object // https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object
@ -35,7 +59,7 @@ function toUSVString(val) {
const match = unpairedSurrogateRe.exec(str); const match = unpairedSurrogateRe.exec(str);
if (!match) if (!match)
return str; return str;
return binding.toUSVString(str, match.index); return _toUSVString(str, match.index);
} }
// Refs: https://html.spec.whatwg.org/multipage/browsers.html#concept-origin-opaque // Refs: https://html.spec.whatwg.org/multipage/browsers.html#concept-origin-opaque
@ -74,10 +98,10 @@ function onParseComplete(flags, protocol, username, password,
var ctx = this[context]; var ctx = this[context];
ctx.flags = flags; ctx.flags = flags;
ctx.scheme = protocol; ctx.scheme = protocol;
ctx.username = (flags & binding.URL_FLAGS_HAS_USERNAME) !== 0 ? username : ''; ctx.username = (flags & URL_FLAGS_HAS_USERNAME) !== 0 ? username : '';
ctx.password = (flags & binding.URL_FLAGS_HAS_PASSWORD) !== 0 ? password : ''; ctx.password = (flags & URL_FLAGS_HAS_PASSWORD) !== 0 ? password : '';
ctx.port = port; ctx.port = port;
ctx.path = (flags & binding.URL_FLAGS_HAS_PATH) !== 0 ? path : []; ctx.path = (flags & URL_FLAGS_HAS_PATH) !== 0 ? path : [];
ctx.query = query; ctx.query = query;
ctx.fragment = fragment; ctx.fragment = fragment;
ctx.host = host; ctx.host = host;
@ -98,18 +122,17 @@ function onParseError(flags, input) {
function parse(url, input, base) { function parse(url, input, base) {
const base_context = base ? base[context] : undefined; const base_context = base ? base[context] : undefined;
url[context] = new URLContext(); url[context] = new URLContext();
binding.parse(input.trim(), -1, _parse(input.trim(), -1, base_context, undefined,
base_context, undefined, onParseComplete.bind(url), onParseError);
onParseComplete.bind(url), onParseError);
} }
function onParseProtocolComplete(flags, protocol, username, password, function onParseProtocolComplete(flags, protocol, username, password,
host, port, path, query, fragment) { host, port, path, query, fragment) {
const ctx = this[context]; const ctx = this[context];
if ((flags & binding.URL_FLAGS_SPECIAL) !== 0) { if ((flags & URL_FLAGS_SPECIAL) !== 0) {
ctx.flags |= binding.URL_FLAGS_SPECIAL; ctx.flags |= URL_FLAGS_SPECIAL;
} else { } else {
ctx.flags &= ~binding.URL_FLAGS_SPECIAL; ctx.flags &= ~URL_FLAGS_SPECIAL;
} }
ctx.scheme = protocol; ctx.scheme = protocol;
} }
@ -117,12 +140,12 @@ function onParseProtocolComplete(flags, protocol, username, password,
function onParseHostComplete(flags, protocol, username, password, function onParseHostComplete(flags, protocol, username, password,
host, port, path, query, fragment) { host, port, path, query, fragment) {
const ctx = this[context]; const ctx = this[context];
if ((flags & binding.URL_FLAGS_HAS_HOST) !== 0) { if ((flags & URL_FLAGS_HAS_HOST) !== 0) {
ctx.host = host; ctx.host = host;
ctx.flags |= binding.URL_FLAGS_HAS_HOST; ctx.flags |= URL_FLAGS_HAS_HOST;
} else { } else {
ctx.host = null; ctx.host = null;
ctx.flags &= ~binding.URL_FLAGS_HAS_HOST; ctx.flags &= ~URL_FLAGS_HAS_HOST;
} }
if (port !== null) if (port !== null)
ctx.port = port; ctx.port = port;
@ -131,12 +154,12 @@ function onParseHostComplete(flags, protocol, username, password,
function onParseHostnameComplete(flags, protocol, username, password, function onParseHostnameComplete(flags, protocol, username, password,
host, port, path, query, fragment) { host, port, path, query, fragment) {
const ctx = this[context]; const ctx = this[context];
if ((flags & binding.URL_FLAGS_HAS_HOST) !== 0) { if ((flags & URL_FLAGS_HAS_HOST) !== 0) {
ctx.host = host; ctx.host = host;
ctx.flags |= binding.URL_FLAGS_HAS_HOST; ctx.flags |= URL_FLAGS_HAS_HOST;
} else { } else {
ctx.host = null; ctx.host = null;
ctx.flags &= ~binding.URL_FLAGS_HAS_HOST; ctx.flags &= ~URL_FLAGS_HAS_HOST;
} }
} }
@ -148,18 +171,18 @@ function onParsePortComplete(flags, protocol, username, password,
function onParsePathComplete(flags, protocol, username, password, function onParsePathComplete(flags, protocol, username, password,
host, port, path, query, fragment) { host, port, path, query, fragment) {
const ctx = this[context]; const ctx = this[context];
if ((flags & binding.URL_FLAGS_HAS_PATH) !== 0) { if ((flags & URL_FLAGS_HAS_PATH) !== 0) {
ctx.path = path; ctx.path = path;
ctx.flags |= binding.URL_FLAGS_HAS_PATH; ctx.flags |= URL_FLAGS_HAS_PATH;
} else { } else {
ctx.path = []; ctx.path = [];
ctx.flags &= ~binding.URL_FLAGS_HAS_PATH; ctx.flags &= ~URL_FLAGS_HAS_PATH;
} }
// The C++ binding may set host to empty string. // The C++ binding may set host to empty string.
if ((flags & binding.URL_FLAGS_HAS_HOST) !== 0) { if ((flags & URL_FLAGS_HAS_HOST) !== 0) {
ctx.host = host; ctx.host = host;
ctx.flags |= binding.URL_FLAGS_HAS_HOST; ctx.flags |= URL_FLAGS_HAS_HOST;
} }
} }
@ -185,11 +208,11 @@ class URL {
} }
get [special]() { get [special]() {
return (this[context].flags & binding.URL_FLAGS_SPECIAL) !== 0; return (this[context].flags & URL_FLAGS_SPECIAL) !== 0;
} }
get [cannotBeBase]() { get [cannotBeBase]() {
return (this[context].flags & binding.URL_FLAGS_CANNOT_BE_BASE) !== 0; return (this[context].flags & URL_FLAGS_CANNOT_BE_BASE) !== 0;
} }
// https://url.spec.whatwg.org/#cannot-have-a-username-password-port // https://url.spec.whatwg.org/#cannot-have-a-username-password-port
@ -348,8 +371,8 @@ Object.defineProperties(URL.prototype, {
(ctx.host === '' || ctx.host === null)) { (ctx.host === '' || ctx.host === null)) {
return; return;
} }
binding.parse(scheme, binding.kSchemeStart, null, ctx, _parse(scheme, kSchemeStart, null, ctx,
onParseProtocolComplete.bind(this)); onParseProtocolComplete.bind(this));
} }
}, },
username: { username: {
@ -366,11 +389,11 @@ Object.defineProperties(URL.prototype, {
const ctx = this[context]; const ctx = this[context];
if (username === '') { if (username === '') {
ctx.username = ''; ctx.username = '';
ctx.flags &= ~binding.URL_FLAGS_HAS_USERNAME; ctx.flags &= ~URL_FLAGS_HAS_USERNAME;
return; return;
} }
ctx.username = binding.encodeAuth(username); ctx.username = encodeAuth(username);
ctx.flags |= binding.URL_FLAGS_HAS_USERNAME; ctx.flags |= URL_FLAGS_HAS_USERNAME;
} }
}, },
password: { password: {
@ -387,11 +410,11 @@ Object.defineProperties(URL.prototype, {
const ctx = this[context]; const ctx = this[context];
if (password === '') { if (password === '') {
ctx.password = ''; ctx.password = '';
ctx.flags &= ~binding.URL_FLAGS_HAS_PASSWORD; ctx.flags &= ~URL_FLAGS_HAS_PASSWORD;
return; return;
} }
ctx.password = binding.encodeAuth(password); ctx.password = encodeAuth(password);
ctx.flags |= binding.URL_FLAGS_HAS_PASSWORD; ctx.flags |= URL_FLAGS_HAS_PASSWORD;
} }
}, },
host: { host: {
@ -412,8 +435,7 @@ Object.defineProperties(URL.prototype, {
// Cannot set the host if cannot-be-base is set // Cannot set the host if cannot-be-base is set
return; return;
} }
binding.parse(host, binding.kHost, null, ctx, _parse(host, kHost, null, ctx, onParseHostComplete.bind(this));
onParseHostComplete.bind(this));
} }
}, },
hostname: { hostname: {
@ -430,8 +452,7 @@ Object.defineProperties(URL.prototype, {
// Cannot set the host if cannot-be-base is set // Cannot set the host if cannot-be-base is set
return; return;
} }
binding.parse(host, binding.kHostname, null, ctx, _parse(host, kHostname, null, ctx, onParseHostnameComplete.bind(this));
onParseHostnameComplete.bind(this));
} }
}, },
port: { port: {
@ -451,8 +472,7 @@ Object.defineProperties(URL.prototype, {
ctx.port = null; ctx.port = null;
return; return;
} }
binding.parse(port, binding.kPort, null, ctx, _parse(port, kPort, null, ctx, onParsePortComplete.bind(this));
onParsePortComplete.bind(this));
} }
}, },
pathname: { pathname: {
@ -471,8 +491,8 @@ Object.defineProperties(URL.prototype, {
path = `${path}`; path = `${path}`;
if (this[cannotBeBase]) if (this[cannotBeBase])
return; return;
binding.parse(path, binding.kPathStart, null, this[context], _parse(path, kPathStart, null, this[context],
onParsePathComplete.bind(this)); onParsePathComplete.bind(this));
} }
}, },
search: { search: {
@ -489,14 +509,13 @@ Object.defineProperties(URL.prototype, {
search = toUSVString(search); search = toUSVString(search);
if (search === '') { if (search === '') {
ctx.query = null; ctx.query = null;
ctx.flags &= ~binding.URL_FLAGS_HAS_QUERY; ctx.flags &= ~URL_FLAGS_HAS_QUERY;
} else { } else {
if (search[0] === '?') search = search.slice(1); if (search[0] === '?') search = search.slice(1);
ctx.query = ''; ctx.query = '';
ctx.flags |= binding.URL_FLAGS_HAS_QUERY; ctx.flags |= URL_FLAGS_HAS_QUERY;
if (search) { if (search) {
binding.parse(search, binding.kQuery, null, ctx, _parse(search, kQuery, null, ctx, onParseSearchComplete.bind(this));
onParseSearchComplete.bind(this));
} }
} }
initSearchParams(this[searchParams], search); initSearchParams(this[searchParams], search);
@ -524,14 +543,13 @@ Object.defineProperties(URL.prototype, {
hash = `${hash}`; hash = `${hash}`;
if (!hash) { if (!hash) {
ctx.fragment = null; ctx.fragment = null;
ctx.flags &= ~binding.URL_FLAGS_HAS_FRAGMENT; ctx.flags &= ~URL_FLAGS_HAS_FRAGMENT;
return; return;
} }
if (hash[0] === '#') hash = hash.slice(1); if (hash[0] === '#') hash = hash.slice(1);
ctx.fragment = ''; ctx.fragment = '';
ctx.flags |= binding.URL_FLAGS_HAS_FRAGMENT; ctx.flags |= URL_FLAGS_HAS_FRAGMENT;
binding.parse(hash, binding.kFragment, null, ctx, _parse(hash, kFragment, null, ctx, onParseHashComplete.bind(this));
onParseHashComplete.bind(this));
} }
}, },
toJSON: { toJSON: {
@ -553,10 +571,10 @@ function update(url, params) {
const serializedParams = params.toString(); const serializedParams = params.toString();
if (serializedParams) { if (serializedParams) {
ctx.query = serializedParams; ctx.query = serializedParams;
ctx.flags |= binding.URL_FLAGS_HAS_QUERY; ctx.flags |= URL_FLAGS_HAS_QUERY;
} else { } else {
ctx.query = null; ctx.query = null;
ctx.flags &= ~binding.URL_FLAGS_HAS_QUERY; ctx.flags &= ~URL_FLAGS_HAS_QUERY;
} }
} }
@ -1257,7 +1275,7 @@ function domainToASCII(domain) {
throw new errors.TypeError('ERR_MISSING_ARGS', 'domain'); throw new errors.TypeError('ERR_MISSING_ARGS', 'domain');
// toUSVString is not needed. // toUSVString is not needed.
return binding.domainToASCII(`${domain}`); return _domainToASCII(`${domain}`);
} }
function domainToUnicode(domain) { function domainToUnicode(domain) {
@ -1265,7 +1283,7 @@ function domainToUnicode(domain) {
throw new errors.TypeError('ERR_MISSING_ARGS', 'domain'); throw new errors.TypeError('ERR_MISSING_ARGS', 'domain');
// toUSVString is not needed. // toUSVString is not needed.
return binding.domainToUnicode(`${domain}`); return _domainToUnicode(`${domain}`);
} }
// Utility function that converts a URL object into an ordinary // Utility function that converts a URL object into an ordinary
@ -1365,10 +1383,10 @@ function constructUrl(flags, protocol, username, password,
var ctx = new URLContext(); var ctx = new URLContext();
ctx.flags = flags; ctx.flags = flags;
ctx.scheme = protocol; ctx.scheme = protocol;
ctx.username = (flags & binding.URL_FLAGS_HAS_USERNAME) !== 0 ? username : ''; ctx.username = (flags & URL_FLAGS_HAS_USERNAME) !== 0 ? username : '';
ctx.password = (flags & binding.URL_FLAGS_HAS_PASSWORD) !== 0 ? password : ''; ctx.password = (flags & URL_FLAGS_HAS_PASSWORD) !== 0 ? password : '';
ctx.port = port; ctx.port = port;
ctx.path = (flags & binding.URL_FLAGS_HAS_PATH) !== 0 ? path : []; ctx.path = (flags & URL_FLAGS_HAS_PATH) !== 0 ? path : [];
ctx.query = query; ctx.query = query;
ctx.fragment = fragment; ctx.fragment = fragment;
ctx.host = host; ctx.host = host;
@ -1378,7 +1396,7 @@ function constructUrl(flags, protocol, username, password,
initSearchParams(url[searchParams], query); initSearchParams(url[searchParams], query);
return url; return url;
} }
binding.setURLConstructor(constructUrl); setURLConstructor(constructUrl);
module.exports = { module.exports = {
toUSVString, toUSVString,