|
1 |
| -use js_sys::JsString; |
2 |
| - |
| 1 | +use gloo_utils::format::JsValueSerdeExt; |
| 2 | +use serde::{Deserialize, Serialize}; |
3 | 3 | use wasm_bindgen::prelude::*;
|
4 | 4 |
|
| 5 | +use fm::FileManager; |
| 6 | +use noirc_errors::FileDiagnostic; |
| 7 | + |
5 | 8 | #[wasm_bindgen(typescript_custom_section)]
|
6 |
| -const COMPILE_ERROR: &'static str = r#" |
7 |
| -export type CompileError = Error; |
| 9 | +const DIAGNOSTICS: &'static str = r#" |
| 10 | +export type Diagnostic = { |
| 11 | + message: string; |
| 12 | + file_path: string; |
| 13 | + secondaries: ReadonlyArray<{ |
| 14 | + message: string; |
| 15 | + start: number; |
| 16 | + end: number; |
| 17 | + }>; |
| 18 | +} |
| 19 | +
|
| 20 | +interface CompileError { |
| 21 | + diagnostics: ReadonlyArray<Diagnostic>; |
| 22 | +} |
8 | 23 | "#;
|
9 | 24 |
|
10 |
| -/// `CompileError` is a raw js error. |
11 |
| -/// It'd be ideal that `CompileError` was a subclass of `Error`, but for that we'd need to use JS snippets or a js module. |
12 |
| -/// Currently JS snippets don't work with a nodejs target. And a module would be too much for just a custom error type. |
13 |
| -#[wasm_bindgen] |
14 |
| -extern "C" { |
15 |
| - #[wasm_bindgen(extends = js_sys::Error, js_name = "CompileError", typescript_type = "CompileError")] |
16 |
| - #[derive(Clone, Debug, PartialEq, Eq)] |
17 |
| - pub type JsCompileError; |
18 |
| - |
19 |
| - #[wasm_bindgen(constructor, js_class = "Error")] |
20 |
| - fn constructor(message: JsString) -> JsCompileError; |
| 25 | +#[derive(Serialize, Deserialize)] |
| 26 | +struct JsDiagnosticLabel { |
| 27 | + message: String, |
| 28 | + start: u32, |
| 29 | + end: u32, |
| 30 | +} |
| 31 | + |
| 32 | +#[derive(Serialize, Deserialize)] |
| 33 | +struct JsDiagnostic { |
| 34 | + message: String, |
| 35 | + file_path: String, |
| 36 | + secondaries: Vec<JsDiagnosticLabel>, |
| 37 | +} |
| 38 | + |
| 39 | +impl JsDiagnostic { |
| 40 | + fn new(file_diagnostic: &FileDiagnostic, file_path: String) -> JsDiagnostic { |
| 41 | + let diagnostic = &file_diagnostic.diagnostic; |
| 42 | + let message = diagnostic.message.clone(); |
| 43 | + |
| 44 | + let secondaries = diagnostic |
| 45 | + .secondaries |
| 46 | + .iter() |
| 47 | + .map(|label| JsDiagnosticLabel { |
| 48 | + message: label.message.clone(), |
| 49 | + start: label.span.start(), |
| 50 | + end: label.span.end(), |
| 51 | + }) |
| 52 | + .collect(); |
| 53 | + |
| 54 | + JsDiagnostic { message, file_path, secondaries } |
| 55 | + } |
| 56 | +} |
| 57 | + |
| 58 | +#[wasm_bindgen(getter_with_clone, js_name = "CompileError")] |
| 59 | +pub struct JsCompileError { |
| 60 | + pub message: js_sys::JsString, |
| 61 | + pub diagnostics: JsValue, |
21 | 62 | }
|
22 | 63 |
|
23 | 64 | impl JsCompileError {
|
24 |
| - /// Creates a new execution error with the given call stack. |
25 |
| - /// Call stacks won't be optional in the future, after removing ErrorLocation in ACVM. |
26 |
| - pub fn new(message: String) -> Self { |
27 |
| - JsCompileError::constructor(JsString::from(message)) |
| 65 | + pub fn new( |
| 66 | + message: &str, |
| 67 | + file_diagnostics: Vec<FileDiagnostic>, |
| 68 | + file_manager: &FileManager, |
| 69 | + ) -> JsCompileError { |
| 70 | + let diagnostics: Vec<_> = file_diagnostics |
| 71 | + .iter() |
| 72 | + .map(|err| { |
| 73 | + JsDiagnostic::new(err, file_manager.path(err.file_id).to_str().unwrap().to_string()) |
| 74 | + }) |
| 75 | + .collect(); |
| 76 | + |
| 77 | + JsCompileError { |
| 78 | + message: js_sys::JsString::from(message.to_string()), |
| 79 | + diagnostics: <JsValue as JsValueSerdeExt>::from_serde(&diagnostics).unwrap(), |
| 80 | + } |
28 | 81 | }
|
29 | 82 | }
|
0 commit comments