Skip to content

Commit ba888e4

Browse files
committed
url: Fixed pathname setter, throw when parsing http, ftp, ws URLs without host or path.
1 parent 86a40d6 commit ba888e4

File tree

2 files changed

+58
-15
lines changed

2 files changed

+58
-15
lines changed

url/testdata/url_test.js

+33
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ assert.sameValue(myURL.href, "https://abc:123@example.com/");
8888
myURL = new URL("https://example.org/abc/xyz?123");
8989
myURL.pathname = "/abcdef";
9090
assert.sameValue(myURL.href, "https://example.org/abcdef?123");
91+
assert.sameValue(myURL.toString(), "https://example.org/abcdef?123");
9192

9293
myURL.pathname = "";
9394
assert.sameValue(myURL.href, "https://example.org/?123");
@@ -96,6 +97,32 @@ myURL.pathname = "á";
9697
assert.sameValue(myURL.pathname, "/%C3%A1");
9798
assert.sameValue(myURL.href, "https://example.org/%C3%A1?123");
9899

100+
myURL = new URL("file:///./abc");
101+
assert.sameValue(myURL.pathname, "/abc");
102+
103+
myURL = new URL("fish://host/.");
104+
assert.sameValue(myURL.pathname, "/");
105+
myURL.pathname = ".";
106+
assert.sameValue(myURL.pathname, "/");
107+
108+
myURL = new URL("fish://host/a/../b");
109+
assert.sameValue(myURL.pathname, '/b');
110+
myURL.pathname = 'a/../c';
111+
assert.sameValue(myURL.pathname, '/c');
112+
113+
myURL = new URL("file://");
114+
assert.sameValue(myURL.pathname, "/");
115+
assert.sameValue(myURL.href, "file:///");
116+
117+
assert.throwsNodeError(() => {
118+
new URL("http://");
119+
}, TypeError, "ERR_INVALID_URL");
120+
121+
// myURL = new URL("fish://");
122+
// assert.sameValue(myURL.pathname, "");
123+
// Currently returns "fish:"
124+
// assert.sameValue(myURL.href, "fish://");
125+
99126
// port
100127

101128
myURL = new URL("https://example.org:8888");
@@ -227,3 +254,9 @@ assert.sameValue(myURL.toString(), "https://example.com/?first=one");
227254
assert.sameValue(url.domainToUnicode('xn--fiq228c.com'), "中文.com");
228255
assert.sameValue(url.domainToUnicode('xn--iñvalid.com'), "");
229256
}
257+
258+
{
259+
const url = new URL("otpauth://totp");
260+
url.pathname = 'domain.com Domain:user@domain.com';
261+
assert.sameValue(url.toString(), 'otpauth://totp/domain.com%20Domain:user@domain.com');
262+
}

url/url.go

+25-15
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package url
33
import (
44
"math"
55
"net/url"
6+
"path"
67
"reflect"
78
"strconv"
89
"strings"
@@ -131,6 +132,14 @@ func isSpecialProtocol(protocol string) bool {
131132
return false
132133
}
133134

135+
func isSpecialNetProtocol(protocol string) bool {
136+
switch protocol {
137+
case "https", "http", "ftp", "wss", "ws":
138+
return true
139+
}
140+
return false
141+
}
142+
134143
func clearURLPort(u *url.URL) {
135144
u.Host = u.Hostname()
136145
}
@@ -167,6 +176,9 @@ func (m *urlModule) parseURL(s string, isBase bool) *url.URL {
167176
if isBase && !u.IsAbs() {
168177
panic(m.newInvalidURLError(URLNotAbsolute, s))
169178
}
179+
if isSpecialNetProtocol(u.Scheme) && u.Host == "" && u.Path == "" {
180+
panic(m.newInvalidURLError(InvalidURL, s))
181+
}
170182
if portStr := u.Port(); portStr != "" {
171183
if port, err := strconv.Atoi(portStr); err != nil || isDefaultURLPort(u.Scheme, port) {
172184
u.Host = u.Hostname() // Clear port
@@ -182,12 +194,19 @@ func fixRawQuery(u *url.URL) {
182194
}
183195
}
184196

197+
func cleanPath(p, proto string) string {
198+
if !strings.HasPrefix(p, "/") && (isSpecialProtocol(proto) || p != "") {
199+
p = "/" + p
200+
}
201+
if p != "" {
202+
return path.Clean(p)
203+
}
204+
return ""
205+
}
206+
185207
func (m *urlModule) fixURL(u *url.URL) {
186-
switch u.Scheme {
187-
case "https", "http", "ftp", "wss", "ws":
188-
if u.Path == "" {
189-
u.Path = "/"
190-
}
208+
u.Path = cleanPath(u.Path, u.Scheme)
209+
if isSpecialNetProtocol(u.Scheme) {
191210
hostname := u.Hostname()
192211
lh := strings.ToLower(hostname)
193212
ch, err := idna.Punycode.ToASCII(lh)
@@ -262,16 +281,7 @@ func (m *urlModule) createURLPrototype() *goja.Object {
262281
m.defineURLAccessorProp(p, "pathname", func(u *nodeURL) interface{} {
263282
return u.url.EscapedPath()
264283
}, func(u *nodeURL, arg goja.Value) {
265-
p := arg.String()
266-
if _, err := url.Parse(p); err == nil {
267-
switch u.url.Scheme {
268-
case "https", "http", "ftp", "ws", "wss":
269-
if !strings.HasPrefix(p, "/") {
270-
p = "/" + p
271-
}
272-
}
273-
u.url.Path = p
274-
}
284+
u.url.Path = cleanPath(arg.String(), u.url.Scheme)
275285
})
276286

277287
// origin

0 commit comments

Comments
 (0)