Skip to content

Commit

Permalink
path: fix relative on Windows
Browse files Browse the repository at this point in the history
PR-URL: #53991
Fixes: #27534
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
huseyinacacak-janea authored Aug 6, 2024
1 parent 5bfebfe commit c852e22
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 0 deletions.
1 change: 1 addition & 0 deletions benchmark/path/relative-win32.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const bench = common.createBenchmark(main, {
['C:\\foo\\bar\\baz', 'C:\\foo\\bar\\baz'].join('|'),
['C:\\foo\\BAR\\BAZ', 'C:\\foo\\bar\\baz'].join('|'),
['C:\\foo\\bar\\baz\\quux', 'C:\\'].join('|'),
['c:\\İ\\a\\İ', 'c:\\İ\\b\\İ\\test.txt', '..\\..\\b\\İ\\test.txt'].join('|'),
],
n: [1e5],
});
Expand Down
40 changes: 40 additions & 0 deletions lib/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@
'use strict';

const {
ArrayPrototypeJoin,
ArrayPrototypeSlice,
FunctionPrototypeBind,
StringPrototypeCharCodeAt,
StringPrototypeIndexOf,
StringPrototypeLastIndexOf,
StringPrototypeRepeat,
StringPrototypeReplace,
StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeToLowerCase,
} = primordials;

Expand Down Expand Up @@ -539,6 +543,42 @@ const win32 = {
if (from === to)
return '';

if (fromOrig.length !== from.length || toOrig.length !== to.length) {
const fromSplit = StringPrototypeSplit(fromOrig, '\\');
const toSplit = StringPrototypeSplit(toOrig, '\\');
if (fromSplit[fromSplit.length - 1] === '') {
fromSplit.pop();
}
if (toSplit[toSplit.length - 1] === '') {
toSplit.pop();
}

const fromLen = fromSplit.length;
const toLen = toSplit.length;
const length = fromLen < toLen ? fromLen : toLen;

let i;
for (i = 0; i < length; i++) {
if (StringPrototypeToLowerCase(fromSplit[i]) !== StringPrototypeToLowerCase(toSplit[i])) {
break;
}
}

if (i === 0) {
return toOrig;
} else if (i === length) {
if (toLen > length) {
return ArrayPrototypeJoin(ArrayPrototypeSlice(toSplit, i), '\\');
}
if (fromLen > length) {
return StringPrototypeRepeat('..\\', fromLen - 1 - i) + '..';
}
return '';
}

return StringPrototypeRepeat('..\\', fromLen - i) + ArrayPrototypeJoin(ArrayPrototypeSlice(toSplit, i), '\\');
}

// Trim any leading backslashes
let fromStart = 0;
while (fromStart < from.length &&
Expand Down
5 changes: 5 additions & 0 deletions test/parallel/test-path-relative.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ const relativeTests = [
['\\\\foo\\baz', '\\\\foo\\baz-quux', '..\\baz-quux'],
['C:\\baz', '\\\\foo\\bar\\baz', '\\\\foo\\bar\\baz'],
['\\\\foo\\bar\\baz', 'C:\\baz', 'C:\\baz'],
['c:\\a\\İ', 'c:\\a\\İ\\test.txt', 'test.txt'],
['c:\\İ\\a\\İ', 'c:\\İ\\b\\İ\\test.txt', '..\\..\\b\\İ\\test.txt'],
['c:\\İ\\a\\i̇', 'c:\\İ\\b\\İ\\test.txt', '..\\..\\b\\İ\\test.txt'],
['c:\\i̇\\a\\İ', 'c:\\İ\\b\\İ\\test.txt', '..\\..\\b\\İ\\test.txt'],
['c:\\ß\\a\\ß', 'c:\\ß\\b\\ß\\test.txt', '..\\..\\b\\ß\\test.txt'],
],
],
[ path.posix.relative,
Expand Down

0 comments on commit c852e22

Please sign in to comment.