summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2020-04-10 17:26:52 +0100
committerGitHub <noreply@github.com>2020-04-10 18:26:52 +0200
commit8b4508338b15dcc08503553dc9179a154c0165c7 (patch)
tree82d3d283edcff994c5b998d0d948985dc04f1b8c
parent195ad4c6264c3563044480685931999ffa9d3d5c (diff)
fix(core/js_error): Get frame data from prepareStackTrace() (#4690)
Fixes: #2703 Fixes: #2710 Closes: #4153 Closes: #4232 Co-authored-by: Kevin (Kun) Kassimo Qian <kevinkassimo@gmail.com>
-rw-r--r--cli/fmt_errors.rs18
-rw-r--r--cli/js/error_stack.ts60
-rw-r--r--cli/source_maps.rs28
-rw-r--r--cli/tests/044_bad_resource.ts.out2
-rw-r--r--cli/tests/error_004_missing_module.ts.out8
-rw-r--r--cli/tests/error_005_missing_dynamic_import.ts.out8
-rw-r--r--cli/tests/error_006_import_ext_failure.ts.out6
-rw-r--r--cli/tests/error_011_bad_module_specifier.ts.out13
-rw-r--r--cli/tests/error_012_bad_dynamic_import_specifier.ts.out13
-rw-r--r--cli/tests/error_type_definitions.ts.out14
-rw-r--r--core/js_errors.rs135
11 files changed, 257 insertions, 48 deletions
diff --git a/cli/fmt_errors.rs b/cli/fmt_errors.rs
index 5ba0bce77..b7cfbbce9 100644
--- a/cli/fmt_errors.rs
+++ b/cli/fmt_errors.rs
@@ -155,9 +155,21 @@ fn format_stack_frame(frame: &JSStackFrame, is_internal_frame: bool) -> String {
source_loc = colors::gray(source_loc).to_string();
}
if !frame.function_name.is_empty() {
- format!("{} {} {}", at_prefix, function_name, source_loc)
+ if frame.is_async {
+ format!(
+ "{} {} {} {}",
+ at_prefix,
+ colors::gray("async".to_owned()).to_string(),
+ function_name,
+ source_loc
+ )
+ } else {
+ format!("{} {} {}", at_prefix, function_name, source_loc)
+ }
} else if frame.is_eval {
format!("{} eval {}", at_prefix, source_loc)
+ } else if frame.is_async {
+ format!("{} async {}", at_prefix, source_loc)
} else {
format!("{} {}", at_prefix, source_loc)
}
@@ -272,6 +284,7 @@ mod tests {
function_name: "foo".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
JSStackFrame {
line_number: 5,
@@ -280,6 +293,7 @@ mod tests {
function_name: "qat".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
JSStackFrame {
line_number: 1,
@@ -288,8 +302,10 @@ mod tests {
function_name: "".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
],
+ already_source_mapped: true,
};
let formatted_error = JSError(core_js_error).to_string();
let actual = strip_ansi_codes(&formatted_error);
diff --git a/cli/js/error_stack.ts b/cli/js/error_stack.ts
index 97e9f68de..bab179e48 100644
--- a/cli/js/error_stack.ts
+++ b/cli/js/error_stack.ts
@@ -140,7 +140,7 @@ function callSiteToString(callSite: CallSite): string {
result += "async ";
}
if (isPromiseAll) {
- result += `Promise.all (index ${callSite.getPromiseIndex})`;
+ result += `Promise.all (index ${callSite.getPromiseIndex()})`;
return result;
}
if (isMethodCall) {
@@ -163,11 +163,52 @@ function callSiteToString(callSite: CallSite): string {
return result;
}
+interface CallSiteEval {
+ this: unknown;
+ typeName: string;
+ function: Function;
+ functionName: string;
+ methodName: string;
+ fileName: string;
+ lineNumber: number | null;
+ columnNumber: number | null;
+ evalOrigin: string | null;
+ isToplevel: boolean;
+ isEval: boolean;
+ isNative: boolean;
+ isConstructor: boolean;
+ isAsync: boolean;
+ isPromiseAll: boolean;
+ promiseIndex: number | null;
+}
+
+function evaluateCallSite(callSite: CallSite): CallSiteEval {
+ return {
+ this: callSite.getThis(),
+ typeName: callSite.getTypeName(),
+ function: callSite.getFunction(),
+ functionName: callSite.getFunctionName(),
+ methodName: callSite.getMethodName(),
+ fileName: callSite.getFileName(),
+ lineNumber: callSite.getLineNumber(),
+ columnNumber: callSite.getColumnNumber(),
+ evalOrigin: callSite.getEvalOrigin(),
+ isToplevel: callSite.isToplevel(),
+ isEval: callSite.isEval(),
+ isNative: callSite.isNative(),
+ isConstructor: callSite.isConstructor(),
+ isAsync: callSite.isAsync(),
+ isPromiseAll: callSite.isPromiseAll(),
+ promiseIndex: callSite.getPromiseIndex(),
+ };
+}
+
function prepareStackTrace(
error: Error,
structuredStackTrace: CallSite[]
): string {
- return (
+ Object.defineProperty(error, "__callSiteEvals", { value: [] });
+ const errorString =
`${error.name}: ${error.message}\n` +
structuredStackTrace
.map(
@@ -188,9 +229,18 @@ function prepareStackTrace(
return callSite;
}
)
- .map((callSite): string => ` at ${callSiteToString(callSite)}`)
- .join("\n")
- );
+ .map((callSite): string => {
+ const callSiteEv = Object.freeze(evaluateCallSite(callSite));
+ if (callSiteEv.lineNumber != null && callSiteEv.columnNumber != null) {
+ // @ts-ignore
+ error["__callSiteEvals"].push(callSiteEv);
+ }
+ return ` at ${callSiteToString(callSite)}`;
+ })
+ .join("\n");
+ // @ts-ignore
+ Object.freeze(error["__callSiteEvals"]);
+ return errorString;
}
// @internal
diff --git a/cli/source_maps.rs b/cli/source_maps.rs
index bdfee11e9..b22cd4469 100644
--- a/cli/source_maps.rs
+++ b/cli/source_maps.rs
@@ -49,11 +49,16 @@ pub fn apply_source_map<G: SourceMapGetter>(
) -> deno_core::JSError {
let mut mappings_map: CachedMaps = HashMap::new();
- let mut frames = Vec::<JSStackFrame>::new();
- for frame in &js_error.frames {
- let f = frame_apply_source_map(&frame, &mut mappings_map, getter);
- frames.push(f);
- }
+ let frames = if !js_error.already_source_mapped {
+ let mut frames = Vec::<JSStackFrame>::new();
+ for frame in &js_error.frames {
+ let f = frame_apply_source_map(&frame, &mut mappings_map, getter);
+ frames.push(f);
+ }
+ frames
+ } else {
+ js_error.frames.clone()
+ };
let (script_resource_name, line_number, start_column) =
get_maybe_orig_position(
@@ -98,6 +103,7 @@ pub fn apply_source_map<G: SourceMapGetter>(
start_column,
end_column,
frames,
+ already_source_mapped: js_error.already_source_mapped,
}
}
@@ -121,6 +127,7 @@ fn frame_apply_source_map<G: SourceMapGetter>(
column,
is_eval: frame.is_eval,
is_constructor: frame.is_constructor,
+ is_async: frame.is_async,
}
}
@@ -255,6 +262,7 @@ mod tests {
function_name: "foo".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
JSStackFrame {
line_number: 5,
@@ -263,6 +271,7 @@ mod tests {
function_name: "qat".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
JSStackFrame {
line_number: 1,
@@ -271,8 +280,10 @@ mod tests {
function_name: "".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
],
+ already_source_mapped: false,
};
let getter = MockSourceMapGetter {};
let actual = apply_source_map(&core_js_error, &getter);
@@ -291,6 +302,7 @@ mod tests {
function_name: "foo".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
JSStackFrame {
line_number: 4,
@@ -299,6 +311,7 @@ mod tests {
function_name: "qat".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
JSStackFrame {
line_number: 1,
@@ -307,8 +320,10 @@ mod tests {
function_name: "".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
],
+ already_source_mapped: false,
};
assert_eq!(actual, expected);
}
@@ -329,7 +344,9 @@ mod tests {
function_name: "setLogDebug".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
}],
+ already_source_mapped: false,
};
let getter = MockSourceMapGetter {};
let actual = apply_source_map(&e, &getter);
@@ -348,6 +365,7 @@ mod tests {
start_column: Some(16),
end_column: None,
frames: vec![],
+ already_source_mapped: false,
};
let getter = MockSourceMapGetter {};
let actual = apply_source_map(&e, &getter);
diff --git a/cli/tests/044_bad_resource.ts.out b/cli/tests/044_bad_resource.ts.out
index 6009d2549..026beb341 100644
--- a/cli/tests/044_bad_resource.ts.out
+++ b/cli/tests/044_bad_resource.ts.out
@@ -1,6 +1,6 @@
[WILDCARD]
error: Uncaught BadResource: Bad resource ID
[WILDCARD]dispatch_json.ts:[WILDCARD]
- at BadResource ([WILDCARD]errors.ts:[WILDCARD])
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
at sendAsync ([WILDCARD]dispatch_json.ts:[WILDCARD])
+ at async main ([WILDCARD]tests/044_bad_resource.ts:[WILDCARD])
diff --git a/cli/tests/error_004_missing_module.ts.out b/cli/tests/error_004_missing_module.ts.out
index 8e9f7f925..691d5ce5a 100644
--- a/cli/tests/error_004_missing_module.ts.out
+++ b/cli/tests/error_004_missing_module.ts.out
@@ -1,5 +1,9 @@
[WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/bad-module.ts" from "[WILDCARD]/error_004_missing_module.ts"
[WILDCARD]dispatch_json.ts:[WILDCARD]
- at NotFound ([WILDCARD]errors.ts:[WILDCARD])
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
- at sendAsync[WILDCARD] ([WILDCARD]dispatch_json.ts:[WILDCARD])
+ at sendAsync ([WILDCARD]dispatch_json.ts:[WILDCARD])
+ at async processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async compile ([WILDCARD]compiler.ts:[WILDCARD])
+ at async tsCompilerOnMessage ([WILDCARD]compiler.ts:[WILDCARD])
+ at async workerMessageRecvCallback ([WILDCARD]runtime_worker.ts:[WILDCARD])
diff --git a/cli/tests/error_005_missing_dynamic_import.ts.out b/cli/tests/error_005_missing_dynamic_import.ts.out
index 7eb20fe04..4a7822e43 100644
--- a/cli/tests/error_005_missing_dynamic_import.ts.out
+++ b/cli/tests/error_005_missing_dynamic_import.ts.out
@@ -1,5 +1,9 @@
[WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/bad-module.ts" from "[WILDCARD]/error_005_missing_dynamic_import.ts"
[WILDCARD]dispatch_json.ts:[WILDCARD]
- at NotFound ([WILDCARD]errors.ts:[WILDCARD])
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
- at sendAsync[WILDCARD] ([WILDCARD]dispatch_json.ts:[WILDCARD])
+ at sendAsync ([WILDCARD]dispatch_json.ts:[WILDCARD])
+ at async processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async compile ([WILDCARD]compiler.ts:[WILDCARD])
+ at async tsCompilerOnMessage ([WILDCARD]compiler.ts:[WILDCARD])
+ at async workerMessageRecvCallback ([WILDCARD]runtime_worker.ts:[WILDCARD])
diff --git a/cli/tests/error_006_import_ext_failure.ts.out b/cli/tests/error_006_import_ext_failure.ts.out
index 41b9b7bf8..c4e6a1037 100644
--- a/cli/tests/error_006_import_ext_failure.ts.out
+++ b/cli/tests/error_006_import_ext_failure.ts.out
@@ -1,5 +1,9 @@
[WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/non-existent" from "[WILDCARD]/error_006_import_ext_failure.ts"
[WILDCARD]dispatch_json.ts:[WILDCARD]
- at NotFound ([WILDCARD]errors.ts:[WILDCARD])
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
at sendAsync[WILDCARD] ([WILDCARD]dispatch_json.ts:[WILDCARD])
+ at async processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async compile ([WILDCARD]compiler.ts:[WILDCARD])
+ at async tsCompilerOnMessage ([WILDCARD]compiler.ts:[WILDCARD])
+ at async workerMessageRecvCallback ([WILDCARD]runtime_worker.ts:[WILDCARD])
diff --git a/cli/tests/error_011_bad_module_specifier.ts.out b/cli/tests/error_011_bad_module_specifier.ts.out
index 773ddf8a8..5ac95002f 100644
--- a/cli/tests/error_011_bad_module_specifier.ts.out
+++ b/cli/tests/error_011_bad_module_specifier.ts.out
@@ -1,7 +1,10 @@
[WILDCARD]error: Uncaught URIError: relative import path "bad-module.ts" not prefixed with / or ./ or ../ Imported from "[WILDCARD]/error_011_bad_module_specifier.ts"
[WILDCARD]dispatch_json.ts:[WILDCARD]
- at unwrapResponse ($deno$/ops/dispatch_json.ts:[WILDCARD])
- at sendSync ($deno$/ops/dispatch_json.ts:[WILDCARD])
- at resolveModules ($deno$/compiler/imports.ts:[WILDCARD])
- at processImports ($deno$/compiler/imports.ts:[WILDCARD])
- at processImports ($deno$/compiler/imports.ts:[WILDCARD])
+ at unwrapResponse ([WILDCARD]ops/dispatch_json.ts:[WILDCARD])
+ at sendSync ([WILDCARD]ops/dispatch_json.ts:[WILDCARD])
+ at resolveModules ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async compile ([WILDCARD]compiler.ts:[WILDCARD])
+ at async tsCompilerOnMessage ([WILDCARD]compiler.ts:[WILDCARD])
+ at async workerMessageRecvCallback ([WILDCARD]runtime_worker.ts:[WILDCARD])
diff --git a/cli/tests/error_012_bad_dynamic_import_specifier.ts.out b/cli/tests/error_012_bad_dynamic_import_specifier.ts.out
index 618f45acd..505f29f82 100644
--- a/cli/tests/error_012_bad_dynamic_import_specifier.ts.out
+++ b/cli/tests/error_012_bad_dynamic_import_specifier.ts.out
@@ -1,7 +1,10 @@
[WILDCARD]error: Uncaught URIError: relative import path "bad-module.ts" not prefixed with / or ./ or ../ Imported from "[WILDCARD]/error_012_bad_dynamic_import_specifier.ts"
[WILDCARD]dispatch_json.ts:[WILDCARD]
- at unwrapResponse ($deno$/ops/dispatch_json.ts:[WILDCARD])
- at sendSync ($deno$/ops/dispatch_json.ts:[WILDCARD])
- at resolveModules ($deno$/compiler/imports.ts:[WILDCARD])
- at processImports ($deno$/compiler/imports.ts:[WILDCARD])
- at processImports ($deno$/compiler/imports.ts:[WILDCARD])
+ at unwrapResponse ([WILDCARD]ops/dispatch_json.ts:[WILDCARD])
+ at sendSync ([WILDCARD]ops/dispatch_json.ts:[WILDCARD])
+ at resolveModules ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async compile ([WILDCARD]compiler.ts:[WILDCARD])
+ at async tsCompilerOnMessage ([WILDCARD]compiler.ts:[WILDCARD])
+ at async workerMessageRecvCallback ([WILDCARD]runtime_worker.ts:[WILDCARD])
diff --git a/cli/tests/error_type_definitions.ts.out b/cli/tests/error_type_definitions.ts.out
index 20c03d0be..59773ac35 100644
--- a/cli/tests/error_type_definitions.ts.out
+++ b/cli/tests/error_type_definitions.ts.out
@@ -1,7 +1,11 @@
[WILDCARD]error: Uncaught URIError: relative import path "baz" not prefixed with / or ./ or ../ Imported from "[WILDCARD]/type_definitions/bar.d.ts"
[WILDCARD]dispatch_json.ts:[WILDCARD]
- at unwrapResponse ($deno$/ops/dispatch_json.ts:[WILDCARD])
- at sendSync ($deno$/ops/dispatch_json.ts:[WILDCARD])
- at resolveModules ($deno$/compiler/imports.ts:[WILDCARD])
- at processImports ($deno$/compiler/imports.ts:[WILDCARD])
- at processImports ($deno$/compiler/imports.ts:[WILDCARD])
+ at unwrapResponse ([WILDCARD]ops/dispatch_json.ts:[WILDCARD])
+ at sendSync ([WILDCARD]ops/dispatch_json.ts:[WILDCARD])
+ at resolveModules ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async processImports ([WILDCARD]compiler/imports.ts:[WILDCARD])
+ at async compile ([WILDCARD]compiler.ts:[WILDCARD])
+ at async tsCompilerOnMessage ([WILDCARD]compiler.ts:[WILDCARD])
+ at async workerMessageRecvCallback ([WILDCARD]runtime_worker.ts:[WILDCARD])
diff --git a/core/js_errors.rs b/core/js_errors.rs
index 4d6110c5f..64009b9ee 100644
--- a/core/js_errors.rs
+++ b/core/js_errors.rs
@@ -18,7 +18,7 @@ use std::fmt;
/// A `JSError` represents an exception coming from V8, with stack frames and
/// line numbers. The deno_cli crate defines another `JSError` type, which wraps
-/// the one defined here, that adds source map support and colorful formatting.
+/// the one defined here, that adds source map support and colorful formatting.
#[derive(Debug, PartialEq, Clone)]
pub struct JSError {
pub message: String,
@@ -28,6 +28,12 @@ pub struct JSError {
pub start_column: Option<i64>,
pub end_column: Option<i64>,
pub frames: Vec<JSStackFrame>,
+ // TODO: Remove this field. It is required because JSError::from_v8_exception
+ // will generally (but not always) return stack frames passed from
+ // `prepareStackTrace()` which have already been source-mapped, and we need a
+ // flag saying not to do it again. Note: applies to `frames` but not
+ // `source_line`.
+ pub already_source_mapped: bool,
}
#[derive(Debug, PartialEq, Clone)]
@@ -38,6 +44,18 @@ pub struct JSStackFrame {
pub function_name: String,
pub is_eval: bool,
pub is_constructor: bool,
+ pub is_async: bool,
+ // TODO(nayeemrmn): Support more CallSite fields.
+}
+
+fn get_property<'a>(
+ scope: &mut impl v8::ToLocal<'a>,
+ context: v8::Local<v8::Context>,
+ object: v8::Local<v8::Object>,
+ key: &str,
+) -> Option<v8::Local<'a, v8::Value>> {
+ let key = v8::String::new(scope, key).unwrap();
+ object.get(scope, context, key.into())
}
impl JSError {
@@ -53,23 +71,85 @@ impl JSError {
// handles below.
let mut hs = v8::HandleScope::new(scope);
let scope = hs.enter();
- let context = scope.get_current_context().unwrap();
+ let context = { scope.get_current_context().unwrap() };
let msg = v8::Exception::create_message(scope, exception);
- Self {
- message: msg.get(scope).to_rust_string_lossy(scope),
- script_resource_name: msg
- .get_script_resource_name(scope)
- .and_then(|v| v8::Local::<v8::String>::try_from(v).ok())
- .map(|v| v.to_rust_string_lossy(scope)),
- source_line: msg
- .get_source_line(scope, context)
- .map(|v| v.to_rust_string_lossy(scope)),
- line_number: msg.get_line_number(context).and_then(|v| v.try_into().ok()),
- start_column: msg.get_start_column().try_into().ok(),
- end_column: msg.get_end_column().try_into().ok(),
- frames: msg
+ let exception: Option<v8::Local<v8::Object>> =
+ exception.clone().try_into().ok();
+ let _ = exception.map(|e| get_property(scope, context, e, "stack"));
+
+ let maybe_call_sites = exception
+ .and_then(|e| get_property(scope, context, e, "__callSiteEvals"));
+ let maybe_call_sites: Option<v8::Local<v8::Array>> =
+ maybe_call_sites.and_then(|a| a.try_into().ok());
+
+ let already_source_mapped;
+ let frames = if let Some(call_sites) = maybe_call_sites {
+ already_source_mapped = true;
+ let mut output: Vec<JSStackFrame> = vec![];
+ for i in 0..call_sites.length() {
+ let call_site: v8::Local<v8::Object> = call_sites
+ .get_index(scope, context, i)
+ .unwrap()
+ .try_into()
+ .unwrap();
+ let line_number: v8::Local<v8::Integer> =
+ get_property(scope, context, call_site, "lineNumber")
+ .unwrap()
+ .try_into()
+ .unwrap();
+ let line_number = line_number.value() - 1;
+ let column_number: v8::Local<v8::Integer> =
+ get_property(scope, context, call_site, "columnNumber")
+ .unwrap()
+ .try_into()
+ .unwrap();
+ let column_number = column_number.value() - 1;
+ let file_name: Result<v8::Local<v8::String>, _> =
+ get_property(scope, context, call_site, "fileName")
+ .unwrap()
+ .try_into();
+ let file_name = file_name
+ .map_or_else(|_| String::new(), |s| s.to_rust_string_lossy(scope));
+ let function_name: Result<v8::Local<v8::String>, _> =
+ get_property(scope, context, call_site, "functionName")
+ .unwrap()
+ .try_into();
+ let function_name = function_name
+ .map_or_else(|_| String::new(), |s| s.to_rust_string_lossy(scope));
+ let is_constructor: v8::Local<v8::Boolean> =
+ get_property(scope, context, call_site, "isConstructor")
+ .unwrap()
+ .try_into()
+ .unwrap();
+ let is_constructor = is_constructor.is_true();
+ let is_eval: v8::Local<v8::Boolean> =
+ get_property(scope, context, call_site, "isEval")
+ .unwrap()
+ .try_into()
+ .unwrap();
+ let is_eval = is_eval.is_true();
+ let is_async: v8::Local<v8::Boolean> =
+ get_property(scope, context, call_site, "isAsync")
+ .unwrap()
+ .try_into()
+ .unwrap();
+ let is_async = is_async.is_true();
+ output.push(JSStackFrame {
+ line_number,
+ column: column_number,
+ script_name: file_name,
+ function_name,
+ is_constructor,
+ is_eval,
+ is_async,
+ });
+ }
+ output
+ } else {
+ already_source_mapped = false;
+ msg
.get_stack_trace(scope)
.map(|stack_trace| {
(0..stack_trace.get_frame_count())
@@ -96,11 +176,28 @@ impl JSError {
.unwrap_or_else(|| "".to_owned()),
is_constructor: frame.is_constructor(),
is_eval: frame.is_eval(),
+ is_async: false,
}
})
.collect::<Vec<_>>()
})
- .unwrap_or_else(Vec::<_>::new),
+ .unwrap_or_else(Vec::<_>::new)
+ };
+
+ Self {
+ message: msg.get(scope).to_rust_string_lossy(scope),
+ script_resource_name: msg
+ .get_script_resource_name(scope)
+ .and_then(|v| v8::Local::<v8::String>::try_from(v).ok())
+ .map(|v| v.to_rust_string_lossy(scope)),
+ source_line: msg
+ .get_source_line(scope, context)
+ .map(|v| v.to_rust_string_lossy(scope)),
+ line_number: msg.get_line_number(context).and_then(|v| v.try_into().ok()),
+ start_column: msg.get_start_column().try_into().ok(),
+ end_column: msg.get_end_column().try_into().ok(),
+ frames,
+ already_source_mapped,
}
}
}
@@ -127,6 +224,8 @@ fn format_stack_frame(frame: &JSStackFrame) -> String {
format!(" at {} ({})", frame.function_name, source_loc)
} else if frame.is_eval {
format!(" at eval ({})", source_loc)
+ } else if frame.is_async {
+ format!(" at async ({})", source_loc)
} else {
format!(" at {}", source_loc)
}
@@ -190,6 +289,7 @@ mod tests {
function_name: "foo".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
JSStackFrame {
line_number: 5,
@@ -198,6 +298,7 @@ mod tests {
function_name: "qat".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
JSStackFrame {
line_number: 1,
@@ -206,8 +307,10 @@ mod tests {
function_name: "".to_string(),
is_eval: false,
is_constructor: false,
+ is_async: false,
},
],
+ already_source_mapped: true,
};
let actual = js_error.to_string();
let expected = "Error: foo bar\n at foo (foo_bar.ts:5:17)\n at qat (bar_baz.ts:6:21)\n at deno_main.js:2:2";