Skip to content

fix: treat ** adjacent to a literal as a single star (#99)#181

Open
fdma wants to merge 1 commit into
micromatch:masterfrom
fdma:fix/globstar-adjacent-literal-issue-99
Open

fix: treat ** adjacent to a literal as a single star (#99)#181
fdma wants to merge 1 commit into
micromatch:masterfrom
fdma:fix/globstar-adjacent-literal-issue-99

Conversation

@fdma

@fdma fdma commented Jun 25, 2026

Copy link
Copy Markdown

Description

picomatch('**.thing.js')('somepath/test.thing.js') returns true but should return false. Per Bash semantics (confirmed by @jonschlinkert in #99), ** only acts as a globstar when it is the sole content of a path segment. When ** is adjacent to other characters in the same segment (here .thing.js), it must behave like a single * and must not match across path separators.

Closes #99.

Root cause

The bug is in the fast-path builder parse.fastpaths (lib/parse.js). Its create() helper strips a trailing .ext in the default branch and recurses on the remaining base. For **.thing.js the base is reduced to a bare **, which hits the case '**' branch and expands to a globstar ((?:(?!...).)*?) that crosses /.

Patterns like **.dash-thing.js were unaffected only by accident: - is not a \w character, so they never matched the .ext fast path and fell back to the full parser, which already produces the correct single-star regex.

Fix

In the default branch, if stripping the extension reduces the base to a bare **, bail out of the fast path (return) and let the full parser handle the pattern — exactly the path that already produced correct output for **.dash-thing.js. This keeps the change minimal and guarantees the fast path agrees with the full parser.

Tests

Added a regression test in test/issue-related.js. The full suite passes (npm test): 1976 passing, including the existing globstar / "non-exclusive double-stars" specs.

In the fast-path regex builder, `**.ext` patterns (e.g. `**.js`,
`**.thing.js`) were reduced to a bare `**` and expanded to a globstar,
so they incorrectly matched across path separators — `**.thing.js`
matched `somepath/test.thing.js`.

Per Bash semantics, `**` is only a globstar when it is the sole content
of a path segment; adjacent to other characters it behaves as a single
star. Bail out of the fast path for this shape and let the full parser
produce the correct single-star regex (as it already did for patterns
the fast path skipped, e.g. `**.dash-thing.js`).

Closes micromatch#99
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can't match **.internal-test.js

1 participant