use javascript::*;
#[ctor::ctor(unsafe)]
fn __init_test_logger() {
let _ = env_logger::Builder::from_env(env_logger::Env::default()).is_test(true).try_init();
}
#[test]
fn nested_method_stack_contains_frames() {
let script = r#"
let obj = {};
obj.a = function() { obj.b(); };
obj.b = function() { throw new Error('boom'); };
try { obj.a(); } catch (e) { String(e.stack) }
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert!(result.contains("Error: boom"));
println!("STACK:\n{result}");
}
#[test]
fn throw_stack_includes_decl_site() {
let script = r#"
function doThirdThing() { throw new Error('boom'); }
try { doThirdThing(); } catch (e) { String(e.stack) }
"#;
let result = evaluate_script(script, false, Some(std::path::Path::new("some.js"))).unwrap();
assert_eq!(
result,
"\"Error: boom\\n at doThirdThing (some.js:2:35)\\n at <anonymous> (some.js:3:15)\""
);
}
#[test]
fn async_unhandled_rejection_points_to_throw_site() {
let script = r#"
function boom() { throw new Error('async-boom'); }
new Promise(function(resolve, reject) { resolve(1); }).then(function() { boom(); });
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>);
match result {
Err(e) => {
assert!(e.js_line().is_some(), "Expected js location on unhandled rejection");
assert!(
e.user_message().contains("async-boom"),
"Expected thrown message in user_message: {}",
e.user_message()
);
}
Ok(v) => panic!("Expected error for unhandled rejection, got {:?}", v),
}
}
#[test]
fn assert_throw_shows_thrown_site_and_stack_shows_callsite() {
let script = r#"
function assert(condition, message) {
if (!condition) {
throw new Error(message);
}
}
assert(false, 'boom');
"#;
let result = evaluate_script(script, false, Some(std::path::Path::new("file.js")));
match result {
Err(e) => {
let lines: Vec<&str> = script.split('\n').collect();
let thrown_line = lines
.iter()
.position(|l| l.contains("throw new Error(message);"))
.map(|i| i + 1)
.expect("could not find throw site in script");
let callsite_line = lines
.iter()
.position(|l| l.contains("assert(false"))
.map(|i| i + 1)
.expect("could not find call site in script");
assert!(
e.user_message().contains(&format!("line {}:", thrown_line)),
"Expected thrown-site in user_message: {}",
e.user_message()
);
let stack_str = e.stack().join("\n");
println!("STACK_STR:\n{}", stack_str);
assert!(
stack_str.contains(&format!("at assert (file.js:{}:", thrown_line))
|| stack_str.contains(&format!("assert (file.js:{}:", thrown_line)),
"Expected assert frame at thrown-site in stack: {}",
stack_str
);
assert!(
stack_str.contains(&format!("file.js:{}:", callsite_line)),
"Expected call-site line in stack: {}",
stack_str
);
}
Ok(v) => panic!("Expected thrown error, got {:?}", v),
}
}