@samitouri / QOS-React-1 / commits / 9c13e4413c

[rust] Expose parse function to napi

Updates the `forget_napi` crate to call the parser and semantic analyzer and convert their values to JS.

Joe Savona committed Aug 21, 2023 at 16:04 UTC 9c13e4413c270da3acfbe0956a71fb90fc6c8475
4 files changed +131 -10
compiler/forget/Cargo.lock
+5
@@ -285,9 +285,14 @@ dependencies = [
285 name = "forget_napi"
286 version = "0.1.0"
287 dependencies = [
288 + "forget_diagnostics",
289 + "forget_estree",
290 + "forget_hermes_parser",
291 + "forget_semantic_analysis",
292 "napi",
293 "napi-build",
294 "napi-derive",
295 + "serde_json",
296 ]
297
298 [[package]]
compiler/forget/crates/forget_napi/Cargo.toml
+5
@@ -14,8 +14,13 @@ repository.workspace = true
14 crate-type = ["cdylib"]
15
16 [dependencies]
17 +forget_diagnostics = { workspace = true }
18 +forget_hermes_parser = { workspace = true }
19 +forget_estree = { workspace = true }
20 +forget_semantic_analysis = { workspace = true }
21 napi = { version = "2.13.3", features = ["serde-json", "async"] }
22 napi-derive = { version = "2.12" }
23 +serde_json = { workspace = true }
24
25 [build-dependencies]
26 napi-build = "2"
\ No newline at end of file
compiler/forget/crates/forget_napi/README.md new
+13
@@ -0,0 +1,13 @@
1 +# forget_napi
2 +
3 +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).
4 +
5 +## Build
6 +
7 +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
8 +
9 +```
10 +yarn build
11 +```
12 +
13 +To use the canonical build, which will ensure that all files are placed in the right location.
\ No newline at end of file
compiler/forget/crates/forget_napi/src/lib.rs
+108 -10
@@ -1,17 +1,115 @@
1 +use forget_diagnostics::Diagnostic;
2 +use forget_semantic_analysis::{analyze, AnalyzeOptions};
3 use napi_derive::napi;
4
5 +pub const GLOBALS: &[&str] = &[
6 + "AggregateError",
7 + "Array",
8 + "ArrayBuffer",
9 + "AsyncFunction",
10 + "AsyncGenerator",
11 + "AsyncGeneratorFunction",
12 + "AsyncIterator",
13 + "Atomics",
14 + "BigInt",
15 + "BigInt64Array",
16 + "BigUint64Array",
17 + "Boolean",
18 + "DataView",
19 + "Date",
20 + "decodeURI",
21 + "decodeURIComponent",
22 + "encodeURI",
23 + "encodeURIComponent",
24 + "Error",
25 + "escape",
26 + "eval",
27 + "EvalError",
28 + "FinalizationRegistry",
29 + "Float32Array",
30 + "Float64Array",
31 + "Function",
32 + "Generator",
33 + "GeneratorFunction",
34 + "globalThis",
35 + "Infinity",
36 + "Int16Array",
37 + "Int32Array",
38 + "Int8Array",
39 + // "InternalError", // non-standard
40 + "Intl",
41 + "isFinite",
42 + "isNaN",
43 + "Iterator",
44 + "JSON",
45 + "Map",
46 + "Math",
47 + "NaN",
48 + "Number",
49 + "Object",
50 + "parseFloat",
51 + "parseInt",
52 + "Promise",
53 + "Proxy",
54 + "RangeError",
55 + "ReferenceError",
56 + "Reflect",
57 + "RegExp",
58 + "Set",
59 + "SharedArrayBuffer",
60 + "String",
61 + "Symbol",
62 + "SyntaxError",
63 + "TypeError",
64 + "Uint16Array",
65 + "Uint32Array",
66 + "Uint8Array",
67 + "Uint8ClampedArray",
68 + "undefined",
69 + "unescape",
70 + "URIError",
71 + "WeakMap",
72 + "WeakRef",
73 + "WeakSet",
74 +];
75 +
76 #[napi]
4 -pub fn add(left: i32, right: i32) -> i32 {
5 - left + right
77 +pub fn parse(source: String, options: ParseOptions) -> ParseResult {
78 + let program = match forget_hermes_parser::parse(&source, &options.file) {
79 + Ok(program) => program,
80 + Err(diagnostics) => {
81 + return ParseResult {
82 + program: None,
83 + diagnostics: convert_diagnostics(diagnostics),
84 + };
85 + }
86 + };
87 + let mut analysis = analyze(
88 + &program,
89 + AnalyzeOptions {
90 + globals: GLOBALS.iter().map(|s| s.to_string()).collect(),
91 + },
92 + );
93 + ParseResult {
94 + program: Some(serde_json::to_string(&program).unwrap()),
95 + diagnostics: convert_diagnostics(analysis.diagnostics()),
96 + }
97 +}
98 +
99 +fn convert_diagnostics(diagnostics: Vec<Diagnostic>) -> Vec<String> {
100 + diagnostics
101 + .into_iter()
102 + .map(|diagnostic| format!("{}", diagnostic))
103 + .collect()
104 }
105
8 -#[cfg(test)]
9 -mod tests {
10 - use super::*;
106 +#[napi(object)]
107 +pub struct ParseOptions {
108 + pub file: String,
109 +}
110
12 - #[test]
13 - fn it_works() {
14 - let result = add(2, 2);
15 - assert_eq!(result, 4);
16 - }
111 +#[napi(object)]
112 +pub struct ParseResult {
113 + pub program: Option<String>,
114 + pub diagnostics: Vec<String>,
115 }