diff options
Diffstat (limited to 'core/error.rs')
-rw-r--r-- | core/error.rs | 140 |
1 files changed, 56 insertions, 84 deletions
diff --git a/core/error.rs b/core/error.rs index b35544bb1..64898678a 100644 --- a/core/error.rs +++ b/core/error.rs @@ -195,6 +195,44 @@ impl JsStackFrame { promise_index: None, } } + + /// Gets the source mapped stack frame corresponding to the + /// (script_resource_name, line_number, column_number) from a v8 message. + /// For non-syntax errors, it should also correspond to the first stack frame. + pub fn from_v8_message<'a>( + scope: &'a mut v8::HandleScope, + message: v8::Local<'a, v8::Message>, + ) -> Option<Self> { + let f = message.get_script_resource_name(scope)?; + let f: v8::Local<v8::String> = f.try_into().ok()?; + let f = f.to_rust_string_lossy(scope); + let l = message.get_line_number(scope)? as i64; + // V8's column numbers are 0-based, we want 1-based. + let c = message.get_start_column() as i64 + 1; + let state_rc = JsRuntime::state(scope); + let state = &mut *state_rc.borrow_mut(); + if let Some(source_map_getter) = &state.source_map_getter { + let (f, l, c) = apply_source_map( + f, + l, + c, + &mut state.source_map_cache, + source_map_getter.as_ref(), + ); + Some(JsStackFrame::from_location(Some(f), Some(l), Some(c))) + } else { + Some(JsStackFrame::from_location(Some(f), Some(l), Some(c))) + } + } + + pub fn maybe_format_location(&self) -> Option<String> { + Some(format!( + "{}:{}:{}", + self.file_name.as_ref()?, + self.line_number?, + self.column_number? + )) + } } fn get_property<'a>( @@ -231,42 +269,18 @@ impl JsError { let scope = &mut v8::HandleScope::new(scope); let exception_message = msg.get(scope).to_rust_string_lossy(scope); - let state_rc = JsRuntime::state(scope); // Convert them into Vec<JsStackFrame> let mut frames: Vec<JsStackFrame> = vec![]; - let mut source_line = None; let mut source_line_frame_index = None; + + if let Some(stack_frame) = JsStackFrame::from_v8_message(scope, msg) { + frames = vec![stack_frame]; + } { + let state_rc = JsRuntime::state(scope); let state = &mut *state_rc.borrow_mut(); - - let 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)); - let line_number: Option<i64> = - msg.get_line_number(scope).and_then(|v| v.try_into().ok()); - let column_number: Option<i64> = msg.get_start_column().try_into().ok(); - if let (Some(f), Some(l), Some(c)) = - (script_resource_name, line_number, column_number) - { - // V8's column numbers are 0-based, we want 1-based. - let c = c + 1; - if let Some(source_map_getter) = &state.source_map_getter { - let (f, l, c) = apply_source_map( - f, - l, - c, - &mut state.source_map_cache, - source_map_getter.as_ref(), - ); - frames = vec![JsStackFrame::from_location(Some(f), Some(l), Some(c))]; - } else { - frames = vec![JsStackFrame::from_location(Some(f), Some(l), Some(c))]; - } - } - if let Some(source_map_getter) = &state.source_map_getter { for (i, frame) in frames.iter().enumerate() { if let (Some(file_name), Some(line_number)) = @@ -377,48 +391,21 @@ impl JsError { Some(frames_v8) => serde_v8::from_v8(scope, frames_v8.into()).unwrap(), None => vec![], }; - let mut source_line = None; let mut source_line_frame_index = None; + + // When the stack frame array is empty, but the source location given by + // (script_resource_name, line_number, start_column + 1) exists, this is + // likely a syntax error. For the sake of formatting we treat it like it + // was given as a single stack frame. + if frames.is_empty() { + if let Some(stack_frame) = JsStackFrame::from_v8_message(scope, msg) { + frames = vec![stack_frame]; + } + } { let state_rc = JsRuntime::state(scope); let state = &mut *state_rc.borrow_mut(); - - // When the stack frame array is empty, but the source location given by - // (script_resource_name, line_number, start_column + 1) exists, this is - // likely a syntax error. For the sake of formatting we treat it like it - // was given as a single stack frame. - if frames.is_empty() { - let 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)); - let line_number: Option<i64> = - msg.get_line_number(scope).and_then(|v| v.try_into().ok()); - let column_number: Option<i64> = - msg.get_start_column().try_into().ok(); - if let (Some(f), Some(l), Some(c)) = - (script_resource_name, line_number, column_number) - { - // V8's column numbers are 0-based, we want 1-based. - let c = c + 1; - if let Some(source_map_getter) = &state.source_map_getter { - let (f, l, c) = apply_source_map( - f, - l, - c, - &mut state.source_map_cache, - source_map_getter.as_ref(), - ); - frames = - vec![JsStackFrame::from_location(Some(f), Some(l), Some(c))]; - } else { - frames = - vec![JsStackFrame::from_location(Some(f), Some(l), Some(c))]; - } - } - } - if let Some(source_map_getter) = &state.source_map_getter { for (i, frame) in frames.iter().enumerate() { if let (Some(file_name), Some(line_number)) = @@ -502,16 +489,6 @@ impl JsError { impl std::error::Error for JsError {} -fn format_source_loc( - file_name: &str, - line_number: i64, - column_number: i64, -) -> String { - let line_number = line_number; - let column_number = column_number; - format!("{file_name}:{line_number}:{column_number}") -} - impl Display for JsError { fn fmt(&self, f: &mut Formatter) -> fmt::Result { if let Some(stack) = &self.stack { @@ -521,14 +498,9 @@ impl Display for JsError { } } write!(f, "{}", self.exception_message)?; - let frame = self.frames.first(); - if let Some(frame) = frame { - if let (Some(f_), Some(l), Some(c)) = - (&frame.file_name, frame.line_number, frame.column_number) - { - let source_loc = format_source_loc(f_, l, c); - write!(f, "\n at {source_loc}")?; - } + let location = self.frames.first().and_then(|f| f.maybe_format_location()); + if let Some(location) = location { + write!(f, "\n at {location}")?; } Ok(()) } |