11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst { isWindows } = require('../common');
31cb0ef41Sopenharmony_ciconst assert = require('assert');
41cb0ef41Sopenharmony_ciconst url = require('url');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci{
71cb0ef41Sopenharmony_ci  const fileURL = url.pathToFileURL('test/').href;
81cb0ef41Sopenharmony_ci  assert.ok(fileURL.startsWith('file:///'));
91cb0ef41Sopenharmony_ci  assert.ok(fileURL.endsWith('/'));
101cb0ef41Sopenharmony_ci}
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci{
131cb0ef41Sopenharmony_ci  const fileURL = url.pathToFileURL('test\\').href;
141cb0ef41Sopenharmony_ci  assert.ok(fileURL.startsWith('file:///'));
151cb0ef41Sopenharmony_ci  if (isWindows)
161cb0ef41Sopenharmony_ci    assert.ok(fileURL.endsWith('/'));
171cb0ef41Sopenharmony_ci  else
181cb0ef41Sopenharmony_ci    assert.ok(fileURL.endsWith('%5C'));
191cb0ef41Sopenharmony_ci}
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci{
221cb0ef41Sopenharmony_ci  const fileURL = url.pathToFileURL('test/%').href;
231cb0ef41Sopenharmony_ci  assert.ok(fileURL.includes('%25'));
241cb0ef41Sopenharmony_ci}
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci{
271cb0ef41Sopenharmony_ci  if (isWindows) {
281cb0ef41Sopenharmony_ci    // UNC path: \\server\share\resource
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci    // Missing server:
311cb0ef41Sopenharmony_ci    assert.throws(() => url.pathToFileURL('\\\\\\no-server'), {
321cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_VALUE',
331cb0ef41Sopenharmony_ci    });
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci    // Missing share or resource:
361cb0ef41Sopenharmony_ci    assert.throws(() => url.pathToFileURL('\\\\host'), {
371cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_VALUE',
381cb0ef41Sopenharmony_ci    });
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci    // Regression test for direct String.prototype.startsWith call
411cb0ef41Sopenharmony_ci    assert.throws(() => url.pathToFileURL([
421cb0ef41Sopenharmony_ci      '\\\\',
431cb0ef41Sopenharmony_ci      { [Symbol.toPrimitive]: () => 'blep\\blop' },
441cb0ef41Sopenharmony_ci    ]), {
451cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
461cb0ef41Sopenharmony_ci    });
471cb0ef41Sopenharmony_ci    assert.throws(() => url.pathToFileURL(['\\\\', 'blep\\blop']), {
481cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
491cb0ef41Sopenharmony_ci    });
501cb0ef41Sopenharmony_ci    assert.throws(() => url.pathToFileURL({
511cb0ef41Sopenharmony_ci      [Symbol.toPrimitive]: () => '\\\\blep\\blop',
521cb0ef41Sopenharmony_ci    }), {
531cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
541cb0ef41Sopenharmony_ci    });
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  } else {
571cb0ef41Sopenharmony_ci    // UNC paths on posix are considered a single path that has backslashes:
581cb0ef41Sopenharmony_ci    const fileURL = url.pathToFileURL('\\\\nas\\share\\path.txt').href;
591cb0ef41Sopenharmony_ci    assert.match(fileURL, /file:\/\/.+%5C%5Cnas%5Cshare%5Cpath\.txt$/);
601cb0ef41Sopenharmony_ci  }
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci{
641cb0ef41Sopenharmony_ci  let testCases;
651cb0ef41Sopenharmony_ci  if (isWindows) {
661cb0ef41Sopenharmony_ci    testCases = [
671cb0ef41Sopenharmony_ci      // Lowercase ascii alpha
681cb0ef41Sopenharmony_ci      { path: 'C:\\foo', expected: 'file:///C:/foo' },
691cb0ef41Sopenharmony_ci      // Uppercase ascii alpha
701cb0ef41Sopenharmony_ci      { path: 'C:\\FOO', expected: 'file:///C:/FOO' },
711cb0ef41Sopenharmony_ci      // dir
721cb0ef41Sopenharmony_ci      { path: 'C:\\dir\\foo', expected: 'file:///C:/dir/foo' },
731cb0ef41Sopenharmony_ci      // trailing separator
741cb0ef41Sopenharmony_ci      { path: 'C:\\dir\\', expected: 'file:///C:/dir/' },
751cb0ef41Sopenharmony_ci      // dot
761cb0ef41Sopenharmony_ci      { path: 'C:\\foo.mjs', expected: 'file:///C:/foo.mjs' },
771cb0ef41Sopenharmony_ci      // space
781cb0ef41Sopenharmony_ci      { path: 'C:\\foo bar', expected: 'file:///C:/foo%20bar' },
791cb0ef41Sopenharmony_ci      // question mark
801cb0ef41Sopenharmony_ci      { path: 'C:\\foo?bar', expected: 'file:///C:/foo%3Fbar' },
811cb0ef41Sopenharmony_ci      // number sign
821cb0ef41Sopenharmony_ci      { path: 'C:\\foo#bar', expected: 'file:///C:/foo%23bar' },
831cb0ef41Sopenharmony_ci      // ampersand
841cb0ef41Sopenharmony_ci      { path: 'C:\\foo&bar', expected: 'file:///C:/foo&bar' },
851cb0ef41Sopenharmony_ci      // equals
861cb0ef41Sopenharmony_ci      { path: 'C:\\foo=bar', expected: 'file:///C:/foo=bar' },
871cb0ef41Sopenharmony_ci      // colon
881cb0ef41Sopenharmony_ci      { path: 'C:\\foo:bar', expected: 'file:///C:/foo:bar' },
891cb0ef41Sopenharmony_ci      // semicolon
901cb0ef41Sopenharmony_ci      { path: 'C:\\foo;bar', expected: 'file:///C:/foo;bar' },
911cb0ef41Sopenharmony_ci      // percent
921cb0ef41Sopenharmony_ci      { path: 'C:\\foo%bar', expected: 'file:///C:/foo%25bar' },
931cb0ef41Sopenharmony_ci      // backslash
941cb0ef41Sopenharmony_ci      { path: 'C:\\foo\\bar', expected: 'file:///C:/foo/bar' },
951cb0ef41Sopenharmony_ci      // backspace
961cb0ef41Sopenharmony_ci      { path: 'C:\\foo\bbar', expected: 'file:///C:/foo%08bar' },
971cb0ef41Sopenharmony_ci      // tab
981cb0ef41Sopenharmony_ci      { path: 'C:\\foo\tbar', expected: 'file:///C:/foo%09bar' },
991cb0ef41Sopenharmony_ci      // newline
1001cb0ef41Sopenharmony_ci      { path: 'C:\\foo\nbar', expected: 'file:///C:/foo%0Abar' },
1011cb0ef41Sopenharmony_ci      // carriage return
1021cb0ef41Sopenharmony_ci      { path: 'C:\\foo\rbar', expected: 'file:///C:/foo%0Dbar' },
1031cb0ef41Sopenharmony_ci      // latin1
1041cb0ef41Sopenharmony_ci      { path: 'C:\\fóóbàr', expected: 'file:///C:/f%C3%B3%C3%B3b%C3%A0r' },
1051cb0ef41Sopenharmony_ci      // Euro sign (BMP code point)
1061cb0ef41Sopenharmony_ci      { path: 'C:\\€', expected: 'file:///C:/%E2%82%AC' },
1071cb0ef41Sopenharmony_ci      // Rocket emoji (non-BMP code point)
1081cb0ef41Sopenharmony_ci      { path: 'C:\\�', expected: 'file:///C:/%F0%9F%9A%80' },
1091cb0ef41Sopenharmony_ci      // UNC path (see https://docs.microsoft.com/en-us/archive/blogs/ie/file-uris-in-windows)
1101cb0ef41Sopenharmony_ci      { path: '\\\\nas\\My Docs\\File.doc', expected: 'file://nas/My%20Docs/File.doc' },
1111cb0ef41Sopenharmony_ci    ];
1121cb0ef41Sopenharmony_ci  } else {
1131cb0ef41Sopenharmony_ci    testCases = [
1141cb0ef41Sopenharmony_ci      // Lowercase ascii alpha
1151cb0ef41Sopenharmony_ci      { path: '/foo', expected: 'file:///foo' },
1161cb0ef41Sopenharmony_ci      // Uppercase ascii alpha
1171cb0ef41Sopenharmony_ci      { path: '/FOO', expected: 'file:///FOO' },
1181cb0ef41Sopenharmony_ci      // dir
1191cb0ef41Sopenharmony_ci      { path: '/dir/foo', expected: 'file:///dir/foo' },
1201cb0ef41Sopenharmony_ci      // trailing separator
1211cb0ef41Sopenharmony_ci      { path: '/dir/', expected: 'file:///dir/' },
1221cb0ef41Sopenharmony_ci      // dot
1231cb0ef41Sopenharmony_ci      { path: '/foo.mjs', expected: 'file:///foo.mjs' },
1241cb0ef41Sopenharmony_ci      // space
1251cb0ef41Sopenharmony_ci      { path: '/foo bar', expected: 'file:///foo%20bar' },
1261cb0ef41Sopenharmony_ci      // question mark
1271cb0ef41Sopenharmony_ci      { path: '/foo?bar', expected: 'file:///foo%3Fbar' },
1281cb0ef41Sopenharmony_ci      // number sign
1291cb0ef41Sopenharmony_ci      { path: '/foo#bar', expected: 'file:///foo%23bar' },
1301cb0ef41Sopenharmony_ci      // ampersand
1311cb0ef41Sopenharmony_ci      { path: '/foo&bar', expected: 'file:///foo&bar' },
1321cb0ef41Sopenharmony_ci      // equals
1331cb0ef41Sopenharmony_ci      { path: '/foo=bar', expected: 'file:///foo=bar' },
1341cb0ef41Sopenharmony_ci      // colon
1351cb0ef41Sopenharmony_ci      { path: '/foo:bar', expected: 'file:///foo:bar' },
1361cb0ef41Sopenharmony_ci      // semicolon
1371cb0ef41Sopenharmony_ci      { path: '/foo;bar', expected: 'file:///foo;bar' },
1381cb0ef41Sopenharmony_ci      // percent
1391cb0ef41Sopenharmony_ci      { path: '/foo%bar', expected: 'file:///foo%25bar' },
1401cb0ef41Sopenharmony_ci      // backslash
1411cb0ef41Sopenharmony_ci      { path: '/foo\\bar', expected: 'file:///foo%5Cbar' },
1421cb0ef41Sopenharmony_ci      // backspace
1431cb0ef41Sopenharmony_ci      { path: '/foo\bbar', expected: 'file:///foo%08bar' },
1441cb0ef41Sopenharmony_ci      // tab
1451cb0ef41Sopenharmony_ci      { path: '/foo\tbar', expected: 'file:///foo%09bar' },
1461cb0ef41Sopenharmony_ci      // newline
1471cb0ef41Sopenharmony_ci      { path: '/foo\nbar', expected: 'file:///foo%0Abar' },
1481cb0ef41Sopenharmony_ci      // carriage return
1491cb0ef41Sopenharmony_ci      { path: '/foo\rbar', expected: 'file:///foo%0Dbar' },
1501cb0ef41Sopenharmony_ci      // latin1
1511cb0ef41Sopenharmony_ci      { path: '/fóóbàr', expected: 'file:///f%C3%B3%C3%B3b%C3%A0r' },
1521cb0ef41Sopenharmony_ci      // Euro sign (BMP code point)
1531cb0ef41Sopenharmony_ci      { path: '/€', expected: 'file:///%E2%82%AC' },
1541cb0ef41Sopenharmony_ci      // Rocket emoji (non-BMP code point)
1551cb0ef41Sopenharmony_ci      { path: '/�', expected: 'file:///%F0%9F%9A%80' },
1561cb0ef41Sopenharmony_ci    ];
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  for (const { path, expected } of testCases) {
1601cb0ef41Sopenharmony_ci    const actual = url.pathToFileURL(path).href;
1611cb0ef41Sopenharmony_ci    assert.strictEqual(actual, expected);
1621cb0ef41Sopenharmony_ci  }
1631cb0ef41Sopenharmony_ci}
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci// Test for non-string parameter
1661cb0ef41Sopenharmony_ci{
1671cb0ef41Sopenharmony_ci  for (const badPath of [
1681cb0ef41Sopenharmony_ci    undefined, null, true, 42, 42n, Symbol('42'), NaN, {}, [], () => {},
1691cb0ef41Sopenharmony_ci    Promise.resolve('foo'),
1701cb0ef41Sopenharmony_ci    new Date(),
1711cb0ef41Sopenharmony_ci    new String('notPrimitive'),
1721cb0ef41Sopenharmony_ci    { toString() { return 'amObject'; } },
1731cb0ef41Sopenharmony_ci    { [Symbol.toPrimitive]: (hint) => 'amObject' },
1741cb0ef41Sopenharmony_ci  ]) {
1751cb0ef41Sopenharmony_ci    assert.throws(() => url.pathToFileURL(badPath), {
1761cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1771cb0ef41Sopenharmony_ci    });
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci}
180