diff --git a/doc/api/fs.md b/doc/api/fs.md index e70411e2d07..cd9632c4ee1 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1078,6 +1078,9 @@ changes: - version: REPLACEME pr-url: https://github.com/nodejs/node/pull/57513 description: Marking the API stable. + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/58182 + description: Add support for `URL` instances for `cwd` option. - version: v22.14.0 pr-url: https://github.com/nodejs/node/pull/56489 description: Add support for `exclude` option to accept glob patterns. @@ -1088,7 +1091,7 @@ changes: * `pattern` {string|string\[]} * `options` {Object} - * `cwd` {string} current working directory. **Default:** `process.cwd()` + * `cwd` {string|URL} current working directory. **Default:** `process.cwd()` * `exclude` {Function|string\[]} Function to filter out files/directories or a list of glob patterns to be excluded. If a function is provided, return `true` to exclude the item, `false` to include it. **Default:** `undefined`. @@ -3131,6 +3134,9 @@ changes: - version: REPLACEME pr-url: https://github.com/nodejs/node/pull/57513 description: Marking the API stable. + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/58182 + description: Add support for `URL` instances for `cwd` option. - version: v22.14.0 pr-url: https://github.com/nodejs/node/pull/56489 description: Add support for `exclude` option to accept glob patterns. @@ -3142,7 +3148,7 @@ changes: * `pattern` {string|string\[]} * `options` {Object} - * `cwd` {string} current working directory. **Default:** `process.cwd()` + * `cwd` {string|URL} current working directory. **Default:** `process.cwd()` * `exclude` {Function|string\[]} Function to filter out files/directories or a list of glob patterns to be excluded. If a function is provided, return `true` to exclude the item, `false` to include it. **Default:** `undefined`. @@ -5682,6 +5688,9 @@ changes: - version: REPLACEME pr-url: https://github.com/nodejs/node/pull/57513 description: Marking the API stable. + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/58182 + description: Add support for `URL` instances for `cwd` option. - version: v22.14.0 pr-url: https://github.com/nodejs/node/pull/56489 description: Add support for `exclude` option to accept glob patterns. @@ -5692,7 +5701,7 @@ changes: * `pattern` {string|string\[]} * `options` {Object} - * `cwd` {string} current working directory. **Default:** `process.cwd()` + * `cwd` {string|URL} current working directory. **Default:** `process.cwd()` * `exclude` {Function|string\[]} Function to filter out files/directories or a list of glob patterns to be excluded. If a function is provided, return `true` to exclude the item, `false` to include it. **Default:** `undefined`. diff --git a/lib/internal/fs/glob.js b/lib/internal/fs/glob.js index 5e6b4828ceb..b5966549045 100644 --- a/lib/internal/fs/glob.js +++ b/lib/internal/fs/glob.js @@ -38,6 +38,7 @@ const { hideStackFrames, } = require('internal/errors'); const assert = require('internal/assert'); +const { toPathIfFileURL } = require('internal/url'); let minimatch; function lazyMinimatch() { @@ -268,7 +269,7 @@ class Glob { constructor(pattern, options = kEmptyObject) { validateObject(options, 'options'); const { exclude, cwd, withFileTypes } = options; - this.#root = cwd ?? '.'; + this.#root = toPathIfFileURL(cwd) ?? '.'; this.#withFileTypes = !!withFileTypes; if (exclude != null) { validateStringArrayOrFunction(exclude, 'options.exclude'); diff --git a/test/parallel/test-fs-glob.mjs b/test/parallel/test-fs-glob.mjs index 077c0527991..b3708f46637 100644 --- a/test/parallel/test-fs-glob.mjs +++ b/test/parallel/test-fs-glob.mjs @@ -4,6 +4,7 @@ import { resolve, dirname, sep, relative, join, isAbsolute } from 'node:path'; import { mkdir, writeFile, symlink, glob as asyncGlob } from 'node:fs/promises'; import { glob, globSync, Dirent } from 'node:fs'; import { test, describe } from 'node:test'; +import { pathToFileURL } from 'node:url'; import { promisify } from 'node:util'; import assert from 'node:assert'; @@ -338,6 +339,39 @@ describe('fsPromises glob', function() { } }); +describe('glob - with file: URL as cwd', function() { + const promisified = promisify(glob); + for (const [pattern, expected] of Object.entries(patterns)) { + test(pattern, async () => { + const actual = (await promisified(pattern, { cwd: pathToFileURL(fixtureDir) })).sort(); + const normalized = expected.filter(Boolean).map((item) => item.replaceAll('/', sep)).sort(); + assert.deepStrictEqual(actual, normalized); + }); + } +}); + +describe('globSync - with file: URL as cwd', function() { + for (const [pattern, expected] of Object.entries(patterns)) { + test(pattern, () => { + const actual = globSync(pattern, { cwd: pathToFileURL(fixtureDir) }).sort(); + const normalized = expected.filter(Boolean).map((item) => item.replaceAll('/', sep)).sort(); + assert.deepStrictEqual(actual, normalized); + }); + } +}); + +describe('fsPromises.glob - with file: URL as cwd', function() { + for (const [pattern, expected] of Object.entries(patterns)) { + test(pattern, async () => { + const actual = []; + for await (const item of asyncGlob(pattern, { cwd: pathToFileURL(fixtureDir) })) actual.push(item); + actual.sort(); + const normalized = expected.filter(Boolean).map((item) => item.replaceAll('/', sep)).sort(); + assert.deepStrictEqual(actual, normalized); + }); + } +}); + const normalizeDirent = (dirent) => relative(fixtureDir, join(dirent.parentPath, dirent.name)); // The call to `join()` with only one argument is important, as // it ensures that the proper path seperators are applied.