Skip to content

Commit da7b7cb

Browse files
authored
feat: Convert windows path to unix path before comparing against ModuleMatcher file_path value. (#40)
1 parent 804a9c6 commit da7b7cb

11 files changed

Lines changed: 139 additions & 11 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ type FunctionQuery =
139139
type ModuleMatcher = {
140140
name: string; // Module name
141141
versionRange: string; // Matching semver range
142-
filePath: string; // Path to the file from the module root
142+
filePath: string; // Relative Unix-style path to the file from the module root (e.g. "lib/index.js")
143143
};
144144
```
145145

@@ -177,7 +177,7 @@ matching instrumentation configurations.
177177

178178
- `module_name` - Name of the module.
179179
- `version` - Version of the module.
180-
- `file_path` - Path to the file from the module root.
180+
- `file_path` - Relative Unix-style path to the file from the module root (e.g. `"lib/index.js"`). Windows-style backslash paths are also accepted and will be normalized automatically.
181181

182182
```ts
183183
free(): void;

src/config.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
**/
55
use crate::function_query::FunctionQuery;
66
use nodejs_semver::{Range, SemverError, Version};
7-
use std::path::PathBuf;
7+
use std::path::{Path, PathBuf};
88

99
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
1010
#[cfg_attr(
@@ -37,7 +37,7 @@ impl ModuleMatcher {
3737
}
3838

3939
#[must_use]
40-
pub fn matches(&self, module_name: &str, version: &str, file_path: &PathBuf) -> bool {
40+
pub fn matches(&self, module_name: &str, version: &str, file_path: &Path) -> bool {
4141
let version: Version = match version.parse() {
4242
Ok(v) => v,
4343
Err(e) => {
@@ -46,9 +46,11 @@ impl ModuleMatcher {
4646
}
4747
};
4848

49+
// convert windows paths to unix before comparing against `self.file_path`
50+
let normalized_path = PathBuf::from(file_path.to_string_lossy().replace('\\', "/"));
4951
self.name == module_name
5052
&& version.satisfies(&self.version_range)
51-
&& self.file_path == *file_path
53+
&& self.file_path == normalized_path
5254
}
5355
}
5456

@@ -120,7 +122,7 @@ impl Config {
120122

121123
impl InstrumentationConfig {
122124
#[must_use]
123-
pub fn matches(&self, module_name: &str, version: &str, file_path: &PathBuf) -> bool {
125+
pub fn matches(&self, module_name: &str, version: &str, file_path: &Path) -> bool {
124126
self.module.matches(module_name, version, file_path)
125127
}
126128
}

src/instrumentation.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
**/
55
use crate::config::InstrumentationConfig;
66
use std::collections::HashMap;
7-
use std::path::PathBuf;
7+
use std::path::Path;
88
use swc_core::common::{Span, SyntaxContext};
99
use swc_core::ecma::{
1010
ast::{
@@ -244,7 +244,7 @@ impl Instrumentation {
244244
}
245245

246246
#[must_use]
247-
pub fn matches(&self, module_name: &str, version: &str, file_path: &PathBuf) -> bool {
247+
pub fn matches(&self, module_name: &str, version: &str, file_path: &Path) -> bool {
248248
self.config.matches(module_name, version, file_path)
249249
}
250250

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
1919
* This product includes software developed at Datadog (<https://www.datadoghq.com>/). Copyright 2025 Datadog, Inc.
2020
**/
21-
use std::{collections::HashMap, error::Error, path::PathBuf, sync::Arc};
21+
use std::{collections::HashMap, error::Error, path::Path, path::PathBuf, sync::Arc};
2222
use swc::{
2323
config::{IsModule, SourceMapsConfig},
2424
sourcemap::SourceMap,
@@ -134,7 +134,7 @@ impl Instrumentor {
134134
&self,
135135
module_name: &str,
136136
version: &str,
137-
file_path: &PathBuf,
137+
file_path: &Path,
138138
) -> InstrumentationVisitor {
139139
let instrumentations = self
140140
.instrumentations

tests/common/mod.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,18 @@ static TEST_MODULE_NAME: &str = "undici";
1313
static TEST_MODULE_PATH: &str = "index.mjs";
1414

1515
pub fn transpile_and_test(test_file: &str, mjs: bool, config: Config) {
16+
transpile_and_test_with_path(test_file, mjs, config, PathBuf::from(TEST_MODULE_PATH));
17+
}
18+
19+
pub fn transpile_and_test_with_path(
20+
test_file: &str,
21+
mjs: bool,
22+
config: Config,
23+
file_path: PathBuf,
24+
) {
1625
let test_file = PathBuf::from(test_file);
1726
let test_dir = test_file.parent().expect("Couldn't find test directory");
1827

19-
let file_path = PathBuf::from("index.mjs");
2028
let instrumentor = Instrumentor::new(config);
2129
let mut instrumentations =
2230
instrumentor.get_matching_instrumentations(TEST_MODULE_NAME, "0.0.1", &file_path);
@@ -46,3 +54,9 @@ pub fn transpile_and_test(test_file: &str, mjs: bool, config: Config) {
4654
pub fn test_module_matcher() -> ModuleMatcher {
4755
ModuleMatcher::new(TEST_MODULE_NAME, ">=0.0.1", TEST_MODULE_PATH).unwrap()
4856
}
57+
58+
static WINDOWS_TEST_MODULE_PATH: &str = "lib/index.mjs";
59+
60+
pub fn windows_module_matcher() -> ModuleMatcher {
61+
ModuleMatcher::new(TEST_MODULE_NAME, ">=0.0.1", WINDOWS_TEST_MODULE_PATH).unwrap()
62+
}

tests/instrumentor_test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ mod polyfill_mjs;
2929
mod private_method_cjs;
3030
mod var_class_export_alias_mjs;
3131
mod var_named_class_export_alias_mjs;
32+
mod windows_path;

tests/wasm/__snapshots__/tests.test.mjs.snap

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,32 @@ export class Up {
287287
"map": "{"version":3,"file":"module.js","sources":["module.ts"],"sourceRoot":"","names":[],"mappings":";;;;;;AAEA,MAAM,CAAA,MAAO,EAAE;IACX,aAAA;;;;;;;;;YACI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;;;;;;;;;;;;;;;;IAC/B,CAAC;IACD,KAAK,IAAS,EAAA;;;mCAAR;gBACF,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;;;;;;;;;;IACD,KAAK,CAAC,UAAU,GAAA;;;;;;;;;;;;IAAU,CAAC;IAC3B,GAAG,GAAA;;;;;;;;;;;;IAAU,CAAC;IACd,KAAK,EAAC,IAAK;;;;;;;;;;;;IAAU,CAAC;IACtB,KAAK,CAAC,IAAI,GAAA,CAAU,CAAC;CACxB"}",
288288
}
289289
`;
290+
291+
exports[`windows style paths > should transform ESM module correctly 1`] = `
292+
{
293+
"code": "import { tracingChannel as tr_ch_apm_tracingChannel } from "diagnostics_channel";
294+
const tr_ch_apm$up_fetch = tr_ch_apm_tracingChannel("orchestrion:one:up:fetch");
295+
export class Up {
296+
constructor(){
297+
console.log('constructor');
298+
}
299+
fetch() {
300+
const __apm$original_args = arguments;
301+
const __apm$traced = ()=>{
302+
const __apm$wrapped = ()=>{
303+
console.log('fetch');
304+
};
305+
return __apm$wrapped.apply(null, __apm$original_args);
306+
};
307+
if (!tr_ch_apm$up_fetch.hasSubscribers) return __apm$traced();
308+
return tr_ch_apm$up_fetch.traceSync(__apm$traced, {
309+
arguments,
310+
self: this,
311+
moduleVersion: "1.0.0"
312+
});
313+
}
314+
}
315+
",
316+
"map": undefined,
317+
}
318+
`;

tests/wasm/tests.test.mjs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,42 @@ export class Up {
166166
}).toThrow('Failed to find injection points for: ["constructor", "fetch", "asyncFetch", "get", "send"]');
167167
});
168168
});
169+
170+
describe('windows style paths', () => {
171+
const instrumentor = create([
172+
{
173+
channelName: "up:fetch",
174+
module: { name: "one", versionRange: ">=1", filePath: "path/to/file.js" },
175+
functionQuery: {
176+
className: "Up",
177+
methodName: "fetch",
178+
kind: "Sync",
179+
},
180+
},
181+
]);
182+
183+
const matchedTransforms = instrumentor.getTransformer(
184+
"one",
185+
"1.0.0",
186+
"path\\to\\file.js",
187+
);
188+
189+
test('should get transformer for matching module', () => {
190+
expect(matchedTransforms).toBeTruthy();
191+
});
192+
193+
test('should transform ESM module correctly', () => {
194+
const originalEsm = `export class Up {
195+
constructor() {
196+
console.log('constructor')
197+
}
198+
199+
fetch() {
200+
console.log('fetch')
201+
}
202+
}`;
203+
204+
const output = matchedTransforms.transform(originalEsm, 'esm');
205+
expect(output).toMatchSnapshot();
206+
});
207+
})

tests/windows_path/mod.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2025 Datadog, Inc.
4+
**/
5+
async function fetch (url) {
6+
return 42;
7+
}
8+
9+
module.exports = { fetch };

tests/windows_path/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use crate::common::*;
2+
use orchestrion_js::*;
3+
use std::path::PathBuf;
4+
5+
#[test]
6+
fn windows_path() {
7+
transpile_and_test_with_path(
8+
file!(),
9+
false,
10+
Config::new_single(InstrumentationConfig::new(
11+
"fetch_decl",
12+
windows_module_matcher(),
13+
FunctionQuery::function_declaration("fetch", FunctionKind::Async),
14+
)),
15+
PathBuf::from("lib\\index.mjs"),
16+
);
17+
}

0 commit comments

Comments
 (0)