Skip to content

Commit

Permalink
Pipe new exception info through into JSError
Browse files Browse the repository at this point in the history
Adds a new integration test for syntax error.
  • Loading branch information
ry committed Jan 12, 2019
1 parent 8fdc125 commit 6322f45
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 4 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
js/flatbuffers.js
tests/error_syntax.js
118 changes: 114 additions & 4 deletions src/js_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ pub struct StackFrame {
#[derive(Debug, PartialEq)]
pub struct JSError {
pub message: String,

pub source_line: Option<String>,
pub script_resource_name: Option<String>,
pub line_number: Option<i64>,
pub start_position: Option<i64>,
pub end_position: Option<i64>,
pub error_level: Option<i64>,
pub start_column: Option<i64>,
pub end_column: Option<i64>,

pub frames: Vec<StackFrame>,
}

Expand All @@ -65,7 +75,29 @@ impl ToString for StackFrame {

impl ToString for JSError {
fn to_string(&self) -> String {
let mut s = self.message.clone();
// TODO use fewer clones.
// TODO Improve the formatting of these error messages.
let mut s = String::new();

if self.script_resource_name.is_some() {
s.push_str(&self.script_resource_name.clone().unwrap());
}
if self.line_number.is_some() {
s.push_str(&format!(
":{}:{}",
self.line_number.unwrap(),
self.start_column.unwrap()
));
assert!(self.start_column.is_some());
}
if self.source_line.is_some() {
s.push_str("\n");
s.push_str(&self.source_line.clone().unwrap());
s.push_str("\n\n");
}

s.push_str(&self.message.clone());

for frame in &self.frames {
s.push_str("\n");
s.push_str(&frame.to_string());
Expand Down Expand Up @@ -243,6 +275,19 @@ impl JSError {
}
let message = String::from(message_v.as_str().unwrap());

let source_line = obj
.get("sourceLine")
.and_then(|v| v.as_str().map(String::from));
let script_resource_name = obj
.get("scriptResourceName")
.and_then(|v| v.as_str().map(String::from));
let line_number = obj.get("lineNumber").and_then(|v| v.as_i64());
let start_position = obj.get("startPosition").and_then(|v| v.as_i64());
let end_position = obj.get("endPosition").and_then(|v| v.as_i64());
let error_level = obj.get("errorLevel").and_then(|v| v.as_i64());
let start_column = obj.get("startColumn").and_then(|v| v.as_i64());
let end_column = obj.get("endColumn").and_then(|v| v.as_i64());

let frames_v = &obj["frames"];
if !frames_v.is_array() {
return None;
Expand All @@ -257,18 +302,40 @@ impl JSError {
}
}

Some(JSError { message, frames })
Some(JSError {
message,
source_line,
script_resource_name,
line_number,
start_position,
end_position,
error_level,
start_column,
end_column,
frames,
})
}

pub fn apply_source_map(&self, getter: &SourceMapGetter) -> Self {
let message = self.message.clone();
let mut mappings_map: CachedMaps = HashMap::new();
let mut frames = Vec::<StackFrame>::new();
for frame in &self.frames {
let f = frame.apply_source_map(&mut mappings_map, getter);
frames.push(f);
}
JSError { message, frames }
JSError {
message: self.message.clone(),
frames,
error_level: self.error_level,
source_line: self.source_line.clone(),
// TODO the following need to be source mapped:
script_resource_name: self.script_resource_name.clone(),
line_number: self.line_number,
start_position: self.start_position,
end_position: self.end_position,
start_column: self.start_column,
end_column: self.end_column,
}
}
}

Expand Down Expand Up @@ -309,6 +376,14 @@ mod tests {
fn error1() -> JSError {
JSError {
message: "Error: foo bar".to_string(),
source_line: None,
script_resource_name: None,
line_number: None,
start_position: None,
end_position: None,
error_level: None,
start_column: None,
end_column: None,
frames: vec![
StackFrame {
line: 4,
Expand Down Expand Up @@ -442,6 +517,25 @@ mod tests {
)
}

#[test]
fn js_error_from_v8_exception2() {
let r = JSError::from_v8_exception(
"{\"message\":\"Error: boo\",\"sourceLine\":\"throw Error('boo');\",\"scriptResourceName\":\"a.js\",\"lineNumber\":3,\"startPosition\":8,\"endPosition\":9,\"errorLevel\":8,\"startColumn\":6,\"endColumn\":7,\"isSharedCrossOrigin\":false,\"isOpaque\":false,\"frames\":[{\"line\":3,\"column\":7,\"functionName\":\"\",\"scriptName\":\"a.js\",\"isEval\":false,\"isConstructor\":false,\"isWasm\":false}]}"
);
assert!(r.is_some());
let e = r.unwrap();
assert_eq!(e.message, "Error: boo");
assert_eq!(e.source_line, Some("throw Error('boo');".to_string()));
assert_eq!(e.script_resource_name, Some("a.js".to_string()));
assert_eq!(e.line_number, Some(3));
assert_eq!(e.start_position, Some(8));
assert_eq!(e.end_position, Some(9));
assert_eq!(e.error_level, Some(8));
assert_eq!(e.start_column, Some(6));
assert_eq!(e.end_column, Some(7));
assert_eq!(e.frames.len(), 1);
}

#[test]
fn stack_frame_to_string() {
let e = error1();
Expand All @@ -462,6 +556,14 @@ mod tests {
let actual = e.apply_source_map(&getter);
let expected = JSError {
message: "Error: foo bar".to_string(),
source_line: None,
script_resource_name: None,
line_number: None,
start_position: None,
end_position: None,
error_level: None,
start_column: None,
end_column: None,
frames: vec![
StackFrame {
line: 5,
Expand Down Expand Up @@ -499,6 +601,14 @@ mod tests {
fn js_error_apply_source_map_2() {
let e = JSError {
message: "TypeError: baz".to_string(),
source_line: None,
script_resource_name: None,
line_number: None,
start_position: None,
end_position: None,
error_level: None,
start_column: None,
end_column: None,
frames: vec![StackFrame {
line: 11,
column: 12,
Expand Down
3 changes: 3 additions & 0 deletions tests/async_error.ts.out
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
[WILDCARD]hello
before error
world
[WILDCARD]tests/async_error.ts:4:10
throw Error("error");

Error: error
at foo ([WILDCARD]tests/async_error.ts:4:9)
at [WILDCARD]tests/async_error.ts:7:1
3 changes: 3 additions & 0 deletions tests/error_008_checkjs.js.out
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
[WILDCARD]tests/error_008_checkjs.js:2:0
consol.log("hello world!");

ReferenceError: consol is not defined
at [WILDCARD]tests/error_008_checkjs.js:2:1
3 changes: 3 additions & 0 deletions tests/error_syntax.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

// prettier-ignore
(the following is a syntax error ^^ ! )
4 changes: 4 additions & 0 deletions tests/error_syntax.js.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[WILDCARD]tests/error_syntax.js:3:5
(the following is a syntax error ^^ ! )

SyntaxError: Unexpected identifier
4 changes: 4 additions & 0 deletions tests/error_syntax.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
args: tests/error_syntax.js --reload
check_stderr: true
exit_code: 1
output: tests/error_syntax.js.out

0 comments on commit 6322f45

Please sign in to comment.