Repository: denoland/deno_core
Pull request #855 (2024-07-31 10:09:26)

fix: remove some unwraps in serde_v8
Towards https://github.com/denoland/deno/issues/24784


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 18ec920..d8b42aa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -555,7 +555,7 @@ dependencies = [
 
 [[package]]
 name = "deno_core"
-version = "0.300.0"
+version = "0.301.0"
 dependencies = [
  "anyhow",
  "bencher",
@@ -624,7 +624,7 @@ dependencies = [
 
 [[package]]
 name = "deno_ops"
-version = "0.176.0"
+version = "0.177.0"
 dependencies = [
  "pretty_assertions",
  "prettyplease",
@@ -1841,7 +1841,7 @@ dependencies = [
 
 [[package]]
 name = "serde_v8"
-version = "0.209.0"
+version = "0.210.0"
 dependencies = [
  "bencher",
  "num-bigint",
diff --git a/Cargo.toml b/Cargo.toml
index 1548fbc..3cc1613 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,9 +19,9 @@ repository = "https://github.com/denoland/deno_core"
 
 [workspace.dependencies]
 # Local dependencies
-deno_core = { version = "0.300.0", path = "./core" }
-deno_ops = { version = "0.176.0", path = "./ops" }
-serde_v8 = { version = "0.209.0", path = "./serde_v8" }
+deno_core = { version = "0.301.0", path = "./core" }
+deno_ops = { version = "0.177.0", path = "./ops" }
+serde_v8 = { version = "0.210.0", path = "./serde_v8" }
 deno_core_testing = { path = "./testing" }
 
 v8 = { version = "0.101.0", default-features = false }
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 156cb63..e3508f2 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -2,7 +2,7 @@
 
 [package]
 name = "deno_core"
-version = "0.300.0"
+version = "0.301.0"
 authors.workspace = true
 edition.workspace = true
 license.workspace = true
diff --git a/core/error.rs b/core/error.rs
index 79988fd..0c9a127 100644
--- a/core/error.rs
+++ b/core/error.rs
@@ -9,6 +9,7 @@ use std::fmt::Formatter;
 use std::fmt::Write as _;
 
 use anyhow::Error;
+use v8::Object;
 
 use crate::runtime::v8_static_strings;
 use crate::runtime::JsRealm;
@@ -328,7 +329,19 @@ impl JsStackFrame {
     macro_rules! call {
       ($key: ident : $t: ty) => {{
         let res = call_method(scope, callsite, $key, &[])?;
-        let res: $t = serde_v8::from_v8(scope, res).ok()?;
+        let res: $t = match serde_v8::from_v8(scope, res) {
+          Ok(res) => res,
+          Err(err) => {
+            let message = format!(
+              "Failed to deserialize return value from callsite property '{}' to correct type: {err:?}.",
+              $key
+            );
+            let message = v8::String::new(scope, &message).unwrap();
+            let exception = v8::Exception::type_error(scope, message);
+            scope.throw_exception(exception);
+            return None;
+          }
+        };
         res
       }};
       ($key: ident) => { call!($key : _) };
@@ -352,7 +365,10 @@ impl JsStackFrame {
 
     // apply source map to the eval origin, if the error originates from `eval`ed code
     let eval_origin = call!(GET_EVAL_ORIGIN: Option<String>).and_then(|o| {
-      let (before, (file, line, col), after) = parse_eval_origin(&o)?;
+      let Some((before, (file, line, col), after)) = parse_eval_origin(&o)
+      else {
+        return Some(o);
+      };
       let (file, line, col) =
         apply_source_map(&mut source_mapper, file.into(), line, col);
       Some(format!("{before}{file}:{line}:{col}{after}"))
@@ -427,13 +443,37 @@ fn call_method<'a, T>(
   args: &[v8::Local<'a, v8::Value>],
 ) -> Option<v8::Local<'a, T>>
 where
-  v8::Local<'a, T>: TryFrom<v8::Local<'a, v8::Value>>,
+  v8::Local<'a, T>: TryFrom<v8::Local<'a, v8::Value>, Error: Debug>,
 {
-  get_property(scope, object, key)?
-    .try_cast::<v8::Function>()
-    .ok()?
-    .call(scope, object.into(), args)
-    .and_then(|v| v8::Local::try_from(v).ok())
+  let func = match get_property(scope, object, key)?.try_cast::<v8::Function>()
+  {
+    Ok(func) => func,
+    Err(err) => {
+      let message =
+        format!("Callsite property '{key}' is not a function: {err}");
+      let message = v8::String::new(scope, &message).unwrap();
+      let exception = v8::Exception::type_error(scope, message);
+      scope.throw_exception(exception);
+      return None;
+    }
+  };
+
+  let res = func.call(scope, object.into(), args)?;
+
+  let result = match v8::Local::try_from(res) {
+    Ok(result) => result,
+    Err(err) => {
+      let message = format!(
+        "Failed to cast callsite method '{key}' return value to correct value: {err:?}."
+      );
+      let message = v8::String::new(scope, &message).unwrap();
+      let exception = v8::Exception::type_error(scope, message);
+      scope.throw_exception(exception);
+      return None;
+    }
+  };
+
+  Some(result)
 }
 
 #[derive(Default, serde::Deserialize)]
@@ -603,9 +643,21 @@ impl JsError {
           let mut buf = Vec::with_capacity(frames_v8.length() as usize);
           for i in 0..frames_v8.length() {
             let callsite = frames_v8.get_index(scope, i).unwrap().cast();
-            buf.push(
-              JsStackFrame::from_callsite_object(scope, callsite).unwrap(),
-            );
+            let tc_scope = &mut v8::TryCatch::new(scope);
+            let Some(stack_frame) =
+              JsStackFrame::from_callsite_object(tc_scope, callsite)
+            else {
+              let message = tc_scope
+                .exception()
+                .expect(
+                  "JsStackFrame::from_callsite_object raised an exception",
+                )
+                .to_rust_string_lossy(tc_scope);
+              panic!(
+                "Failed to create JsStackFrame from callsite object: {message}"
+              );
+            };
+            buf.push(stack_frame);
           }
           buf
         }
@@ -948,8 +1000,10 @@ v8_static_strings::v8_static_strings! {
   IS_ASYNC = "isAsync",
   IS_PROMISE_ALL = "isPromiseAll",
   GET_PROMISE_INDEX = "getPromiseIndex",
+  TO_STRING = "toString",
   PREPARE_STACK_TRACE = "prepareStackTrace",
-  ORIGINAL = "_orig",
+  ORIGINAL = "deno_core::original_call_site",
+  ERROR_RECEIVER_IS_NOT_VALID_CALLSITE_OBJECT = "The receiver is not a valid callsite object.",
 }
 
 #[inline(always)]
@@ -963,14 +1017,145 @@ pub(crate) fn original_call_site_key<'a>(
 fn make_patched_callsite<'s>(
   scope: &mut v8::HandleScope<'s>,
   callsite: v8::Local<'s, v8::Object>,
-  template: v8::Local<'s, v8::ObjectTemplate>,
+  prototype: v8::Local<'s, v8::Object>,
 ) -> v8::Local<'s, v8::Object> {
-  let out_obj = template.new_instance(scope).unwrap();
+  let out_obj = Object::new(scope);
+  out_obj.set_prototype(scope, prototype.into());
   let orig_key = original_call_site_key(scope);
   out_obj.set_private(scope, orig_key, callsite.into());
   out_obj
 }
 
+fn original_call_site<'a>(
+  scope: &mut v8::HandleScope<'a>,
+  this: v8::Local<'_, v8::Object>,
+) -> Option<v8::Local<'a, v8::Object>> {
+  let orig_key = original_call_site_key(scope);
+  let Some(orig) = this
+    .get_private(scope, orig_key)
+    .and_then(|v| v8::Local::<v8::Object>::try_from(v).ok())
+  else {
+    let message = ERROR_RECEIVER_IS_NOT_VALID_CALLSITE_OBJECT.v8_string(scope);
+    let exception = v8::Exception::type_error(scope, message);
+    scope.throw_exception(exception);
+    return None;
+  };
+  Some(orig)
+}
+
+macro_rules! make_callsite_fn {
+  ($fn:ident, $field:ident) => {
+    pub fn $fn(
+      scope: &mut v8::HandleScope<'_>,
+      args: v8::FunctionCallbackArguments<'_>,
+      mut rv: v8::ReturnValue<'_>,
+    ) {
+      let Some(orig) = original_call_site(scope, args.this()) else {
+        return;
+      };
+      let key = $field.v8_string(scope).into();
+      let orig_ret = orig
+        .cast::<v8::Object>()
+        .get(scope, key)
+        .unwrap()
+        .cast::<v8::Function>()
+        .call(scope, orig.into(), &[]);
+      rv.set(orig_ret.unwrap_or_else(|| v8::undefined(scope).into()));
+    }
+  };
+}
+
+fn maybe_to_path_str(string: &str) -> Option<String> {
+  if string.starts_with("file://") {
+    Some(
+      Url::parse(string)
+        .unwrap()
+        .to_file_path()
+        .unwrap()
+        .to_string_lossy()
+        .into_owned(),
+    )
+  } else {
+    None
+  }
+}
+
+pub mod callsite_fns {
+  use super::*;
+
+  make_callsite_fn!(get_this, GET_THIS);
+  make_callsite_fn!(get_type_name, GET_TYPE_NAME);
+  make_callsite_fn!(get_function, GET_FUNCTION);
+  make_callsite_fn!(get_function_name, GET_FUNCTION_NAME);
+  make_callsite_fn!(get_method_name, GET_METHOD_NAME);
+
+  pub fn get_file_name(
+    scope: &mut v8::HandleScope<'_>,
+    args: v8::FunctionCallbackArguments<'_>,
+    mut rv: v8::ReturnValue<'_>,
+  ) {
+    let Some(orig) = original_call_site(scope, args.this()) else {
+      return;
+    };
+    // call getFileName
+    let orig_ret =
+      call_method::<v8::String>(scope, orig, super::GET_FILE_NAME, &[]);
+    if let Some(ret_val) = orig_ret {
+      // strip off `file://`
+      let string = ret_val.to_rust_string_lossy(scope);
+      if let Some(file_name) = maybe_to_path_str(&string) {
+        let v8_str = crate::FastString::from(file_name).v8_string(scope).into();
+        rv.set(v8_str);
+      } else {
+        rv.set(ret_val.into());
+      }
+    }
+  }
+
+  make_callsite_fn!(get_line_number, GET_LINE_NUMBER);
+  make_callsite_fn!(get_column_number, GET_COLUMN_NUMBER);
+  make_callsite_fn!(get_eval_origin, GET_EVAL_ORIGIN);
+  make_callsite_fn!(is_toplevel, IS_TOPLEVEL);
+  make_callsite_fn!(is_eval, IS_EVAL);
+  make_callsite_fn!(is_native, IS_NATIVE);
+  make_callsite_fn!(is_constructor, IS_CONSTRUCTOR);
+  make_callsite_fn!(is_async, IS_ASYNC);
+  make_callsite_fn!(is_promise_all, IS_PROMISE_ALL);
+  make_callsite_fn!(get_promise_index, GET_PROMISE_INDEX);
+
+  pub fn to_string(
+    scope: &mut v8::HandleScope<'_>,
+    args: v8::FunctionCallbackArguments<'_>,
+    mut rv: v8::ReturnValue<'_>,
+  ) {
+    let Some(orig) = original_call_site(scope, args.this()) else {
+      return;
+    };
+    // `this[kOriginalCallsite].toString()`
+    let Some(orig_to_string_v8) =
+      call_method::<v8::String>(scope, orig, TO_STRING, &[])
+    else {
+      return;
+    };
+    let orig_to_string = serde_v8::to_utf8(orig_to_string_v8, scope);
+    // `this[kOriginalCallsite].getFileName()`
+    let Some(orig_file_name) =
+      call_method::<v8::String>(scope, orig, GET_FILE_NAME, &[])
+    else {
+      return;
+    };
+    // replace file URL with file path in original `toString`
+    let orig_file_name = serde_v8::to_utf8(orig_file_name, scope);
+    if let Some(file_name) = maybe_to_path_str(&orig_file_name) {
+      let to_string = orig_to_string.replace(&orig_file_name, &file_name);
+      let v8_str = crate::FastString::from(to_string).v8_string(scope).into();
+      rv.set(v8_str);
+    } else {
+      rv.set(orig_to_string_v8.into());
+    }
+  }
+}
+
 /// Creates a template for a `Callsite`-like object, with
 /// a patched `getFileName`.
 /// Effectively:
@@ -988,111 +1173,45 @@ fn make_patched_callsite<'s>(
 ///   }
 /// }
 /// ```
-pub(crate) fn make_callsite_template<'s>(
+pub(crate) fn make_callsite_prototype<'s>(
   scope: &mut v8::HandleScope<'s>,
-) -> v8::Local<'s, v8::ObjectTemplate> {
+) -> v8::Local<'s, v8::Object> {
   let template = v8::ObjectTemplate::new(scope);
 
-  // effectively
-  // `$field() { return this[kOriginalCallsite].$field() }`
-  macro_rules! make_delegate {
-    ($scope: ident, $template: ident, [$($field: ident),+ $(,)?]) => {
-      $(
-        {
-          let key = $field.v8_string($scope).into();
-          $template.set_with_attr(
-            key,
-            v8::FunctionBuilder::<v8::FunctionTemplate>::new(
-              |scope: &mut v8::HandleScope<'_>,
-              args: v8::FunctionCallbackArguments<'_>,
-              mut rv: v8::ReturnValue<'_>| {
-                let orig_key = original_call_site_key(scope);
-                let orig = args.this().get_private(scope, orig_key).unwrap();
-                let key = $field.v8_string(scope).into();
-                let orig_ret = orig
-                  .cast::<v8::Object>()
-                  .get(scope, key)
-                  .unwrap()
-                  .cast::<v8::Function>()
-                  .call(scope, orig, &[]);
-                rv.set(orig_ret.unwrap_or_else(|| v8::undefined(scope).into()));
-              },
-            )
-            .build($scope)
-            .into(),
-            v8::PropertyAttribute::DONT_DELETE
-            | v8::PropertyAttribute::DONT_ENUM
-            | v8::PropertyAttribute::READ_ONLY,
-          );
-        }
-      )+
+  macro_rules! set_attr {
+    ($scope:ident, $template:ident, $fn:ident, $field:ident) => {
+      let key = $field.v8_string($scope).into();
+      $template.set_with_attr(
+        key,
+        v8::FunctionBuilder::<v8::FunctionTemplate>::new(callsite_fns::$fn)
+          .build($scope)
+          .into(),
+        v8::PropertyAttribute::DONT_DELETE
+          | v8::PropertyAttribute::DONT_ENUM
+          | v8::PropertyAttribute::READ_ONLY,
+      );
     };
   }
 
-  // delegate to the original callsite object
-  make_delegate!(
-    scope,
-    template,
-    [
-      // excludes getFileName, which we'll override below
-      GET_THIS,
-      GET_TYPE_NAME,
-      GET_FUNCTION,
-      GET_FUNCTION_NAME,
-      GET_METHOD_NAME,
-      GET_LINE_NUMBER,
-      GET_COLUMN_NUMBER,
-      GET_EVAL_ORIGIN,
-      IS_TOPLEVEL,
-      IS_EVAL,
-      IS_NATIVE,
-      IS_CONSTRUCTOR,
-      IS_ASYNC,
-      IS_PROMISE_ALL,
-      GET_PROMISE_INDEX,
-    ]
-  );
-
-  let get_file_name_key = GET_FILE_NAME.v8_string(scope).into();
-  template.set_with_attr(
-    get_file_name_key,
-    v8::FunctionBuilder::<v8::FunctionTemplate>::new(
-      |scope: &mut v8::HandleScope<'_>,
-       args: v8::FunctionCallbackArguments<'_>,
-       mut rv: v8::ReturnValue<'_>| {
-        // lookup the original call site object
-        let orig_key = original_call_site_key(scope);
-        let orig = args.this().get_private(scope, orig_key).unwrap().cast();
-        // call getFileName
-        let orig_ret =
-          call_method::<v8::String>(scope, orig, GET_FILE_NAME, &[]);
-        if let Some(ret_val) = orig_ret {
-          // strip off `file://`
-          let string = ret_val.to_rust_string_lossy(scope);
-          let file_name = if string.starts_with("file://") {
-            Url::parse(&string)
-              .unwrap()
-              .to_file_path()
-              .unwrap()
-              .to_string_lossy()
-              .into_owned()
-          } else {
-            string
-          };
-          let v8_str =
-            crate::FastString::from(file_name).v8_string(scope).into();
-          rv.set(v8_str);
-        }
-      },
-    )
-    .build(scope)
-    .into(),
-    v8::PropertyAttribute::DONT_DELETE
-      | v8::PropertyAttribute::DONT_ENUM
-      | v8::PropertyAttribute::READ_ONLY,
-  );
-
-  template
+  set_attr!(scope, template, get_this, GET_THIS);
+  set_attr!(scope, template, get_type_name, GET_TYPE_NAME);
+  set_attr!(scope, template, get_function, GET_FUNCTION);
+  set_attr!(scope, template, get_function_name, GET_FUNCTION_NAME);
+  set_attr!(scope, template, get_method_name, GET_METHOD_NAME);
+  set_attr!(scope, template, get_file_name, GET_FILE_NAME);
+  set_attr!(scope, template, get_line_number, GET_LINE_NUMBER);
+  set_attr!(scope, template, get_column_number, GET_COLUMN_NUMBER);
+  set_attr!(scope, template, get_eval_origin, GET_EVAL_ORIGIN);
+  set_attr!(scope, template, is_toplevel, IS_TOPLEVEL);
+  set_attr!(scope, template, is_eval, IS_EVAL);
+  set_attr!(scope, template, is_native, IS_NATIVE);
+  set_attr!(scope, template, is_constructor, IS_CONSTRUCTOR);
+  set_attr!(scope, template, is_async, IS_ASYNC);
+  set_attr!(scope, template, is_promise_all, IS_PROMISE_ALL);
+  set_attr!(scope, template, get_promise_index, GET_PROMISE_INDEX);
+  set_attr!(scope, template, to_string, TO_STRING);
+
+  template.new_instance(scope).unwrap()
 }
 
 // called by V8 whenever a stack trace is created.
@@ -1123,15 +1242,15 @@ pub fn prepare_stack_trace_callback<'s>(
     let len = callsites.length();
     let mut patched = Vec::with_capacity(len as usize);
     let template = JsRuntime::state_from(scope)
-      .callsite_template
+      .callsite_prototype
       .borrow()
       .clone()
       .unwrap();
-    let template = v8::Local::new(scope, template);
+    let prototype = v8::Local::new(scope, template);
     for i in 0..len {
       let callsite =
         callsites.get_index(scope, i).unwrap().cast::<v8::Object>();
-      patched.push(make_patched_callsite(scope, callsite, template).into());
+      patched.push(make_patched_callsite(scope, callsite, prototype).into());
     }
     let patched_callsites = v8::Array::new_with_elements(scope, &patched);
 
@@ -1176,7 +1295,15 @@ fn format_stack_trace<'s>(
   // format each stack frame
   for i in 0..callsites.length() {
     let callsite = callsites.get_index(scope, i).unwrap().cast::<v8::Object>();
-    let frame = JsStackFrame::from_callsite_object(scope, callsite).unwrap();
+    let tc_scope = &mut v8::TryCatch::new(scope);
+    let Some(frame) = JsStackFrame::from_callsite_object(tc_scope, callsite)
+    else {
+      let message = tc_scope
+        .exception()
+        .expect("JsStackFrame::from_callsite_object raised an exception")
+        .to_rust_string_lossy(tc_scope);
+      panic!("Failed to create JsStackFrame from callsite object: {message}");
+    };
     write!(result, "\n    at {}", format_frame::<NoAnsiColors>(&frame))
       .unwrap();
   }
diff --git a/core/lib.rs b/core/lib.rs
index 5d246f3..977fa13 100644
--- a/core/lib.rs
+++ b/core/lib.rs
@@ -151,6 +151,8 @@ pub use crate::runtime::CompiledWasmModuleStore;
 pub use crate::runtime::ContextState;
 pub use crate::runtime::CreateRealmOptions;
 pub use crate::runtime::CrossIsolateStore;
+pub use crate::runtime::ImportAssertionsSupport;
+pub use crate::runtime::ImportAssertionsSupportCustomCallbackArgs;
 pub use crate::runtime::JsRuntime;
 pub use crate::runtime::JsRuntimeForSnapshot;
 pub use crate::runtime::PollEventLoopOptions;
diff --git a/core/runtime/bindings.rs b/core/runtime/bindings.rs
index 9f6a406..264ab28 100644
--- a/core/runtime/bindings.rs
+++ b/core/runtime/bindings.rs
@@ -10,6 +10,7 @@ use super::jsruntime::BUILTIN_SOURCES;
 use super::jsruntime::CONTEXT_SETUP_SOURCES;
 use super::v8_static_strings::*;
 use crate::cppgc::cppgc_template_constructor;
+use crate::error::callsite_fns;
 use crate::error::has_call_site;
 use crate::error::is_instance_of_error;
 use crate::error::throw_type_error;
@@ -42,7 +43,8 @@ pub(crate) fn create_external_references(
       + BUILTIN_SOURCES.len()
       + (ops.len() * 4)
       + additional_references.len()
-      + sources.len(),
+      + sources.len()
+      + 18, // for callsite_fns
   );
 
   references.push(v8::ExternalReference {
@@ -103,6 +105,58 @@ pub(crate) fn create_external_references(
     })
   }
 
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_this.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_type_name.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_function.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_function_name.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_method_name.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_file_name.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_line_number.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_column_number.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_eval_origin.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::is_toplevel.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::is_eval.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::is_native.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::is_constructor.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::is_async.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::is_promise_all.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::get_promise_index.map_fn_to(),
+  });
+  references.push(v8::ExternalReference {
+    function: callsite_fns::to_string.map_fn_to(),
+  });
+
   v8::ExternalReferences::new(&references)
 }
 
diff --git a/core/runtime/jsruntime.rs b/core/runtime/jsruntime.rs
index 4bcbbbf..d139cb1 100644
--- a/core/runtime/jsruntime.rs
+++ b/core/runtime/jsruntime.rs
@@ -69,6 +69,7 @@ use futures::Future;
 use futures::FutureExt;
 use smallvec::SmallVec;
 use std::any::Any;
+use v8::MessageErrorLevel;
 
 use std::cell::Cell;
 use std::cell::RefCell;
@@ -433,11 +434,12 @@ pub struct JsRuntimeState {
   pub(crate) eval_context_code_cache_ready_cb:
     Option<EvalContextCodeCacheReadyCb>,
   pub(crate) cppgc_template: RefCell<Option<v8::Global<v8::FunctionTemplate>>>,
-  pub(crate) callsite_template: RefCell<Option<v8::Global<v8::ObjectTemplate>>>,
+  pub(crate) callsite_prototype: RefCell<Option<v8::Global<v8::Object>>>,
   waker: Arc<AtomicWaker>,
   /// Accessed through [`JsRuntimeState::with_inspector`].
   inspector: RefCell<Option<Rc<RefCell<JsRuntimeInspector>>>>,
   has_inspector: Cell<bool>,
+  import_assertions_support: ImportAssertionsSupport,
 }
 
 #[derive(Default)]
@@ -550,6 +552,104 @@ pub struct RuntimeOptions {
   /// through evalContext.
   pub eval_context_code_cache_cbs:
     Option<(EvalContextGetCodeCacheCb, EvalContextCodeCacheReadyCb)>,
+
+  pub import_assertions_support: ImportAssertionsSupport,
+}
+
+pub struct ImportAssertionsSupportCustomCallbackArgs {
+  pub maybe_specifier: Option<String>,
+  pub maybe_line_number: Option<usize>,
+  pub column_number: usize,
+  pub maybe_source_line: Option<String>,
+}
+
+#[derive(Default)]
+pub enum ImportAssertionsSupport {
+  /// `assert` keyword is no longer supported and causes a SyntaxError.
+  /// This is the default setting, because V8 unshipped import assertions
+  /// support in v12.6. To enable import assertion one must pass
+  /// `--harmony-import-assertions` V8 flag when initializing the runtime.
+  #[default]
+  Error,
+
+  /// `assert` keyword is supported.
+  Yes,
+
+  /// `assert` keyword is supported, but prints a warning message on occurence.
+  Warning,
+
+  /// `assert` keyword is supported, provided callback is called on each occurence.
+  /// Callback receives optional specifier, optional line number, column number and optional
+  /// source line.
+  CustomCallback(Box<dyn Fn(ImportAssertionsSupportCustomCallbackArgs)>),
+}
+
+impl ImportAssertionsSupport {
+  fn is_enabled(&self) -> bool {
+    matches!(self, Self::Yes | Self::Warning | Self::CustomCallback(_))
+  }
+
+  fn has_warning(&self) -> bool {
+    matches!(self, Self::Warning | Self::CustomCallback(_))
+  }
+}
+
+/// Currently only handles warnings for "import assertions" deprecation
+extern "C" fn isolate_message_listener(
+  message: v8::Local<v8::Message>,
+  _exception: v8::Local<v8::Value>,
+) {
+  let scope = &mut unsafe { v8::CallbackScope::new(message) };
+  let scope = &mut v8::HandleScope::new(scope);
+  let message_v8_str = message.get(scope);
+  let message_str = message_v8_str.to_rust_string_lossy(scope);
+
+  if !message_str.starts_with("'assert' is deprecated") {
+    return;
+  }
+
+  let maybe_script_resource_name = message
+    .get_script_resource_name(scope)
+    .map(|s| s.to_rust_string_lossy(scope));
+  let maybe_source_line = message
+    .get_source_line(scope)
+    .map(|s| s.to_rust_string_lossy(scope));
+  let maybe_line_number = message.get_line_number(scope);
+  let start_column = message.get_start_column();
+
+  let js_runtime_state = JsRuntime::state_from(scope);
+  match &js_runtime_state.import_assertions_support {
+    ImportAssertionsSupport::Warning => {
+      let mut msg = "⚠️  Import assertions are deprecated. Use `with` keyword, instead of 'assert' keyword.".to_string();
+      if let Some(specifier) = maybe_script_resource_name {
+        if let Some(source_line) = maybe_source_line {
+          msg.push('\n');
+          msg.push_str(&source_line);
+          msg.push('\n');
+          msg.push_str(&format!("{:0width$}^", " ", width = start_column));
+        }
+        msg.push_str(&format!(
+          "  at {}:{}:{}",
+          specifier,
+          maybe_line_number.unwrap(),
+          start_column
+        ));
+        #[allow(clippy::print_stderr)]
+        {
+          eprintln!("{}", msg);
+        }
+      }
+    }
+    ImportAssertionsSupport::CustomCallback(cb) => {
+      cb(ImportAssertionsSupportCustomCallbackArgs {
+        maybe_specifier: maybe_script_resource_name,
+        maybe_line_number,
+        column_number: start_column,
+        maybe_source_line,
+      });
+    }
+    _ => unreachable!(),
+  }
 }
 
 impl RuntimeOptions {
@@ -594,8 +694,11 @@ impl JsRuntime {
   /// should only be called once per process. Further calls will be silently
   /// ignored.
   #[cfg(not(any(test, feature = "unsafe_runtime_options")))]
-  pub fn init_platform(v8_platform: Option<v8::SharedRef<v8::Platform>>) {
-    setup::init_v8(v8_platform, cfg!(test), false);
+  pub fn init_platform(
+    v8_platform: Option<v8::SharedRef<v8::Platform>>,
+    import_assertions_enabled: bool,
+  ) {
+    setup::init_v8(v8_platform, cfg!(test), false, import_assertions_enabled);
   }
 
   /// Explicitly initalizes the V8 platform using the passed platform. This
@@ -610,8 +713,14 @@ impl JsRuntime {
   pub fn init_platform(
     v8_platform: Option<v8::SharedRef<v8::Platform>>,
     expose_natives: bool,
+    import_assertions_enabled: bool,
   ) {
-    setup::init_v8(v8_platform, cfg!(test), expose_natives);
+    setup::init_v8(
+      v8_platform,
+      cfg!(test),
+      expose_natives,
+      import_assertions_enabled,
+    );
   }
 
   /// Only constructor, configuration is done through `options`.
@@ -632,6 +741,7 @@ impl JsRuntime {
       options.v8_platform.take(),
       cfg!(test),
       options.unsafe_expose_natives_and_gc(),
+      options.import_assertions_support.is_enabled(),
     );
     JsRuntime::new_inner(options, false)
   }
@@ -736,7 +846,8 @@ impl JsRuntime {
       inspector: None.into(),
       has_inspector: false.into(),
       cppgc_template: None.into(),
-      callsite_template: None.into(),
+      callsite_prototype: None.into(),
+      import_assertions_support: options.import_assertions_support,
     });
 
     // ...now we're moving on to ops; set them up, create `OpCtx` for each op
@@ -816,6 +927,13 @@ impl JsRuntime {
       external_refs_static,
     );
 
+    if state_rc.import_assertions_support.has_warning() {
+      isolate.add_message_listener_with_error_level(
+        isolate_message_listener,
+        MessageErrorLevel::ALL,
+      );
+    }
+
     // ...isolate is fully set up, we can forward its pointer to the ops to finish
     // their' setup...
     for op_ctx in op_ctxs.iter_mut() {
@@ -894,11 +1012,11 @@ impl JsRuntime {
     let scope = &mut context_scope;
     let context = v8::Local::new(scope, &main_context);
 
-    let callsite_template = crate::error::make_callsite_template(scope);
+    let callsite_prototype = crate::error::make_callsite_prototype(scope);
     state_rc
-      .callsite_template
+      .callsite_prototype
       .borrow_mut()
-      .replace(v8::Global::new(scope, callsite_template));
+      .replace(v8::Global::new(scope, callsite_prototype));
 
     // ...followed by creation of `Deno.core` namespace, as well as internal
     // infrastructure to provide JavaScript bindings for ops...
@@ -1956,6 +2074,7 @@ impl JsRuntimeForSnapshot {
       options.v8_platform.take(),
       true,
       options.unsafe_expose_natives_and_gc(),
+      options.import_assertions_support.is_enabled(),
     );
 
     let runtime = JsRuntime::new_inner(options, true)?;
diff --git a/core/runtime/mod.rs b/core/runtime/mod.rs
index 8bae616..c01bdc8 100644
--- a/core/runtime/mod.rs
+++ b/core/runtime/mod.rs
@@ -27,6 +27,8 @@ pub use jsruntime::CompiledWasmModuleStore;
 pub use jsruntime::CreateRealmOptions;
 pub use jsruntime::CrossIsolateStore;
 pub use jsruntime::ExtensionTranspiler;
+pub use jsruntime::ImportAssertionsSupport;
+pub use jsruntime::ImportAssertionsSupportCustomCallbackArgs;
 pub(crate) use jsruntime::InitMode;
 pub use jsruntime::JsRuntime;
 pub use jsruntime::JsRuntimeForSnapshot;
diff --git a/core/runtime/setup.rs b/core/runtime/setup.rs
index dd44e4a..15e0b00 100644
--- a/core/runtime/setup.rs
+++ b/core/runtime/setup.rs
@@ -15,6 +15,7 @@ fn v8_init(
   v8_platform: Option<v8::SharedRef<v8::Platform>>,
   snapshot: bool,
   expose_natives: bool,
+  import_assertions_enabled: bool,
 ) {
   #[cfg(feature = "include_icu_data")]
   {
@@ -35,16 +36,36 @@ fn v8_init(
   } else {
     ""
   };
+  let import_assertions_flag = if import_assertions_enabled {
+    "--harmony-import-assertions"
+  } else {
+    "--no-harmony-import-assertions"
+  };
+  // TODO(bartlomieju): this is ridiculous, rewrite this
   #[allow(clippy::useless_format)]
-  let flags = match (snapshot, expose_natives) {
-    (false, false) => format!("{base_flags}"),
-    (true, false) => format!("{base_flags} {snapshot_flags} {lazy_flags}"),
-    (false, true) => format!("{base_flags} {expose_natives_flags}"),
-    (true, true) => {
+  let flags = match (snapshot, expose_natives, import_assertions_enabled) {
+    (false, false, false) => format!("{base_flags}"),
+    (false, false, true) => format!("{base_flags} {import_assertions_flag}"),
+    (true, false, false) => {
+      format!("{base_flags} {snapshot_flags} {lazy_flags}")
+    }
+    (true, false, true) => format!(
+      "{base_flags} {snapshot_flags} {lazy_flags} {import_assertions_flag}"
+    ),
+    (false, true, false) => format!("{base_flags} {expose_natives_flags}"),
+    (false, true, true) => {
+      format!("{base_flags} {expose_natives_flags} {import_assertions_flag}")
+    }
+    (true, true, false) => {
       format!(
         "{base_flags} {snapshot_flags} {lazy_flags} {expose_natives_flags}"
       )
     }
+    (true, true, true) => {
+      format!(
+        "{base_flags} {snapshot_flags} {lazy_flags} {expose_natives_flags} {import_assertions_flag}"
+      )
+    }
   };
   v8::V8::set_flags_from_string(&flags);
 
@@ -67,6 +88,7 @@ pub fn init_v8(
   v8_platform: Option<v8::SharedRef<v8::Platform>>,
   snapshot: bool,
   expose_natives: bool,
+  import_assertions_enabled: bool,
 ) {
   static DENO_INIT: Once = Once::new();
   static DENO_SNAPSHOT: AtomicBool = AtomicBool::new(false);
@@ -79,7 +101,14 @@ pub fn init_v8(
     DENO_SNAPSHOT.store(snapshot, Ordering::SeqCst);
   }
 
-  DENO_INIT.call_once(move || v8_init(v8_platform, snapshot, expose_natives));
+  DENO_INIT.call_once(move || {
+    v8_init(
+      v8_platform,
+      snapshot,
+      expose_natives,
+      import_assertions_enabled,
+    )
+  });
 }
 
 fn create_cpp_heap() -> v8::UniqueRef<v8::cppgc::Heap> {
diff --git a/core/runtime/v8_static_strings.rs b/core/runtime/v8_static_strings.rs
index 0fad47f..b106d9c 100644
--- a/core/runtime/v8_static_strings.rs
+++ b/core/runtime/v8_static_strings.rs
@@ -12,7 +12,7 @@ pub(crate) use v8_static_strings;
 v8_static_strings!(
   BUILD_CUSTOM_ERROR = "buildCustomError",
   CALL_CONSOLE = "callConsole",
-  CALL_SITE_EVALS = "callSiteEvals",
+  CALL_SITE_EVALS = "deno_core::call_site_evals",
   CAUSE = "cause",
   CODE = "code",
   CONSOLE = "console",
diff --git a/ops/Cargo.toml b/ops/Cargo.toml
index d624faf..7938bd6 100644
--- a/ops/Cargo.toml
+++ b/ops/Cargo.toml
@@ -2,7 +2,7 @@
 
 [package]
 name = "deno_ops"
-version = "0.176.0"
+version = "0.177.0"
 authors.workspace = true
 edition.workspace = true
 license.workspace = true
diff --git a/serde_v8/Cargo.toml b/serde_v8/Cargo.toml
index 47e2a71..3e2798a 100644
--- a/serde_v8/Cargo.toml
+++ b/serde_v8/Cargo.toml
@@ -2,7 +2,7 @@
 
 [package]
 name = "serde_v8"
-version = "0.209.0"
+version = "0.210.0"
 authors.workspace = true
 edition.workspace = true
 license.workspace = true
diff --git a/serde_v8/de.rs b/serde_v8/de.rs
index 49b4407..968d0e8 100644
--- a/serde_v8/de.rs
+++ b/serde_v8/de.rs
@@ -200,6 +200,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
     V: Visitor<'de>,
   {
     if self.input.is_string() || self.input.is_string_object() {
+      // fixme: this unwrap is not safe because stringifier could have thrown
       let v8_string = self.input.to_string(self.scope).unwrap();
       let string = to_utf8(v8_string, self.scope);
       visitor.visit_string(string)
@@ -265,10 +266,10 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
   where
     V: Visitor<'de>,
   {
-    let obj = v8::Local::<v8::Object>::try_from(self.input).unwrap();
-    if obj.is_array() {
+    let obj = v8::Local::<v8::Object>::try_from(self.input)
+      .map_err(|_| Error::ExpectedObject(self.input.type_repr()))?;
+    if let Ok(array) = v8::Local::<v8::Array>::try_from(obj) {
       // If the obj is an array fail if it's length differs from the tuple length
-      let array = v8::Local::<v8::Array>::try_from(self.input).unwrap();
       let array_len = array.length() as usize;
       if array_len != len {
         return Err(Error::LengthMismatch(array_len, len));
@@ -298,10 +299,8 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
     let obj = v8::Local::<v8::Object>::try_from(self.input)
       .map_err(|_| Error::ExpectedObject(self.input.type_repr()))?;
 
-    if v8::Local::<v8::Map>::try_from(self.input).is_ok() {
-      let pairs_array = v8::Local::<v8::Map>::try_from(self.input)
-        .unwrap()
-        .as_array(self.scope);
+    if let Ok(map) = v8::Local::<v8::Map>::try_from(self.input) {
+      let pairs_array = map.as_array(self.scope);
       let map = MapPairsAccess {
         pos: 0,
         len: pairs_array.length(),
@@ -394,9 +393,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
       })
     }
     // Struct or tuple variant
-    else if self.input.is_object() {
-      // Assume object
-      let obj = v8::Local::<v8::Object>::try_from(self.input).unwrap();
+    else if let Ok(obj) = v8::Local::<v8::Object>::try_from(self.input) {
       // Unpack single-key
       let tag = {
         let prop_names =
@@ -407,9 +404,11 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
         if prop_names_len != 1 {
           return Err(Error::LengthMismatch(prop_names_len as usize, 1));
         }
+        // fixme: this unwrap  is not safe because of proxies
         prop_names.get_index(self.scope, 0).unwrap()
       };
 
+      // fixme: this unwrap  is not safe because of proxies
       let payload = obj.get(self.scope, tag).unwrap();
       visitor.visit_enum(EnumAccess {
         scope: self.scope,
@@ -629,6 +628,7 @@ impl<'de> de::SeqAccess<'de> for SeqAccess<'_, '_> {
     seed: T,
   ) -> Result<Option<T::Value>> {
     if let Some(pos) = self.range.next() {
+      // fixme: this unwrap  is not safe because of proxies
       let val = self.obj.get_index(self.scope, pos).unwrap();
       let mut deserializer = Deserializer::new(self.scope, val, None);
       seed.deserialize(&mut deserializer).map(Some)


Test patch:
diff --git a/testing/checkin/runner/mod.rs b/testing/checkin/runner/mod.rs
index 98dc529..37c5ae2 100644
--- a/testing/checkin/runner/mod.rs
+++ b/testing/checkin/runner/mod.rs
@@ -11,6 +11,7 @@ use deno_core::CrossIsolateStore;
 use deno_core::CustomModuleEvaluationKind;
 use deno_core::Extension;
 use deno_core::FastString;
+use deno_core::ImportAssertionsSupport;
 use deno_core::JsRuntime;
 use deno_core::ModuleSourceCode;
 use deno_core::RuntimeOptions;
@@ -127,6 +128,7 @@ pub fn create_runtime_from_snapshot(
     shared_array_buffer_store: Some(CrossIsolateStore::default()),
     custom_module_evaluation_cb: Some(Box::new(custom_module_evaluation_cb)),
     inspector,
+    import_assertions_support: ImportAssertionsSupport::Warning,
     ..Default::default()
   });
 
diff --git a/testing/integration/error_callsite/error_callsite.out b/testing/integration/error_callsite/error_callsite.out
new file mode 100644
index 0000000..183e4a1
--- /dev/null
+++ b/testing/integration/error_callsite/error_callsite.out
@@ -0,0 +1,32 @@
+{
+  "getTypeName": null,
+  "getFunctionName": "Foo",
+  "getMethodName": null,
+  "getFileName": "test:///integration/error_callsite/error_callsite.ts",
+  "getLineNumber": 36,
+  "getColumnNumber": 5,
+  "isToplevel": false,
+  "isEval": false,
+  "isNative": false,
+  "isConstructor": true,
+  "isAsync": false,
+  "isPromiseAll": false,
+  "getPromiseIndex": null
+}
+new Foo (test:///integration/error_callsite/error_callsite.ts:36:5)
+{
+  "getTypeName": null,
+  "getFunctionName": null,
+  "getMethodName": null,
+  "getFileName": "test:///integration/error_callsite/error_callsite.ts",
+  "getLineNumber": 39,
+  "getColumnNumber": 1,
+  "isToplevel": true,
+  "isEval": false,
+  "isNative": false,
+  "isConstructor": false,
+  "isAsync": false,
+  "isPromiseAll": false,
+  "getPromiseIndex": null
+}
+test:///integration/error_callsite/error_callsite.ts:39:1
diff --git a/testing/integration/error_callsite/error_callsite.ts b/testing/integration/error_callsite/error_callsite.ts
new file mode 100644
index 0000000..9477f86
--- /dev/null
+++ b/testing/integration/error_callsite/error_callsite.ts
@@ -0,0 +1,38 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+// deno-lint-ignore-file no-explicit-any
+function toObj(callsite: any) {
+  const keys = [
+    "getThis",
+    "getTypeName",
+    "getFunction",
+    "getFunctionName",
+    "getMethodName",
+    "getFileName",
+    "getLineNumber",
+    "getColumnNumber",
+    "getEvalOrigin",
+    "isToplevel",
+    "isEval",
+    "isNative",
+    "isConstructor",
+    "isAsync",
+    "isPromiseAll",
+    "getPromiseIndex",
+  ];
+  return Object.fromEntries(keys.map((key) => [key, callsite[key]()]));
+}
+(Error as any).prepareStackTrace = function (_: any, callsites: any) {
+  callsites.forEach((callsite: any) => {
+    console.log(toObj(callsite));
+    console.log(callsite.toString());
+  });
+  return callsites;
+};
+
+class Foo {
+  constructor() {
+    new Error().stack;
+  }
+}
+
+new Foo();
diff --git a/testing/integration/error_non_existent_eval_source/error_non_existent_eval_source.out b/testing/integration/error_non_existent_eval_source/error_non_existent_eval_source.out
new file mode 100644
index 0000000..c11aac7
--- /dev/null
+++ b/testing/integration/error_non_existent_eval_source/error_non_existent_eval_source.out
@@ -0,0 +1,3 @@
+[ERR] ReferenceError: doesNotExist is not defined
+[ERR]     at Object.eval (empty.eval, <anonymous>:3:1)
+[ERR]     at test:///integration/error_non_existent_eval_source/error_non_existent_eval_source.ts:11:6
diff --git a/testing/integration/error_non_existent_eval_source/error_non_existent_eval_source.ts b/testing/integration/error_non_existent_eval_source/error_non_existent_eval_source.ts
new file mode 100644
index 0000000..07b30ab
--- /dev/null
+++ b/testing/integration/error_non_existent_eval_source/error_non_existent_eval_source.ts
@@ -0,0 +1,11 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+const AsyncFunction = Object.getPrototypeOf(async function () {
+  // empty
+}).constructor;
+
+const func = new AsyncFunction(
+  `return doesNotExist();
+    //# sourceURL=empty.eval`,
+);
+
+func.call({});
diff --git a/testing/integration/error_prepare_stack_trace/error_prepare_stack_trace.out b/testing/integration/error_prepare_stack_trace/error_prepare_stack_trace.out
new file mode 100644
index 0000000..d9eba84
--- /dev/null
+++ b/testing/integration/error_prepare_stack_trace/error_prepare_stack_trace.out
@@ -0,0 +1,40 @@
+[
+  "getThis",
+  "getTypeName",
+  "getFunction",
+  "getFunctionName",
+  "getMethodName",
+  "getFileName",
+  "getLineNumber",
+  "getColumnNumber",
+  "getEvalOrigin",
+  "isToplevel",
+  "isEval",
+  "isNative",
+  "isConstructor",
+  "isAsync",
+  "isPromiseAll",
+  "getPromiseIndex",
+  "toString"
+]
+[]
+[
+  "test:///integration/error_prepare_stack_trace/error_prepare_stack_trace.ts:12:13"
+]
+getThis() threw an error: The receiver is not a valid callsite object.
+getTypeName() threw an error: The receiver is not a valid callsite object.
+getFunction() threw an error: The receiver is not a valid callsite object.
+getFunctionName() threw an error: The receiver is not a valid callsite object.
+getMethodName() threw an error: The receiver is not a valid callsite object.
+getFileName() threw an error: The receiver is not a valid callsite object.
+getLineNumber() threw an error: The receiver is not a valid callsite object.
+getColumnNumber() threw an error: The receiver is not a valid callsite object.
+getEvalOrigin() threw an error: The receiver is not a valid callsite object.
+isToplevel() threw an error: The receiver is not a valid callsite object.
+isEval() threw an error: The receiver is not a valid callsite object.
+isNative() threw an error: The receiver is not a valid callsite object.
+isConstructor() threw an error: The receiver is not a valid callsite object.
+isAsync() threw an error: The receiver is not a valid callsite object.
+isPromiseAll() threw an error: The receiver is not a valid callsite object.
+getPromiseIndex() threw an error: The receiver is not a valid callsite object.
+toString() threw an error: The receiver is not a valid callsite object.
diff --git a/testing/integration/error_prepare_stack_trace/error_prepare_stack_trace.ts b/testing/integration/error_prepare_stack_trace/error_prepare_stack_trace.ts
new file mode 100644
index 0000000..c8c9348
--- /dev/null
+++ b/testing/integration/error_prepare_stack_trace/error_prepare_stack_trace.ts
@@ -0,0 +1,29 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+let errorCallsitePrototype;
+// deno-lint-ignore no-explicit-any
+(Error as any).prepareStackTrace = (_err, frames) => {
+  return frames.map((frame) => {
+    errorCallsitePrototype = Object.getPrototypeOf(frame);
+    console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(frame)));
+    console.log(Object.getOwnPropertyNames(frame));
+    return frame.toString();
+  });
+};
+
+console.log(new Error("fail").stack);
+
+for (const prop of Object.getOwnPropertyNames(errorCallsitePrototype)) {
+  if (typeof errorCallsitePrototype[prop] === "function") {
+    let error;
+    try {
+      errorCallsitePrototype[prop]();
+    } catch (e) {
+      error = e;
+    }
+    if (error) {
+      console.log(`${prop}() threw an error: ${error.message}`);
+    } else {
+      console.log(`${prop}() did not throw an error`);
+    }
+  }
+}
diff --git a/testing/lib.rs b/testing/lib.rs
index 6314e80..00494ac 100644
--- a/testing/lib.rs
+++ b/testing/lib.rs
@@ -57,10 +57,13 @@ integration_test!(
   dyn_import_op,
   dyn_import_no_hang,
   error_async_stack,
+  error_callsite,
+  error_non_existent_eval_source,
   error_rejection_catch,
   error_rejection_order,
   error_eval_stack,
   error_ext_stack,
+  error_prepare_stack_trace,
   error_with_stack,
   error_without_stack,
   main_module_handler,