Skip to content

Commit 94872e7

Browse files
committed
[fix] Do not incorrectly set the slashes property to true
Set it to `true` only if the protocol is special or if it is actually followed by two forward slashes.
1 parent 81ab967 commit 94872e7

File tree

2 files changed

+66
-18
lines changed

2 files changed

+66
-18
lines changed

index.js

+32-12
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
var required = require('requires-port')
44
, qs = require('querystringify')
5-
, slashes = /^[A-Za-z][A-Za-z0-9+-.]*:[\\/]+/
6-
, protocolre = /^([a-z][a-z0-9.+-]*:)?([\\/]{1,})?([\S\s]*)/i
5+
, slashes = /^[A-Za-z][A-Za-z0-9+-.]*:\/\//
6+
, protocolre = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i
77
, whitespace = '[\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF]'
88
, left = new RegExp('^'+ whitespace +'+');
99

@@ -138,26 +138,46 @@ function extractProtocol(address, location) {
138138

139139
var match = protocolre.exec(address);
140140
var protocol = match[1] ? match[1].toLowerCase() : '';
141-
var rest = match[2] ? match[2] + match[3] : match[3];
142-
var slashes = !!(match[2] && match[2].length >= 2);
141+
var forwardSlashes = !!match[2];
142+
var otherSlashes = !!match[3];
143+
var slashesCount = 0;
144+
var rest;
145+
146+
if (forwardSlashes) {
147+
if (otherSlashes) {
148+
rest = match[2] + match[3] + match[4];
149+
slashesCount = match[2].length + match[3].length;
150+
} else {
151+
rest = match[2] + match[4];
152+
slashesCount = match[2].length;
153+
}
154+
} else {
155+
if (otherSlashes) {
156+
rest = match[3] + match[4];
157+
slashesCount = match[3].length;
158+
} else {
159+
rest = match[4]
160+
}
161+
}
143162

144163
if (protocol === 'file:') {
145-
if (slashes) {
164+
if (slashesCount >= 2) {
146165
rest = rest.slice(2);
147166
}
148167
} else if (isSpecial(protocol)) {
149-
rest = match[3];
168+
rest = match[4];
150169
} else if (protocol) {
151-
if (rest.indexOf('//') === 0) {
170+
if (forwardSlashes) {
152171
rest = rest.slice(2);
153172
}
154-
} else if (slashes && location.hostname) {
155-
rest = match[3];
173+
} else if (slashesCount >= 2 && location.hostname) {
174+
rest = match[4];
156175
}
157176

158177
return {
159178
protocol: protocol,
160-
slashes: slashes,
179+
slashes: forwardSlashes || isSpecial(protocol),
180+
slashesCount: slashesCount,
161181
rest: rest
162182
};
163183
}
@@ -260,7 +280,7 @@ function Url(address, location, parser) {
260280
//
261281
if (
262282
url.protocol === 'file:' ||
263-
(!extracted.slashes && !isSpecial(extracted.protocol))
283+
(extracted.slashesCount < 2 && !isSpecial(extracted.protocol))
264284
) {
265285
instructions[3] = [/(.*)/, 'pathname'];
266286
}
@@ -472,7 +492,7 @@ function toString(stringify) {
472492

473493
if (protocol && protocol.charAt(protocol.length - 1) !== ':') protocol += ':';
474494

475-
var result = protocol + (url.slashes || url.protocol === 'file:' ? '//' : '');
495+
var result = protocol + (url.slashes || isSpecial(url.protocol) ? '//' : '');
476496

477497
if (url.username) {
478498
result += url.username;

test/test.js

+34-6
Original file line numberDiff line numberDiff line change
@@ -71,29 +71,33 @@ describe('url-parse', function () {
7171
assume(parse.extractProtocol('http://example.com')).eql({
7272
slashes: true,
7373
protocol: 'http:',
74-
rest: 'example.com'
74+
rest: 'example.com',
75+
slashesCount: 2
7576
});
7677
});
7778

7879
it('extracts the protocol data for nothing', function () {
7980
assume(parse.extractProtocol('')).eql({
8081
slashes: false,
8182
protocol: '',
82-
rest: ''
83+
rest: '',
84+
slashesCount: 0
8385
});
8486
});
8587

8688
it('correctly resolves paths', function () {
8789
assume(parse.extractProtocol('/foo')).eql({
8890
slashes: false,
8991
protocol: '',
90-
rest: '/foo'
92+
rest: '/foo',
93+
slashesCount: 1
9194
});
9295

9396
assume(parse.extractProtocol('//foo/bar')).eql({
9497
slashes: true,
9598
protocol: '',
96-
rest: '//foo/bar'
99+
rest: '//foo/bar',
100+
slashesCount: 2
97101
});
98102
});
99103

@@ -103,15 +107,17 @@ describe('url-parse', function () {
103107
assume(parse.extractProtocol(input)).eql({
104108
slashes: false,
105109
protocol: '',
106-
rest: input
110+
rest: input,
111+
slashesCount: 0
107112
});
108113
});
109114

110115
it('trimsLeft', function () {
111116
assume(parse.extractProtocol(' javascript://foo')).eql({
112117
slashes: true,
113118
protocol: 'javascript:',
114-
rest: 'foo'
119+
rest: 'foo',
120+
slashesCount: 2
115121
});
116122
});
117123
});
@@ -281,6 +287,12 @@ describe('url-parse', function () {
281287

282288
assume(parsed.host).equals('what-is-up.com');
283289
assume(parsed.href).equals('http://what-is-up.com/');
290+
291+
url = '\\\\\\\\what-is-up.com'
292+
parsed = parse(url, parse('http://google.com'));
293+
294+
assume(parsed.host).equals('what-is-up.com');
295+
assume(parsed.href).equals('http://what-is-up.com/');
284296
});
285297

286298
it('ignores slashes after the protocol for special URLs', function () {
@@ -290,32 +302,44 @@ describe('url-parse', function () {
290302
assume(parsed.host).equals('github.com');
291303
assume(parsed.hostname).equals('github.com');
292304
assume(parsed.pathname).equals('/foo/bar');
305+
assume(parsed.slashes).is.true();
306+
assume(parsed.href).equals('https://github.com/foo/bar');
293307

294308
url = 'https:/\\/\\/\\github.com/foo/bar';
295309
parsed = parse(url);
296310
assume(parsed.host).equals('github.com');
297311
assume(parsed.hostname).equals('github.com');
298312
assume(parsed.pathname).equals('/foo/bar');
313+
assume(parsed.slashes).is.true();
314+
assume(parsed.href).equals('https://github.com/foo/bar');
299315

300316
url = 'https:/github.com/foo/bar';
301317
parsed = parse(url);
302318
assume(parsed.host).equals('github.com');
303319
assume(parsed.pathname).equals('/foo/bar');
320+
assume(parsed.slashes).is.true();
321+
assume(parsed.href).equals('https://github.com/foo/bar');
304322

305323
url = 'https:\\github.com/foo/bar';
306324
parsed = parse(url);
307325
assume(parsed.host).equals('github.com');
308326
assume(parsed.pathname).equals('/foo/bar');
327+
assume(parsed.slashes).is.true();
328+
assume(parsed.href).equals('https://github.com/foo/bar');
309329

310330
url = 'https:github.com/foo/bar';
311331
parsed = parse(url);
312332
assume(parsed.host).equals('github.com');
313333
assume(parsed.pathname).equals('/foo/bar');
334+
assume(parsed.slashes).is.true();
335+
assume(parsed.href).equals('https://github.com/foo/bar');
314336

315337
url = 'https:github.com/foo/bar';
316338
parsed = parse(url);
317339
assume(parsed.host).equals('github.com');
318340
assume(parsed.pathname).equals('/foo/bar');
341+
assume(parsed.slashes).is.true();
342+
assume(parsed.href).equals('https://github.com/foo/bar');
319343
});
320344

321345
it('handles slashes after the protocol for non special URLs', function () {
@@ -325,24 +349,28 @@ describe('url-parse', function () {
325349
assume(parsed.hostname).equals('');
326350
assume(parsed.pathname).equals('example.com');
327351
assume(parsed.href).equals('foo:example.com');
352+
assume(parsed.slashes).is.false();
328353

329354
url = 'foo:/example.com';
330355
parsed = parse(url);
331356
assume(parsed.hostname).equals('');
332357
assume(parsed.pathname).equals('/example.com');
333358
assume(parsed.href).equals('foo:/example.com');
359+
assume(parsed.slashes).is.false();
334360

335361
url = 'foo://example.com';
336362
parsed = parse(url);
337363
assume(parsed.hostname).equals('example.com');
338364
assume(parsed.pathname).equals('/');
339365
assume(parsed.href).equals('foo://example.com/');
366+
assume(parsed.slashes).is.true();
340367

341368
url = 'foo:///example.com';
342369
parsed = parse(url);
343370
assume(parsed.hostname).equals('');
344371
assume(parsed.pathname).equals('/example.com');
345372
assume(parsed.href).equals('foo:///example.com');
373+
assume(parsed.slashes).is.true();
346374
})
347375

348376
describe('origin', function () {

0 commit comments

Comments
 (0)