summaryrefslogtreecommitdiff
path: root/core/isolate.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/isolate.rs')
-rw-r--r--core/isolate.rs37
1 files changed, 29 insertions, 8 deletions
diff --git a/core/isolate.rs b/core/isolate.rs
index 12ddb529a..d2822e2b9 100644
--- a/core/isolate.rs
+++ b/core/isolate.rs
@@ -31,6 +31,7 @@ use futures::stream::TryStreamExt;
use futures::task::AtomicWaker;
use libc::c_char;
use libc::c_void;
+use libc::strdup;
use std::ffi::CStr;
use std::ffi::CString;
use std::fmt;
@@ -158,6 +159,7 @@ pub enum StartupData<'a> {
}
type JSErrorCreateFn = dyn Fn(V8Exception) -> ErrBox;
+type IsolateErrorHandleFn = dyn FnMut(ErrBox) -> Result<(), ErrBox>;
/// A single execution context of JavaScript. Corresponds roughly to the "Web
/// Worker" concept in the DOM. An Isolate is a Future that can be used with
@@ -180,6 +182,7 @@ pub struct Isolate {
startup_script: Option<OwnedScript>,
pub op_registry: Arc<OpRegistry>,
waker: AtomicWaker,
+ error_handler: Option<Box<IsolateErrorHandleFn>>,
}
unsafe impl Send for Isolate {}
@@ -246,9 +249,14 @@ impl Isolate {
startup_script,
op_registry: Arc::new(OpRegistry::new()),
waker: AtomicWaker::new(),
+ error_handler: None,
}
}
+ pub fn set_error_handler(&mut self, handler: Box<IsolateErrorHandleFn>) {
+ self.error_handler = Some(handler);
+ }
+
/// Defines the how Deno.core.dispatch() acts.
/// Called whenever Deno.core.dispatch() is called in JavaScript. zero_copy_buf
/// corresponds to the second argument of Deno.core.dispatch().
@@ -402,17 +410,30 @@ impl Isolate {
self.check_last_exception()
}
- fn check_last_exception(&self) -> Result<(), ErrBox> {
+ fn check_last_exception(&mut self) -> Result<(), ErrBox> {
let ptr = unsafe { libdeno::deno_last_exception(self.libdeno_isolate) };
if ptr.is_null() {
Ok(())
} else {
let js_error_create = &*self.js_error_create;
let cstr = unsafe { CStr::from_ptr(ptr) };
- let json_str = cstr.to_str().unwrap();
- let v8_exception = V8Exception::from_json(json_str).unwrap();
- let js_error = js_error_create(v8_exception);
- Err(js_error)
+ if self.error_handler.is_some() {
+ // We duplicate the string and assert ownership.
+ // This is due to we want the user to safely clone the error.
+ let cstring = unsafe { CString::from_raw(strdup(ptr)) };
+ // We need to clear last exception to avoid double handling.
+ unsafe { libdeno::deno_clear_last_exception(self.libdeno_isolate) };
+ let json_string = cstring.into_string().unwrap();
+ let v8_exception = V8Exception::from_json(&json_string).unwrap();
+ let js_error = js_error_create(v8_exception);
+ let handler = self.error_handler.as_mut().unwrap();
+ handler(js_error)
+ } else {
+ let json_str = cstr.to_str().unwrap();
+ let v8_exception = V8Exception::from_json(json_str).unwrap();
+ let js_error = js_error_create(v8_exception);
+ Err(js_error)
+ }
}
}
@@ -445,7 +466,7 @@ impl Isolate {
/// Low-level module creation.
pub fn mod_new(
- &self,
+ &mut self,
main: bool,
name: &str,
source: &str,
@@ -484,7 +505,7 @@ impl Isolate {
/// ErrBox can be downcast to a type that exposes additional information about
/// the V8 exception. By default this type is CoreJSError, however it may be a
/// different type if Isolate::set_js_error_create() has been used.
- pub fn snapshot(&self) -> Result<Snapshot1<'static>, ErrBox> {
+ pub fn snapshot(&mut self) -> Result<Snapshot1<'static>, ErrBox> {
let snapshot = unsafe { libdeno::deno_snapshot_new(self.libdeno_isolate) };
match self.check_last_exception() {
Ok(..) => Ok(snapshot),
@@ -497,7 +518,7 @@ impl Isolate {
}
fn dyn_import_done(
- &self,
+ &mut self,
id: libdeno::deno_dyn_import_id,
result: Result<deno_mod, Option<String>>,
) -> Result<(), ErrBox> {