271 lines
6.9 KiB
JavaScript
Executable File
271 lines
6.9 KiB
JavaScript
Executable File
"use strict";
|
|
var URL = require('./URL');
|
|
|
|
module.exports = URLUtils;
|
|
|
|
// Allow the `x == null` pattern. This is eslint's "null: 'ignore'" option,
|
|
// but jshint doesn't support this.
|
|
/* jshint eqeqeq: false */
|
|
|
|
// This is an abstract superclass for Location, HTMLAnchorElement and
|
|
// other types that have the standard complement of "URL decomposition
|
|
// IDL attributes". This is now standardized as URLUtils, see:
|
|
// https://url.spec.whatwg.org/#urlutils
|
|
// Subclasses must define a getter/setter on href.
|
|
// The getter and setter methods parse and rebuild the URL on each
|
|
// invocation; there is no attempt to cache the value and be more efficient
|
|
function URLUtils() {}
|
|
URLUtils.prototype = Object.create(Object.prototype, {
|
|
|
|
_url: { get: function() {
|
|
// XXX: this should do the "Reinitialize url" steps, and "null" should
|
|
// be a valid return value.
|
|
return new URL(this.href);
|
|
} },
|
|
|
|
protocol: {
|
|
get: function() {
|
|
var url = this._url;
|
|
if (url && url.scheme) return url.scheme + ":";
|
|
else return ":";
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
if (url.isAbsolute()) {
|
|
v = v.replace(/:+$/, "");
|
|
v = v.replace(/[^-+\.a-zA-Z0-9]/g, URL.percentEncode);
|
|
if (v.length > 0) {
|
|
url.scheme = v;
|
|
output = url.toString();
|
|
}
|
|
}
|
|
this.href = output;
|
|
},
|
|
},
|
|
|
|
host: {
|
|
get: function() {
|
|
var url = this._url;
|
|
if (url.isAbsolute() && url.isAuthorityBased())
|
|
return url.host + (url.port ? (":" + url.port) : "");
|
|
else
|
|
return "";
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
if (url.isAbsolute() && url.isAuthorityBased()) {
|
|
v = v.replace(/[^-+\._~!$&'()*,;:=a-zA-Z0-9]/g, URL.percentEncode);
|
|
if (v.length > 0) {
|
|
url.host = v;
|
|
delete url.port;
|
|
output = url.toString();
|
|
}
|
|
}
|
|
this.href = output;
|
|
},
|
|
},
|
|
|
|
hostname: {
|
|
get: function() {
|
|
var url = this._url;
|
|
if (url.isAbsolute() && url.isAuthorityBased())
|
|
return url.host;
|
|
else
|
|
return "";
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
if (url.isAbsolute() && url.isAuthorityBased()) {
|
|
v = v.replace(/^\/+/, "");
|
|
v = v.replace(/[^-+\._~!$&'()*,;:=a-zA-Z0-9]/g, URL.percentEncode);
|
|
if (v.length > 0) {
|
|
url.host = v;
|
|
output = url.toString();
|
|
}
|
|
}
|
|
this.href = output;
|
|
},
|
|
},
|
|
|
|
port: {
|
|
get: function() {
|
|
var url = this._url;
|
|
if (url.isAbsolute() && url.isAuthorityBased() && url.port!==undefined)
|
|
return url.port;
|
|
else
|
|
return "";
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
if (url.isAbsolute() && url.isAuthorityBased()) {
|
|
v = '' + v;
|
|
v = v.replace(/[^0-9].*$/, "");
|
|
v = v.replace(/^0+/, "");
|
|
if (v.length === 0) v = "0";
|
|
if (parseInt(v, 10) <= 65535) {
|
|
url.port = v;
|
|
output = url.toString();
|
|
}
|
|
}
|
|
this.href = output;
|
|
},
|
|
},
|
|
|
|
pathname: {
|
|
get: function() {
|
|
var url = this._url;
|
|
if (url.isAbsolute() && url.isHierarchical())
|
|
return url.path;
|
|
else
|
|
return "";
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
if (url.isAbsolute() && url.isHierarchical()) {
|
|
if (v.charAt(0) !== "/")
|
|
v = "/" + v;
|
|
v = v.replace(/[^-+\._~!$&'()*,;:=@\/a-zA-Z0-9]/g, URL.percentEncode);
|
|
url.path = v;
|
|
output = url.toString();
|
|
}
|
|
this.href = output;
|
|
},
|
|
},
|
|
|
|
search: {
|
|
get: function() {
|
|
var url = this._url;
|
|
if (url.isAbsolute() && url.isHierarchical() && url.query!==undefined)
|
|
return "?" + url.query;
|
|
else
|
|
return "";
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
if (url.isAbsolute() && url.isHierarchical()) {
|
|
if (v.charAt(0) === "?") v = v.substring(1);
|
|
v = v.replace(/[^-+\._~!$&'()*,;:=@\/?a-zA-Z0-9]/g, URL.percentEncode);
|
|
url.query = v;
|
|
output = url.toString();
|
|
}
|
|
this.href = output;
|
|
},
|
|
},
|
|
|
|
hash: {
|
|
get: function() {
|
|
var url = this._url;
|
|
if (url == null || url.fragment == null || url.fragment === '') {
|
|
return "";
|
|
} else {
|
|
return "#" + url.fragment;
|
|
}
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
|
|
if (v.charAt(0) === "#") v = v.substring(1);
|
|
v = v.replace(/[^-+\._~!$&'()*,;:=@\/?a-zA-Z0-9]/g, URL.percentEncode);
|
|
url.fragment = v;
|
|
output = url.toString();
|
|
|
|
this.href = output;
|
|
},
|
|
},
|
|
|
|
username: {
|
|
get: function() {
|
|
var url = this._url;
|
|
return url.username || '';
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
if (url.isAbsolute()) {
|
|
v = v.replace(/[\x00-\x1F\x7F-\uFFFF "#<>?`\/@\\:]/g, URL.percentEncode);
|
|
url.username = v;
|
|
output = url.toString();
|
|
}
|
|
this.href = output;
|
|
},
|
|
},
|
|
|
|
password: {
|
|
get: function() {
|
|
var url = this._url;
|
|
return url.password || '';
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
if (url.isAbsolute()) {
|
|
if (v==='') {
|
|
url.password = null;
|
|
} else {
|
|
v = v.replace(/[\x00-\x1F\x7F-\uFFFF "#<>?`\/@\\]/g, URL.percentEncode);
|
|
url.password = v;
|
|
}
|
|
output = url.toString();
|
|
}
|
|
this.href = output;
|
|
},
|
|
},
|
|
|
|
origin: { get: function() {
|
|
var url = this._url;
|
|
if (url == null) { return ''; }
|
|
var originForPort = function(defaultPort) {
|
|
var origin = [url.scheme, url.host, +url.port || defaultPort];
|
|
// XXX should be "unicode serialization"
|
|
return origin[0] + '://' + origin[1] +
|
|
(origin[2] === defaultPort ? '' : (':' + origin[2]));
|
|
};
|
|
switch (url.scheme) {
|
|
case 'ftp':
|
|
return originForPort(21);
|
|
case 'gopher':
|
|
return originForPort(70);
|
|
case 'http':
|
|
case 'ws':
|
|
return originForPort(80);
|
|
case 'https':
|
|
case 'wss':
|
|
return originForPort(443);
|
|
default:
|
|
// this is what chrome does
|
|
return url.scheme + '://';
|
|
}
|
|
} },
|
|
|
|
/*
|
|
searchParams: {
|
|
get: function() {
|
|
var url = this._url;
|
|
// XXX
|
|
},
|
|
set: function(v) {
|
|
var output = this.href;
|
|
var url = new URL(output);
|
|
// XXX
|
|
this.href = output;
|
|
},
|
|
},
|
|
*/
|
|
});
|
|
|
|
URLUtils._inherit = function(proto) {
|
|
// copy getters/setters from URLUtils to o.
|
|
Object.getOwnPropertyNames(URLUtils.prototype).forEach(function(p) {
|
|
if (p==='constructor' || p==='href') { return; }
|
|
var desc = Object.getOwnPropertyDescriptor(URLUtils.prototype, p);
|
|
Object.defineProperty(proto, p, desc);
|
|
});
|
|
};
|