Skip to content

oxfmt: Paths with consecutive slashes fail to resolve #21086

@a1678991

Description

@a1678991

Summary

oxfmt fails with "Expected at least one target file" when a file path contains consecutive slashes (e.g. .//src/app.js), even though the file exists and works with a single slash.

Per POSIX (IEEE Std 1003.1-2024, §3.254 "pathname"):

"Multiple successive <slash> characters are considered to be the same as one <slash>, except it is implementation-defined whether the case of exactly two leading
<slash> characters is treated specially."

The // in .//src/app.js is mid-path (not a leading //), so it must be equivalent to ./src/app.js.

Reproduction

# Create a test file
mkdir -p /tmp/oxfmt-test/src && echo 'const x = 1' > /tmp/oxfmt-test/src/app.js
cd /tmp/oxfmt-test

# Works
bunx oxfmt ./src/app.js
# Finished in 63ms on 1 files using 32 threads.

# Fails
bunx oxfmt .//src/app.js
# Expected at least one target file

Root Cause

// Normalize `./` prefix
let normalized =
if let Some(stripped) = path_str.strip_prefix("./") { stripped } else { &path_str };
// Separate glob patterns from concrete paths
if is_glob_pattern(normalized, cwd) {
glob_patterns.push(normalized.to_string());
continue;
}
// Resolve full path for concrete paths
let full_path = if path.is_absolute() {
path.clone()
} else if normalized == "." {
// NOTE: `.` and cwd behave differently, need to normalize
cwd.to_path_buf()
} else {
cwd.join(normalized)
};

For input .//src/app.js:

  1. strip_prefix("./") removes ./ → leaves /src/app.js
  2. path.is_absolute() on .//src/app.js → false
  3. cwd.join("/src/app.js") — Rust's Path::join treats an argument starting with / as absolute and discards the base path, returning /src/app.js
  4. /src/app.js doesn't exist → empty target paths → error

Expected Behavior

oxfmt .//src/app.js should behave identically to oxfmt ./src/app.js .

Environment

  • OS: Linux
  • oxfmt: 0.43.0

Metadata

Metadata

Assignees

Labels

Type

Priority

None yet

Effort

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions