-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
fs: create consistent behavior for fs module across platforms #17927
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1365,13 +1365,16 @@ function getPathFromURLPosix(url) { | |
return decodeURIComponent(pathname); | ||
} | ||
|
||
function getPathFromURL(path) { | ||
function getPathFromURL(path, assertFilename) { | ||
if (path == null || !path[searchParams] || | ||
!path[searchParams][searchParams]) { | ||
return path; | ||
} | ||
if (path.protocol !== 'file:') | ||
throw new errors.TypeError('ERR_INVALID_URL_SCHEME', 'file'); | ||
|
||
if (assertFilename && path.href[path.href.length - 1] === '/') | ||
throw new errors.Error('ERR_PATH_IS_DIRECTORY', 'path', path.pathname); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The string being checked and reported here should be the result of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or, maybe |
||
return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const fs = require('fs'); | ||
const URL = require('url').URL; | ||
const util = require('util'); | ||
|
||
function runPathTests(withSlash, withoutSlash, slashedPath, realName) { | ||
|
||
if (!slashedPath) { | ||
slashedPath = withSlash; | ||
} else if (typeof slashedPath === 'boolean') { | ||
realName = slashedPath; | ||
slashedPath = withSlash; | ||
} | ||
|
||
common.expectsError( | ||
() => { | ||
fs.readFile(withSlash, common.mustNotCall()); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.readFileSync(withSlash, { flag: 'r' }); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.open(withSlash, 'r', common.mustNotCall()); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.openSync(withSlash, 'r'); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.appendFile(withSlash, 'test data', common.mustNotCall()); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.appendFileSync(withSlash, 'test data'); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.createReadStream(withSlash); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
|
||
common.expectsError( | ||
() => { | ||
fs.createWriteStream(withSlash); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.truncate(withSlash, 4, common.mustNotCall()); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.truncateSync(withSlash, 4); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.writeFile(withSlash, 'test data', common.mustNotCall()); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.writeFileSync(withSlash, 'test data'); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: 'The argument "path" must not end with "/". ' + | ||
`Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.copyFile(withSlash, withoutSlash, common.mustNotCall()); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: `The argument "${realName ? 'src' : 'path'}" must not end ` + | ||
`with "/". Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.copyFile(withoutSlash, withSlash, common.mustNotCall()); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: `The argument "${realName ? 'dest' : 'path'}" must not end ` + | ||
`with "/". Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.copyFileSync(withSlash, withoutSlash); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: `The argument "${realName ? 'src' : 'path'}" must not end ` + | ||
`with "/". Received ${util.inspect(slashedPath)}` | ||
}); | ||
|
||
common.expectsError( | ||
() => { | ||
fs.copyFileSync(withoutSlash, withSlash); | ||
}, | ||
{ | ||
code: 'ERR_PATH_IS_DIRECTORY', | ||
type: Error, | ||
message: `The argument "${realName ? 'dest' : 'path'}" must not end ` + | ||
`with "/". Received ${util.inspect(slashedPath)}` | ||
}); | ||
} | ||
|
||
const path = '/tmp/test'; | ||
const stringWithSlash = common.isWindows ? `file:///c:${path}/` : | ||
`file://${path}/`; | ||
const stringWithoutSlash = common.isWindows ? `file:///c:${path}` : | ||
`file://${path}`; | ||
const urlWithSlash = new URL(stringWithSlash); | ||
const urlWithoutSlash = new URL(stringWithoutSlash); | ||
const U8ABufferWithSlash = new Uint8Array(Buffer.from(stringWithSlash)); | ||
const U8ABufferWithoutSlash = new Uint8Array(Buffer.from(stringWithoutSlash)); | ||
runPathTests(urlWithSlash, urlWithoutSlash, `${path}/`); | ||
runPathTests(stringWithSlash, stringWithoutSlash, true); | ||
runPathTests(U8ABufferWithSlash, U8ABufferWithoutSlash, true); |
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 is already one
this.path = getPathFromURL(path);
below. Alsopath
is ignored ifoptions.fd !== undefined
so maybe we just need to delete this and change the line below to:Same about
ReadStream
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.
validatePath
only acceptsUint8Array
this will work if Stream path is alwaysUint8Array
orstring
.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.
@timotew The path in the fs stream classes can be falsy if
options.fd
is provdided, e.g.fs.createReadStream(null, { fd: fd, encoding: 'utf8' })
is valid. From what I can tell,validatePath
accepts bothstring
andUint8Array
.