Skip to content

Commit

Permalink
refactor: use v8::OneByteConst (denoland#531)
Browse files Browse the repository at this point in the history
  • Loading branch information
bartlomieju authored Feb 1, 2024
1 parent 8c3dc51 commit 8c19f5e
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 54 deletions.
122 changes: 76 additions & 46 deletions core/runtime/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub fn script_origin<'a>(
pub(crate) fn get<'s, T>(
scope: &mut v8::HandleScope<'s>,
from: v8::Local<v8::Object>,
key: &'static [u8],
key: &'static v8::OneByteConst,
path: &'static str,
) -> T
where
Expand All @@ -132,32 +132,49 @@ where

pub mod v8_static_strings {
pub fn new<'s>(
scope: &mut v8::HandleScope<'s>,
str_: &'static v8::OneByteConst,
) -> v8::Local<'s, v8::String> {
v8::String::new_from_onebyte_const(scope, str_).unwrap()
}

pub fn new_from_static_str<'s>(
scope: &mut v8::HandleScope<'s>,
str_: &'static [u8],
) -> v8::Local<'s, v8::String> {
v8::String::new_external_onebyte_static(scope, str_).unwrap()
}

pub static DENO: &[u8] = b"Deno";
pub static CORE: &[u8] = b"core";
pub static OPS: &[u8] = b"ops";
pub static URL: &[u8] = b"url";
pub static MAIN: &[u8] = b"main";
pub static RESOLVE: &[u8] = b"resolve";
pub static MESSAGE: &[u8] = b"message";
pub static CODE: &[u8] = b"code";
pub static ERR_MODULE_NOT_FOUND: &[u8] = b"ERR_MODULE_NOT_FOUND";
pub static EVENT_LOOP_TICK: &[u8] = b"eventLoopTick";
pub static BUILD_CUSTOM_ERROR: &[u8] = b"buildCustomError";
pub static CONSOLE: &[u8] = b"console";
pub static CALL_CONSOLE: &[u8] = b"callConsole";
pub static FILENAME: &[u8] = b"filename";
pub static DIRNAME: &[u8] = b"dirname";
pub static SET_UP_ASYNC_STUB: &[u8] = b"setUpAsyncStub";
pub static WEBASSEMBLY: &[u8] = b"WebAssembly";
pub static MODULE: &[u8] = b"Module";
pub static IMPORTS: &[u8] = b"imports";
pub static EXPORTS: &[u8] = b"exports";
macro_rules! onebyte_const {
($str_:literal) => {
v8::String::create_external_onebyte_const($str_.as_bytes())
};
}

pub static DENO: v8::OneByteConst = onebyte_const!("Deno");
pub static CORE: v8::OneByteConst = onebyte_const!("core");
pub static OPS: v8::OneByteConst = onebyte_const!("ops");
pub static URL: v8::OneByteConst = onebyte_const!("url");
pub static MAIN: v8::OneByteConst = onebyte_const!("main");
pub static RESOLVE: v8::OneByteConst = onebyte_const!("resolve");
pub static MESSAGE: v8::OneByteConst = onebyte_const!("message");
pub static CODE: v8::OneByteConst = onebyte_const!("code");
pub static ERR_MODULE_NOT_FOUND: v8::OneByteConst =
onebyte_const!("ERR_MODULE_NOT_FOUND");
pub static EVENT_LOOP_TICK: v8::OneByteConst =
onebyte_const!("eventLoopTick");
pub static BUILD_CUSTOM_ERROR: v8::OneByteConst =
onebyte_const!("buildCustomError");
pub static CONSOLE: v8::OneByteConst = onebyte_const!("console");
pub static CALL_CONSOLE: v8::OneByteConst = onebyte_const!("callConsole");
pub static FILENAME: v8::OneByteConst = onebyte_const!("filename");
pub static DIRNAME: v8::OneByteConst = onebyte_const!("dirname");
pub static SET_UP_ASYNC_STUB: v8::OneByteConst =
onebyte_const!("setUpAsyncStub");
pub static WEBASSEMBLY: v8::OneByteConst = onebyte_const!("WebAssembly");
pub static MODULE: v8::OneByteConst = onebyte_const!("Module");
pub static IMPORTS: v8::OneByteConst = onebyte_const!("imports");
pub static EXPORTS: v8::OneByteConst = onebyte_const!("exports");
}

