[rust] Expose parse function to napi

Updates the `forget_napi` crate to call the parser and semantic analyzer and 
convert their values to JS.
This commit is contained in:
Joe Savona
2023-08-21 16:04:03 -07:00
parent 7fc7488ac8
commit 9c13e4413c
4 changed files with 133 additions and 12 deletions
+5
View File
@@ -285,9 +285,14 @@ dependencies = [
name = "forget_napi"
version = "0.1.0"
dependencies = [
"forget_diagnostics",
"forget_estree",
"forget_hermes_parser",
"forget_semantic_analysis",
"napi",
"napi-build",
"napi-derive",
"serde_json",
]
[[package]]
@@ -14,8 +14,13 @@ repository.workspace = true
crate-type = ["cdylib"]
[dependencies]
forget_diagnostics = { workspace = true }
forget_hermes_parser = { workspace = true }
forget_estree = { workspace = true }
forget_semantic_analysis = { workspace = true }
napi = { version = "2.13.3", features = ["serde-json", "async"] }
napi-derive = { version = "2.12" }
serde_json = { workspace = true }
[build-dependencies]
napi-build = "2"
@@ -0,0 +1,13 @@
# forget_napi
This crate uses [napi-rs](https://napi.rs/) to expose Forget's analysis to JavaScript via the [Node-API](https://nodejs.org/api/n-api.html#node-api).
## Build
Note that `napi-rs` is a bit finicky and doesn't offer full control over where its outputs are emitted. For consistency, be sure to build with
```
yarn build
```
To use the canonical build, which will ensure that all files are placed in the right location.
+110 -12
View File
@@ -1,17 +1,115 @@
use forget_diagnostics::Diagnostic;
use forget_semantic_analysis::{analyze, AnalyzeOptions};
use napi_derive::napi;
pub const GLOBALS: &[&str] = &[
"AggregateError",
"Array",
"ArrayBuffer",
"AsyncFunction",
"AsyncGenerator",
"AsyncGeneratorFunction",
"AsyncIterator",
"Atomics",
"BigInt",
"BigInt64Array",
"BigUint64Array",
"Boolean",
"DataView",
"Date",
"decodeURI",
"decodeURIComponent",
"encodeURI",
"encodeURIComponent",
"Error",
"escape",
"eval",
"EvalError",
"FinalizationRegistry",
"Float32Array",
"Float64Array",
"Function",
"Generator",
"GeneratorFunction",
"globalThis",
"Infinity",
"Int16Array",
"Int32Array",
"Int8Array",
// "InternalError", // non-standard
"Intl",
"isFinite",
"isNaN",
"Iterator",
"JSON",
"Map",
"Math",
"NaN",
"Number",
"Object",
"parseFloat",
"parseInt",
"Promise",
"Proxy",
"RangeError",
"ReferenceError",
"Reflect",
"RegExp",
"Set",
"SharedArrayBuffer",
"String",
"Symbol",
"SyntaxError",
"TypeError",
"Uint16Array",
"Uint32Array",
"Uint8Array",
"Uint8ClampedArray",
"undefined",
"unescape",
"URIError",
"WeakMap",
"WeakRef",
"WeakSet",
];
#[napi]
pub fn add(left: i32, right: i32) -> i32 {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
pub fn parse(source: String, options: ParseOptions) -> ParseResult {
let program = match forget_hermes_parser::parse(&source, &options.file) {
Ok(program) => program,
Err(diagnostics) => {
return ParseResult {
program: None,
diagnostics: convert_diagnostics(diagnostics),
};
}
};
let mut analysis = analyze(
&program,
AnalyzeOptions {
globals: GLOBALS.iter().map(|s| s.to_string()).collect(),
},
);
ParseResult {
program: Some(serde_json::to_string(&program).unwrap()),
diagnostics: convert_diagnostics(analysis.diagnostics()),
}
}
fn convert_diagnostics(diagnostics: Vec<Diagnostic>) -> Vec<String> {
diagnostics
.into_iter()
.map(|diagnostic| format!("{}", diagnostic))
.collect()
}
#[napi(object)]
pub struct ParseOptions {
pub file: String,
}
#[napi(object)]
pub struct ParseResult {
pub program: Option<String>,
pub diagnostics: Vec<String>,
}