-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
path: fix posix.relative returns different results #13738
Conversation
I’m sorry, but imho this is not worth breaking people’s code. |
@XadillaX I’ve replied in the issue thread, but this just seems like it’s breaking code without a good reason, switching to a warning doesn’t change that. |
-1 I don't think we should be artificially limiting these functions. |
@addaleax @mscdex do you think limiting the assertion to only to when > path.posix.resolve('./gaga/')
'C:\\bin\\dev\\node/gaga' // bug
> path.posix.resolve('/gaga/')
'/gaga' // Ok |
I really don't think they need changing. IMHO when you explicitly access the |
🤔 it's a thinker indeed... |
It would be better to only throw error when rely on |
I might agree if the answer was actually nonsense … but it isn’t? The result may not directly usable for file system operations, but that doesn’t make it less consistent or meaningless.
I agree with @mscdex, we should not artificially limit these methods. |
I will continue to fix it. |
@addaleax If do not limit the method user will get incorrect result, it is also unreasonable. |
IMHO this is nonsensical: > path.posix.resolve('./gaga/')
'C:\\bin\\dev\\node/gaga' // bug > path.win32.resolve('.\\gaga\\')
'\\mnt\\d\\code\\node\\gaga' Consistent, yes, meaningful, I don't think so. P.S. Just a point of thought, the use of P.P.S. Let see what @DuanPengfei comes up with 👍 |
My idea is make the result correct when do't rely on |
Implemented some feature in my local code. Idea
If
If one of
Examples
on Windows // both relative
path.posix.relative('a/b/c', '../../x'); // => '../../../../../x'
path.posix.relative('../../x, 'a/b/c''); // => '../home/node/a/b/c'
/**
* `from`'s upper path is too long beyond the root path
*/
path.posix.relative('../../../../../../../x, 'a/b/c''); // => '../home/node/a/b/c'
// one relative
path.posix.relative('/a/b/c', 'd/e/f'); // => 'd/e/f'
path.posix.relative('a/b/c', '/d/e/f'); // => '../../..'
// both absolute
path.posix.relative('/a/b/c', '/d/e/f'); // => '../../../d/e/f' on POSIX // both relative
path.win32.relative('a\b\c', '..\..\x'); // => '..\..\..\..\..\x'
path.win32.relative('..\..\..\..\..\x', 'a\b\c'); // => '.\Users\nodea\b\c'
// one relative
path.win32.relative('C:\a\b\c', '..\..\..\x'); // => '..\..\..\x'
path.win32.relative('C:\..\..\..\x', 'a\b\c'); // => 'a\b\c'
// both absolute
path.win32.relative('C:\a\b\c', 'C:\d\e\f'); // => '..\..\..\d\e\f' @refack @addaleax @mscdex What do you think of how this is done? |
😁 My ability to speak in English is weak. I will improve the code, document and test, then push the code. By the way, for the surrogate path, my colleague suggested me use |
If chrome is using |
Throw an error `ERR_UNSUPPORTED_PLATFOMR` when direct use `path.posix.resolve` on Windows or direct use `path.win32.resolve` on *nix. Update docs, list win32 functions do not support direct use on *nix and posix functions do not support direct use on Windows. Update tests, only run current platform type test. Fixes: nodejs#13683 Refs: nodejs#13714
6d17e03
to
8d604e1
Compare
According to the idea, implement the code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look good, just a few nits.
|
||
if (process.platform !== 'win32') { | ||
if (!isFromAbsolute && !isToAbsolute) { | ||
from = 'c:\\fakepath\\' + from; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
store the surrogate in a const
(or even a function if it works)
function absoluteWithSurrogate(p) {
return win32.resolve(win32.join(`c:\\fakepath`, p));
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
} | ||
|
||
if (process.platform !== 'win32') { | ||
if (!isFromAbsolute && !isToAbsolute) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like you can do this separately for to
and from
if (isFromAbsolute) ...
else ...
if (isToAbsolute) ...
else ...
Or maybe I'm wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because need to know both type of from
and to
, so I think I can't do this separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok 👍
|
||
if (process.platform === 'win32') { | ||
if (!isFromAbsolute && !isToAbsolute) { | ||
from = '/fakepath/' + from; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrap (same as above)
}; | ||
|
||
{ | ||
let tests; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const tests = common.isWindows ? resolveTest.win32 : resolveTest.posix;
const throwing = common.isWindows ? path.posix.resolve : path.posix.resolve;
failures.push(`\n${message}`); | ||
}; | ||
{ | ||
let tests; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
['\\\\foo\\baz', '\\\\foo\\baz-quux', '..\\baz-quux'], | ||
['C:\\baz', '\\\\foo\\bar\\baz', '\\\\foo\\bar\\baz'], | ||
['\\\\foo\\bar\\baz', 'C:\\baz', 'C:\\baz'] | ||
const relativeTest = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be best to split out only the tests that would throw.
The other cases need to be tested on all platforms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making my -1 explicit. I don't think we should be changing the behavior of these functions.
@refack As I said, I don't think we should be changing the behavior of these functions. That includes both the throwing and the injecting of arbitrary path components into |
I’m sorry, but I agree with @mscdex; we really should not be doing this kind of change. IIUC, the original bug report had one clear problem it pointed to: |
Trying to figure out a path forward (sorry about the pun). Should we keep the |
I wouldn’t think of adding
You can do that but I think both @mscdex and I have made it pretty clear that we don’t think those changes are a good idea at all. |
So the main goal is to add more working cases to the tests (no changes). Specifically |
😵 Change so much code is because in the modification of this problem I found more bottom bug. Inject |
👍 I think that will be good. |
@@ -431,6 +431,39 @@ added: v0.11.15 | |||
The `path.posix` property provides access to POSIX specific implementations | |||
of the `path` methods. | |||
|
|||
*Note*: Be careful when using the following functions directly on Windows. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This note should be moved into the bodies of each of the API sections. Sitting above it, it is far more likely that the Note will become disconnected...
### path.posix.resolve([...path]) | ||
If after processing all given `path` segments an absolute path has not yet | ||
been generated, `path.posix.resolve` will throw [`UNSUPPORTED_PLATFORM`] error. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps:
*Note*: Care should be taken when using `path.posix.resolve()` on Windows due to ...
Then include a short snippet about why...
Same with the path.posix.relative()
below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion:
*Note*: Care should be taken when using `path.posix.resolve()` on Windows due to the fact that resolve will use `process.cwd()` verbatim, and so the output will be a concatenation of Windows and POSIX style paths.
been generated, `path.posix.resolve` will throw [`UNSUPPORTED_PLATFORM`] error. | ||
|
||
### path.posix.relative(from, to) | ||
If `from` and `to` are both relative path, `path.posix.relative` will use the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please include the ()
when referencing functions... e.g. path.posix.relative()
@@ -187,6 +199,10 @@ const win32 = { | |||
path = arguments[i]; | |||
} else if (!resolvedDevice) { | |||
path = process.cwd(); | |||
|
|||
// If you use the current working directory, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// If the current working directory is used ...
@@ -201,6 +217,10 @@ const win32 = { | |||
path.slice(0, 3).toLowerCase() !== | |||
resolvedDevice.toLowerCase() + '\\') { | |||
path = resolvedDevice + '\\'; | |||
} else { | |||
// If you use the current working directory, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// The the current working directory is used...
👌 Then I will modify the code only resolve the problem |
@DuanPengfei anything I can do you assist in this? |
@refack 😂 Sorry for a long time no response. Some time ago sick leave, this weekend will continue to repair the bug. If there is a need, I will ask you for help. |
Accept the recommendations of @timothy Gu, decide to refer to the implementation of the Python or any other language. Do you think this is a good way? |
FWIW Python 3's >>> ntpath.realpath(r'.\gaga')
'\\home\\timothy-gu\\dev\\node\\node\\gaga'
>>> ntpath.relpath(r'a\b\c', r'..\..\x')
'..\\node\\node\\a\\b\\c' (I'm on Linux.) I'm reluctant to change Node.js' current behavior. |
We will not change the current behavior. And in this PR I will only make the return of |
I am closing this due to the long inactivity. @DuanPengfei please feel free to leave a comment if you would like to follow up on this by fixing the issue itself. Your work is much appreciated nevertheless. |
Using path.posix.relative is not an option because it returns the wrong path. See: * nodejs/node#13887 * nodejs/node#13738
Using path.posix.relative is not an option because it returns the wrong path. See: * nodejs/node#13887 * nodejs/node#13738
Throw an error
ERR_UNSUPPORTED_PLATFOMR
when direct usepath.posix.resolve
on Windows or direct usepath.win32.resolve
on *nix.
Update docs, list win32 functions do not support direct use on
*nix and posix functions do not support direct use on Windows.
Update tests, only run current platform type test.
Fixes: #13683
Refs: #13714
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
doc, path