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