Skip to content

Commit e56c73c

Browse files
committed
fix(linter): get cli args on JS side, to avoid runtime inconsistencies (#14223)
fixes #14150 related: #14112, #14071 This seems to be the only reliable way to get arguments across different runtimes. when running with deno, the args from `std::env::args_os()` look like: ``` [ "/Users/cameron/.deno/bin/deno", "run", "--ext=js", "-A", "/Users/cameron/github/camc314/oxlint-repros/issue-14150/node_modules/.deno/oxlint@1.18.0/node_modules/oxlint/bin/oxlint", ".", ] ``` however `process.argv` looks like: ``` [ "oxlint", "/Users/cameron/github/camc314/oxlint-repros/issue-14150/node_modules/.deno/oxlint@1.18.0/node_modules/oxlint/bin/oxlint", "." ] ``` so skipping the first two means that we end up with incorrect args that we're trying to parts. There are (potentially) other solutions e.g. search for one of the args ending in`oxlint`, or other methods of trying to guess. However, this feels like the most reliable solution.
1 parent e045391 commit e56c73c

File tree

3 files changed

+23
-16
lines changed

3 files changed

+23
-16
lines changed

apps/oxlint/src-js/bindings.d.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ export type JsLoadPluginCb =
1111
/**
1212
* NAPI entry point.
1313
*
14-
* JS side passes in two callbacks:
15-
* 1. `load_plugin`: Load a JS plugin from a file path.
16-
* 2. `lint_file`: Lint a file.
14+
* JS side passes in:
15+
* 1. `args`: Command line arguments (process.argv.slice(2))
16+
* 2. `load_plugin`: Load a JS plugin from a file path.
17+
* 3. `lint_file`: Lint a file.
1718
*
1819
* Returns `true` if linting succeeded without errors, `false` otherwise.
1920
*/
20-
export declare function lint(loadPlugin: JsLoadPluginCb, lintFile: JsLintFileCb): Promise<boolean>
21+
export declare function lint(args: Array<string>, loadPlugin: JsLoadPluginCb, lintFile: JsLintFileCb): Promise<boolean>

apps/oxlint/src-js/cli.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ function lintFileWrapper(filePath: string, bufferId: number, buffer: Uint8Array
2020
return lintFile(filePath, bufferId, buffer, ruleIds);
2121
}
2222

23-
// Call Rust, passing `loadPlugin` and `lintFile` as callbacks
24-
const success = await lint(loadPluginWrapper, lintFileWrapper);
23+
// Get command line arguments, skipping first 2 (node binary and script path)
24+
const args = process.argv.slice(2);
25+
26+
// Call Rust, passing `loadPlugin` and `lintFile` as callbacks, and CLI arguments
27+
const success = await lint(args, loadPluginWrapper, lintFileWrapper);
2528

2629
// Note: It's recommended to set `process.exitCode` instead of calling `process.exit()`.
2730
// `process.exit()` kills the process immediately and `stdout` may not be flushed before process dies.

apps/oxlint/src/run.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,27 +49,30 @@ pub type JsLintFileCb = ThreadsafeFunction<
4949

5050
/// NAPI entry point.
5151
///
52-
/// JS side passes in two callbacks:
53-
/// 1. `load_plugin`: Load a JS plugin from a file path.
54-
/// 2. `lint_file`: Lint a file.
52+
/// JS side passes in:
53+
/// 1. `args`: Command line arguments (process.argv.slice(2))
54+
/// 2. `load_plugin`: Load a JS plugin from a file path.
55+
/// 3. `lint_file`: Lint a file.
5556
///
5657
/// Returns `true` if linting succeeded without errors, `false` otherwise.
5758
#[expect(clippy::allow_attributes)]
5859
#[allow(clippy::trailing_empty_array, clippy::unused_async)] // https://github.com/napi-rs/napi-rs/issues/2758
5960
#[napi]
60-
pub async fn lint(load_plugin: JsLoadPluginCb, lint_file: JsLintFileCb) -> bool {
61-
lint_impl(load_plugin, lint_file).report() == ExitCode::SUCCESS
61+
pub async fn lint(args: Vec<String>, load_plugin: JsLoadPluginCb, lint_file: JsLintFileCb) -> bool {
62+
lint_impl(args, load_plugin, lint_file).report() == ExitCode::SUCCESS
6263
}
6364

6465
/// Run the linter.
65-
fn lint_impl(load_plugin: JsLoadPluginCb, lint_file: JsLintFileCb) -> CliRunResult {
66+
fn lint_impl(
67+
args: Vec<String>,
68+
load_plugin: JsLoadPluginCb,
69+
lint_file: JsLintFileCb,
70+
) -> CliRunResult {
6671
init_tracing();
6772
init_miette();
6873

69-
// 1st arg is path to NodeJS binary.
70-
// 2nd arg is path to `oxlint/.bin/oxlint` (in released packages)
71-
// or `apps/oxlint/dist/cli.js` (in development).
72-
let args = std::env::args_os().skip(2).collect::<Vec<_>>();
74+
// Convert String args to OsString for compatibility with bpaf
75+
let args: Vec<std::ffi::OsString> = args.into_iter().map(std::ffi::OsString::from).collect();
7376

7477
let cmd = crate::cli::lint_command();
7578
let command = match cmd.run_inner(&*args) {

0 commit comments

Comments
 (0)