diff --git a/core/modules.rs b/core/modules.rs index f1d4273e88409..b6220bb3bc6ac 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -161,6 +161,7 @@ fn json_module_evaluation_steps<'a>( /// the module against an import assertion (if one is present /// in the import statement). #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[repr(u32)] pub enum ModuleType { JavaScript, Json, @@ -774,7 +775,7 @@ impl RecursiveModuleLoad { self.visited.insert(module_request.clone()); while let Some((module_id, module_request)) = already_registered.pop_front() { - let referrer = module_request.specifier.clone(); + let referrer = ModuleSpecifier::parse(&module_request.specifier).unwrap(); let imports = self .module_map_rc .borrow() @@ -789,17 +790,15 @@ impl RecursiveModuleLoad { ) { already_registered.push_back((module_id, module_request.clone())); } else { - let referrer = referrer.clone(); let request = module_request.clone(); + let specifier = + ModuleSpecifier::parse(&module_request.specifier).unwrap(); + let referrer = referrer.clone(); let loader = self.loader.clone(); let is_dynamic_import = self.is_dynamic_import(); let fut = async move { let load_result = loader - .load( - &request.specifier, - Some(referrer.clone()), - is_dynamic_import, - ) + .load(&specifier, Some(referrer.clone()), is_dynamic_import) .await; load_result.map(|s| (request, s)) }; @@ -851,7 +850,7 @@ impl Stream for RecursiveModuleLoad { let asserted_module_type = inner.root_asserted_module_type.unwrap(); let module_type = inner.root_module_type.unwrap(); let module_request = ModuleRequest { - specifier: module_specifier.clone(), + specifier: module_specifier.to_string(), asserted_module_type, }; let module_source = ModuleSource { @@ -875,7 +874,7 @@ impl Stream for RecursiveModuleLoad { _ => AssertedModuleType::JavaScriptOrWasm, }; let module_request = ModuleRequest { - specifier: module_specifier.clone(), + specifier: module_specifier.to_string(), asserted_module_type, }; let loader = inner.loader.clone(); @@ -905,6 +904,7 @@ impl Stream for RecursiveModuleLoad { } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[repr(u32)] pub(crate) enum AssertedModuleType { JavaScriptOrWasm, Json, @@ -934,7 +934,7 @@ impl std::fmt::Display for AssertedModuleType { /// which case this will have a `AssertedModuleType::Json`. #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub(crate) struct ModuleRequest { - pub specifier: ModuleSpecifier, + pub specifier: String, pub asserted_module_type: AssertedModuleType, } @@ -995,46 +995,94 @@ impl ModuleMap { pub fn serialize_for_snapshotting( &self, scope: &mut v8::HandleScope, - ) -> (v8::Global, Vec>) { - let obj = v8::Object::new(scope); + ) -> (v8::Global, Vec>) { + let array = v8::Array::new(scope, 3); - 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); - obj.set(scope, next_load_id_str.into(), next_load_id.into()); + array.set_index(scope, 0, next_load_id.into()); - let info_val = serde_v8::to_v8(scope, self.info.clone()).unwrap(); - let info_str = v8::String::new(scope, "info").unwrap(); - obj.set(scope, info_str.into(), info_val); + let info_arr = v8::Array::new(scope, self.info.len() as i32); + for (i, info) in self.info.iter().enumerate() { + let module_info_arr = v8::Array::new(scope, 5); - let by_name_triples: Vec<(String, AssertedModuleType, SymbolicModule)> = - self - .by_name - .clone() - .into_iter() - .map(|el| (el.0 .0, el.0 .1, el.1)) - .collect(); - let by_name_array = serde_v8::to_v8(scope, by_name_triples).unwrap(); - let by_name_str = v8::String::new(scope, "by_name").unwrap(); - obj.set(scope, by_name_str.into(), by_name_array); + let id = v8::Integer::new(scope, info.id as i32); + module_info_arr.set_index(scope, 0, id.into()); + + let main = v8::Boolean::new(scope, info.main); + module_info_arr.set_index(scope, 1, main.into()); + + let name = v8::String::new(scope, &info.name).unwrap(); + module_info_arr.set_index(scope, 2, name.into()); + + let array_len = 2 * info.requests.len() as i32; + let requests_arr = v8::Array::new(scope, array_len); + for (i, request) in info.requests.iter().enumerate() { + let specifier = v8::String::new(scope, &request.specifier).unwrap(); + requests_arr.set_index(scope, 2 * i as u32, specifier.into()); + + let asserted_module_type = + v8::Integer::new(scope, request.asserted_module_type as i32); + requests_arr.set_index( + scope, + (2 * i) as u32 + 1, + asserted_module_type.into(), + ); + } + module_info_arr.set_index(scope, 3, requests_arr.into()); + + let module_type = v8::Integer::new(scope, info.module_type as i32); + module_info_arr.set_index(scope, 4, module_type.into()); + + info_arr.set_index(scope, i as u32, module_info_arr.into()); + } + array.set_index(scope, 1, info_arr.into()); + + let by_name_array = v8::Array::new(scope, self.by_name.len() as i32); + { + for (i, elem) in self.by_name.iter().enumerate() { + let arr = v8::Array::new(scope, 3); + + let (specifier, asserted_module_type) = elem.0; + let specifier = v8::String::new(scope, specifier).unwrap(); + arr.set_index(scope, 0, specifier.into()); - let obj_global = v8::Global::new(scope, obj); + let asserted_module_type = + v8::Integer::new(scope, *asserted_module_type as i32); + arr.set_index(scope, 1, asserted_module_type.into()); + + let symbolic_module: v8::Local = match &elem.1 { + SymbolicModule::Alias(alias) => { + let alias = v8::String::new(scope, alias).unwrap(); + alias.into() + } + SymbolicModule::Mod(id) => { + let id = v8::Integer::new(scope, *id as i32); + id.into() + } + }; + arr.set_index(scope, 2, symbolic_module); + + by_name_array.set_index(scope, i as u32, arr.into()); + } + } + array.set_index(scope, 2, by_name_array.into()); + + let array_global = v8::Global::new(scope, array); let handles = self.handles.clone(); - (obj_global, handles) + (array_global, handles) } pub fn update_with_snapshot_data( &mut self, scope: &mut v8::HandleScope, - data: v8::Global, + data: v8::Global, module_handles: Vec>, ) { - let local_data: v8::Local = v8::Local::new(scope, data); + let local_data: v8::Local = v8::Local::new(scope, data); { - let next_load_id_str = v8::String::new(scope, "next_load_id").unwrap(); - let next_load_id = - local_data.get(scope, next_load_id_str.into()).unwrap(); + let next_load_id = local_data.get_index(scope, 0).unwrap(); assert!(next_load_id.is_int32()); let integer = next_load_id.to_integer(scope).unwrap(); let val = integer.int32_value(scope).unwrap(); @@ -1042,22 +1090,136 @@ impl ModuleMap { } { - let info_str = v8::String::new(scope, "info").unwrap(); - let info_val = local_data.get(scope, info_str.into()).unwrap(); - self.info = serde_v8::from_v8(scope, info_val).unwrap(); + let info_val = local_data.get_index(scope, 1).unwrap(); + + let info_arr: v8::Local = info_val.try_into().unwrap(); + let len = info_arr.length() as usize; + let mut info = Vec::with_capacity(len); + + for i in 0..len { + let module_info_arr: v8::Local = info_arr + .get_index(scope, i as u32) + .unwrap() + .try_into() + .unwrap(); + let id = module_info_arr + .get_index(scope, 0) + .unwrap() + .to_integer(scope) + .unwrap() + .value() as ModuleId; + + let main = module_info_arr + .get_index(scope, 1) + .unwrap() + .to_boolean(scope) + .is_true(); + + let name = module_info_arr + .get_index(scope, 2) + .unwrap() + .to_rust_string_lossy(scope); + + let requests_arr: v8::Local = module_info_arr + .get_index(scope, 3) + .unwrap() + .try_into() + .unwrap(); + let len = (requests_arr.length() as usize) / 2; + let mut requests = Vec::with_capacity(len); + for i in 0..len { + let specifier = requests_arr + .get_index(scope, (2 * i) as u32) + .unwrap() + .to_rust_string_lossy(scope); + let asserted_module_type_no = requests_arr + .get_index(scope, (2 * i + 1) as u32) + .unwrap() + .to_integer(scope) + .unwrap() + .value(); + let asserted_module_type = match asserted_module_type_no { + 0 => AssertedModuleType::JavaScriptOrWasm, + 1 => AssertedModuleType::Json, + _ => unreachable!(), + }; + requests.push(ModuleRequest { + specifier, + asserted_module_type, + }); + } + + let module_type_no = module_info_arr + .get_index(scope, 4) + .unwrap() + .to_integer(scope) + .unwrap() + .value(); + let module_type = match module_type_no { + 0 => ModuleType::JavaScript, + 1 => ModuleType::Json, + _ => unreachable!(), + }; + + let module_info = ModuleInfo { + id, + main, + name, + requests, + module_type, + }; + info.push(module_info); + } + + self.info = info; } { - let by_name_str = v8::String::new(scope, "by_name").unwrap(); - let by_name_data = local_data.get(scope, by_name_str.into()).unwrap(); - let by_name_deser: Vec<(String, AssertedModuleType, SymbolicModule)> = - serde_v8::from_v8(scope, by_name_data).unwrap(); - self.by_name = by_name_deser - .into_iter() - .map(|(name, module_type, symbolic_module)| { - ((name, module_type), symbolic_module) - }) - .collect(); + let by_name_arr: v8::Local = + local_data.get_index(scope, 2).unwrap().try_into().unwrap(); + let len = by_name_arr.length() as usize; + let mut by_name = HashMap::with_capacity(len); + + for i in 0..len { + let arr: v8::Local = by_name_arr + .get_index(scope, i as u32) + .unwrap() + .try_into() + .unwrap(); + + let specifier = + arr.get_index(scope, 0).unwrap().to_rust_string_lossy(scope); + let asserted_module_type = match arr + .get_index(scope, 1) + .unwrap() + .to_integer(scope) + .unwrap() + .value() + { + 0 => AssertedModuleType::JavaScriptOrWasm, + 1 => AssertedModuleType::Json, + _ => unreachable!(), + }; + let key = (specifier, asserted_module_type); + + let symbolic_module_val = arr.get_index(scope, 2).unwrap(); + let val = if symbolic_module_val.is_number() { + SymbolicModule::Mod( + symbolic_module_val + .to_integer(scope) + .unwrap() + .value() + .try_into() + .unwrap(), + ) + } else { + SymbolicModule::Alias(symbolic_module_val.to_rust_string_lossy(scope)) + }; + + by_name.insert(key, val); + } + + self.by_name = by_name; } self.handles = module_handles; @@ -1223,7 +1385,7 @@ impl ModuleMap { let asserted_module_type = get_asserted_module_type_from_assertions(&assertions); let request = ModuleRequest { - specifier: module_specifier, + specifier: module_specifier.to_string(), asserted_module_type, }; requests.push(request); @@ -1719,11 +1881,11 @@ import "/a.js"; modules.get_requested_modules(a_id), Some(&vec![ ModuleRequest { - specifier: resolve_url("file:///b.js").unwrap(), + specifier: "file:///b.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, }, ModuleRequest { - specifier: resolve_url("file:///c.js").unwrap(), + specifier: "file:///c.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, }, ]) @@ -1731,14 +1893,14 @@ import "/a.js"; assert_eq!( modules.get_requested_modules(b_id), Some(&vec![ModuleRequest { - specifier: resolve_url("file:///c.js").unwrap(), + specifier: "file:///c.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, },]) ); assert_eq!( modules.get_requested_modules(c_id), Some(&vec![ModuleRequest { - specifier: resolve_url("file:///d.js").unwrap(), + specifier: "file:///d.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, },]) ); @@ -1839,7 +2001,7 @@ import "/a.js"; assert_eq!( imports, Some(&vec![ModuleRequest { - specifier: resolve_url("file:///b.js").unwrap(), + specifier: "file:///b.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, },]) ); @@ -1947,7 +2109,7 @@ import "/a.js"; assert_eq!( imports, Some(&vec![ModuleRequest { - specifier: resolve_url("file:///b.json").unwrap(), + specifier: "file:///b.json".to_string(), asserted_module_type: AssertedModuleType::Json, },]) ); @@ -2275,7 +2437,7 @@ import "/a.js"; assert_eq!( modules.get_requested_modules(circular1_id), Some(&vec![ModuleRequest { - specifier: resolve_url("file:///circular2.js").unwrap(), + specifier: "file:///circular2.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, }]) ); @@ -2283,7 +2445,7 @@ import "/a.js"; assert_eq!( modules.get_requested_modules(circular2_id), Some(&vec![ModuleRequest { - specifier: resolve_url("file:///circular3.js").unwrap(), + specifier: "file:///circular3.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, }]) ); @@ -2298,11 +2460,11 @@ import "/a.js"; modules.get_requested_modules(circular3_id), Some(&vec![ ModuleRequest { - specifier: resolve_url("file:///circular1.js").unwrap(), + specifier: "file:///circular1.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, }, ModuleRequest { - specifier: resolve_url("file:///circular2.js").unwrap(), + specifier: "file:///circular2.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, } ]) @@ -2522,11 +2684,11 @@ if (import.meta.url != 'file:///main_with_code.js') throw Error(); modules.get_requested_modules(main_id), Some(&vec![ ModuleRequest { - specifier: resolve_url("file:///b.js").unwrap(), + specifier: "file:///b.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, }, ModuleRequest { - specifier: resolve_url("file:///c.js").unwrap(), + specifier: "file:///c.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, } ]) @@ -2534,14 +2696,14 @@ if (import.meta.url != 'file:///main_with_code.js') throw Error(); assert_eq!( modules.get_requested_modules(b_id), Some(&vec![ModuleRequest { - specifier: resolve_url("file:///c.js").unwrap(), + specifier: "file:///c.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, }]) ); assert_eq!( modules.get_requested_modules(c_id), Some(&vec![ModuleRequest { - specifier: resolve_url("file:///d.js").unwrap(), + specifier: "file:///d.js".to_string(), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, }]) ); diff --git a/core/runtime.rs b/core/runtime.rs index d098c25b13cdf..9c6b7afeaf9df 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -438,7 +438,7 @@ impl JsRuntime { fn get_context_data( scope: &mut v8::HandleScope<()>, context: v8::Local, - ) -> (Vec>, v8::Global) { + ) -> (Vec>, v8::Global) { fn data_error_to_panic(err: v8::DataError) -> ! { match err { v8::DataError::BadType { actual, expected } => { @@ -457,15 +457,11 @@ impl JsRuntime { // The 0th element is the module map itself, followed by X number of module // handles. We need to deserialize the "next_module_id" field from the // map to see how many module handles we expect. - match scope.get_context_data_from_snapshot_once::(0) { + match scope.get_context_data_from_snapshot_once::(0) { Ok(val) => { let next_module_id = { - let info_str = v8::String::new(&mut scope, "info").unwrap(); - let info_data: v8::Local = val - .get(&mut scope, info_str.into()) - .unwrap() - .try_into() - .unwrap(); + let info_data: v8::Local = + val.get_index(&mut scope, 1).unwrap().try_into().unwrap(); info_data.length() }; @@ -3648,7 +3644,7 @@ pub mod tests { main, name: specifier.to_string(), requests: vec![crate::modules::ModuleRequest { - specifier: crate::resolve_url(&format!("file:///{prev}.js")).unwrap(), + specifier: format!("file:///{prev}.js"), asserted_module_type: AssertedModuleType::JavaScriptOrWasm, }], module_type: ModuleType::JavaScript,