-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fs: improve errors thrown from fs.watch()
- Add an accessor property `initialized `to FSEventWrap to check the state of the handle from the JS land - Introduce ERR_FS_WATCHER_ALREADY_STARTED so calling start() on a watcher that is already started will throw instead of doing nothing silently. - Introduce ERR_FS_WATCHER_NOT_STARTED so calling close() on a watcher that is already closed will throw instead of doing nothing silently. - Validate the filename passed to fs.watch() - Assert that the handle in the watcher are instances of FSEvent instead of relying on the illegal invocation error from the VM. - Add more assertions in FSEventWrap methods now that we check `initialized` and the filename in JS land before invoking the binding. - Use uvException instead of errornoException to create the errors with the error numbers from libuv to make them consistent with other errors in fs. TODO: - Improve fs.watchFile() the same way this patch improves fs.watch() - It seems possible to fire both rename and change event from libuv together now that we can check if the handle is closed via `initialized` in JS land. PR-URL: #19089 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
- Loading branch information
1 parent
48b5c11
commit 6c25f2e
Showing
7 changed files
with
179 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,64 @@ | ||
'use strict'; | ||
|
||
// This verifies the error thrown by fs.watch. | ||
|
||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const fs = require('fs'); | ||
const tmpdir = require('../common/tmpdir'); | ||
const path = require('path'); | ||
const nonexistentFile = path.join(tmpdir.path, 'non-existent'); | ||
const uv = process.binding('uv'); | ||
|
||
tmpdir.refresh(); | ||
|
||
{ | ||
const validateError = (err) => { | ||
assert.strictEqual(err.path, nonexistentFile); | ||
assert.strictEqual(err.filename, nonexistentFile); | ||
assert.strictEqual(err.syscall, 'watch'); | ||
if (err.code === 'ENOENT') { | ||
assert.strictEqual( | ||
err.message, | ||
`ENOENT: no such file or directory, watch '${nonexistentFile}'`); | ||
assert.strictEqual(err.errno, uv.UV_ENOENT); | ||
assert.strictEqual(err.code, 'ENOENT'); | ||
} else { // AIX | ||
assert.strictEqual( | ||
err.message, | ||
`ENODEV: no such device, watch '${nonexistentFile}'`); | ||
assert.strictEqual(err.errno, uv.UV_ENODEV); | ||
assert.strictEqual(err.code, 'ENODEV'); | ||
} | ||
return true; | ||
}; | ||
|
||
assert.throws( | ||
() => fs.watch(nonexistentFile, common.mustNotCall()), | ||
validateError | ||
); | ||
} | ||
|
||
{ | ||
const file = path.join(tmpdir.path, 'file-to-watch'); | ||
fs.writeFileSync(file, 'test'); | ||
const watcher = fs.watch(file, common.mustNotCall()); | ||
|
||
const validateError = (err) => { | ||
assert.strictEqual(err.path, nonexistentFile); | ||
assert.strictEqual(err.filename, nonexistentFile); | ||
assert.strictEqual( | ||
err.message, | ||
`ENOENT: no such file or directory, watch '${nonexistentFile}'`); | ||
assert.strictEqual(err.errno, uv.UV_ENOENT); | ||
assert.strictEqual(err.code, 'ENOENT'); | ||
assert.strictEqual(err.syscall, 'watch'); | ||
fs.unlinkSync(file); | ||
return true; | ||
}; | ||
|
||
watcher.on('error', common.mustCall(validateError)); | ||
|
||
assert.throws(function() { | ||
fs.watch('non-existent-file'); | ||
}, function(err) { | ||
assert(err); | ||
assert(/non-existent-file/.test(err)); | ||
assert.strictEqual(err.filename, 'non-existent-file'); | ||
return true; | ||
}); | ||
|
||
const watcher = fs.watch(__filename); | ||
watcher.on('error', common.mustCall(function(err) { | ||
assert(err); | ||
assert(/non-existent-file/.test(err)); | ||
assert.strictEqual(err.filename, 'non-existent-file'); | ||
})); | ||
watcher._handle.onchange(-1, 'ENOENT', 'non-existent-file'); | ||
// Simulate the invocation from the binding | ||
watcher._handle.onchange(uv.UV_ENOENT, 'ENOENT', nonexistentFile); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters