paulmillr/chokidar

Parentheses in cwd option isn't escaped

nozomuikuta opened this issue · 1 comments

Describe the bug

Parentheses in cwd option are not escaped, or no way is provided to escape them.
As a result, if names of directories of cwd includes parentheses, the glob patterns never matches and no change events are emitted.

Although I found this behavior with parentheses, I guess this is same for other regular expression special characters.

Versions (please complete the following information):

  • Chokidar version 3.5.2
  • Node version 16.3.0
  • OS version: macOS Big Sur (11.6)

To Reproduce:

Here is a demo.

Most valuable could be one or more test cases for test.js to demonstrate the problem.

Sorry, I created the reproduction before I see your message in this bug report template. 🙏

Expected behavior

If it is assumed that cwd option is just a string literal, chokidar should apply escape to the string when it passes it to matcher. Otherwise, watchCallback alway returns at the line if (globFilter && !globFilter(path)) return;, and no events are emitted.

const watchCallback = async (fullPath, flags, info) => {
if (this.fsw.closed) return;
if (
opts.depth !== undefined &&
calcDepth(fullPath, realPath) > opts.depth
) return;
const path = transform(sysPath.join(
watchPath, sysPath.relative(watchPath, fullPath)
));
if (globFilter && !globFilter(path)) return;
// ensure directories are tracked
const parent = sysPath.dirname(path);
const item = sysPath.basename(path);
const watchedDir = this.fsw._getWatchedDir(
info.type === FSEVENT_TYPE_DIRECTORY ? path : parent
);

Additional context

This report might be related to #984.

By the way, I dug into this issue to find the root cause of an issue of Nuxt Content module.

Nuxt Content listens to change events of chokidar, so that it hot-reloads UI in the browser (like code below):

this.watcher = chokidar.watch(['**/*'], {
  cwd: this.dir, // <-- This may include parentheses
  ignoreInitial: true,
  ignored: 'node_modules/**/*'
})
  .on('change', path => this.queue.add(this.refresh.bind(this, 'change', path)))
  .on('add', path => this.queue.add(this.refresh.bind(this, 'add', path)))
  .on('unlink', path => this.queue.add(this.refresh.bind(this, 'unlink', path)))

This is also a problem for a non-cwd rooted path containing parens. If you attempt to escape them (with \) because the path is converted to unix style. Unfortunately, I'm not sure of a good way to fix this because chokidar needs to retain the conversion of Windows paths which use \.

Maybe an option to bypass path normalization or to say "I've already normalized this path for you plz trust me"