in node/internal.ts [815:902]
export function _getDirectoryName(p: string): string {
// short-circuit if empty
if (!p) {
return '';
}
// normalize separators
p = _normalizeSeparators(p);
// on Windows, the goal of this function is to match the behavior of
// [System.IO.Path]::GetDirectoryName(), e.g.
// C:/ =>
// C:/hello => C:\
// C:/hello/ => C:\hello
// C:/hello/world => C:\hello
// C:/hello/world/ => C:\hello\world
// C: =>
// C:hello => C:
// C:hello/ => C:hello
// / =>
// /hello => \
// /hello/ => \hello
// //hello =>
// //hello/ =>
// //hello/world =>
// //hello/world/ => \\hello\world
//
// unfortunately, path.dirname() can't simply be used. for example, on Windows
// it yields different results from Path.GetDirectoryName:
// C:/ => C:/
// C:/hello => C:/
// C:/hello/ => C:/
// C:/hello/world => C:/hello
// C:/hello/world/ => C:/hello
// C: => C:
// C:hello => C:
// C:hello/ => C:
// / => /
// /hello => /
// /hello/ => /
// //hello => /
// //hello/ => /
// //hello/world => //hello/world
// //hello/world/ => //hello/world/
// //hello/world/again => //hello/world/
// //hello/world/again/ => //hello/world/
// //hello/world/again/again => //hello/world/again
// //hello/world/again/again/ => //hello/world/again
if (process.platform == 'win32') {
if (/^[A-Z]:\\?[^\\]+$/i.test(p)) { // e.g. C:\hello or C:hello
return p.charAt(2) == '\\' ? p.substring(0, 3) : p.substring(0, 2);
}
else if (/^[A-Z]:\\?$/i.test(p)) { // e.g. C:\ or C:
return '';
}
let lastSlashIndex = p.lastIndexOf('\\');
if (lastSlashIndex < 0) { // file name only
return '';
}
else if (p == '\\') { // relative root
return '';
}
else if (lastSlashIndex == 0) { // e.g. \\hello
return '\\';
}
else if (/^\\\\[^\\]+(\\[^\\]*)?$/.test(p)) { // UNC root, e.g. \\hello or \\hello\ or \\hello\world
return '';
}
return p.substring(0, lastSlashIndex); // e.g. hello\world => hello or hello\world\ => hello\world
// note, this means trailing slashes for non-root directories
// (i.e. not C:\, \, or \\unc\) will simply be removed.
}
// OSX/Linux
if (p.indexOf('/') < 0) { // file name only
return '';
}
else if (p == '/') {
return '';
}
else if (_endsWith(p, '/')) {
return p.substring(0, p.length - 1);
}
return path.dirname(p);
}