1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-06 14:26:02 -05:00

refactor: cleanup ModuleMap (#17469)

- changes module id to be usize & 0 based instead of 1 based
- merges `ids_by_handle` & `handles_by_id` to be a single `handles`
vector
- removes `next_module_id`, as vector is used
- turns `info` into a vector
This commit is contained in:
Leo Kettmeir 2023-01-19 13:47:41 +01:00 committed by GitHub
parent 8dbf7d7866
commit f85b006628
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 112 deletions

View file

@ -26,7 +26,7 @@ use std::rc::Rc;
use std::task::Context; use std::task::Context;
use std::task::Poll; use std::task::Poll;
pub type ModuleId = i32; pub type ModuleId = usize;
pub(crate) type ModuleLoadId = i32; pub(crate) type ModuleLoadId = i32;
pub const BOM_CHAR: &[u8] = &[0xef, 0xbb, 0xbf]; pub const BOM_CHAR: &[u8] = &[0xef, 0xbb, 0xbf];
@ -453,7 +453,7 @@ impl RecursiveModuleLoad {
load.root_module_type = Some( load.root_module_type = Some(
module_map_rc module_map_rc
.borrow() .borrow()
.get_info_by_id(&module_id) .get_info_by_id(module_id)
.unwrap() .unwrap()
.module_type, .module_type,
); );
@ -787,11 +787,9 @@ pub(crate) enum ModuleError {
/// A collection of JS modules. /// A collection of JS modules.
pub(crate) struct ModuleMap { pub(crate) struct ModuleMap {
// Handling of specifiers and v8 objects // Handling of specifiers and v8 objects
pub(crate) ids_by_handle: HashMap<v8::Global<v8::Module>, ModuleId>, pub handles: Vec<v8::Global<v8::Module>>,
pub handles_by_id: HashMap<ModuleId, v8::Global<v8::Module>>, pub info: Vec<ModuleInfo>,
pub info: HashMap<ModuleId, ModuleInfo>,
pub(crate) by_name: HashMap<(String, AssertedModuleType), SymbolicModule>, pub(crate) by_name: HashMap<(String, AssertedModuleType), SymbolicModule>,
pub(crate) next_module_id: ModuleId,
pub(crate) next_load_id: ModuleLoadId, pub(crate) next_load_id: ModuleLoadId,
// Handling of futures for loading module sources // Handling of futures for loading module sources
@ -816,22 +814,13 @@ impl ModuleMap {
) -> (v8::Global<v8::Object>, Vec<v8::Global<v8::Module>>) { ) -> (v8::Global<v8::Object>, Vec<v8::Global<v8::Module>>) {
let obj = v8::Object::new(scope); let obj = v8::Object::new(scope);
let next_module_id_str = v8::String::new(scope, "next_module_id").unwrap();
let next_module_id = v8::Integer::new(scope, self.next_module_id);
obj.set(scope, next_module_id_str.into(), next_module_id.into());
let next_load_id_str = v8::String::new(scope, "next_load_id").unwrap(); let next_load_id_str = v8::String::new(scope, "next_load_id").unwrap();
let next_load_id = v8::Integer::new(scope, self.next_load_id); let next_load_id = v8::Integer::new(scope, self.next_load_id);
obj.set(scope, next_load_id_str.into(), next_load_id.into()); obj.set(scope, next_load_id_str.into(), next_load_id.into());
let info_obj = v8::Object::new(scope); let info_val = serde_v8::to_v8(scope, self.info.clone()).unwrap();
for (key, value) in self.info.clone().into_iter() {
let key_val = v8::Integer::new(scope, key);
let module_info = serde_v8::to_v8(scope, value).unwrap();
info_obj.set(scope, key_val.into(), module_info);
}
let info_str = v8::String::new(scope, "info").unwrap(); let info_str = v8::String::new(scope, "info").unwrap();
obj.set(scope, info_str.into(), info_obj.into()); obj.set(scope, info_str.into(), info_val);
let by_name_triples: Vec<(String, AssertedModuleType, SymbolicModule)> = let by_name_triples: Vec<(String, AssertedModuleType, SymbolicModule)> =
self self
@ -846,13 +835,7 @@ impl ModuleMap {
let obj_global = v8::Global::new(scope, obj); let obj_global = v8::Global::new(scope, obj);
let mut handles_and_ids: Vec<(ModuleId, v8::Global<v8::Module>)> = let handles = self.handles.clone();
self.handles_by_id.clone().into_iter().collect();
handles_and_ids.sort_by_key(|(id, _)| *id);
let handles: Vec<v8::Global<v8::Module>> = handles_and_ids
.into_iter()
.map(|(_, handle)| handle)
.collect();
(obj_global, handles) (obj_global, handles)
} }
@ -864,17 +847,6 @@ impl ModuleMap {
) { ) {
let local_data: v8::Local<v8::Object> = v8::Local::new(scope, data); let local_data: v8::Local<v8::Object> = v8::Local::new(scope, data);
{
let next_module_id_str =
v8::String::new(scope, "next_module_id").unwrap();
let next_module_id =
local_data.get(scope, next_module_id_str.into()).unwrap();
assert!(next_module_id.is_int32());
let integer = next_module_id.to_integer(scope).unwrap();
let val = integer.int32_value(scope).unwrap();
self.next_module_id = val;
}
{ {
let next_load_id_str = v8::String::new(scope, "next_load_id").unwrap(); let next_load_id_str = v8::String::new(scope, "next_load_id").unwrap();
let next_load_id = let next_load_id =
@ -886,27 +858,9 @@ impl ModuleMap {
} }
{ {
let mut info = HashMap::new();
let info_str = v8::String::new(scope, "info").unwrap(); let info_str = v8::String::new(scope, "info").unwrap();
let info_data: v8::Local<v8::Object> = local_data let info_val = local_data.get(scope, info_str.into()).unwrap();
.get(scope, info_str.into()) self.info = serde_v8::from_v8(scope, info_val).unwrap();
.unwrap()
.try_into()
.unwrap();
let keys = info_data
.get_own_property_names(scope, v8::GetPropertyNamesArgs::default())
.unwrap();
let keys_len = keys.length();
for i in 0..keys_len {
let key = keys.get_index(scope, i).unwrap();
let key_val = key.to_integer(scope).unwrap();
let key_int = key_val.int32_value(scope).unwrap();
let value = info_data.get(scope, key).unwrap();
let module_info = serde_v8::from_v8(scope, value).unwrap();
info.insert(key_int, module_info);
}
self.info = info;
} }
{ {
@ -922,17 +876,7 @@ impl ModuleMap {
.collect(); .collect();
} }
self.ids_by_handle = module_handles self.handles = module_handles;
.iter()
.enumerate()
.map(|(index, handle)| (handle.clone(), (index + 1) as i32))
.collect();
self.handles_by_id = module_handles
.iter()
.enumerate()
.map(|(index, handle)| ((index + 1) as i32, handle.clone()))
.collect();
} }
pub(crate) fn new( pub(crate) fn new(
@ -940,11 +884,9 @@ impl ModuleMap {
op_state: Rc<RefCell<OpState>>, op_state: Rc<RefCell<OpState>>,
) -> ModuleMap { ) -> ModuleMap {
Self { Self {
ids_by_handle: HashMap::new(), handles: vec![],
handles_by_id: HashMap::new(), info: vec![],
info: HashMap::new(),
by_name: HashMap::new(), by_name: HashMap::new(),
next_module_id: 1,
next_load_id: 1, next_load_id: 1,
loader, loader,
op_state, op_state,
@ -1100,7 +1042,7 @@ impl ModuleMap {
} }
if main { if main {
let maybe_main_module = self.info.values().find(|module| module.main); let maybe_main_module = self.info.iter().find(|module| module.main);
if let Some(main_module) = maybe_main_module { if let Some(main_module) = maybe_main_module {
return Err(ModuleError::Other(generic_error( return Err(ModuleError::Other(generic_error(
format!("Trying to create \"main\" module ({:?}), when one already exists ({:?})", format!("Trying to create \"main\" module ({:?}), when one already exists ({:?})",
@ -1130,30 +1072,25 @@ impl ModuleMap {
main: bool, main: bool,
requests: Vec<ModuleRequest>, requests: Vec<ModuleRequest>,
) -> ModuleId { ) -> ModuleId {
let id = self.next_module_id; let id = self.handles.len();
self.next_module_id += 1;
self.by_name.insert( self.by_name.insert(
(name.to_string(), module_type.into()), (name.to_string(), module_type.into()),
SymbolicModule::Mod(id), SymbolicModule::Mod(id),
); );
self.handles_by_id.insert(id, handle.clone()); self.handles.push(handle);
self.ids_by_handle.insert(handle, id); self.info.push(ModuleInfo {
self.info.insert(
id, id,
ModuleInfo { main,
id, name: name.to_string(),
main, requests,
name: name.to_string(), module_type,
requests, });
module_type,
},
);
id id
} }
fn get_requested_modules(&self, id: ModuleId) -> Option<&Vec<ModuleRequest>> { fn get_requested_modules(&self, id: ModuleId) -> Option<&Vec<ModuleRequest>> {
self.info.get(&id).map(|i| &i.requests) self.info.get(id).map(|i| &i.requests)
} }
fn is_registered( fn is_registered(
@ -1162,7 +1099,7 @@ impl ModuleMap {
asserted_module_type: AssertedModuleType, asserted_module_type: AssertedModuleType,
) -> bool { ) -> bool {
if let Some(id) = self.get_id(specifier.as_str(), asserted_module_type) { if let Some(id) = self.get_id(specifier.as_str(), asserted_module_type) {
let info = self.get_info_by_id(&id).unwrap(); let info = self.get_info_by_id(id).unwrap();
return asserted_module_type == info.module_type.into(); return asserted_module_type == info.module_type.into();
} }
@ -1195,21 +1132,21 @@ impl ModuleMap {
&self, &self,
id: ModuleId, id: ModuleId,
) -> Option<v8::Global<v8::Module>> { ) -> Option<v8::Global<v8::Module>> {
self.handles_by_id.get(&id).cloned() self.handles.get(id).cloned()
} }
pub(crate) fn get_info( pub(crate) fn get_info(
&self, &self,
global: &v8::Global<v8::Module>, global: &v8::Global<v8::Module>,
) -> Option<&ModuleInfo> { ) -> Option<&ModuleInfo> {
if let Some(id) = self.ids_by_handle.get(global) { if let Some(id) = self.handles.iter().position(|module| module == global) {
return self.info.get(id); return self.info.get(id);
} }
None None
} }
pub(crate) fn get_info_by_id(&self, id: &ModuleId) -> Option<&ModuleInfo> { pub(crate) fn get_info_by_id(&self, id: ModuleId) -> Option<&ModuleInfo> {
self.info.get(id) self.info.get(id)
} }

View file

@ -453,17 +453,16 @@ impl JsRuntime {
match scope.get_context_data_from_snapshot_once::<v8::Object>(0) { match scope.get_context_data_from_snapshot_once::<v8::Object>(0) {
Ok(val) => { Ok(val) => {
let next_module_id = { let next_module_id = {
let next_module_id_str = let info_str = v8::String::new(&mut scope, "info").unwrap();
v8::String::new(&mut scope, "next_module_id").unwrap(); let info_data: v8::Local<v8::Array> = val
let next_module_id = .get(&mut scope, info_str.into())
val.get(&mut scope, next_module_id_str.into()).unwrap(); .unwrap()
assert!(next_module_id.is_int32()); .try_into()
let integer = next_module_id.to_integer(&mut scope).unwrap(); .unwrap();
integer.int32_value(&mut scope).unwrap() info_data.length()
}; };
let no_of_modules = next_module_id - 1;
for i in 1..=no_of_modules { for i in 1..=next_module_id {
match scope match scope
.get_context_data_from_snapshot_once::<v8::Module>(i as usize) .get_context_data_from_snapshot_once::<v8::Module>(i as usize)
{ {
@ -1411,7 +1410,7 @@ fn get_stalled_top_level_await_message_for_module(
) -> Vec<v8::Global<v8::Message>> { ) -> Vec<v8::Global<v8::Message>> {
let module_map = JsRuntime::module_map(scope); let module_map = JsRuntime::module_map(scope);
let module_map = module_map.borrow(); let module_map = module_map.borrow();
let module_handle = module_map.handles_by_id.get(&module_id).unwrap(); let module_handle = module_map.handles.get(module_id).unwrap();
let module = v8::Local::new(scope, module_handle); let module = v8::Local::new(scope, module_handle);
let stalled = module.get_stalled_top_level_await_message(scope); let stalled = module.get_stalled_top_level_await_message(scope);
@ -1431,7 +1430,7 @@ fn find_stalled_top_level_await(
// First check if that's root module // First check if that's root module
let root_module_id = module_map let root_module_id = module_map
.info .info
.values() .iter()
.filter(|m| m.main) .filter(|m| m.main)
.map(|m| m.id) .map(|m| m.id)
.next(); .next();
@ -1446,8 +1445,7 @@ fn find_stalled_top_level_await(
// It wasn't a top module, so iterate over all modules and try to find // It wasn't a top module, so iterate over all modules and try to find
// any with stalled top level await // any with stalled top level await
let module_ids = module_map.handles_by_id.keys().copied().collect::<Vec<_>>(); for module_id in 0..module_map.handles.len() {
for module_id in module_ids {
let messages = let messages =
get_stalled_top_level_await_message_for_module(scope, module_id); get_stalled_top_level_await_message_for_module(scope, module_id);
if !messages.is_empty() { if !messages.is_empty() {
@ -3570,7 +3568,7 @@ pub mod tests {
) )
.unwrap() .unwrap()
}; };
assert_eq!(i + 1, id as usize); assert_eq!(i, id);
let _ = runtime.mod_evaluate(id); let _ = runtime.mod_evaluate(id);
futures::executor::block_on(runtime.run_event_loop(false)).unwrap(); futures::executor::block_on(runtime.run_event_loop(false)).unwrap();
@ -3590,20 +3588,15 @@ pub mod tests {
fn assert_module_map(runtime: &mut JsRuntime, modules: &Vec<ModuleInfo>) { fn assert_module_map(runtime: &mut JsRuntime, modules: &Vec<ModuleInfo>) {
let module_map_rc = runtime.get_module_map(); let module_map_rc = runtime.get_module_map();
let module_map = module_map_rc.borrow(); let module_map = module_map_rc.borrow();
assert_eq!(module_map.ids_by_handle.len(), modules.len()); assert_eq!(module_map.handles.len(), modules.len());
assert_eq!(module_map.handles_by_id.len(), modules.len());
assert_eq!(module_map.info.len(), modules.len()); assert_eq!(module_map.info.len(), modules.len());
assert_eq!(module_map.by_name.len(), modules.len()); assert_eq!(module_map.by_name.len(), modules.len());
assert_eq!(module_map.next_module_id, (modules.len() + 1) as ModuleId); assert_eq!(module_map.next_load_id, (modules.len() + 1) as ModuleLoadId);
assert_eq!(module_map.next_load_id, (modules.len() + 1) as ModuleId);
let ids_by_handle = module_map.ids_by_handle.values().collect::<Vec<_>>();
for info in modules { for info in modules {
assert!(ids_by_handle.contains(&&info.id)); assert!(module_map.handles.get(info.id).is_some());
assert!(module_map.handles_by_id.contains_key(&info.id)); assert_eq!(module_map.info.get(info.id).unwrap(), info);
assert_eq!(module_map.info.get(&info.id).unwrap(), info);
assert_eq!( assert_eq!(
module_map module_map
.by_name .by_name