/// Create an object on the `globalThis` that looks like this:
Expand All @@ -178,7 +195,7 @@ pub(crate) fn initialize_deno_core_namespace<'s>(
init_mode: InitMode,
) {
let global = context.global(scope);
let deno_str = v8_static_strings::new(scope, v8_static_strings::DENO);
let deno_str = v8_static_strings::new(scope, &v8_static_strings::DENO);

let maybe_deno_obj_val = global.get(scope, deno_str.into());

Expand All @@ -190,10 +207,11 @@ pub(crate) fn initialize_deno_core_namespace<'s>(
}

let deno_obj = v8::Object::new(scope);
let deno_core_key = v8_static_strings::new(scope, v8_static_strings::CORE);
let deno_core_key = v8_static_strings::new(scope, &v8_static_strings::CORE);
// Set up `Deno.core.ops` object
let deno_core_ops_obj = v8::Object::new(scope);
let deno_core_ops_key = v8_static_strings::new(scope, v8_static_strings::OPS);
let deno_core_ops_key =
v8_static_strings::new(scope, &v8_static_strings::OPS);

let deno_core_obj = v8::Object::new(scope);
deno_core_obj
Expand All @@ -205,18 +223,19 @@ pub(crate) fn initialize_deno_core_namespace<'s>(
// Bind `call_console` to Deno.core.callConsole
let call_console_fn = v8::Function::new(scope, call_console).unwrap();
let call_console_key =
v8_static_strings::new(scope, v8_static_strings::CALL_CONSOLE);
v8_static_strings::new(scope, &v8_static_strings::CALL_CONSOLE);
deno_core_obj.set(scope, call_console_key.into(), call_console_fn.into());

// Bind v8 console object to Deno.core.console
let extra_binding_obj = context.get_extras_binding_object(scope);
let console_obj: v8::Local<v8::Object> = get(
scope,
extra_binding_obj,
v8_static_strings::CONSOLE,
&v8_static_strings::CONSOLE,
"ExtrasBindingObject.console",
);
let console_key = v8_static_strings::new(scope, v8_static_strings::CONSOLE);
let console_key =
v8_static_strings::new(scope, &v8_static_strings::CONSOLE);
deno_core_obj.set(scope, console_key.into(), console_obj.into());
}

