mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 04:48:52 -05:00
refactor(core): unwrap sync ops in rust (#15449)
This commit is contained in:
parent
321a42d1fb
commit
25a1cc1b28
5 changed files with 60 additions and 7 deletions
|
@ -127,6 +127,18 @@
|
|||
errorMap[className] = errorBuilder;
|
||||
}
|
||||
|
||||
function buildCustomError(className, message, code) {
|
||||
const error = errorMap[className]?.(message);
|
||||
// Strip buildCustomError() calls from stack trace
|
||||
if (typeof error == "object") {
|
||||
ErrorCaptureStackTrace(error, buildCustomError);
|
||||
if (code) {
|
||||
error.code = code;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
function unwrapOpResult(res) {
|
||||
// .$err_class_name is a special key that should only exist on errors
|
||||
if (res?.$err_class_name) {
|
||||
|
@ -168,7 +180,7 @@
|
|||
}
|
||||
|
||||
function opSync(opName, ...args) {
|
||||
return unwrapOpResult(ops[opName](...args));
|
||||
return ops[opName](...args);
|
||||
}
|
||||
|
||||
function refOp(promiseId) {
|
||||
|
@ -229,6 +241,7 @@
|
|||
metrics,
|
||||
registerErrorBuilder,
|
||||
registerErrorClass,
|
||||
buildCustomError,
|
||||
opresolve,
|
||||
BadResource,
|
||||
BadResourcePrototype,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
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;
|
||||
|
@ -91,6 +93,30 @@ pub fn get_custom_error_class(error: &Error) -> Option<&'static str> {
|
|||
error.downcast_ref::<CustomError>().map(|e| e.class)
|
||||
}
|
||||
|
||||
pub fn to_v8_error<'a>(
|
||||
scope: &mut v8::HandleScope<'a>,
|
||||
get_class: GetErrorClassFn,
|
||||
error: &Error,
|
||||
) -> v8::Local<'a, v8::Value> {
|
||||
let cb = JsRealm::state_from_scope(scope)
|
||||
.borrow()
|
||||
.js_build_custom_error_cb
|
||||
.clone()
|
||||
.expect("Custom error builder must be set");
|
||||
let cb = cb.open(scope);
|
||||
let this = v8::undefined(scope).into();
|
||||
let class = v8::String::new(scope, get_class(error)).unwrap();
|
||||
let message = v8::String::new(scope, &error.to_string()).unwrap();
|
||||
let mut args = vec![class.into(), message.into()];
|
||||
if let Some(code) = crate::error_codes::get_error_code(error) {
|
||||
args.push(v8::String::new(scope, code).unwrap().into());
|
||||
}
|
||||
let exception = cb
|
||||
.call(scope, this, &args)
|
||||
.expect("Custom error class must have a builder registered");
|
||||
exception
|
||||
}
|
||||
|
||||
/// A `JsError` represents an exception coming from V8, with stack frames and
|
||||
/// line numbers. The deno_cli crate defines another `JsError` type, which wraps
|
||||
/// the one defined here, that adds source map support and colorful formatting.
|
||||
|
|
|
@ -473,7 +473,8 @@ fn op_serialize(
|
|||
value_serializer.write_value(scope.get_current_context(), value.v8_value);
|
||||
if scope.has_caught() || scope.has_terminated() {
|
||||
scope.rethrow();
|
||||
Err(type_error("unreachable"))
|
||||
// Dummy value, this result will be discarded because an error was thrown.
|
||||
Ok(ZeroCopyBuf::empty())
|
||||
} else if let Some(true) = ret {
|
||||
let vector = value_serializer.release();
|
||||
Ok(vector.into())
|
||||
|
|
|
@ -150,6 +150,7 @@ pub type CompiledWasmModuleStore = CrossIsolateStore<v8::CompiledWasmModule>;
|
|||
#[derive(Default)]
|
||||
pub(crate) struct ContextState {
|
||||
js_recv_cb: Option<v8::Global<v8::Function>>,
|
||||
pub(crate) js_build_custom_error_cb: Option<v8::Global<v8::Function>>,
|
||||
// TODO(andreubotella): Move the rest of Option<Global<Function>> fields from
|
||||
// JsRuntimeState to this struct.
|
||||
pub(crate) unrefed_ops: HashSet<i32>,
|
||||
|
@ -653,16 +654,25 @@ impl JsRuntime {
|
|||
|
||||
/// Grabs a reference to core.js' opresolve & syncOpsCache()
|
||||
fn init_cbs(&mut self, realm: &JsRealm) {
|
||||
let recv_cb = {
|
||||
let (recv_cb, build_custom_error_cb) = {
|
||||
let scope = &mut realm.handle_scope(self.v8_isolate());
|
||||
let recv_cb =
|
||||
Self::grab_global::<v8::Function>(scope, "Deno.core.opresolve")
|
||||
.expect("Deno.core.opresolve is undefined in the realm");
|
||||
v8::Global::new(scope, recv_cb)
|
||||
let recv_cb = v8::Global::new(scope, recv_cb);
|
||||
let build_custom_error_cb =
|
||||
Self::grab_global::<v8::Function>(scope, "Deno.core.buildCustomError")
|
||||
.expect("Deno.core.buildCustomError is undefined in the realm");
|
||||
let build_custom_error_cb = v8::Global::new(scope, build_custom_error_cb);
|
||||
(recv_cb, build_custom_error_cb)
|
||||
};
|
||||
// Put global handle in callback state
|
||||
let state = realm.state(self.v8_isolate());
|
||||
state.borrow_mut().js_recv_cb.replace(recv_cb);
|
||||
state
|
||||
.borrow_mut()
|
||||
.js_build_custom_error_cb
|
||||
.replace(build_custom_error_cb);
|
||||
}
|
||||
|
||||
/// Returns the runtime's op state, which can be used to maintain ops
|
||||
|
@ -737,6 +747,9 @@ impl JsRuntime {
|
|||
let realm = JsRealm::new(context.clone());
|
||||
let realm_state = realm.state(self.v8_isolate());
|
||||
std::mem::take(&mut realm_state.borrow_mut().js_recv_cb);
|
||||
std::mem::take(
|
||||
&mut realm_state.borrow_mut().js_build_custom_error_cb,
|
||||
);
|
||||
context
|
||||
.open(self.v8_isolate())
|
||||
.clear_all_slots(self.v8_isolate());
|
||||
|
|
|
@ -399,8 +399,8 @@ fn codegen_sync_ret(
|
|||
#ok_block
|
||||
},
|
||||
Err(err) => {
|
||||
let err = #core::OpError::new(op_state.get_error_class_fn, err);
|
||||
rv.set(#core::serde_v8::to_v8(scope, err).unwrap());
|
||||
let exception = #core::error::to_v8_error(scope, op_state.get_error_class_fn, &err);
|
||||
scope.throw_exception(exception);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue