1
0
Fork 0
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:
Nayeem Rahman 2022-08-11 10:57:20 +01:00 committed by GitHub
parent 321a42d1fb
commit 25a1cc1b28
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 7 deletions

View file

@ -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,

View file

@ -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.

View file

@ -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())

View file

@ -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());

View file

@ -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);
},
};
}