Expand All @@ -232,7 +251,10 @@ pub(crate) fn initialize_primordials_and_infra(
for file_source in CONTEXT_SETUP_SOURCES {
let code = file_source.load().unwrap();
let source_str = code.v8_string(scope).unwrap();
let name = v8_static_strings::new(scope, file_source.specifier.as_bytes());
let name = v8_static_strings::new_from_static_str(
scope,
file_source.specifier.as_bytes(),
);
let origin = script_origin(scope, name);
// TODO(bartlomieju): these two calls will panic if there's any problem in the JS code
let script = v8::Script::compile(scope, source_str, Some(&origin))
Expand All @@ -255,26 +277,29 @@ pub(crate) fn initialize_deno_core_ops_bindings<'s>(
// Set up JavaScript bindings for the defined op - this will insert proper
// `v8::Function` into `Deno.core.ops` object. For async ops, there a bit
// more machinery involved, see comment below.
let deno_obj = get(scope, global, v8_static_strings::DENO, "Deno");
let deno_obj = get(scope, global, &v8_static_strings::DENO, "Deno");
let deno_core_obj =
get(scope, deno_obj, v8_static_strings::CORE, "Deno.core");
get(scope, deno_obj, &v8_static_strings::CORE, "Deno.core");
let deno_core_ops_obj: v8::Local<v8::Object> = get(
scope,
deno_core_obj,
v8_static_strings::OPS,
&v8_static_strings::OPS,
"Deno.core.ops",
);
let set_up_async_stub_fn: v8::Local<v8::Function> = get(
scope,
deno_core_obj,
v8_static_strings::SET_UP_ASYNC_STUB,
&v8_static_strings::SET_UP_ASYNC_STUB,
"Deno.core.setUpAsyncStub",
);

let undefined = v8::undefined(scope);
for op_ctx in op_ctxs {
let mut op_fn = op_ctx_function(scope, op_ctx);
let key = v8_static_strings::new(scope, op_ctx.decl.name.as_bytes());
let key = v8_static_strings::new_from_static_str(
scope,
op_ctx.decl.name.as_bytes(),
);

// For async ops we need to set them up, by calling `Deno.core.setUpAsyncStub` -
// this call will generate an optimized function that binds to the provided
Expand All @@ -296,7 +321,8 @@ fn op_ctx_function<'s>(
) -> v8::Local<'s, v8::Function> {
let op_ctx_ptr = op_ctx as *const OpCtx as *const c_void;
let external = v8::External::new(scope, op_ctx_ptr as *mut c_void);
let v8name = v8_static_strings::new(scope, op_ctx.decl.name.as_bytes());
let v8name =
v8_static_strings::new_from_static_str(scope, op_ctx.decl.name.as_bytes());

let (slow_fn, fast_fn) = if op_ctx.metrics_enabled() {
(
Expand Down Expand Up @@ -436,19 +462,19 @@ pub extern "C" fn host_initialize_import_meta_object_callback(
.get_name_by_module(&module_global)
.expect("Module not found");

let url_key = v8_static_strings::new(scope, v8_static_strings::URL);
let url_key = v8_static_strings::new(scope, &v8_static_strings::URL);
let url_val = v8::String::new(scope, &name).unwrap();
meta.create_data_property(scope, url_key.into(), url_val.into());

let main_key = v8_static_strings::new(scope, v8_static_strings::MAIN);
let main_key = v8_static_strings::new(scope, &v8_static_strings::MAIN);
let main = module_map.is_main_module(&module_global);
let main_val = v8::Boolean::new(scope, main);
meta.create_data_property(scope, main_key.into(), main_val.into());

let builder =
v8::FunctionBuilder::new(import_meta_resolve).data(url_val.into());
let val = v8::FunctionBuilder::<v8::Function>::build(builder, scope).unwrap();
let resolve_key = v8_static_strings::new(scope, v8_static_strings::RESOLVE);
let resolve_key = v8_static_strings::new(scope, &v8_static_strings::RESOLVE);
meta.set(scope, resolve_key.into(), val.into());

maybe_add_import_meta_filename_dirname(scope, meta, &name);
Expand Down Expand Up @@ -480,7 +506,8 @@ fn maybe_add_import_meta_filename_dirname(
let Some(filename_val) = v8::String::new(scope, &escaped_filename) else {
return;
};
let filename_key = v8_static_strings::new(scope, v8_static_strings::FILENAME);
let filename_key =
v8_static_strings::new(scope, &v8_static_strings::FILENAME);
meta.create_data_property(scope, filename_key.into(), filename_val.into());

let dir_path = file_path
Expand All @@ -491,7 +518,7 @@ fn maybe_add_import_meta_filename_dirname(
let Some(dirname_val) = v8::String::new(scope, &escaped_dirname) else {
return;
};
let dirname_key = v8_static_strings::new(scope, v8_static_strings::DIRNAME);
let dirname_key = v8_static_strings::new(scope, &v8_static_strings::DIRNAME);
meta.create_data_property(scope, dirname_key.into(), dirname_val.into());
}

Expand Down Expand Up @@ -573,7 +600,7 @@ fn catch_dynamic_import_promise_error(
let msg = v8::Exception::create_message(scope, arg);
let arg: v8::Local<v8::Object> = arg.try_into().unwrap();
let message_key =
v8_static_strings::new(scope, v8_static_strings::MESSAGE);
v8_static_strings::new(scope, &v8_static_strings::MESSAGE);
let message = arg.get(scope, message_key.into()).unwrap();
let mut message: v8::Local<v8::String> = message.try_into().unwrap();
if let Some(stack_frame) = JsStackFrame::from_v8_message(scope, msg) {
Expand All @@ -590,9 +617,9 @@ fn catch_dynamic_import_promise_error(
"ReferenceError" => v8::Exception::reference_error(scope, message),
_ => v8::Exception::error(scope, message),
};
let code_key = v8_static_strings::new(scope, v8_static_strings::CODE);
let code_key = v8_static_strings::new(scope, &v8_static_strings::CODE);
let code_value =
v8_static_strings::new(scope, v8_static_strings::ERR_MODULE_NOT_FOUND);
v8_static_strings::new(scope, &v8_static_strings::ERR_MODULE_NOT_FOUND);
let exception_obj = exception.to_object(scope).unwrap();
exception_obj.set(scope, code_key.into(), code_value.into());
scope.throw_exception(exception);
Expand Down Expand Up @@ -738,20 +765,23 @@ pub fn create_exports_for_ops_virtual_module<'s>(
) -> Vec<(FastString, v8::Local<'s, v8::Value>)> {
let mut exports = Vec::with_capacity(op_ctxs.len());

let deno_obj = get(scope, global, v8_static_strings::DENO, "Deno");
let deno_obj = get(scope, global, &v8_static_strings::DENO, "Deno");
let deno_core_obj =
get(scope, deno_obj, v8_static_strings::CORE, "Deno.core");
get(scope, deno_obj, &v8_static_strings::CORE, "Deno.core");
let set_up_async_stub_fn: v8::Local<v8::Function> = get(
scope,
deno_core_obj,
v8_static_strings::SET_UP_ASYNC_STUB,
&v8_static_strings::SET_UP_ASYNC_STUB,
"Deno.core.setUpAsyncStub",
);

let undefined = v8::undefined(scope);

for op_ctx in op_ctxs {
let name = v8_static_strings::new(scope, op_ctx.decl.name.as_bytes());
let name = v8_static_strings::new_from_static_str(
scope,
op_ctx.decl.name.as_bytes(),
);
let mut op_fn = op_ctx_function(scope, op_ctx);

// For async ops we need to set them up, by calling `Deno.core.setUpAsyncStub` -
Expand Down
16 changes: 8 additions & 8 deletions core/runtime/jsruntime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1125,20 +1125,20 @@ impl JsRuntime {
// TODO(bartlomieju): these probably could be captured from main realm so we don't have to
// look up them again?
let deno_obj: v8::Local<v8::Object> =
bindings::get(scope, global, v8_static_strings::DENO, "Deno");
bindings::get(scope, global, &v8_static_strings::DENO, "Deno");
let core_obj: v8::Local<v8::Object> =
bindings::get(scope, deno_obj, v8_static_strings::CORE, "Deno.core");
bindings::get(scope, deno_obj, &v8_static_strings::CORE, "Deno.core");

let event_loop_tick_cb: v8::Local<v8::Function> = bindings::get(
scope,
core_obj,
v8_static_strings::EVENT_LOOP_TICK,
&v8_static_strings::EVENT_LOOP_TICK,
"Deno.core.eventLoopTick",
);
let build_custom_error_cb: v8::Local<v8::Function> = bindings::get(
scope,
core_obj,
v8_static_strings::BUILD_CUSTOM_ERROR,
&v8_static_strings::BUILD_CUSTOM_ERROR,
"Deno.core.buildCustomError",
);

Expand All @@ -1149,27 +1149,27 @@ impl JsRuntime {
let web_assembly_object: v8::Local<v8::Object> = bindings::get(
scope,
global,
v8_static_strings::WEBASSEMBLY,
&v8_static_strings::WEBASSEMBLY,
"WebAssembly",
);
let web_assembly_module_object: v8::Local<v8::Object> = bindings::get(
scope,
web_assembly_object,
v8_static_strings::MODULE,
&v8_static_strings::MODULE,
"WebAssembly.Module",
);
web_assembly_module_imports_fn =
Some(bindings::get::<v8::Local<v8::Function>>(
scope,
web_assembly_module_object,
v8_static_strings::IMPORTS,
&v8_static_strings::IMPORTS,
"WebAssembly.Module.imports",
));
web_assembly_module_exports_fn =
Some(bindings::get::<v8::Local<v8::Function>>(
scope,
web_assembly_module_object,
v8_static_strings::EXPORTS,
&v8_static_strings::EXPORTS,
"WebAssembly.Module.exports",
));
}
Expand Down

0 comments on commit 8c19f5e

Please sign in to comment.