fs: unguarded fs.watchFile cache statWatchers checking fixed

Use hasOwnProperty to check filepath cache; previous code could fail if
a filepath duplicated a chained property name.

Fixes #1637.
This commit is contained in:
Thomas Shinnick 2011-09-08 23:16:10 -05:00 committed by koichik
parent e58c036c27
commit 7dc2c492e9
2 changed files with 59 additions and 11 deletions

View File

@ -617,6 +617,9 @@ StatWatcher.prototype.stop = function() {
var statWatchers = {}; var statWatchers = {};
function inStatWatchers(filename) {
return Object.prototype.hasOwnProperty.call(statWatchers, filename);
}
fs.watchFile = function(filename) { fs.watchFile = function(filename) {
@ -639,11 +642,10 @@ fs.watchFile = function(filename) {
if (options.persistent === undefined) options.persistent = true; if (options.persistent === undefined) options.persistent = true;
if (options.interval === undefined) options.interval = 0; if (options.interval === undefined) options.interval = 0;
if (statWatchers[filename]) { if (inStatWatchers(filename)) {
stat = statWatchers[filename]; stat = statWatchers[filename];
} else { } else {
statWatchers[filename] = new StatWatcher(); stat = statWatchers[filename] = new StatWatcher();
stat = statWatchers[filename];
stat.start(filename, options.persistent, options.interval); stat.start(filename, options.persistent, options.interval);
} }
stat.addListener('change', listener); stat.addListener('change', listener);
@ -652,7 +654,7 @@ fs.watchFile = function(filename) {
fs.unwatchFile = function(filename) { fs.unwatchFile = function(filename) {
var stat; var stat;
if (statWatchers[filename]) { if (inStatWatchers(filename)) {
stat = statWatchers[filename]; stat = statWatchers[filename];
stat.stop(); stat.stop();
statWatchers[filename] = undefined; statWatchers[filename] = undefined;

View File

@ -27,13 +27,33 @@ var assert = require('assert');
var path = require('path'); var path = require('path');
var fs = require('fs'); var fs = require('fs');
var watchSeenOne = 0;
var watchSeenTwo = 0;
var filename = path.join(common.fixturesDir, 'watch.txt'); var startDir = process.cwd();
fs.writeFileSync(filename, "hello"); var testDir = common.fixturesDir;
var filenameOne = 'watch.txt';
var filepathOne = path.join(testDir, filenameOne);
var filenameTwo = 'hasOwnProperty';
var filepathTwo = filenameTwo;
var filepathTwoAbs = path.join(testDir, filenameTwo);
process.addListener('exit', function() {
fs.unlinkSync(filepathOne);
fs.unlinkSync(filepathTwoAbs);
assert.equal(1, watchSeenOne);
assert.equal(1, watchSeenTwo);
});
fs.writeFileSync(filepathOne, "hello");
assert.throws( assert.throws(
function() { function() {
fs.watchFile(filename); fs.watchFile(filepathOne);
}, },
function(e) { function(e) {
return e.message === 'watchFile requires a listener function'; return e.message === 'watchFile requires a listener function';
@ -42,14 +62,40 @@ assert.throws(
assert.doesNotThrow( assert.doesNotThrow(
function() { function() {
fs.watchFile(filename, function(curr, prev) { fs.watchFile(filepathOne, function(curr, prev) {
fs.unwatchFile(filename); fs.unwatchFile(filepathOne);
fs.unlinkSync(filename); ++watchSeenOne;
}); });
} }
); );
setTimeout(function() { setTimeout(function() {
fs.writeFileSync(filename, "world"); fs.writeFileSync(filepathOne, "world");
}, 1000); }, 1000);
process.chdir(testDir);
fs.writeFileSync(filepathTwoAbs, "howdy");
assert.throws(
function() {
fs.watchFile(filepathTwo);
},
function(e) {
return e.message === 'watchFile requires a listener function';
}
);
assert.doesNotThrow(
function() {
fs.watchFile(filepathTwo, function(curr, prev) {
fs.unwatchFile(filepathTwo);
++watchSeenTwo;
});
}
);
setTimeout(function() {
fs.writeFileSync(filepathTwoAbs, "pardner");
}, 1000);