Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ resolver = "2"
#lto = true

[workspace.dependencies]
istanbul-oxide = { path = "./packages/istanbul-oxide", version = "0.0.28" }
istanbul-oxide = { path = "./packages/istanbul-oxide", version = "0.0.29" }
swc-coverage-instrument = { path = "./packages/swc-coverage-instrument" }

getrandom = { version = "0.2.15" }
Expand All @@ -24,5 +24,6 @@ resolver = "2"
swc_core = { version = "31.1.0" }
tracing = { version = "0.1.37" }
tracing-subscriber = { version = "0.3.17" }
typed-path = { version = "0.11.0" }
wasm-bindgen = { version = "0.2.92" }
wax = { version = "0.6.0" }
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "swc-plugin-coverage-instrument",
"version": "0.0.28",
"version": "0.0.29",
"description": "SWC coverage instrumentation plugin",
"main": "./target/wasm32-wasip1/release/swc_plugin_coverage.wasm",
"napi": {
Expand Down
2 changes: 1 addition & 1 deletion packages/istanbul-oxide/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"
license = "MIT"
name = "istanbul-oxide"
repository = "https://github.com/kwonoj/swc-coverage-instrument"
version = "0.0.28"
version = "0.0.29"

[dependencies]
indexmap = { workspace = true, features = ["serde"] }
Expand Down
2 changes: 1 addition & 1 deletion packages/swc-coverage-instrument/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"
license = "MIT"
name = "swc-coverage-instrument"
repository = "https://github.com/kwonoj/swc-coverage-instrument"
version = "0.0.28"
version = "0.0.29"

[dependencies]
istanbul-oxide = { workspace = true }
Expand Down
3 changes: 2 additions & 1 deletion packages/swc-plugin-coverage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"
license = "MIT"
name = "swc-plugin-coverage"
repository = "https://github.com/kwonoj/swc-coverage-instrument"
version = "0.0.28"
version = "0.0.29"

[lib]
crate-type = ["cdylib"]
Expand All @@ -16,4 +16,5 @@ swc-coverage-instrument = { workspace = true }
swc_core = { workspace = true, features = ["ecma_plugin_transform"] }
tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["fmt"] }
typed-path = { workspace = true }
wax = { workspace = true }
56 changes: 55 additions & 1 deletion packages/swc-plugin-coverage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,23 @@ use swc_coverage_instrument::{
};

use tracing_subscriber::fmt::format::FmtSpan;
use typed_path::Utf8TypedPath;
use wax::Pattern;

/// Normalize a file path to use forward slashes for consistent glob matching
fn normalize_path_for_glob_matching(path: &str) -> String {
let typed_path = Utf8TypedPath::derive(path);
if typed_path.is_windows() {
typed_path.with_unix_encoding().to_string()
} else if path.contains('\\') {
// Fallback: if the path contains backslashes but wasn't detected as Windows,
// still normalize it by replacing backslashes with forward slashes
path.replace('\\', "/")
} else {
path.to_string()
}
}

fn initialize_instrumentation_log(log_options: &InstrumentLogOptions) {
let log_level = match log_options.level.as_deref() {
Some("error") => Some(tracing::Level::ERROR),
Expand Down Expand Up @@ -64,7 +79,8 @@ pub fn process(program: Program, metadata: TransformPluginProgramMetadata) -> Pr
if let Some(exclude) = &instrument_options.unstable_exclude {
match wax::any(exclude.iter().map(|s| s.as_ref()).collect::<Vec<&str>>()) {
Ok(p) => {
if p.is_match(filename) {
let normalized_filename = normalize_path_for_glob_matching(filename);
if p.is_match(normalized_filename.as_str()) {
return program;
}
}
Expand All @@ -86,3 +102,41 @@ pub fn process(program: Program, metadata: TransformPluginProgramMetadata) -> Pr

program.apply(&mut visit_mut_pass(visitor))
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_normalize_path_for_glob_matching() {
// Test Windows paths are normalized to Unix-style
let result = normalize_path_for_glob_matching(r"C:\Users\project\test\index.test.ts");
println!("Windows path result: {}", result);
// The typed-path crate converts Windows paths to Unix format, but may strip the drive letter
// The important thing is that backslashes are converted to forward slashes
assert!(result.contains("/Users/project/test/index.test.ts"));

// Test mixed separators are normalized
let result = normalize_path_for_glob_matching(r"C:\Users/project\test/file.js");
println!("Mixed separators result: {}", result);
assert!(result.contains("/Users/project/test/file.js"));

// Test Unix paths remain unchanged
assert_eq!(
normalize_path_for_glob_matching("/home/user/project/src/utils/helper.js"),
"/home/user/project/src/utils/helper.js"
);

// Test relative Unix paths remain unchanged
assert_eq!(
normalize_path_for_glob_matching("src/components/Button.tsx"),
"src/components/Button.tsx"
);

// Test that backslashes are converted to forward slashes
let windows_path = r"project\src\test\file.ts";
let result = normalize_path_for_glob_matching(windows_path);
println!("Relative Windows path result: {}", result);
assert!(result.contains("project/src/test/file.ts"));
}
}
20 changes: 20 additions & 0 deletions spec/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ ${code}
);
});

it("should normalize paths", () => {
const code = `console.log('hello world');`;

const output = instrumentSync(
code,
"C:\\Users\\project\\test\\index.test.ts",
undefined,
{
unstableExclude: ["**/test/**"],
},
);

assert.equal(
output.code,
`"use strict";
${code}
`,
);
});

it("should preserve emotion styled component labels with template literals", () => {
// This reproduces the issue from GitHub #247
// Input: code AFTER emotion processing (as shown in the GitHub issue)
Expand Down
2 changes: 1 addition & 1 deletion spec/swc-coverage-custom-transform/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ napi-derive = { version = "2.12.3", default-features = false, features = [
] }
serde = { version = "1.0.203", features = ["derive"] }
serde_json = { version = "1.0.120", features = ["unbounded_depth"] }
swc-coverage-instrument = { version = "0.0.28", path = "../../packages/swc-coverage-instrument" }
swc-coverage-instrument = { version = "0.0.29", path = "../../packages/swc-coverage-instrument" }
swc_core = { version = "31.1.0", features = [
"common_concurrent",
"ecma_transforms",
Expand Down
1 change: 0 additions & 1 deletion spec/swc-coverage-instrument-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub struct CoverageMagicValue {
value: String,
}


#[wasm_bindgen(js_name = "getCoverageMagicConstants")]
pub fn get_coverage_magic_constants() -> JsValue {
serde_wasm_bindgen::to_value(&CoverageMagicValue {
Expand Down
Loading