Skip to content

Chokidar chokes on options that are explicitely set to "undefined" #1394

Open
@Fuzzyma

Description

Describe the bug

Chokidar v4 doesnt clean up the passed options. Setting an option to explicit undefined will make node throw.

Versions (please complete the following information):

  • Chokidar version: 4.0.1
  • Node version: 22
  • OS version: Ubuntu

To Reproduce:

Steps to reproduce the behavior. Include filename and chokidar config.

Ideally prove a problem by isolating and making it reproducible with a very short sample program, which you could paste here:

const chokidar = require('chokidar');
const fs = require('fs');
// Passing undefined will crash node
chokidar.watch('test*', { interval: undefined }).on('all', (event, path) => {
  console.log(event, path);
});
fs.writeFileSync('test.txt', 'testing 1');

Expected behavior
It should filter out undefined values so that chokidars defaulst are used instead (which doesnt happen because the explicit undefined overwrites the default when spreading):

chokidar/src/index.ts

Lines 361 to 377 in 5e6daaa

const opts: FSWInstanceOptions = {
// Defaults
persistent: true,
ignoreInitial: false,
ignorePermissionErrors: false,
interval: 100,
binaryInterval: 300,
followSymlinks: true,
usePolling: false,
// useAsync: false,
atomic: true, // NOTE: overwritten later (depends on usePolling)
..._opts,
// Change format
ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),
awaitWriteFinish:
awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,
};

Additional context
I was in the process of testing the feasability to update to v4 in webpack/webpack-dev-server#5368.
However, all watch-tests fail with the error TypeError: The "interval" argument must be of type number. Received undefined.

So either chokidar was cleaning up options in v3 or something else than Nodes native watcher was used.
In any case it is an unexpected breaking change.
I am aware that v4 was a major version bump but this seems to be a minor thing that could be adapted easily to make upgrading to v4 even easier.

Changing the above code to this would solve the problem:

        const opts = {
            ..._opts,
            // Defaults
            persistent: _opts.persistent ?? true,
            ignoreInitial: _opts.ignoreInitial ?? false,
            ignorePermissionErrors: _opts.ignorePermissionErrors ?? false,
            interval: _opts.interval ?? 100,
            binaryInterval: _opts.binaryInterval ?? 300,
            followSymlinks: _opts.followSymlinks ?? true,
            usePolling: _opts.usePolling ?? false,
            // useAsync: _opts.useAsync ?? false,
            atomic: _opts.atomic ?? true, // NOTE: overwritten later (depends on usePolling)
            
            // Change format
            ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),
            awaitWriteFinish: _opts.awaitWriteFinish ?? (awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false),
        };

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions