11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst assert = require('assert');
41cb0ef41Sopenharmony_ciconst url = require('url');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciif (!common.hasIntl)
71cb0ef41Sopenharmony_ci  common.skip('missing Intl');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci// Formatting tests to verify that it'll format slightly wonky content to a
101cb0ef41Sopenharmony_ci// valid URL.
111cb0ef41Sopenharmony_ciconst formatTests = {
121cb0ef41Sopenharmony_ci  'http://example.com?': {
131cb0ef41Sopenharmony_ci    href: 'http://example.com/?',
141cb0ef41Sopenharmony_ci    protocol: 'http:',
151cb0ef41Sopenharmony_ci    slashes: true,
161cb0ef41Sopenharmony_ci    host: 'example.com',
171cb0ef41Sopenharmony_ci    hostname: 'example.com',
181cb0ef41Sopenharmony_ci    search: '?',
191cb0ef41Sopenharmony_ci    query: {},
201cb0ef41Sopenharmony_ci    pathname: '/'
211cb0ef41Sopenharmony_ci  },
221cb0ef41Sopenharmony_ci  'http://example.com?foo=bar#frag': {
231cb0ef41Sopenharmony_ci    href: 'http://example.com/?foo=bar#frag',
241cb0ef41Sopenharmony_ci    protocol: 'http:',
251cb0ef41Sopenharmony_ci    host: 'example.com',
261cb0ef41Sopenharmony_ci    hostname: 'example.com',
271cb0ef41Sopenharmony_ci    hash: '#frag',
281cb0ef41Sopenharmony_ci    search: '?foo=bar',
291cb0ef41Sopenharmony_ci    query: 'foo=bar',
301cb0ef41Sopenharmony_ci    pathname: '/'
311cb0ef41Sopenharmony_ci  },
321cb0ef41Sopenharmony_ci  'http://example.com?foo=@bar#frag': {
331cb0ef41Sopenharmony_ci    href: 'http://example.com/?foo=@bar#frag',
341cb0ef41Sopenharmony_ci    protocol: 'http:',
351cb0ef41Sopenharmony_ci    host: 'example.com',
361cb0ef41Sopenharmony_ci    hostname: 'example.com',
371cb0ef41Sopenharmony_ci    hash: '#frag',
381cb0ef41Sopenharmony_ci    search: '?foo=@bar',
391cb0ef41Sopenharmony_ci    query: 'foo=@bar',
401cb0ef41Sopenharmony_ci    pathname: '/'
411cb0ef41Sopenharmony_ci  },
421cb0ef41Sopenharmony_ci  'http://example.com?foo=/bar/#frag': {
431cb0ef41Sopenharmony_ci    href: 'http://example.com/?foo=/bar/#frag',
441cb0ef41Sopenharmony_ci    protocol: 'http:',
451cb0ef41Sopenharmony_ci    host: 'example.com',
461cb0ef41Sopenharmony_ci    hostname: 'example.com',
471cb0ef41Sopenharmony_ci    hash: '#frag',
481cb0ef41Sopenharmony_ci    search: '?foo=/bar/',
491cb0ef41Sopenharmony_ci    query: 'foo=/bar/',
501cb0ef41Sopenharmony_ci    pathname: '/'
511cb0ef41Sopenharmony_ci  },
521cb0ef41Sopenharmony_ci  'http://example.com?foo=?bar/#frag': {
531cb0ef41Sopenharmony_ci    href: 'http://example.com/?foo=?bar/#frag',
541cb0ef41Sopenharmony_ci    protocol: 'http:',
551cb0ef41Sopenharmony_ci    host: 'example.com',
561cb0ef41Sopenharmony_ci    hostname: 'example.com',
571cb0ef41Sopenharmony_ci    hash: '#frag',
581cb0ef41Sopenharmony_ci    search: '?foo=?bar/',
591cb0ef41Sopenharmony_ci    query: 'foo=?bar/',
601cb0ef41Sopenharmony_ci    pathname: '/'
611cb0ef41Sopenharmony_ci  },
621cb0ef41Sopenharmony_ci  'http://example.com#frag=?bar/#frag': {
631cb0ef41Sopenharmony_ci    href: 'http://example.com/#frag=?bar/#frag',
641cb0ef41Sopenharmony_ci    protocol: 'http:',
651cb0ef41Sopenharmony_ci    host: 'example.com',
661cb0ef41Sopenharmony_ci    hostname: 'example.com',
671cb0ef41Sopenharmony_ci    hash: '#frag=?bar/#frag',
681cb0ef41Sopenharmony_ci    pathname: '/'
691cb0ef41Sopenharmony_ci  },
701cb0ef41Sopenharmony_ci  'http://google.com" onload="alert(42)/': {
711cb0ef41Sopenharmony_ci    href: 'http://google.com/%22%20onload=%22alert(42)/',
721cb0ef41Sopenharmony_ci    protocol: 'http:',
731cb0ef41Sopenharmony_ci    host: 'google.com',
741cb0ef41Sopenharmony_ci    pathname: '/%22%20onload=%22alert(42)/'
751cb0ef41Sopenharmony_ci  },
761cb0ef41Sopenharmony_ci  'http://a.com/a/b/c?s#h': {
771cb0ef41Sopenharmony_ci    href: 'http://a.com/a/b/c?s#h',
781cb0ef41Sopenharmony_ci    protocol: 'http',
791cb0ef41Sopenharmony_ci    host: 'a.com',
801cb0ef41Sopenharmony_ci    pathname: 'a/b/c',
811cb0ef41Sopenharmony_ci    hash: 'h',
821cb0ef41Sopenharmony_ci    search: 's'
831cb0ef41Sopenharmony_ci  },
841cb0ef41Sopenharmony_ci  'xmpp:isaacschlueter@jabber.org': {
851cb0ef41Sopenharmony_ci    href: 'xmpp:isaacschlueter@jabber.org',
861cb0ef41Sopenharmony_ci    protocol: 'xmpp:',
871cb0ef41Sopenharmony_ci    host: 'jabber.org',
881cb0ef41Sopenharmony_ci    auth: 'isaacschlueter',
891cb0ef41Sopenharmony_ci    hostname: 'jabber.org'
901cb0ef41Sopenharmony_ci  },
911cb0ef41Sopenharmony_ci  'http://atpass:foo%40bar@127.0.0.1/': {
921cb0ef41Sopenharmony_ci    href: 'http://atpass:foo%40bar@127.0.0.1/',
931cb0ef41Sopenharmony_ci    auth: 'atpass:foo@bar',
941cb0ef41Sopenharmony_ci    hostname: '127.0.0.1',
951cb0ef41Sopenharmony_ci    protocol: 'http:',
961cb0ef41Sopenharmony_ci    pathname: '/'
971cb0ef41Sopenharmony_ci  },
981cb0ef41Sopenharmony_ci  'http://atslash%2F%40:%2F%40@foo/': {
991cb0ef41Sopenharmony_ci    href: 'http://atslash%2F%40:%2F%40@foo/',
1001cb0ef41Sopenharmony_ci    auth: 'atslash/@:/@',
1011cb0ef41Sopenharmony_ci    hostname: 'foo',
1021cb0ef41Sopenharmony_ci    protocol: 'http:',
1031cb0ef41Sopenharmony_ci    pathname: '/'
1041cb0ef41Sopenharmony_ci  },
1051cb0ef41Sopenharmony_ci  'svn+ssh://foo/bar': {
1061cb0ef41Sopenharmony_ci    href: 'svn+ssh://foo/bar',
1071cb0ef41Sopenharmony_ci    hostname: 'foo',
1081cb0ef41Sopenharmony_ci    protocol: 'svn+ssh:',
1091cb0ef41Sopenharmony_ci    pathname: '/bar',
1101cb0ef41Sopenharmony_ci    slashes: true
1111cb0ef41Sopenharmony_ci  },
1121cb0ef41Sopenharmony_ci  'dash-test://foo/bar': {
1131cb0ef41Sopenharmony_ci    href: 'dash-test://foo/bar',
1141cb0ef41Sopenharmony_ci    hostname: 'foo',
1151cb0ef41Sopenharmony_ci    protocol: 'dash-test:',
1161cb0ef41Sopenharmony_ci    pathname: '/bar',
1171cb0ef41Sopenharmony_ci    slashes: true
1181cb0ef41Sopenharmony_ci  },
1191cb0ef41Sopenharmony_ci  'dash-test:foo/bar': {
1201cb0ef41Sopenharmony_ci    href: 'dash-test:foo/bar',
1211cb0ef41Sopenharmony_ci    hostname: 'foo',
1221cb0ef41Sopenharmony_ci    protocol: 'dash-test:',
1231cb0ef41Sopenharmony_ci    pathname: '/bar'
1241cb0ef41Sopenharmony_ci  },
1251cb0ef41Sopenharmony_ci  'dot.test://foo/bar': {
1261cb0ef41Sopenharmony_ci    href: 'dot.test://foo/bar',
1271cb0ef41Sopenharmony_ci    hostname: 'foo',
1281cb0ef41Sopenharmony_ci    protocol: 'dot.test:',
1291cb0ef41Sopenharmony_ci    pathname: '/bar',
1301cb0ef41Sopenharmony_ci    slashes: true
1311cb0ef41Sopenharmony_ci  },
1321cb0ef41Sopenharmony_ci  'dot.test:foo/bar': {
1331cb0ef41Sopenharmony_ci    href: 'dot.test:foo/bar',
1341cb0ef41Sopenharmony_ci    hostname: 'foo',
1351cb0ef41Sopenharmony_ci    protocol: 'dot.test:',
1361cb0ef41Sopenharmony_ci    pathname: '/bar'
1371cb0ef41Sopenharmony_ci  },
1381cb0ef41Sopenharmony_ci  // IPv6 support
1391cb0ef41Sopenharmony_ci  'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': {
1401cb0ef41Sopenharmony_ci    href: 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature',
1411cb0ef41Sopenharmony_ci    protocol: 'coap:',
1421cb0ef41Sopenharmony_ci    auth: 'u:p',
1431cb0ef41Sopenharmony_ci    hostname: '::1',
1441cb0ef41Sopenharmony_ci    port: '61616',
1451cb0ef41Sopenharmony_ci    pathname: '/.well-known/r',
1461cb0ef41Sopenharmony_ci    search: 'n=Temperature'
1471cb0ef41Sopenharmony_ci  },
1481cb0ef41Sopenharmony_ci  'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton': {
1491cb0ef41Sopenharmony_ci    href: 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton',
1501cb0ef41Sopenharmony_ci    protocol: 'coap',
1511cb0ef41Sopenharmony_ci    host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616',
1521cb0ef41Sopenharmony_ci    pathname: '/s/stopButton'
1531cb0ef41Sopenharmony_ci  },
1541cb0ef41Sopenharmony_ci  'http://[::]/': {
1551cb0ef41Sopenharmony_ci    href: 'http://[::]/',
1561cb0ef41Sopenharmony_ci    protocol: 'http:',
1571cb0ef41Sopenharmony_ci    hostname: '[::]',
1581cb0ef41Sopenharmony_ci    pathname: '/'
1591cb0ef41Sopenharmony_ci  },
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  // Encode context-specific delimiters in path and query, but do not touch
1621cb0ef41Sopenharmony_ci  // other non-delimiter chars like `%`.
1631cb0ef41Sopenharmony_ci  // <https://github.com/nodejs/node-v0.x-archive/issues/4082>
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci  // `#`,`?` in path
1661cb0ef41Sopenharmony_ci  '/path/to/%%23%3F+=&.txt?foo=theA1#bar': {
1671cb0ef41Sopenharmony_ci    href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar',
1681cb0ef41Sopenharmony_ci    pathname: '/path/to/%#?+=&.txt',
1691cb0ef41Sopenharmony_ci    query: {
1701cb0ef41Sopenharmony_ci      foo: 'theA1'
1711cb0ef41Sopenharmony_ci    },
1721cb0ef41Sopenharmony_ci    hash: '#bar'
1731cb0ef41Sopenharmony_ci  },
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  // `#`,`?` in path + `#` in query
1761cb0ef41Sopenharmony_ci  '/path/to/%%23%3F+=&.txt?foo=the%231#bar': {
1771cb0ef41Sopenharmony_ci    href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar',
1781cb0ef41Sopenharmony_ci    pathname: '/path/to/%#?+=&.txt',
1791cb0ef41Sopenharmony_ci    query: {
1801cb0ef41Sopenharmony_ci      foo: 'the#1'
1811cb0ef41Sopenharmony_ci    },
1821cb0ef41Sopenharmony_ci    hash: '#bar'
1831cb0ef41Sopenharmony_ci  },
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci  // `#` in path end + `#` in query
1861cb0ef41Sopenharmony_ci  '/path/to/%%23?foo=the%231#bar': {
1871cb0ef41Sopenharmony_ci    href: '/path/to/%%23?foo=the%231#bar',
1881cb0ef41Sopenharmony_ci    pathname: '/path/to/%#',
1891cb0ef41Sopenharmony_ci    query: {
1901cb0ef41Sopenharmony_ci      foo: 'the#1'
1911cb0ef41Sopenharmony_ci    },
1921cb0ef41Sopenharmony_ci    hash: '#bar'
1931cb0ef41Sopenharmony_ci  },
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci  // `?` and `#` in path and search
1961cb0ef41Sopenharmony_ci  'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': {
1971cb0ef41Sopenharmony_ci    href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag',
1981cb0ef41Sopenharmony_ci    protocol: 'http:',
1991cb0ef41Sopenharmony_ci    hostname: 'ex.com',
2001cb0ef41Sopenharmony_ci    hash: '#frag',
2011cb0ef41Sopenharmony_ci    search: '?abc=the#1?&foo=bar',
2021cb0ef41Sopenharmony_ci    pathname: '/foo?100%m#r',
2031cb0ef41Sopenharmony_ci  },
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  // `?` and `#` in search only
2061cb0ef41Sopenharmony_ci  'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': {
2071cb0ef41Sopenharmony_ci    href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag',
2081cb0ef41Sopenharmony_ci    protocol: 'http:',
2091cb0ef41Sopenharmony_ci    hostname: 'ex.com',
2101cb0ef41Sopenharmony_ci    hash: '#frag',
2111cb0ef41Sopenharmony_ci    search: '?abc=the#1?&foo=bar',
2121cb0ef41Sopenharmony_ci    pathname: '/fooA100%mBr',
2131cb0ef41Sopenharmony_ci  },
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  // Multiple `#` in search
2161cb0ef41Sopenharmony_ci  'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag': {
2171cb0ef41Sopenharmony_ci    href: 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag',
2181cb0ef41Sopenharmony_ci    protocol: 'http:',
2191cb0ef41Sopenharmony_ci    slashes: true,
2201cb0ef41Sopenharmony_ci    host: 'example.com',
2211cb0ef41Sopenharmony_ci    hostname: 'example.com',
2221cb0ef41Sopenharmony_ci    hash: '#frag',
2231cb0ef41Sopenharmony_ci    search: '?foo=bar#1#2#3&abc=#4##5',
2241cb0ef41Sopenharmony_ci    query: {},
2251cb0ef41Sopenharmony_ci    pathname: '/'
2261cb0ef41Sopenharmony_ci  },
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci  // More than 255 characters in hostname which exceeds the limit
2291cb0ef41Sopenharmony_ci  [`http://${'a'.repeat(255)}.com/node`]: {
2301cb0ef41Sopenharmony_ci    href: 'http:///node',
2311cb0ef41Sopenharmony_ci    protocol: 'http:',
2321cb0ef41Sopenharmony_ci    slashes: true,
2331cb0ef41Sopenharmony_ci    host: '',
2341cb0ef41Sopenharmony_ci    hostname: '',
2351cb0ef41Sopenharmony_ci    pathname: '/node',
2361cb0ef41Sopenharmony_ci    path: '/node'
2371cb0ef41Sopenharmony_ci  },
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  // Greater than or equal to 63 characters after `.` in hostname
2401cb0ef41Sopenharmony_ci  [`http://www.${'z'.repeat(63)}example.com/node`]: {
2411cb0ef41Sopenharmony_ci    href: `http://www.${'z'.repeat(63)}example.com/node`,
2421cb0ef41Sopenharmony_ci    protocol: 'http:',
2431cb0ef41Sopenharmony_ci    slashes: true,
2441cb0ef41Sopenharmony_ci    host: `www.${'z'.repeat(63)}example.com`,
2451cb0ef41Sopenharmony_ci    hostname: `www.${'z'.repeat(63)}example.com`,
2461cb0ef41Sopenharmony_ci    pathname: '/node',
2471cb0ef41Sopenharmony_ci    path: '/node'
2481cb0ef41Sopenharmony_ci  },
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci  // https://github.com/nodejs/node/issues/3361
2511cb0ef41Sopenharmony_ci  'file:///home/user': {
2521cb0ef41Sopenharmony_ci    href: 'file:///home/user',
2531cb0ef41Sopenharmony_ci    protocol: 'file',
2541cb0ef41Sopenharmony_ci    pathname: '/home/user',
2551cb0ef41Sopenharmony_ci    path: '/home/user'
2561cb0ef41Sopenharmony_ci  },
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci  // surrogate in auth
2591cb0ef41Sopenharmony_ci  'http://%F0%9F%98%80@www.example.com/': {
2601cb0ef41Sopenharmony_ci    href: 'http://%F0%9F%98%80@www.example.com/',
2611cb0ef41Sopenharmony_ci    protocol: 'http:',
2621cb0ef41Sopenharmony_ci    auth: '\uD83D\uDE00',
2631cb0ef41Sopenharmony_ci    hostname: 'www.example.com',
2641cb0ef41Sopenharmony_ci    pathname: '/'
2651cb0ef41Sopenharmony_ci  }
2661cb0ef41Sopenharmony_ci};
2671cb0ef41Sopenharmony_cifor (const u in formatTests) {
2681cb0ef41Sopenharmony_ci  const expect = formatTests[u].href;
2691cb0ef41Sopenharmony_ci  delete formatTests[u].href;
2701cb0ef41Sopenharmony_ci  const actual = url.format(u);
2711cb0ef41Sopenharmony_ci  const actualObj = url.format(formatTests[u]);
2721cb0ef41Sopenharmony_ci  assert.strictEqual(actual, expect,
2731cb0ef41Sopenharmony_ci                     `wonky format(${u}) == ${expect}\nactual:${actual}`);
2741cb0ef41Sopenharmony_ci  assert.strictEqual(actualObj, expect,
2751cb0ef41Sopenharmony_ci                     `wonky format(${JSON.stringify(formatTests[u])}) == ${
2761cb0ef41Sopenharmony_ci                       expect}\nactual: ${actualObj}`);
2771cb0ef41Sopenharmony_ci}
278