Skip to content

Commit

Permalink
fix: use return number for napi
Browse files Browse the repository at this point in the history
fix #205
  • Loading branch information
HerringtonDarkholme committed Jan 26, 2023
1 parent 44e53e1 commit ac266db
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
12 changes: 8 additions & 4 deletions crates/napi/__test__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,18 @@ test('test find files', async t => {
t.is(tree.filename(), './__test__/index.spec.ts')
t.assert(tree.root() !== null)
})
})

let i = 0;
let fileCount = await parseFiles(['../../../test/volar'], (err, _) => {
let start = Date.now()
test('test file count', async t => {
let i = 0
let fileCount: number | undefined = undefined
fileCount = await parseFiles(['./'], (err, _) => {
// ZZZ... sleep a while to mock expensive operation
while (Date.now() - start < 1) { continue }
let start = Date.now()
while (Date.now() - start < 1) continue
t.is(err, null)
i += 1;
if (fileCount) console.log(_.filename())
})
t.is(i, fileCount)
})
2 changes: 1 addition & 1 deletion crates/napi/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface NapiConfig {
constraints?: any
language?: FrontEndLanguage
}
export function parseFiles(paths: string[], callback: (err: null | Error, result: SgRoot) => void): Promise<unknown>
export function parseFiles(paths: string[], callback: (err: null | Error, result: SgRoot) => void): Promise<number>
export class SgNode {
range(): Range
isLeaf(): boolean
Expand Down
20 changes: 13 additions & 7 deletions crates/napi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,14 +438,16 @@ impl Task for ParseFiles {
let tx = tx.clone();
let file_count = &file_count;
Box::new(move |entry| match call_sg_root(tsfn, entry) {
Ok(_) => {
Ok(true) => {
// file is sent to JS thread, increment file count
if tx.send(()).is_ok() {
file_count.fetch_add(1, Ordering::AcqRel);
WalkState::Continue
} else {
WalkState::Quit
}
}
Ok(false) => WalkState::Continue,
Err(_) => WalkState::Skip,
})
});
Expand All @@ -463,29 +465,33 @@ impl Task for ParseFiles {
}

// See https://github.com/ast-grep/ast-grep/issues/206
// NodeJS has a 1000 file limitation on sync iteration count
// NodeJS has a 1000 file limitation on sync iteration count.
// https://github.com/nodejs/node/blob/8ba54e50496a6a5c21d93133df60a9f7cb6c46ce/src/node_api.cc#L336
const THREAD_FUNC_QUEUE_SIZE: usize = 900;
const THREAD_FUNC_QUEUE_SIZE: usize = 1000;

#[napi(ts_args_type = "paths: string[], callback: (err: null | Error, result: SgRoot) => void")]
#[napi(
ts_args_type = "paths: string[], callback: (err: null | Error, result: SgRoot) => void",
ts_return_type = "Promise<number>"
)]
pub fn parse_files(paths: Vec<String>, callback: JsFunction) -> Result<AsyncTask<ParseFiles>> {
let tsfn: ThreadsafeFunction<SgRoot, ErrorStrategy::CalleeHandled> =
callback.create_threadsafe_function(THREAD_FUNC_QUEUE_SIZE, |ctx| Ok(vec![ctx.value]))?;
Ok(AsyncTask::new(ParseFiles { paths, tsfn }))
}

// returns if the entry is a file and sent to JavaScript queue
fn call_sg_root(
tsfn: &ThreadsafeFunction<SgRoot, ErrorStrategy::CalleeHandled>,
entry: std::result::Result<ignore::DirEntry, ignore::Error>,
) -> Ret<()> {
) -> Ret<bool> {
use FrontEndLanguage::*;
let entry = entry?;
if !entry
.file_type()
.context("could not use stdin as file")?
.is_file()
{
return Ok(());
return Ok(false);
}
let path = entry.into_path();
let file_content = std::fs::read_to_string(&path)?;
Expand All @@ -504,5 +510,5 @@ fn call_sg_root(
};
let sg = SgRoot(lang.ast_grep(file_content), path.to_string_lossy().into());
tsfn.call(Ok(sg), ThreadsafeFunctionCallMode::Blocking);
Ok(())
Ok(true)
}

0 comments on commit ac266db

Please sign in to comment.