summaryrefslogtreecommitdiff
path: root/core/runtime/jsruntime.rs
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2023-06-14 10:45:59 -0600
committerGitHub <noreply@github.com>2023-06-14 16:45:59 +0000
commit88e6e9c1e6263f326d30b7fcc33465e0428faf33 (patch)
tree956e60abea884d89e4c76cc792e2b3159317278e /core/runtime/jsruntime.rs
parentcd27757184e683575c2540f73a96dc96e268943a (diff)
refactor(core): some runtime methods should live on the module map (#19502)
A few easy migrations of module code from the runtime to the module map. The module map already has a few places where it needs a handle scope, so we're not coupling it any further with the v8 runtime. `init_runtime_module_map` is replaced with an option to reduce API surface of JsRuntime. `module_resolve_callback` now lives in the `ModuleMap` and we use a annex data to avoid having to go through the `Rc<RefCell<...>>` stored in the `JsRuntime`'s isolate.
Diffstat (limited to 'core/runtime/jsruntime.rs')
-rw-r--r--core/runtime/jsruntime.rs153
1 files changed, 25 insertions, 128 deletions
diff --git a/core/runtime/jsruntime.rs b/core/runtime/jsruntime.rs
index 3b41a90f1..2e473e7c9 100644
--- a/core/runtime/jsruntime.rs
+++ b/core/runtime/jsruntime.rs
@@ -21,14 +21,12 @@ use crate::modules::ModuleId;
use crate::modules::ModuleLoadId;
use crate::modules::ModuleLoader;
use crate::modules::ModuleMap;
-use crate::modules::ModuleName;
use crate::ops::*;
use crate::runtime::ContextState;
use crate::runtime::JsRealm;
use crate::source_map::SourceMapCache;
use crate::source_map::SourceMapGetter;
use crate::Extension;
-use crate::ModuleType;
use crate::NoopModuleLoader;
use crate::OpMiddlewareFn;
use crate::OpResult;
@@ -391,6 +389,11 @@ pub struct RuntimeOptions {
/// JavaScript sources in the extensions.
pub extensions: Vec<Extension>,
+ /// If provided, the module map will be cleared and left only with the specifiers
+ /// in this list, with the new names provided. If not provided, the module map is
+ /// left intact.
+ pub rename_modules: Option<Vec<(&'static str, &'static str)>>,
+
/// V8 snapshot that should be loaded on startup.
pub startup_snapshot: Option<Snapshot>,
@@ -694,6 +697,15 @@ impl JsRuntime {
js_runtime
.init_extension_js(&realm, maybe_load_callback)
.unwrap();
+
+ // If the user has requested that we rename modules
+ if let Some(rename_modules) = options.rename_modules {
+ js_runtime
+ .module_map
+ .borrow_mut()
+ .clear_module_map(rename_modules.into_iter());
+ }
+
js_runtime
}
@@ -1143,31 +1155,11 @@ impl JsRuntime {
&mut self,
module_id: ModuleId,
) -> Result<v8::Global<v8::Object>, Error> {
- let module_handle = self
+ self
.module_map
+ .clone()
.borrow()
- .get_handle(module_id)
- .expect("ModuleInfo not found");
-
- let scope = &mut self.handle_scope();
-
- let module = module_handle.open(scope);
-
- if module.get_status() == v8::ModuleStatus::Errored {
- let exception = module.get_exception();
- return exception_to_err_result(scope, exception, false);
- }
-
- assert!(matches!(
- module.get_status(),
- v8::ModuleStatus::Instantiated | v8::ModuleStatus::Evaluated
- ));
-
- let module_namespace: v8::Local<v8::Object> =
- v8::Local::try_from(module.get_module_namespace())
- .map_err(|err: v8::DataError| generic_error(err.to_string()))?;
-
- Ok(v8::Global::new(scope, module_namespace))
+ .get_module_namespace(&mut self.handle_scope(), module_id)
}
/// Registers a callback on the isolate when the memory limits are approached.
@@ -1323,6 +1315,7 @@ impl JsRuntime {
let _ = self.inspector().borrow().poll_sessions(Some(cx)).unwrap();
}
+ let module_map = self.module_map.clone();
self.pump_v8_message_loop()?;
// Dynamic module loading - ie. modules loaded using "import()"
@@ -1426,7 +1419,7 @@ impl JsRuntime {
// pass, will be polled again
} else {
let scope = &mut self.handle_scope();
- let messages = find_stalled_top_level_await(scope);
+ let messages = module_map.borrow().find_stalled_top_level_await(scope);
// We are gonna print only a single message to provide a nice formatting
// with source line of offending promise shown. Once user fixed it, then
// they will get another error message for the next promise (but this
@@ -1448,7 +1441,7 @@ impl JsRuntime {
} else if self.inner.state.borrow().dyn_module_evaluate_idle_counter >= 1
{
let scope = &mut self.handle_scope();
- let messages = find_stalled_top_level_await(scope);
+ let messages = module_map.borrow().find_stalled_top_level_await(scope);
// We are gonna print only a single message to provide a nice formatting
// with source line of offending promise shown. Once user fixed it, then
// they will get another error message for the next promise (but this
@@ -1537,58 +1530,6 @@ impl JsRuntimeForSnapshot {
}
}
-fn get_stalled_top_level_await_message_for_module(
- scope: &mut v8::HandleScope,
- module_id: ModuleId,
-) -> Vec<v8::Global<v8::Message>> {
- let module_map = JsRuntime::module_map_from(scope);
- let module_map = module_map.borrow();
- let module_handle = module_map.handles.get(module_id).unwrap();
-
- let module = v8::Local::new(scope, module_handle);
- let stalled = module.get_stalled_top_level_await_message(scope);
- let mut messages = vec![];
- for (_, message) in stalled {
- messages.push(v8::Global::new(scope, message));
- }
- messages
-}
-
-fn find_stalled_top_level_await(
- scope: &mut v8::HandleScope,
-) -> Vec<v8::Global<v8::Message>> {
- let module_map = JsRuntime::module_map_from(scope);
- let module_map = module_map.borrow();
-
- // First check if that's root module
- let root_module_id = module_map
- .info
- .iter()
- .filter(|m| m.main)
- .map(|m| m.id)
- .next();
-
- if let Some(root_module_id) = root_module_id {
- let messages =
- get_stalled_top_level_await_message_for_module(scope, root_module_id);
- if !messages.is_empty() {
- return messages;
- }
- }
-
- // It wasn't a top module, so iterate over all modules and try to find
- // any with stalled top level await
- for module_id in 0..module_map.handles.len() {
- let messages =
- get_stalled_top_level_await_message_for_module(scope, module_id);
- if !messages.is_empty() {
- return messages;
- }
- }
-
- unreachable!()
-}
-
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) struct EventLoopPendingState {
has_pending_refed_ops: bool,
@@ -1666,32 +1607,11 @@ impl JsRuntime {
&mut self,
id: ModuleId,
) -> Result<(), v8::Global<v8::Value>> {
- let module_map_rc = self.module_map.clone();
- let scope = &mut self.handle_scope();
- let tc_scope = &mut v8::TryCatch::new(scope);
-
- let module = module_map_rc
- .borrow()
- .get_handle(id)
- .map(|handle| v8::Local::new(tc_scope, handle))
- .expect("ModuleInfo not found");
-
- if module.get_status() == v8::ModuleStatus::Errored {
- return Err(v8::Global::new(tc_scope, module.get_exception()));
- }
-
- // IMPORTANT: No borrows to `ModuleMap` can be held at this point because
- // `module_resolve_callback` will be calling into `ModuleMap` from within
- // the isolate.
- let instantiate_result =
- module.instantiate_module(tc_scope, bindings::module_resolve_callback);
-
- if instantiate_result.is_none() {
- let exception = tc_scope.exception().unwrap();
- return Err(v8::Global::new(tc_scope, exception));
- }
-
- Ok(())
+ self
+ .module_map
+ .clone()
+ .borrow_mut()
+ .instantiate_module(&mut self.handle_scope(), id)
}
fn dynamic_import_module_evaluate(
@@ -1903,29 +1823,6 @@ impl JsRuntime {
receiver
}
- /// Clear the module map, meant to be used after initializing extensions.
- /// Optionally pass a list of exceptions `(old_name, new_name)` representing
- /// specifiers which will be renamed and preserved in the module map.
- pub fn clear_module_map(
- &self,
- exceptions: impl Iterator<Item = (&'static str, &'static str)>,
- ) {
- let mut module_map = self.module_map.borrow_mut();
- let handles = exceptions
- .map(|(old_name, new_name)| {
- (module_map.get_handle_by_name(old_name).unwrap(), new_name)
- })
- .collect::<Vec<_>>();
- module_map.clear();
- for (handle, new_name) in handles {
- module_map.inject_handle(
- ModuleName::from_static(new_name),
- ModuleType::JavaScript,
- handle,
- )
- }
- }
-
fn dynamic_import_reject(
&mut self,
id: ModuleLoadId,