diff options
author | Matt Mastracci <matthew@mastracci.com> | 2023-06-13 20:03:10 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-14 02:03:10 +0000 |
commit | ec8e9d4f5bd2c8eed5f086356c1c6dd7c8b40b7f (patch) | |
tree | 2ffda9204901bfb757e8ce6359d1fc6aa2f9964b /core/error.rs | |
parent | fd9d6baea311d9b227b130749647a86838ba2ccc (diff) |
chore(core): Refactor runtime and split out tests (#19491)
This is a quick first refactoring to split the tests out of runtime and
move runtime-related code to a top-level runtime module.
There will be a followup to refactor imports a bit, but this is the
major change that will most likely conflict with other work and I want
to merge it early.
Diffstat (limited to 'core/error.rs')
-rw-r--r-- | core/error.rs | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/core/error.rs b/core/error.rs index 16f813b89..07dc98a22 100644 --- a/core/error.rs +++ b/core/error.rs @@ -9,8 +9,7 @@ use std::fmt::Formatter; use anyhow::Error; -use crate::realm::JsRealm; -use crate::runtime::GetErrorClassFn; +use crate::runtime::JsRealm; use crate::runtime::JsRuntime; use crate::source_map::apply_source_map; use crate::source_map::get_source_line; @@ -20,6 +19,9 @@ use crate::url::Url; // TODO(ry) Deprecate AnyError and encourage deno_core::anyhow::Error instead. pub type AnyError = anyhow::Error; +pub type JsErrorCreateFn = dyn Fn(JsError) -> Error; +pub type GetErrorClassFn = &'static dyn for<'e> Fn(&'e Error) -> &'static str; + /// Creates a new error with a caller-specified error class name and message. pub fn custom_error( class: &'static str, @@ -643,6 +645,56 @@ fn abbrev_file_name(file_name: &str) -> Option<String> { Some(format!("{}:{},{}......{}", url.scheme(), head, start, end)) } +pub(crate) fn exception_to_err_result<T>( + scope: &mut v8::HandleScope, + exception: v8::Local<v8::Value>, + in_promise: bool, +) -> Result<T, Error> { + let state_rc = JsRuntime::state_from(scope); + + let was_terminating_execution = scope.is_execution_terminating(); + // Disable running microtasks for a moment. When upgrading to V8 v11.4 + // we discovered that canceling termination here will cause the queued + // microtasks to run which breaks some tests. + scope.set_microtasks_policy(v8::MicrotasksPolicy::Explicit); + // If TerminateExecution was called, cancel isolate termination so that the + // exception can be created. Note that `scope.is_execution_terminating()` may + // have returned false if TerminateExecution was indeed called but there was + // no JS to execute after the call. + scope.cancel_terminate_execution(); + let mut exception = exception; + { + // If termination is the result of a `op_dispatch_exception` call, we want + // to use the exception that was passed to it rather than the exception that + // was passed to this function. + let state = state_rc.borrow(); + exception = if let Some(exception) = &state.dispatched_exception { + v8::Local::new(scope, exception.clone()) + } else if was_terminating_execution && exception.is_null_or_undefined() { + let message = v8::String::new(scope, "execution terminated").unwrap(); + v8::Exception::error(scope, message) + } else { + exception + }; + } + + let mut js_error = JsError::from_v8_exception(scope, exception); + if in_promise { + js_error.exception_message = format!( + "Uncaught (in promise) {}", + js_error.exception_message.trim_start_matches("Uncaught ") + ); + } + + if was_terminating_execution { + // Resume exception termination. + scope.terminate_execution(); + } + scope.set_microtasks_policy(v8::MicrotasksPolicy::Auto); + + Err(js_error.into()) +} + #[cfg(test)] mod tests { use super::*; |