summaryrefslogtreecommitdiff
path: root/cli/fmt_errors.rs
diff options
context:
space:
mode:
authorChristian Dürr <102963075+cd-work@users.noreply.github.com>2022-09-02 20:53:23 +0000
committerGitHub <noreply@github.com>2022-09-02 22:53:23 +0200
commit63b8089bda8c88413bfad24aef415abc09e8d5c2 (patch)
treeb27b798ee77e75b36c487a19edd22e658fe76984 /cli/fmt_errors.rs
parent4f8dea100e751d550a4a40d11b142fc9a7c4a5a8 (diff)
refactor: move JsError formatting to deno_runtime (#15345)
This takes the existing `fmt_error` module from cli and puts it as a public module into `deno_runtime`.
Diffstat (limited to 'cli/fmt_errors.rs')
-rw-r--r--cli/fmt_errors.rs216
1 files changed, 0 insertions, 216 deletions
diff --git a/cli/fmt_errors.rs b/cli/fmt_errors.rs
deleted file mode 100644
index 53cf975bc..000000000
--- a/cli/fmt_errors.rs
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-//! This mod provides DenoError to unify errors across Deno.
-use crate::colors::cyan;
-use crate::colors::italic_bold;
-use crate::colors::red;
-use crate::colors::yellow;
-use deno_core::error::format_file_name;
-use deno_core::error::JsError;
-use deno_core::error::JsStackFrame;
-use std::fmt::Write as _;
-
-// Keep in sync with `/core/error.js`.
-pub fn format_location(frame: &JsStackFrame) -> String {
- let _internal = frame
- .file_name
- .as_ref()
- .map_or(false, |f| f.starts_with("deno:"));
- if frame.is_native {
- return cyan("native").to_string();
- }
- let mut result = String::new();
- let file_name = frame.file_name.clone().unwrap_or_default();
- if !file_name.is_empty() {
- result += &cyan(&format_file_name(&file_name)).to_string();
- } else {
- if frame.is_eval {
- result +=
- &(cyan(&frame.eval_origin.as_ref().unwrap()).to_string() + ", ");
- }
- result += &cyan("<anonymous>").to_string();
- }
- if let Some(line_number) = frame.line_number {
- write!(result, ":{}", yellow(&line_number.to_string())).unwrap();
- if let Some(column_number) = frame.column_number {
- write!(result, ":{}", yellow(&column_number.to_string())).unwrap();
- }
- }
- result
-}
-
-fn format_frame(frame: &JsStackFrame) -> String {
- let _internal = frame
- .file_name
- .as_ref()
- .map_or(false, |f| f.starts_with("deno:"));
- let is_method_call =
- !(frame.is_top_level.unwrap_or_default() || frame.is_constructor);
- let mut result = String::new();
- if frame.is_async {
- result += "async ";
- }
- if frame.is_promise_all {
- result += &italic_bold(&format!(
- "Promise.all (index {})",
- frame.promise_index.unwrap_or_default()
- ))
- .to_string();
- return result;
- }
- if is_method_call {
- let mut formatted_method = String::new();
- if let Some(function_name) = &frame.function_name {
- if let Some(type_name) = &frame.type_name {
- if !function_name.starts_with(type_name) {
- write!(formatted_method, "{}.", type_name).unwrap();
- }
- }
- formatted_method += function_name;
- if let Some(method_name) = &frame.method_name {
- if !function_name.ends_with(method_name) {
- write!(formatted_method, " [as {}]", method_name).unwrap();
- }
- }
- } else {
- if let Some(type_name) = &frame.type_name {
- write!(formatted_method, "{}.", type_name).unwrap();
- }
- if let Some(method_name) = &frame.method_name {
- formatted_method += method_name
- } else {
- formatted_method += "<anonymous>";
- }
- }
- result += &italic_bold(&formatted_method).to_string();
- } else if frame.is_constructor {
- result += "new ";
- if let Some(function_name) = &frame.function_name {
- write!(result, "{}", italic_bold(&function_name)).unwrap();
- } else {
- result += &cyan("<anonymous>").to_string();
- }
- } else if let Some(function_name) = &frame.function_name {
- result += &italic_bold(&function_name).to_string();
- } else {
- result += &format_location(frame);
- return result;
- }
- write!(result, " ({})", format_location(frame)).unwrap();
- result
-}
-
-/// Take an optional source line and associated information to format it into
-/// a pretty printed version of that line.
-fn format_maybe_source_line(
- source_line: Option<&str>,
- column_number: Option<i64>,
- is_error: bool,
- level: usize,
-) -> String {
- if source_line.is_none() || column_number.is_none() {
- return "".to_string();
- }
-
- let source_line = source_line.unwrap();
- // sometimes source_line gets set with an empty string, which then outputs
- // an empty source line when displayed, so need just short circuit here.
- if source_line.is_empty() {
- return "".to_string();
- }
- if source_line.contains("Couldn't format source line: ") {
- return format!("\n{}", source_line);
- }
-
- let mut s = String::new();
- let column_number = column_number.unwrap();
-
- if column_number as usize > source_line.len() {
- return format!(
- "\n{} Couldn't format source line: Column {} is out of bounds (source may have changed at runtime)",
- yellow("Warning"), column_number,
- );
- }
-
- for _i in 0..(column_number - 1) {
- if source_line.chars().nth(_i as usize).unwrap() == '\t' {
- s.push('\t');
- } else {
- s.push(' ');
- }
- }
- s.push('^');
- let color_underline = if is_error {
- red(&s).to_string()
- } else {
- cyan(&s).to_string()
- };
-
- let indent = format!("{:indent$}", "", indent = level);
-
- format!("\n{}{}\n{}{}", indent, source_line, indent, color_underline)
-}
-
-fn format_js_error_inner(js_error: &JsError, is_child: bool) -> String {
- let mut s = String::new();
- s.push_str(&js_error.exception_message);
- if let Some(aggregated) = &js_error.aggregated {
- for aggregated_error in aggregated {
- let error_string = format_js_error_inner(aggregated_error, true);
- for line in error_string.trim_start_matches("Uncaught ").lines() {
- write!(s, "\n {}", line).unwrap();
- }
- }
- }
- let column_number = js_error
- .source_line_frame_index
- .and_then(|i| js_error.frames.get(i).unwrap().column_number);
- s.push_str(&format_maybe_source_line(
- if is_child {
- None
- } else {
- js_error.source_line.as_deref()
- },
- column_number,
- true,
- 0,
- ));
- for frame in &js_error.frames {
- write!(s, "\n at {}", format_frame(frame)).unwrap();
- }
- if let Some(cause) = &js_error.cause {
- let error_string = format_js_error_inner(cause, true);
- write!(
- s,
- "\nCaused by: {}",
- error_string.trim_start_matches("Uncaught ")
- )
- .unwrap();
- }
- s
-}
-
-pub fn format_js_error(js_error: &JsError) -> String {
- format_js_error_inner(js_error, false)
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use test_util::strip_ansi_codes;
-
- #[test]
- fn test_format_none_source_line() {
- let actual = format_maybe_source_line(None, None, false, 0);
- assert_eq!(actual, "");
- }
-
- #[test]
- fn test_format_some_source_line() {
- let actual =
- format_maybe_source_line(Some("console.log('foo');"), Some(9), true, 0);
- assert_eq!(
- strip_ansi_codes(&actual),
- "\nconsole.log(\'foo\');\n ^"
- );
- }
-}