Repository: denoland/deno_core
Pull request #336 (2023-11-21 00:12:27)

refactor(core): stripping out non-main realms
We no longer support multiple realms (aka contexts) in a runtime. 

Allows us to use a single scope for the whole polling operation. This yields a 1% bump on http tests in deno.

Follow-up work will move much of the jsruntime polling code into the realm.


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 8863163..c9c73ef 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -258,7 +258,7 @@ dependencies = [
 
 [[package]]
 name = "deno_core"
-version = "0.231.0"
+version = "0.232.0"
 dependencies = [
  "anyhow",
  "bencher",
@@ -296,7 +296,7 @@ dependencies = [
 
 [[package]]
 name = "deno_ops"
-version = "0.107.0"
+version = "0.108.0"
 dependencies = [
  "pretty_assertions",
  "prettyplease",
@@ -1187,7 +1187,7 @@ dependencies = [
 
 [[package]]
 name = "serde_v8"
-version = "0.140.0"
+version = "0.141.0"
 dependencies = [
  "bencher",
  "bytes",
diff --git a/Cargo.toml b/Cargo.toml
index 1e5e8de..b27a3ed 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,9 +17,9 @@ repository = "https://github.com/denoland/deno_core"
 
 [workspace.dependencies]
 # Local dependencies
-deno_core = { version = "0.231.0", path = "./core" }
-deno_ops = { version = "0.107.0", path = "./ops" }
-serde_v8 = { version = "0.140.0", path = "./serde_v8" }
+deno_core = { version = "0.232.0", path = "./core" }
+deno_ops = { version = "0.108.0", path = "./ops" }
+serde_v8 = { version = "0.141.0", path = "./serde_v8" }
 
 v8 = { version = "0.81.0", default-features = false }
 deno_ast = { version = "0.31.2", features = ["transpiling"] }
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 116886d..415babf 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -2,7 +2,7 @@
 
 [package]
 name = "deno_core"
-version = "0.231.0"
+version = "0.232.0"
 authors.workspace = true
 edition.workspace = true
 license.workspace = true
diff --git a/core/lib.rs b/core/lib.rs
index 884f3a5..e3ea2b1 100644
--- a/core/lib.rs
+++ b/core/lib.rs
@@ -127,7 +127,6 @@ pub use crate::resources::ResourceTable;
 pub use crate::runtime::CompiledWasmModuleStore;
 pub use crate::runtime::CreateRealmOptions;
 pub use crate::runtime::CrossIsolateStore;
-pub use crate::runtime::JsRealm;
 pub use crate::runtime::JsRuntime;
 pub use crate::runtime::JsRuntimeForSnapshot;
 pub use crate::runtime::PollEventLoopOptions;
diff --git a/core/modules/map.rs b/core/modules/map.rs
index a0a9820..fa3ff2d 100644
--- a/core/modules/map.rs
+++ b/core/modules/map.rs
@@ -88,6 +88,95 @@ pub(crate) struct ModuleMap {
   pub(crate) dyn_module_evaluate_idle_counter: Cell<u32>,
 }
 
+/// Map of [`ModuleName`] and [`AssertedModuleType`] to a data field.
+struct ModuleNameTypeMap<T> {
+  submaps: Vec<HashMap<ModuleName, T>>,
+  map_index: HashMap<AssertedModuleType, usize>,
+  len: usize,
+}
+
+impl<T> Default for ModuleNameTypeMap<T> {
+  fn default() -> Self {
+    Self {
+      submaps: Default::default(),
+      map_index: Default::default(),
+      len: 0,
+    }
+  }
+}
+
+impl<T> ModuleNameTypeMap<T> {
+  pub fn len(&self) -> usize {
+    self.len
+  }
+
+  fn map_index(&self, ty: &AssertedModuleType) -> Option<usize> {
+    self.map_index.get(ty).copied()
+  }
+
+  pub fn get<Q>(&self, ty: &AssertedModuleType, name: &Q) -> Option<&T>
+  where
+    ModuleName: std::borrow::Borrow<Q>,
+    Q: std::cmp::Eq + std::hash::Hash + ?Sized,
+  {
+    let Some(index) = self.map_index(ty) else {
+      return None;
+    };
+    let Some(map) = self.submaps.get(index) else {
+      return None;
+    };
+    map.get(name)
+  }
+
+  pub fn clear(&mut self) {
+    self.len = 0;
+    self.map_index.clear();
+    self.submaps.clear();
+  }
+
+  pub fn insert(
+    &mut self,
+    module_type: &AssertedModuleType,
+    name: FastString,
+    module: T,
+  ) {
+    let index = match self.map_index(module_type) {
+      Some(index) => index,
+      None => {
+        let index = self.submaps.len();
+        self.map_index.insert(module_type.clone(), index);
+        self.submaps.push(Default::default());
+        index
+      }
+    };
+
+    if self
+      .submaps
+      .get_mut(index)
+      .unwrap()
+      .insert(name, module)
+      .is_none()
+    {
+      self.len += 1;
+    }
+  }
+
+  /// Rather than providing an iterator, we provide a walk method. This is mainly because Rust
+  /// doesn't have generators.
+  pub fn walk(
+    &self,
+    mut f: impl FnMut(usize, &AssertedModuleType, &ModuleName, &T),
+  ) {
+    let mut i = 0;
+    for (ty, value) in self.map_index.iter() {
+      for (key, value) in self.submaps.get(*value).unwrap() {
+        f(i, ty, key, value);
+        i += 1;
+      }
+    }
+  }
+}
+
 #[derive(Default)]
 pub(crate) struct ModuleMapData {
   /// Inverted index from module to index in `info`.
@@ -96,10 +185,8 @@ pub(crate) struct ModuleMapData {
   handles: Vec<v8::Global<v8::Module>>,
   /// The modules we have loaded so far.
   info: Vec<ModuleInfo>,
-  /// [`ModuleName`] to [`SymbolicModule`] for JS/WASM modules.
-  by_name_js: HashMap<ModuleName, SymbolicModule>,
-  /// [`ModuleName`] to [`SymbolicModule`] for JSON modules.
-  by_name_json: HashMap<ModuleName, SymbolicModule>,
+  /// [`ModuleName`] to [`SymbolicModule`] for modules.
+  by_name: ModuleNameTypeMap<SymbolicModule>,
   /// The next ID used for a load.
   next_load_id: ModuleLoadId,
   /// If a main module has been loaded, points to it by index.
@@ -118,25 +205,6 @@ impl ModuleMap {
     id + 1
   }
 
-  /// Walk the currently registered modules (JS, WASM and JSON) along with their index and names.
-  fn walk_modules(
-    &self,
-    mut f: impl FnMut(usize, AssertedModuleType, &ModuleName, &SymbolicModule),
-  ) {
-    let mut i = 0;
-    for module_type in [
-      AssertedModuleType::JavaScriptOrWasm,
-      AssertedModuleType::Json,
-    ] {
-      self.by_name(module_type, |map| {
-        for (name, module) in map.iter() {
-          f(i, module_type, name, module);
-          i += 1;
-        }
-      });
-    }
-  }
-
   #[cfg(debug_assertions)]
   pub(crate) fn assert_all_modules_evaluated(
     &self,
@@ -196,55 +264,51 @@ impl ModuleMap {
         )
         .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(),
-        );
+        let value = request.asserted_module_type.to_v8(scope);
+        requests_arr.set_index(scope, (2 * i) as u32 + 1, value);
       }
       module_info_arr.set_index(scope, 2, requests_arr.into());
 
-      let module_type = v8::Integer::new(scope, info.module_type as i32);
-      module_info_arr.set_index(scope, 3, module_type.into());
+      let module_type = info.module_type.to_v8(scope);
+      module_info_arr.set_index(scope, 3, module_type);
 
       info_arr.set_index(scope, i as u32, module_info_arr.into());
     }
     array.set_index(scope, 2, info_arr.into());
 
-    let length = self.data.borrow().by_name_js.len()
-      + self.data.borrow().by_name_json.len();
+    let length = self.data.borrow().by_name.len();
     let by_name_array = v8::Array::new(scope, length.try_into().unwrap());
-    self.walk_modules(|i, module_type, name, module| {
-      let arr = v8::Array::new(scope, 3);
-
-      let specifier = name.v8(scope);
-      arr.set_index(scope, 0, specifier.into());
-
-      let asserted_module_type = v8::Integer::new(scope, module_type as i32);
-      arr.set_index(scope, 1, asserted_module_type.into());
-
-      let symbolic_module: v8::Local<v8::Value> = match module {
-        SymbolicModule::Alias(alias) => {
-          let alias = v8::String::new_from_one_byte(
-            scope,
-            alias.as_bytes(),
-            v8::NewStringType::Normal,
-          )
-          .unwrap();
-          alias.into()
-        }
-        SymbolicModule::Mod(id) => {
-          let id = v8::Integer::new(scope, *id as i32);
-          id.into()
-        }
-      };
-      arr.set_index(scope, 2, symbolic_module);
+    self
+      .data
+      .borrow()
+      .by_name
+      .walk(|i, module_type, name, module| {
+        let arr = v8::Array::new(scope, 3);
+
+        let specifier = name.v8(scope);
+        arr.set_index(scope, 0, specifier.into());
+        let value = module_type.to_v8(scope);
+        arr.set_index(scope, 1, value);
+
+        let symbolic_module: v8::Local<v8::Value> = match module {
+          SymbolicModule::Alias(alias) => {
+            let alias = v8::String::new_from_one_byte(
+              scope,
+              alias.as_bytes(),
+              v8::NewStringType::Normal,
+            )
+            .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());
-    });
+        by_name_array.set_index(scope, i as u32, arr.into());
+      });
     array.set_index(scope, 3, by_name_array.into());
 
     let array_global = v8::Global::new(scope, array);
@@ -321,34 +385,19 @@ impl ModuleMap {
             .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!(),
-          };
+          let value =
+            requests_arr.get_index(scope, (2 * i + 1) as u32).unwrap();
+          let asserted_module_type =
+            AssertedModuleType::try_from_v8(scope, value).unwrap();
           requests.push(ModuleRequest {
             specifier,
             asserted_module_type,
           });
         }
 
-        let module_type_no = module_info_arr
-          .get_index(scope, 3)
-          .unwrap()
-          .to_integer(scope)
-          .unwrap()
-          .value();
-        let module_type = match module_type_no {
-          0 => ModuleType::JavaScript,
-          1 => ModuleType::Json,
-          _ => unreachable!(),
-        };
+        let value = module_info_arr.get_index(scope, 3).unwrap();
+        let module_type =
+          AssertedModuleType::try_from_v8(scope, value).unwrap();
 
         let main = self.data.borrow().main_module_id == Some(id);
         let module_info = ModuleInfo {
@@ -364,8 +413,7 @@ impl ModuleMap {
       self.data.borrow_mut().info = info;
     }
 
-    self.data.borrow_mut().by_name_js.clear();
-    self.data.borrow_mut().by_name_json.clear();
+    self.data.borrow_mut().by_name.clear();
 
     {
       let by_name_arr: v8::Local<v8::Array> =
@@ -409,9 +457,11 @@ impl ModuleMap {
           )
         };
 
-        self.by_name_mut(asserted_module_type, move |map| {
-          map.insert(specifier.into(), val)
-        });
+        self.data.borrow_mut().by_name.insert(
+          &asserted_module_type,
+          specifier.into(),
+          val,
+        );
       }
     }
 
@@ -435,25 +485,26 @@ impl ModuleMap {
   pub(crate) fn get_id(
     &self,
     name: impl AsRef<str>,
-    asserted_module_type: AssertedModuleType,
+    asserted_module_type: impl AsRef<AssertedModuleType>,
   ) -> Option<ModuleId> {
-    self.by_name(asserted_module_type, |map| {
-      let first_symbolic_module = map.get(name.as_ref())?;
-      let mut mod_name = match first_symbolic_module {
-        SymbolicModule::Mod(mod_id) => return Some(*mod_id),
-        SymbolicModule::Alias(target) => target,
-      };
-      loop {
-        let symbolic_module = map.get(mod_name.as_ref())?;
-        match symbolic_module {
-          SymbolicModule::Alias(target) => {
-            debug_assert!(mod_name != target);
-            mod_name = target;
-          }
-          SymbolicModule::Mod(mod_id) => return Some(*mod_id),
+    let map = &self.data.borrow().by_name;
+    let first_symbolic_module =
+      map.get(asserted_module_type.as_ref(), name.as_ref())?;
+    let mut mod_name = match first_symbolic_module {
+      SymbolicModule::Mod(mod_id) => return Some(*mod_id),
+      SymbolicModule::Alias(target) => target,
+    };
+    loop {
+      let symbolic_module =
+        map.get(asserted_module_type.as_ref(), mod_name.as_ref())?;
+      match symbolic_module {
+        SymbolicModule::Alias(target) => {
+          debug_assert!(mod_name != target);
+          mod_name = target;
         }
+        SymbolicModule::Mod(mod_id) => return Some(*mod_id),
       }
-    })
+    }
   }
 
   pub(crate) fn new_json_module(
@@ -738,12 +789,16 @@ impl ModuleMap {
   ) -> ModuleId {
     let mut data = self.data.borrow_mut();
     let id = data.handles.len();
+    let module_type = module_type.into();
     let (name1, name2) = name.into_cheap_copy();
     data.handles_inverted.insert(handle.clone(), id);
     data.handles.push(handle);
     if main {
       data.main_module_id = Some(id);
     }
+    data
+      .by_name
+      .insert(&module_type, name1, SymbolicModule::Mod(id));
     data.info.push(ModuleInfo {
       id,
       main,
@@ -751,10 +806,6 @@ impl ModuleMap {
       requests,
       module_type,
     });
-    drop(data);
-    self.by_name_mut(module_type.into(), |map| {
-      map.insert(name1, SymbolicModule::Mod(id))
-    });
 
     id
   }
@@ -770,50 +821,25 @@ impl ModuleMap {
   fn is_registered(
     &self,
     specifier: impl AsRef<str>,
-    asserted_module_type: AssertedModuleType,
+    asserted_module_type: impl AsRef<AssertedModuleType>,
   ) -> bool {
-    if let Some(id) = self.get_id(specifier.as_ref(), asserted_module_type) {
-      return asserted_module_type
-        == self.data.borrow().info.get(id).unwrap().module_type.into();
-    }
-
-    false
-  }
-
-  pub(crate) fn by_name<T>(
-    &self,
-    asserted_module_type: AssertedModuleType,
-    f: impl FnOnce(&HashMap<ModuleName, SymbolicModule>) -> T,
-  ) -> T {
-    match asserted_module_type {
-      AssertedModuleType::Json => f(&self.data.borrow().by_name_json),
-      AssertedModuleType::JavaScriptOrWasm => f(&self.data.borrow().by_name_js),
-    }
-  }
-
-  pub(crate) fn by_name_mut<T>(
-    &self,
-    asserted_module_type: AssertedModuleType,
-    f: impl FnOnce(&mut HashMap<ModuleName, SymbolicModule>) -> T,
-  ) -> T {
-    match asserted_module_type {
-      AssertedModuleType::Json => f(&mut self.data.borrow_mut().by_name_json),
-      AssertedModuleType::JavaScriptOrWasm => {
-        f(&mut self.data.borrow_mut().by_name_js)
-      }
-    }
+    self
+      .get_id(specifier.as_ref(), asserted_module_type.as_ref())
+      .is_some()
   }
 
   pub(crate) fn alias(
     &self,
     name: FastString,
-    asserted_module_type: AssertedModuleType,
+    asserted_module_type: &AssertedModuleType,
     target: FastString,
   ) {
     debug_assert_ne!(name, target);
-    self.by_name_mut(asserted_module_type, |map| {
-      map.insert(name, SymbolicModule::Alias(target))
-    });
+    self.data.borrow_mut().by_name.insert(
+      asserted_module_type,
+      name,
+      SymbolicModule::Alias(target),
+    );
   }
 
   #[cfg(test)]
@@ -822,9 +848,9 @@ impl ModuleMap {
     name: &str,
     asserted_module_type: AssertedModuleType,
   ) -> bool {
-    self.by_name(asserted_module_type, |map| {
-      matches!(map.get(name), Some(SymbolicModule::Alias(_)))
-    })
+    let map = &self.data.borrow().by_name;
+    let entry = map.get(&asserted_module_type, name);
+    matches!(entry, Some(SymbolicModule::Alias(_)))
   }
 
   pub(crate) fn get_handle(
@@ -863,13 +889,6 @@ impl ModuleMap {
       .map(|info| info.name.as_str().to_owned())
   }
 
-  pub(crate) fn get_module_type_by_id(
-    &self,
-    id: ModuleId,
-  ) -> Option<ModuleType> {
-    self.data.borrow().info.get(id).map(|info| info.module_type)
-  }
-
   pub(crate) async fn load_main(
     module_map_rc: Rc<ModuleMap>,
     specifier: impl AsRef<str>,
@@ -901,7 +920,7 @@ impl ModuleMap {
     let load = RecursiveModuleLoad::dynamic_import(
       specifier,
       referrer,
-      asserted_module_type,
+      asserted_module_type.clone(),
       module_map_rc.clone(),
     );
 
@@ -1339,23 +1358,16 @@ impl ModuleMap {
     assert_eq!(data.handles.len(), modules.len());
     assert_eq!(data.info.len(), modules.len());
     assert_eq!(data.next_load_id as usize, modules.len());
-    drop(data);
-
-    assert_eq!(
-      self.by_name(AssertedModuleType::Json, |map| map.len())
-        + self.by_name(AssertedModuleType::JavaScriptOrWasm, |map| map.len()),
-      modules.len()
-    );
+    assert_eq!(data.by_name.len(), modules.len());
 
     for info in modules {
       let data = self.data.borrow();
       assert!(data.handles.get(info.id).is_some());
       assert_eq!(data.info.get(info.id).unwrap(), info);
-      drop(data);
-      assert!(self.by_name(AssertedModuleType::JavaScriptOrWasm, |map| map
-        .get(&info.name)
-        .unwrap()
-        == &SymbolicModule::Mod(info.id)));
+      assert_eq!(
+        data.by_name.get(&info.module_type, &info.name),
+        Some(&SymbolicModule::Mod(info.id))
+      );
     }
   }
 }
diff --git a/core/modules/mod.rs b/core/modules/mod.rs
index d077c4b..ed50d58 100644
--- a/core/modules/mod.rs
+++ b/core/modules/mod.rs
@@ -11,6 +11,7 @@ use futures::stream::TryStreamExt;
 use log::debug;
 use serde::Deserialize;
 use serde::Serialize;
+use std::borrow::Cow;
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::collections::HashSet;
@@ -303,7 +304,6 @@ pub(crate) struct RecursiveModuleLoad {
   pub root_module_id: Option<ModuleId>,
   init: LoadInit,
   root_asserted_module_type: Option<AssertedModuleType>,
-  root_module_type: Option<ModuleType>,
   state: LoadState,
   module_map_rc: Rc<ModuleMap>,
   pending: FuturesUnordered<Pin<Box<ModuleLoadFuture>>>,
@@ -349,15 +349,14 @@ impl RecursiveModuleLoad {
   fn new(init: LoadInit, module_map_rc: Rc<ModuleMap>) -> Self {
     let id = module_map_rc.next_load_id();
     let loader = module_map_rc.loader.borrow().clone();
-    let asserted_module_type = match init {
-      LoadInit::DynamicImport(_, _, module_type) => module_type,
+    let asserted_module_type = match &init {
+      LoadInit::DynamicImport(_, _, module_type) => module_type.clone(),
       _ => AssertedModuleType::JavaScriptOrWasm,
     };
     let mut load = Self {
       id,
       root_module_id: None,
       root_asserted_module_type: None,
-      root_module_type: None,
       init,
       state: LoadState::Init,
       module_map_rc: module_map_rc.clone(),
@@ -370,12 +369,10 @@ impl RecursiveModuleLoad {
     // Ignore the error here, let it be hit in `Stream::poll_next()`.
     if let Ok(root_specifier) = load.resolve_root() {
       if let Some(module_id) =
-        module_map_rc.get_id(root_specifier, asserted_module_type)
+        module_map_rc.get_id(root_specifier, &asserted_module_type)
       {
         load.root_module_id = Some(module_id);
         load.root_asserted_module_type = Some(asserted_module_type);
-        load.root_module_type =
-          Some(module_map_rc.get_module_type_by_id(module_id).unwrap());
       }
     }
     load
@@ -463,7 +460,7 @@ impl RecursiveModuleLoad {
         module_url_found.into_cheap_copy();
       self.module_map_rc.alias(
         module_url_specified,
-        expected_asserted_module_type,
+        &expected_asserted_module_type,
         module_url_found1,
       );
       module_url_found2
@@ -473,7 +470,7 @@ impl RecursiveModuleLoad {
 
     let maybe_module_id = self
       .module_map_rc
-      .get_id(&module_url_found, expected_asserted_module_type);
+      .get_id(&module_url_found, &expected_asserted_module_type);
     let module_id = match maybe_module_id {
       Some(id) => {
         debug!(
@@ -498,6 +495,26 @@ impl RecursiveModuleLoad {
       },
     };
 
+    self.register_and_recurse_inner(module_id, module_request);
+
+    // Update `self.state` however applicable.
+    if self.state == LoadState::LoadingRoot {
+      self.root_module_id = Some(module_id);
+      self.root_asserted_module_type = Some(module_source.module_type.into());
+      self.state = LoadState::LoadingImports;
+    }
+    if self.pending.is_empty() {
+      self.state = LoadState::Done;
+    }
+
+    Ok(())
+  }
+
+  fn register_and_recurse_inner(
+    &mut self,
+    module_id: usize,
+    module_request: &ModuleRequest,
+  ) {
     // Recurse the module's imports. There are two cases for each import:
     // 1. If the module is not in the module map, start a new load for it in
     //    `self.pending`. The result of that load should eventually be passed to
@@ -526,7 +543,7 @@ impl RecursiveModuleLoad {
         {
           if let Some(module_id) = self.module_map_rc.get_id(
             module_request.specifier.as_str(),
-            module_request.asserted_module_type,
+            &module_request.asserted_module_type,
           ) {
             already_registered.push_back((module_id, module_request.clone()));
           } else {
@@ -563,18 +580,6 @@ impl RecursiveModuleLoad {
         }
       }
     }
-
-    // Update `self.state` however applicable.
-    if self.state == LoadState::LoadingRoot {
-      self.root_module_id = Some(module_id);
-      self.root_asserted_module_type = Some(module_source.module_type.into());
-      self.state = LoadState::LoadingImports;
-    }
-    if self.pending.is_empty() {
-      self.state = LoadState::Done;
-    }
-
-    Ok(())
   }
 }
 
@@ -594,28 +599,25 @@ impl Stream for RecursiveModuleLoad {
           Ok(url) => url,
           Err(error) => return Poll::Ready(Some(Err(error))),
         };
-        let load_fut = if let Some(_module_id) = inner.root_module_id {
-          // FIXME(bartlomieju): this is very bad
-          // The root module is already in the module map.
-          // TODO(nayeemrmn): In this case we would ideally skip to
-          // `LoadState::LoadingImports` and synchronously recurse the imports
-          // like the bottom of `RecursiveModuleLoad::register_and_recurse()`.
-          // But the module map cannot be borrowed here. Instead fake a load
-          // event so it gets passed to that function and recursed eventually.
-          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.to_string(),
-            asserted_module_type,
-          };
-          // The code will be discarded, since this module is already in the
-          // module map.
-          let module_source = ModuleSource::new(
-            module_type,
-            Default::default(),
-            &module_specifier,
-          );
-          futures::future::ok(Some((module_request, module_source))).boxed()
+        let asserted_module_type = match &inner.init {
+          LoadInit::DynamicImport(_, _, module_type) => module_type.clone(),
+          _ => AssertedModuleType::JavaScriptOrWasm,
+        };
+        let module_request = ModuleRequest {
+          specifier: module_specifier.to_string(),
+          asserted_module_type,
+        };
+        let load_fut = if let Some(module_id) = inner.root_module_id {
+          // If the inner future is already in the map, we might be done (assuming there are no pending
+          // loads).
+          inner.register_and_recurse_inner(module_id, &module_request);
+          if inner.pending.is_empty() {
+            inner.state = LoadState::Done;
+          } else {
+            inner.state = LoadState::LoadingImports;
+          }
+          // Internally re-poll using the new state to avoid spinning the event loop again.
+          return Self::poll_next(Pin::new(inner), cx);
         } else {
           let maybe_referrer = match inner.init {
             LoadInit::DynamicImport(_, ref referrer, _) => {
@@ -623,14 +625,6 @@ impl Stream for RecursiveModuleLoad {
             }
             _ => None,
           };
-          let asserted_module_type = match inner.init {
-            LoadInit::DynamicImport(_, _, module_type) => module_type,
-            _ => AssertedModuleType::JavaScriptOrWasm,
-          };
-          let module_request = ModuleRequest {
-            specifier: module_specifier.to_string(),
-            asserted_module_type,
-          };
           let loader = inner.loader.clone();
           let is_dynamic_import = inner.is_dynamic_import();
           async move {
@@ -669,11 +663,64 @@ impl Stream for RecursiveModuleLoad {
   }
 }
 
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[repr(u32)]
+#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
+#[repr(u8)]
 pub(crate) enum AssertedModuleType {
+  /// JavaScript or WASM.
   JavaScriptOrWasm,
+  /// JSON.
   Json,
+
+  // IMPORTANT: If you add any additional enum values here, you must update `to_v8`` below!
+  /// Non-well-known module type.
+  Other(Cow<'static, str>),
+}
+
+impl AssertedModuleType {
+  pub fn to_v8<'s>(
+    &self,
+    scope: &mut v8::HandleScope<'s>,
+  ) -> v8::Local<'s, v8::Value> {
+    match self {
+      AssertedModuleType::JavaScriptOrWasm => v8::Integer::new(scope, 0).into(),
+      AssertedModuleType::Json => v8::Integer::new(scope, 1).into(),
+      AssertedModuleType::Other(ty) => {
+        v8::String::new(scope, ty).unwrap().into()
+      }
+    }
+  }
+
+  pub fn try_from_v8(
+    scope: &mut v8::HandleScope,
+    value: v8::Local<v8::Value>,
+  ) -> Option<Self> {
+    Some(if let Some(int) = value.to_integer(scope) {
+      match int.int32_value(scope).unwrap_or_default() {
+        0 => AssertedModuleType::JavaScriptOrWasm,
+        1 => AssertedModuleType::Json,
+        _ => return None,
+      }
+    } else if let Ok(str) = v8::Local::<v8::String>::try_from(value) {
+      AssertedModuleType::Other(Cow::Owned(str.to_rust_string_lossy(scope)))
+    } else {
+      return None;
+    })
+  }
+}
+
+impl AsRef<AssertedModuleType> for AssertedModuleType {
+  fn as_ref(&self) -> &AssertedModuleType {
+    self
+  }
+}
+
+impl PartialEq<ModuleType> for AssertedModuleType {
+  fn eq(&self, other: &ModuleType) -> bool {
+    match other {
+      ModuleType::JavaScript => self == &AssertedModuleType::JavaScriptOrWasm,
+      ModuleType::Json => self == &AssertedModuleType::Json,
+    }
+  }
 }
 
 impl From<ModuleType> for AssertedModuleType {
@@ -690,6 +737,7 @@ impl std::fmt::Display for AssertedModuleType {
     match self {
       Self::JavaScriptOrWasm => write!(f, "JavaScriptOrWasm"),
       Self::Json => write!(f, "JSON"),
+      Self::Other(ty) => write!(f, "Other({ty})"),
     }
   }
 }
@@ -711,7 +759,7 @@ pub(crate) struct ModuleInfo {
   pub main: bool,
   pub name: ModuleName,
   pub requests: Vec<ModuleRequest>,
-  pub module_type: ModuleType,
+  pub module_type: AssertedModuleType,
 }
 
 #[derive(Debug)]
diff --git a/core/ops_builtin_v8.rs b/core/ops_builtin_v8.rs
index 13fbd57..bbf240d 100644
--- a/core/ops_builtin_v8.rs
+++ b/core/ops_builtin_v8.rs
@@ -8,11 +8,11 @@ use crate::op2;
 use crate::ops_builtin::WasmStreamingResource;
 use crate::resolve_url;
 use crate::runtime::script_origin;
+use crate::runtime::JsRealm;
 use crate::runtime::JsRuntimeState;
 use crate::source_map::apply_source_map;
 use crate::source_map::SourceMapApplication;
 use crate::JsBuffer;
-use crate::JsRealm;
 use crate::JsRuntime;
 use crate::OpState;
 use anyhow::Error;
@@ -974,7 +974,7 @@ pub fn op_set_format_exception_callback<'a>(
 
 #[op2]
 pub fn op_event_loop_has_more_work(scope: &mut v8::HandleScope) -> bool {
-  JsRuntime::event_loop_pending_state_from_scope(scope).is_pending()
+  JsRuntime::has_more_work(scope)
 }
 
 #[op2]
diff --git a/core/runtime/bindings.rs b/core/runtime/bindings.rs
index 68ea720..b0472ec 100644
--- a/core/runtime/bindings.rs
+++ b/core/runtime/bindings.rs
@@ -16,7 +16,7 @@ use crate::modules::ModuleMap;
 use crate::modules::ResolutionKind;
 use crate::ops::OpCtx;
 use crate::runtime::InitMode;
-use crate::JsRealm;
+use crate::runtime::JsRealm;
 use crate::JsRuntime;
 
 pub(crate) fn external_references(
diff --git a/core/runtime/jsrealm.rs b/core/runtime/jsrealm.rs
index 10f9d95..6cc2812 100644
--- a/core/runtime/jsrealm.rs
+++ b/core/runtime/jsrealm.rs
@@ -22,6 +22,7 @@ use std::hash::BuildHasherDefault;
 use std::hash::Hasher;
 use std::option::Option;
 use std::rc::Rc;
+use v8::Handle;
 use v8::HandleScope;
 use v8::Local;
 
@@ -92,23 +93,6 @@ pub(crate) struct ContextState {
 /// In other words, the [`v8::Isolate`] parameter for all the related [`JsRealm`] methods
 /// must be extracted from the pre-existing [`JsRuntime`].
 ///
-/// Example usage with the [`JsRealm::execute_script`] method:
-/// ```
-/// use deno_core::JsRuntime;
-/// use deno_core::RuntimeOptions;
-/// use deno_core::CreateRealmOptions;
-///
-/// let mut runtime = JsRuntime::new(RuntimeOptions::default());
-/// let new_realm = runtime
-///         .create_realm(CreateRealmOptions::default())
-///         .expect("Handle the error properly");
-/// let source_code = "var a = 0; a + 1";
-/// let result = new_realm
-///         .execute_script_static(runtime.v8_isolate(), "<anon>", source_code)
-///         .expect("Handle the error properly");
-/// # drop(result);
-/// ```
-///
 /// # Lifetime of the realm
 ///
 /// As long as the corresponding isolate is alive, a [`JsRealm`] instance will
@@ -116,7 +100,7 @@ pub(crate) struct ContextState {
 /// garbage collected.
 #[derive(Clone)]
 #[repr(transparent)]
-pub struct JsRealm(pub(crate) JsRealmInner);
+pub(crate) struct JsRealm(pub(crate) JsRealmInner);
 
 #[derive(Clone)]
 pub(crate) struct JsRealmInner {
@@ -124,7 +108,6 @@ pub(crate) struct JsRealmInner {
   context: Rc<v8::Global<v8::Context>>,
   module_map: Rc<ModuleMap>,
   runtime_state: Rc<RefCell<JsRuntimeState>>,
-  is_main_realm: bool,
 }
 
 impl JsRealmInner {
@@ -133,42 +116,15 @@ impl JsRealmInner {
     context: v8::Global<v8::Context>,
     module_map: Rc<ModuleMap>,
     runtime_state: Rc<RefCell<JsRuntimeState>>,
-    is_main_realm: bool,
   ) -> Self {
     Self {
       context_state,
       context: context.into(),
       module_map,
       runtime_state,
-      is_main_realm,
     }
   }
 
-  #[inline(always)]
-  pub fn num_pending_ops(&self) -> usize {
-    self.context_state.borrow().pending_ops.len()
-  }
-
-  #[inline(always)]
-  pub fn num_unrefed_ops(&self) -> usize {
-    self.context_state.borrow().unrefed_ops.len()
-  }
-
-  #[inline(always)]
-  pub fn has_pending_dyn_imports(&self) -> bool {
-    self.module_map.has_pending_dynamic_imports()
-  }
-
-  #[inline(always)]
-  pub fn has_pending_dyn_module_evaluation(&self) -> bool {
-    self.module_map.has_pending_dyn_module_evaluation()
-  }
-
-  #[inline(always)]
-  pub fn has_pending_module_evaluation(&self) -> bool {
-    self.context_state.borrow().pending_mod_evaluate.is_some()
-  }
-
   #[inline(always)]
   pub fn context(&self) -> &v8::Global<v8::Context> {
     &self.context
@@ -195,13 +151,12 @@ impl JsRealmInner {
 
   pub(crate) fn check_promise_rejections(
     &self,
-    isolate: &mut v8::Isolate,
+    scope: &mut v8::HandleScope,
   ) -> Result<(), Error> {
     let Some((_, handle)) = self.context_state.borrow_mut().pending_promise_rejections.pop_front() else {
       return Ok(());
     };
 
-    let scope = &mut self.handle_scope(isolate);
     let exception = v8::Local::new(scope, handle);
     let state_rc = JsRuntime::state_from(scope);
     let state = state_rc.borrow();
@@ -215,10 +170,6 @@ impl JsRealmInner {
     exception_to_err_result(scope, exception, true)
   }
 
-  pub(crate) fn is_same(&self, other: &Rc<v8::Global<v8::Context>>) -> bool {
-    Rc::ptr_eq(&self.context, other)
-  }
-
   pub fn destroy(self) {
     let state = self.state();
     let raw_ptr = self.state().borrow().isolate.unwrap();
@@ -264,14 +215,16 @@ impl JsRealm {
     context.get_slot::<Rc<ModuleMap>>(scope).unwrap().clone()
   }
 
+  #[cfg(test)]
   #[inline(always)]
   pub fn num_pending_ops(&self) -> usize {
-    self.0.num_pending_ops()
+    self.0.context_state.borrow().pending_ops.len()
   }
 
+  #[cfg(test)]
   #[inline(always)]
   pub fn num_unrefed_ops(&self) -> usize {
-    self.0.num_unrefed_ops()
+    self.0.context_state.borrow().unrefed_ops.len()
   }
 
   /// For info on the [`v8::Isolate`] parameter, check [`JsRealm#panics`].
@@ -288,13 +241,8 @@ impl JsRealm {
     self.0.context()
   }
 
-  /// For info on the [`v8::Isolate`] parameter, check [`JsRealm#panics`].
-  pub fn global_object<'s>(
-    &self,
-    isolate: &'s mut v8::Isolate,
-  ) -> v8::Local<'s, v8::Object> {
-    let scope = &mut self.0.handle_scope(isolate);
-    self.0.context.open(scope).global(scope)
+  pub(crate) fn context_ptr(&self) -> *mut v8::Context {
+    unsafe { self.0.context.get_unchecked() as *const _ as _ }
   }
 
   fn string_from_code<'a>(
@@ -326,6 +274,7 @@ impl JsRealm {
   /// The same `name` value can be used for multiple executions.
   ///
   /// `Error` can usually be downcast to `JsError`.
+  #[cfg(test)]
   pub fn execute_script_static(
     &self,
     isolate: &mut v8::Isolate,
@@ -403,13 +352,10 @@ impl JsRealm {
 
   pub(crate) fn instantiate_module(
     &self,
-    isolate: &mut v8::Isolate,
+    scope: &mut v8::HandleScope,
     id: ModuleId,
   ) -> Result<(), v8::Global<v8::Value>> {
-    self
-      .0
-      .module_map()
-      .instantiate_module(&mut self.handle_scope(isolate), id)
+    self.0.module_map().instantiate_module(scope, id)
   }
 
   // TODO(bartlomieju): make it return `ModuleEvaluationFuture`?
@@ -425,12 +371,11 @@ impl JsRealm {
   /// This function panics if module has not been instantiated.
   pub fn mod_evaluate(
     &self,
-    isolate: &mut v8::Isolate,
+    scope: &mut v8::HandleScope,
     id: ModuleId,
   ) -> oneshot::Receiver<Result<(), Error>> {
     let state_rc = self.0.state();
     let module_map_rc = self.0.module_map();
-    let scope = &mut self.handle_scope(isolate);
     let tc_scope = &mut v8::TryCatch::new(scope);
 
     let module = module_map_rc
@@ -573,7 +518,7 @@ impl JsRealm {
   /// then another turn of event loop must be performed.
   pub(in crate::runtime) fn evaluate_pending_module(
     &self,
-    isolate: &mut v8::Isolate,
+    scope: &mut v8::HandleScope,
   ) {
     let maybe_module_evaluation = self
       .0
@@ -587,7 +532,6 @@ impl JsRealm {
 
     let mut module_evaluation = maybe_module_evaluation.unwrap();
     let state_rc = self.0.state();
-    let scope = &mut self.handle_scope(isolate);
 
     let promise_global = module_evaluation.promise.clone().unwrap();
     let promise = promise_global.open(scope);
@@ -631,7 +575,7 @@ impl JsRealm {
   ///
   /// User must call [`JsRealm::mod_evaluate`] with returned `ModuleId`
   /// manually after load is finished.
-  pub async fn load_main_module(
+  pub(crate) async fn load_main_module(
     &self,
     isolate: &mut v8::Isolate,
     specifier: &ModuleSpecifier,
@@ -671,8 +615,8 @@ impl JsRealm {
     }
 
     let root_id = load.root_module_id.expect("Root module should be loaded");
-    self.instantiate_module(isolate, root_id).map_err(|e| {
-      let scope = &mut self.handle_scope(isolate);
+    let scope = &mut self.handle_scope(isolate);
+    self.instantiate_module(scope, root_id).map_err(|e| {
       let exception = v8::Local::new(scope, e);
       exception_to_err_result::<()>(scope, exception, false).unwrap_err()
     })?;
@@ -686,7 +630,7 @@ impl JsRealm {
   ///
   /// User must call [`JsRealm::mod_evaluate`] with returned `ModuleId`
   /// manually after load is finished.
-  pub async fn load_side_module(
+  pub(crate) async fn load_side_module(
     &self,
     isolate: &mut v8::Isolate,
     specifier: &ModuleSpecifier,
@@ -726,33 +670,11 @@ impl JsRealm {
     }
 
     let root_id = load.root_module_id.expect("Root module should be loaded");
-    self.instantiate_module(isolate, root_id).map_err(|e| {
-      let scope = &mut self.handle_scope(isolate);
+    let scope = &mut self.handle_scope(isolate);
+    self.instantiate_module(scope, root_id).map_err(|e| {
       let exception = v8::Local::new(scope, e);
       exception_to_err_result::<()>(scope, exception, false).unwrap_err()
     })?;
     Ok(root_id)
   }
 }
-
-impl Drop for JsRealm {
-  fn drop(&mut self) {
-    // Don't do anything special with the main realm
-    if self.0.is_main_realm {
-      return;
-    }
-
-    // There's us and there's the runtime
-    if Rc::strong_count(&self.0.context) == 2 {
-      self
-        .0
-        .runtime_state
-        .borrow_mut()
-        .remove_realm(&self.0.context);
-      assert_eq!(Rc::strong_count(&self.0.context), 1);
-      self.0.clone().destroy();
-      assert_eq!(Rc::strong_count(&self.0.context_state), 1);
-      assert_eq!(Rc::strong_count(&self.0.module_map), 1);
-    }
-  }
-}
diff --git a/core/runtime/jsruntime.rs b/core/runtime/jsruntime.rs
index 68ce19c..b4320fd 100644
--- a/core/runtime/jsruntime.rs
+++ b/core/runtime/jsruntime.rs
@@ -115,7 +115,7 @@ impl<T> DerefMut for ManuallyDropRc<T> {
 /// control dropping more closely here using ManuallyDrop.
 pub(crate) struct InnerIsolateState {
   will_snapshot: bool,
-  main_realm: Option<JsRealm>,
+  main_realm: ManuallyDrop<JsRealm>,
   pub(crate) state: ManuallyDropRc<RefCell<JsRuntimeState>>,
   v8_isolate: ManuallyDrop<v8::OwnedIsolate>,
 }
@@ -145,8 +145,9 @@ impl InnerIsolateState {
     // the runtime.
     _ = unsafe { Rc::from_raw(state_ptr as *const RefCell<JsRuntimeState>) };
 
-    self.main_realm.take();
-    self.state.borrow_mut().destroy_all_realms();
+    unsafe {
+      ManuallyDrop::take(&mut self.main_realm).0.destroy();
+    }
 
     debug_assert_eq!(Rc::strong_count(&self.state), 1);
   }
@@ -232,15 +233,10 @@ pub struct JsRuntime {
   pub(crate) inner: InnerIsolateState,
   pub(crate) allocations: IsolateAllocations,
   extensions: Vec<Extension>,
-  preserve_snapshotted_modules: Option<&'static [&'static str]>,
   event_loop_middlewares: Vec<EventLoopMiddlewareFn>,
-  global_template_middlewares: Vec<GlobalTemplateMiddlewareFn>,
-  global_object_middlewares: Vec<GlobalObjectMiddlewareFn>,
   init_mode: InitMode,
   // Marks if this is considered the top-level runtime. Used only by inspector.
   is_main_runtime: bool,
-  /// Have we created additional realms? If so, we have to poison the fast path.
-  additional_realms: bool,
 }
 
 /// The runtime type used for snapshot creation.
@@ -305,7 +301,6 @@ pub type CompiledWasmModuleStore = CrossIsolateStore<v8::CompiledWasmModule>;
 /// Internal state for JsRuntime which is stored in one of v8::Isolate's
 /// embedder slots.
 pub struct JsRuntimeState {
-  known_realms: Vec<JsRealmInner>,
   pub(crate) has_tick_scheduled: bool,
   pub(crate) source_map_getter: Option<Rc<Box<dyn SourceMapGetter>>>,
   pub(crate) source_map_cache: Rc<RefCell<SourceMapCache>>,
@@ -322,23 +317,6 @@ pub struct JsRuntimeState {
   pub(crate) validate_import_attributes_cb: ValidateImportAttributesCb,
 }
 
-impl JsRuntimeState {
-  pub(crate) fn destroy_all_realms(&mut self) {
-    for realm in self.known_realms.drain(..) {
-      realm.destroy()
-    }
-  }
-
-  pub(crate) fn remove_realm(
-    &mut self,
-    realm_context: &Rc<v8::Global<v8::Context>>,
-  ) {
-    self
-      .known_realms
-      .retain(|realm| !realm.is_same(realm_context));
-  }
-}
-
 fn v8_init(
   v8_platform: Option<v8::SharedRef<v8::Platform>>,
   predictable: bool,
@@ -559,12 +537,8 @@ impl JsRuntime {
     state.op_state.clone()
   }
 
-  pub(crate) fn event_loop_pending_state_from_scope(
-    scope: &mut v8::HandleScope,
-  ) -> EventLoopPendingState {
-    let state = JsRuntime::state_from(scope);
-    let state = EventLoopPendingState::new(scope, &mut state.borrow_mut());
-    state
+  pub(crate) fn has_more_work(scope: &mut v8::HandleScope) -> bool {
+    EventLoopPendingState::new_from_scope(scope).is_pending()
   }
 
   fn init_v8(
@@ -641,7 +615,6 @@ impl JsRuntime {
       dispatched_exception: None,
       // Some fields are initialized later after isolate is created
       inspector: None,
-      known_realms: Vec::with_capacity(1),
       validate_import_attributes_cb,
     }));
 
@@ -774,20 +747,18 @@ impl JsRuntime {
     }
     context.set_slot(scope, module_map.clone());
 
-    {
+    let main_realm = {
       let main_realm = JsRealmInner::new(
         context_state,
         main_context,
         module_map.clone(),
         state_rc.clone(),
-        true,
       );
       let mut state = state_rc.borrow_mut();
       state.inspector = inspector;
-      state.known_realms.push(main_realm);
-    }
-    let main_realm =
-      JsRealm::new(state_rc.borrow().known_realms.get(0).unwrap().clone());
+      main_realm
+    };
+    let main_realm = JsRealm::new(main_realm);
     scope.set_data(
       STATE_DATA_OFFSET,
       Rc::into_raw(state_rc.clone()) as *mut c_void,
@@ -798,24 +769,19 @@ impl JsRuntime {
     let mut js_runtime = JsRuntime {
       inner: InnerIsolateState {
         will_snapshot,
-        main_realm: Some(main_realm),
+        main_realm: ManuallyDrop::new(main_realm),
         state: ManuallyDropRc(ManuallyDrop::new(state_rc)),
         v8_isolate: ManuallyDrop::new(isolate),
       },
       init_mode,
       allocations: IsolateAllocations::default(),
       event_loop_middlewares,
-      global_template_middlewares,
-      global_object_middlewares,
       extensions: options.extensions,
-      preserve_snapshotted_modules: options.preserve_snapshotted_modules,
       is_main_runtime: options.is_main,
-      additional_realms: false,
     };
 
-    let realm = js_runtime.main_realm();
     // TODO(mmastrac): We should thread errors back out of the runtime
-    js_runtime.init_extension_js(&realm).unwrap();
+    js_runtime.init_extension_js().unwrap();
 
     // If the embedder has requested to clear the module map resulting from
     // extensions, possibly with exceptions.
@@ -831,20 +797,17 @@ impl JsRuntime {
   #[cfg(test)]
   #[inline]
   pub(crate) fn module_map(&mut self) -> Rc<ModuleMap> {
-    self.main_realm().0.module_map()
+    self.inner.main_realm.0.module_map()
   }
 
   #[inline]
   pub fn main_context(&self) -> v8::Global<v8::Context> {
-    self
-      .inner
-      .state
-      .borrow()
-      .known_realms
-      .get(0)
-      .unwrap()
-      .context()
-      .clone()
+    self.inner.main_realm.0.context().clone()
+  }
+
+  #[cfg(test)]
+  pub(crate) fn main_realm(&self) -> JsRealm {
+    JsRealm::clone(&self.inner.main_realm)
   }
 
   #[inline]
@@ -853,13 +816,13 @@ impl JsRuntime {
   }
 
   #[inline]
-  pub fn inspector(&mut self) -> Rc<RefCell<JsRuntimeInspector>> {
-    self.inner.state.borrow().inspector()
+  fn v8_isolate_ptr(&mut self) -> *mut v8::Isolate {
+    &mut **self.inner.v8_isolate as _
   }
 
   #[inline]
-  pub fn main_realm(&mut self) -> JsRealm {
-    self.inner.main_realm.as_ref().unwrap().clone()
+  pub fn inspector(&mut self) -> Rc<RefCell<JsRuntimeInspector>> {
+    self.inner.state.borrow().inspector()
   }
 
   /// Returns the extensions that this runtime is using (including internal ones).
@@ -867,120 +830,38 @@ impl JsRuntime {
     &self.extensions
   }
 
-  /// Creates a new realm (V8 context) in this JS execution context,
-  /// pre-initialized with all of the extensions that were passed in
-  /// [`RuntimeOptions::extensions`] when the [`JsRuntime`] was
-  /// constructed.
-  pub fn create_realm(
-    &mut self,
-    options: CreateRealmOptions,
-  ) -> Result<JsRealm, Error> {
-    let realm = {
-      let context_state = Rc::new(RefCell::new(ContextState::default()));
-      let op_ctxs: Box<[OpCtx]> = self
-        .main_realm()
-        .0
-        .state()
-        .borrow()
-        .op_ctxs
-        .iter()
-        .map(|op_ctx| {
-          OpCtx::new(
-            op_ctx.id,
-            op_ctx.isolate,
-            context_state.clone(),
-            op_ctx.decl.clone(),
-            op_ctx.state.clone(),
-            op_ctx.runtime_state.clone(),
-            op_ctx.get_error_class_fn,
-            op_ctx.metrics_fn.clone(),
-          )
-        })
-        .collect();
-      context_state.borrow_mut().op_ctxs = op_ctxs;
-      context_state.borrow_mut().isolate = Some(self.v8_isolate() as _);
-
-      let raw_ptr = self.v8_isolate() as *mut v8::OwnedIsolate;
-      // SAFETY: Having the scope tied to self's lifetime makes it impossible to
-      // reference JsRuntimeState::op_ctxs while the scope is alive. Here we
-      // turn it into an unbound lifetime, which is sound because 1. it only
-      // lives until the end of this block, and 2. the HandleScope only has
-      // access to the isolate, and nothing else we're accessing from self does.
-      let isolate = unsafe { raw_ptr.as_mut() }.unwrap();
-      let scope = &mut v8::HandleScope::new(isolate);
-
-      let context = create_context(
-        scope,
-        &self.global_template_middlewares,
-        &self.global_object_middlewares,
-      );
-
-      let scope = &mut v8::ContextScope::new(scope, context);
-
-      let context = bindings::initialize_context(
-        scope,
-        context,
-        &context_state.borrow().op_ctxs,
-        self.init_mode,
-      );
-      context.set_slot(scope, context_state.clone());
-
-      let loader = options
-        .module_loader
-        .unwrap_or_else(|| Rc::new(NoopModuleLoader));
-      let module_map = Rc::new(ModuleMap::new(loader));
-      if self.init_mode.is_from_snapshot() {
-        let snapshotted_data =
-          snapshot_util::get_snapshotted_data(scope, context);
-        module_map.update_with_snapshotted_data(scope, snapshotted_data);
-      }
-      context.set_slot(scope, module_map.clone());
-
-      let realm = JsRealmInner::new(
-        context_state,
-        v8::Global::new(scope, context),
-        module_map,
-        self.inner.state.clone(),
-        false,
-      );
-
-      let mut state = self.inner.state.borrow_mut();
-      // Poison the fast path for realms
-      self.additional_realms = true;
-      state.known_realms.push(realm.clone());
-      JsRealm::new(realm)
-    };
-
-    self.init_extension_js(&realm)?;
-
-    // If the embedder has requested to clear the module map resulting from
-    // extensions, possibly with exceptions.
-    if let Some(preserve_snapshotted_modules) =
-      self.preserve_snapshotted_modules
-    {
-      realm
-        .0
-        .module_map()
-        .clear_module_map(preserve_snapshotted_modules);
-    }
-
-    Ok(realm)
-  }
-
   #[inline]
   pub fn handle_scope(&mut self) -> v8::HandleScope {
-    self.main_realm().handle_scope(self.v8_isolate())
+    let isolate = &mut self.inner.v8_isolate;
+    self.inner.main_realm.handle_scope(isolate)
+  }
+
+  #[inline(always)]
+  /// Create a scope on the stack with the given context
+  fn with_context_scope<'s, T>(
+    isolate: *mut v8::Isolate,
+    context: *mut v8::Context,
+    f: impl FnOnce(&mut v8::HandleScope<'s>) -> T,
+  ) -> T {
+    // SAFETY: We know this isolate is valid and non-null at this time
+    let mut isolate_scope =
+      v8::HandleScope::new(unsafe { isolate.as_mut().unwrap_unchecked() });
+    // SAFETY: We know the context is valid and non-null at this time, and that a Local and pointer share the
+    // same representation
+    let context = unsafe { std::mem::transmute(context) };
+    let mut scope = v8::ContextScope::new(&mut isolate_scope, context);
+    f(&mut scope)
   }
 
   /// Initializes JS of provided Extensions in the given realm.
-  fn init_extension_js(&mut self, realm: &JsRealm) -> Result<(), Error> {
+  fn init_extension_js(&mut self) -> Result<(), Error> {
     // Initialization of JS happens in phases:
     // 1. Iterate through all extensions:
     //  a. Execute all extension "script" JS files
     //  b. Load all extension "module" JS files (but do not execute them yet)
     // 2. Iterate through all extensions:
     //  a. If an extension has a `esm_entry_point`, execute it.
-
+    let realm = JsRealm::clone(&self.inner.main_realm);
     let module_map = realm.0.module_map();
 
     // Take extensions temporarily so we can avoid have a mutable reference to self
@@ -1002,7 +883,7 @@ impl JsRuntime {
           )?;
         }
       }
-      self.init_cbs(realm);
+      self.init_cbs(&realm);
 
       for extension in &extensions {
         let maybe_esm_entry_point = extension.get_esm_entry_point();
@@ -1038,8 +919,14 @@ impl JsRuntime {
               panic!("{} not present in the module map", specifier)
             })
         };
-        let mut receiver = realm.mod_evaluate(self.v8_isolate(), mod_id);
-        realm.evaluate_pending_module(self.v8_isolate());
+
+        let mut receiver = {
+          let isolate = self.v8_isolate();
+          let scope = &mut realm.handle_scope(isolate);
+          let receiver = realm.mod_evaluate(scope, mod_id);
+          realm.evaluate_pending_module(scope);
+          receiver
+        };
 
         // After evaluate_pending_module, if the module isn't fully evaluated
         // and the resolver solved, it means the module or one of its imports
@@ -1242,7 +1129,7 @@ impl JsRuntime {
 
   /// Returns the runtime's op names, ordered by OpId.
   pub fn op_names(&self) -> Vec<&'static str> {
-    let main_realm = self.inner.main_realm.as_ref().unwrap().clone();
+    let main_realm = self.inner.main_realm.clone();
     let state_rc = main_realm.0.state();
     let state = state_rc.borrow();
     state.op_ctxs.iter().map(|o| o.decl.name).collect()
@@ -1267,9 +1154,11 @@ impl JsRuntime {
     name: &'static str,
     source_code: ModuleCode,
   ) -> Result<v8::Global<v8::Value>, Error> {
+    let isolate = &mut self.inner.v8_isolate;
     self
-      .main_realm()
-      .execute_script(self.v8_isolate(), name, source_code)
+      .inner
+      .main_realm
+      .execute_script(isolate, name, source_code)
   }
 
   /// Executes traditional JavaScript code (traditional = not ES modules).
@@ -1291,8 +1180,9 @@ impl JsRuntime {
     name: &'static str,
     source_code: &'static str,
   ) -> Result<v8::Global<v8::Value>, Error> {
-    self.main_realm().execute_script(
-      self.v8_isolate(),
+    let isolate = &mut self.inner.v8_isolate;
+    self.inner.main_realm.execute_script(
+      isolate,
       name,
       ModuleCode::from_static(source_code),
     )
@@ -1317,7 +1207,10 @@ impl JsRuntime {
       v8::Global::new(scope, promise.unwrap())
     };
     let result = self.resolve_value(promise).await;
-    self.check_promise_rejections()?;
+    let isolate = &mut self.inner.v8_isolate;
+    let realm = &self.inner.main_realm;
+    let scope = &mut realm.handle_scope(isolate);
+    realm.0.check_promise_rejections(scope)?;
     result
   }
 
@@ -1329,9 +1222,11 @@ impl JsRuntime {
     &mut self,
     module_id: ModuleId,
   ) -> Result<v8::Global<v8::Object>, Error> {
+    let isolate = &mut self.inner.v8_isolate;
     self
-      .main_realm()
-      .get_module_namespace(self.v8_isolate(), module_id)
+      .inner
+      .main_realm
+      .get_module_namespace(isolate, module_id)
   }
 
   /// Registers a callback on the isolate when the memory limits are approached.
@@ -1370,8 +1265,10 @@ impl JsRuntime {
     }
   }
 
-  fn pump_v8_message_loop(&mut self) -> Result<(), Error> {
-    let scope = &mut self.handle_scope();
+  fn pump_v8_message_loop(
+    &mut self,
+    scope: &mut v8::HandleScope,
+  ) -> Result<(), Error> {
     while v8::Platform::pump_message_loop(
       &v8::V8::get_current_platform(),
       scope,
@@ -1410,45 +1307,60 @@ impl JsRuntime {
 
   pub fn poll_value(
     &mut self,
+    cx: &mut Context,
     global: &v8::Global<v8::Value>,
+  ) -> Poll<Result<v8::Global<v8::Value>, Error>> {
+    Self::with_context_scope(
+      self.v8_isolate_ptr(),
+      self.inner.main_realm.context_ptr(),
+      |scope| self.poll_value_inner(cx, scope, global),
+    )
+  }
+
+  fn poll_value_inner(
+    &mut self,
     cx: &mut Context,
+    scope: &mut v8::HandleScope,
+    global: &v8::Global<v8::Value>,
   ) -> Poll<Result<v8::Global<v8::Value>, Error>> {
+    let promise = v8::Local::new(scope, global);
+
+    // TODO(mmastrac): this would be better if we just type-tested at the top level
+    let Ok(promise) = v8::Local::<v8::Promise>::try_from(promise) else {
+      return Poll::Ready(Ok(global.clone()));
+    };
+
     // Check if the value is not a promise or already settled before polling the
     // event loop.
-    let promise_global = {
-      let scope = &mut self.handle_scope();
-      let local = v8::Local::<v8::Value>::new(scope, global);
-      if let Ok(promise) = v8::Local::<v8::Promise>::try_from(local) {
-        match promise.state() {
-          v8::PromiseState::Pending => v8::Global::new(scope, promise),
-          v8::PromiseState::Fulfilled => {
-            let value = promise.result(scope);
-            let value_handle = v8::Global::new(scope, value);
-            return Poll::Ready(Ok(value_handle));
-          }
-          v8::PromiseState::Rejected => {
-            let exception = promise.result(scope);
-            let promise_global = v8::Global::new(scope, promise);
-            JsRealm::state_from_scope(scope)
-              .borrow_mut()
-              .pending_promise_rejections
-              .retain(|(key, _)| key != &promise_global);
-            return Poll::Ready(exception_to_err_result(
-              scope, exception, false,
-            ));
-          }
-        }
-      } else {
-        return Poll::Ready(Ok(global.clone()));
+    match promise.state() {
+      v8::PromiseState::Pending => {}
+      v8::PromiseState::Fulfilled => {
+        let value = promise.result(scope);
+        let value_handle = v8::Global::new(scope, value);
+        return Poll::Ready(Ok(value_handle));
       }
-    };
+      v8::PromiseState::Rejected => {
+        let exception = promise.result(scope);
+        let promise_global = v8::Global::new(scope, promise);
+        JsRealm::state_from_scope(scope)
+          .borrow_mut()
+          .pending_promise_rejections
+          .retain(|(key, _)| key != &promise_global);
+        return Poll::Ready(exception_to_err_result(scope, exception, false));
+      }
+    }
 
     // Poll the event loop.
-    let event_loop_result = self.poll_event_loop(cx, false)?;
+    let event_loop_result = self.poll_event_loop_inner(
+      cx,
+      scope,
+      PollEventLoopOptions {
+        wait_for_inspector: false,
+        pump_v8_message_loop: true,
+      },
+    )?;
 
     // Check the promise state again.
-    let scope = &mut self.handle_scope();
-    let promise = v8::Local::new(scope, promise_global);
     match promise.state() {
       v8::PromiseState::Pending => match event_loop_result {
         Poll::Ready(_) => {
@@ -1477,7 +1389,7 @@ impl JsRuntime {
     &mut self,
     global: v8::Global<v8::Value>,
   ) -> Result<v8::Global<v8::Value>, Error> {
-    poll_fn(|cx| self.poll_value(&global, cx)).await
+    poll_fn(|cx| self.poll_value(cx, &global)).await
   }
 
   /// Runs event loop to completion
@@ -1537,11 +1449,18 @@ impl JsRuntime {
     cx: &mut Context,
     wait_for_inspector: bool,
   ) -> Poll<Result<(), Error>> {
-    self.poll_event_loop_inner(
-      cx,
-      PollEventLoopOptions {
-        wait_for_inspector,
-        ..Default::default()
+    Self::with_context_scope(
+      self.v8_isolate_ptr(),
+      self.inner.main_realm.context_ptr(),
+      |scope| {
+        self.poll_event_loop_inner(
+          cx,
+          scope,
+          PollEventLoopOptions {
+            wait_for_inspector,
+            ..Default::default()
+          },
+        )
       },
     )
   }
@@ -1555,12 +1474,18 @@ impl JsRuntime {
     cx: &mut Context,
     poll_options: PollEventLoopOptions,
   ) -> Poll<Result<(), Error>> {
-    self.poll_event_loop_inner(cx, poll_options)
+    let isolate = self.v8_isolate_ptr();
+    Self::with_context_scope(
+      isolate,
+      self.inner.main_realm.context_ptr(),
+      move |scope| self.poll_event_loop_inner(cx, scope, poll_options),
+    )
   }
 
   fn poll_event_loop_inner(
     &mut self,
     cx: &mut Context,
+    scope: &mut v8::HandleScope,
     poll_options: PollEventLoopOptions,
   ) -> Poll<Result<(), Error>> {
     let has_inspector: bool;
@@ -1576,7 +1501,7 @@ impl JsRuntime {
     }
 
     if poll_options.pump_v8_message_loop {
-      self.pump_v8_message_loop()?;
+      self.pump_v8_message_loop(scope)?;
     }
 
     // Dynamic module loading - ie. modules loaded using "import()"
@@ -1602,18 +1527,16 @@ impl JsRuntime {
 
         // Fast main realm poll
         {
-          let main_realm = self.inner.main_realm.as_ref().unwrap();
-          let mut scope = main_realm.handle_scope(&mut self.inner.v8_isolate);
+          let main_realm = &self.inner.main_realm;
           let modules = main_realm.0.module_map();
           loop {
-            let poll_imports =
-              modules.poll_prepare_dyn_imports(&mut scope, cx)?;
+            let poll_imports = modules.poll_prepare_dyn_imports(scope, cx)?;
             assert!(poll_imports.is_ready());
 
-            let poll_imports = modules.poll_dyn_imports(&mut scope, cx)?;
+            let poll_imports = modules.poll_dyn_imports(scope, cx)?;
             assert!(poll_imports.is_ready());
 
-            if modules.evaluate_dyn_imports(&mut scope) {
+            if modules.evaluate_dyn_imports(scope) {
               has_evaluated = true;
             } else {
               break;
@@ -1621,35 +1544,6 @@ impl JsRuntime {
           }
         }
 
-        if self.additional_realms {
-          // TODO(bartlomieju|mmastrac): Remove cloning/to_vec in the runtime loop
-          let state = self.inner.state.borrow();
-          let realms = state.known_realms[1..].to_vec();
-          drop(state);
-          for inner_realm in realms {
-            let realm = JsRealm::new(inner_realm);
-            let mut scope = realm.handle_scope(&mut self.inner.v8_isolate);
-            let modules = realm.0.module_map();
-
-            // Try and resolve as many dynamic imports in each realm as possible
-            // before moving to the next.
-            loop {
-              let poll_imports =
-                modules.poll_prepare_dyn_imports(&mut scope, cx)?;
-              assert!(poll_imports.is_ready());
-
-              let poll_imports = modules.poll_dyn_imports(&mut scope, cx)?;
-              assert!(poll_imports.is_ready());
-
-              if modules.evaluate_dyn_imports(&mut scope) {
-                has_evaluated = true;
-              } else {
-                break;
-              }
-            }
-          }
-        }
-
         if !has_evaluated {
           break;
         }
@@ -1660,8 +1554,8 @@ impl JsRuntime {
     // and only then check for any promise exceptions (`unhandledrejection`
     // handlers are run in macrotasks callbacks so we need to let them run
     // first).
-    let dispatched_ops = self.do_js_event_loop_tick(cx)?;
-    self.check_promise_rejections()?;
+    let dispatched_ops = self.do_js_event_loop_tick(cx, scope)?;
+    self.check_promise_rejections(scope)?;
 
     // Event loop middlewares
     let mut maybe_scheduling = false;
@@ -1676,34 +1570,17 @@ impl JsRuntime {
 
     // Top level module
     {
-      self
-        .inner
-        .main_realm
-        .as_ref()
-        .unwrap()
-        .evaluate_pending_module(&mut self.inner.v8_isolate);
-      if self.additional_realms {
-        // TODO(bartlomieju|mmastrac): Remove cloning in the runtime loop
-        let state = self.inner.state.borrow();
-        let realms = state.known_realms[1..].to_vec();
-        drop(state);
-        for inner_realm in realms {
-          let realm = JsRealm::new(inner_realm);
-          realm.evaluate_pending_module(&mut self.inner.v8_isolate);
-        }
-      }
+      self.inner.main_realm.evaluate_pending_module(scope);
     }
 
     // Get the pending state from the main realm, or all realms
-    let pending_state = if self.additional_realms {
-      let mut scope = v8::HandleScope::new(self.inner.v8_isolate.as_mut());
-      EventLoopPendingState::new(&mut scope, &mut self.inner.state.borrow_mut())
-    } else {
-      let mut scope = v8::HandleScope::new(self.inner.v8_isolate.as_mut());
-      EventLoopPendingState::new_from_main_realm(
-        &mut scope,
-        &mut self.inner.state.borrow_mut(),
-        &self.inner.main_realm.as_ref().unwrap().0,
+    let pending_state = {
+      let inner = &self.inner.main_realm.0;
+      EventLoopPendingState::new(
+        scope,
+        &self.inner.state.borrow(),
+        &inner.state().borrow(),
+        &inner.module_map(),
       )
     };
 
@@ -1719,7 +1596,6 @@ impl JsRuntime {
           // to exit the process once debugger disconnects.
           if !has_blocking_sessions {
             let context = self.main_context();
-            let scope = &mut self.handle_scope();
             inspector.borrow_mut().context_destroyed(scope, context);
             println!("Program finished. Waiting for inspector to disconnect to exit the process...");
           }
@@ -1767,11 +1643,10 @@ impl JsRuntime {
       {
         // pass, will be polled again
       } else {
-        let known_realms = &self.inner.state.borrow().known_realms;
         return Poll::Ready(Err(
           find_and_report_stalled_level_await_in_any_realm(
-            &mut self.inner.v8_isolate,
-            known_realms,
+            scope,
+            &self.inner.main_realm.0,
           ),
         ));
       }
@@ -1784,12 +1659,11 @@ impl JsRuntime {
         || pending_state.has_tick_scheduled
       {
         // pass, will be polled again
-      } else if self.inner.main_realm.as_ref().unwrap().modules_idle() {
-        let known_realms = &self.inner.state.borrow().known_realms;
+      } else if self.inner.main_realm.modules_idle() {
         return Poll::Ready(Err(
           find_and_report_stalled_level_await_in_any_realm(
-            &mut self.inner.v8_isolate,
-            known_realms,
+            scope,
+            &self.inner.main_realm.0,
           ),
         ));
       } else {
@@ -1797,12 +1671,7 @@ impl JsRuntime {
         // Delay the above error by one spin of the event loop. A dynamic import
         // evaluation may complete during this, in which case the counter will
         // reset.
-        self
-          .inner
-          .main_realm
-          .as_ref()
-          .unwrap()
-          .increment_modules_idle();
+        self.inner.main_realm.increment_modules_idle();
         state.op_state.borrow().waker.wake();
       }
     }
@@ -1812,23 +1681,20 @@ impl JsRuntime {
 }
 
 fn find_and_report_stalled_level_await_in_any_realm(
-  v8_isolate: &mut v8::Isolate,
-  known_realms: &[JsRealmInner],
+  scope: &mut v8::HandleScope,
+  inner_realm: &JsRealmInner,
 ) -> Error {
-  for inner_realm in known_realms {
-    let scope = &mut inner_realm.handle_scope(v8_isolate);
-    let module_map = inner_realm.module_map();
-    let messages = module_map.find_stalled_top_level_await(scope);
-
-    if !messages.is_empty() {
-      // 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
-      // situation is gonna be very rare, if ever happening).
-      let msg = v8::Local::new(scope, &messages[0]);
-      let js_error = JsError::from_v8_message(scope, msg);
-      return js_error.into();
-    }
+  let module_map = inner_realm.module_map();
+  let messages = module_map.find_stalled_top_level_await(scope);
+
+  if !messages.is_empty() {
+    // 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
+    // situation is gonna be very rare, if ever happening).
+    let msg = v8::Local::new(scope, &messages[0]);
+    let js_error = JsError::from_v8_message(scope, msg);
+    return js_error.into();
   }
 
   unreachable!("Expected at least one stalled top-level await");
@@ -1878,7 +1744,7 @@ impl JsRuntimeForSnapshot {
     // Ensure there are no live inspectors to prevent crashes.
     self.inner.prepare_for_cleanup();
 
-    let realm = self.main_realm();
+    let realm = JsRealm::clone(&self.inner.main_realm);
 
     // Set the context to be snapshot's default context
     {
@@ -1924,60 +1790,39 @@ pub(crate) struct EventLoopPendingState {
   has_pending_background_tasks: bool,
   has_tick_scheduled: bool,
 }
+
 impl EventLoopPendingState {
-  pub fn new_from_main_realm(
+  /// Collect event loop state from all the sub-states.
+  pub fn new(
     scope: &mut v8::HandleScope<()>,
-    state: &mut JsRuntimeState,
-    realm: &JsRealmInner,
+    runtime_state: &JsRuntimeState,
+    state: &ContextState,
+    modules: &ModuleMap,
   ) -> Self {
-    let num_unrefed_ops = realm.num_unrefed_ops();
-    let num_pending_ops = realm.num_pending_ops();
-    let has_pending_dyn_imports = realm.has_pending_dyn_imports();
+    let num_unrefed_ops = state.unrefed_ops.len();
+    let num_pending_ops = state.pending_ops.len();
+    let has_pending_dyn_imports = modules.has_pending_dynamic_imports();
     let has_pending_dyn_module_evaluation =
-      realm.has_pending_dyn_module_evaluation();
-    let has_pending_module_evaluation = realm.has_pending_module_evaluation();
+      modules.has_pending_dyn_module_evaluation();
+    let has_pending_module_evaluation = state.pending_mod_evaluate.is_some();
     EventLoopPendingState {
       has_pending_refed_ops: num_pending_ops > num_unrefed_ops,
       has_pending_dyn_imports,
       has_pending_dyn_module_evaluation,
       has_pending_module_evaluation,
       has_pending_background_tasks: scope.has_pending_background_tasks(),
-      has_tick_scheduled: state.has_tick_scheduled,
+      has_tick_scheduled: runtime_state.has_tick_scheduled,
     }
   }
 
-  pub fn new(
-    scope: &mut v8::HandleScope<()>,
-    state: &mut JsRuntimeState,
-  ) -> EventLoopPendingState {
-    let mut num_unrefed_ops = 0;
-    let mut num_pending_ops = 0;
-    let mut has_pending_dyn_imports = false;
-    let mut has_pending_dyn_module_evaluation = false;
-    let mut has_pending_module_evaluation = false;
-    for realm in &state.known_realms {
-      num_unrefed_ops += realm.num_unrefed_ops();
-      num_pending_ops += realm.num_pending_ops();
-      if !has_pending_dyn_imports {
-        has_pending_dyn_imports = realm.has_pending_dyn_imports();
-      }
-      if !has_pending_dyn_module_evaluation {
-        has_pending_dyn_module_evaluation =
-          realm.has_pending_dyn_module_evaluation();
-      }
-      if !has_pending_module_evaluation {
-        has_pending_module_evaluation = realm.has_pending_module_evaluation();
-      }
-    }
-
-    EventLoopPendingState {
-      has_pending_refed_ops: num_pending_ops > num_unrefed_ops,
-      has_pending_dyn_imports,
-      has_pending_dyn_module_evaluation,
-      has_pending_module_evaluation,
-      has_pending_background_tasks: scope.has_pending_background_tasks(),
-      has_tick_scheduled: state.has_tick_scheduled,
-    }
+  /// Collect event loop state from all the states stored in the scope.
+  pub fn new_from_scope(scope: &mut v8::HandleScope) -> Self {
+    let module_map = JsRealm::module_map_from(scope);
+    let context_state = JsRealm::state_from_scope(scope);
+    let context_state = context_state.borrow();
+    let runtime_state = JsRuntime::state_from(scope);
+    let runtime_state = runtime_state.borrow();
+    Self::new(scope, &runtime_state, &context_state, &module_map)
   }
 
   pub fn is_pending(&self) -> bool {
@@ -2024,7 +1869,10 @@ impl JsRuntime {
     &mut self,
     id: ModuleId,
   ) -> Result<(), v8::Global<v8::Value>> {
-    self.main_realm().instantiate_module(self.v8_isolate(), id)
+    let isolate = &mut self.inner.v8_isolate;
+    let realm = JsRealm::clone(&self.inner.main_realm);
+    let scope = &mut realm.handle_scope(isolate);
+    realm.instantiate_module(scope, id)
   }
 
   // TODO(bartlomieju): make it return `ModuleEvaluationFuture`?
@@ -2042,7 +1890,10 @@ impl JsRuntime {
     &mut self,
     id: ModuleId,
   ) -> oneshot::Receiver<Result<(), Error>> {
-    self.main_realm().mod_evaluate(self.v8_isolate(), id)
+    let isolate = &mut self.inner.v8_isolate;
+    let realm = &self.inner.main_realm;
+    let scope = &mut realm.handle_scope(isolate);
+    realm.mod_evaluate(scope, id)
   }
 
   /// Asynchronously load specified module and all of its dependencies.
@@ -2057,9 +1908,11 @@ impl JsRuntime {
     specifier: &ModuleSpecifier,
     code: Option<ModuleCode>,
   ) -> Result<ModuleId, Error> {
+    let isolate = &mut self.inner.v8_isolate;
     self
-      .main_realm()
-      .load_main_module(self.v8_isolate(), specifier, code)
+      .inner
+      .main_realm
+      .load_main_module(isolate, specifier, code)
       .await
   }
 
@@ -2075,55 +1928,48 @@ impl JsRuntime {
     specifier: &ModuleSpecifier,
     code: Option<ModuleCode>,
   ) -> Result<ModuleId, Error> {
+    let isolate = &mut self.inner.v8_isolate;
     self
-      .main_realm()
-      .load_side_module(self.v8_isolate(), specifier, code)
+      .inner
+      .main_realm
+      .load_side_module(isolate, specifier, code)
       .await
   }
 
-  fn check_promise_rejections(&mut self) -> Result<(), Error> {
-    let state_rc = self.inner.state.clone();
-    let isolate = &mut self.v8_isolate();
-    let state = state_rc.borrow();
-    for realm in &state.known_realms {
-      realm.check_promise_rejections(isolate)?;
-    }
-    Ok(())
+  fn check_promise_rejections(
+    &self,
+    scope: &mut v8::HandleScope,
+  ) -> Result<(), Error> {
+    self.inner.main_realm.0.check_promise_rejections(scope)
   }
 
   // Polls pending ops and then runs `Deno.core.eventLoopTick` callback.
-  fn do_js_event_loop_tick(&mut self, cx: &mut Context) -> Result<bool, Error> {
+  fn do_js_event_loop_tick(
+    &mut self,
+    cx: &mut Context,
+    scope: &mut v8::HandleScope,
+  ) -> Result<bool, Error> {
     // Handle responses for each realm.
     let state = self.inner.state.clone();
-    let isolate = &mut self.inner.v8_isolate;
 
-    let mut dispatched_ops = Self::do_js_event_loop_tick_realm(
+    let dispatched_ops = Self::do_js_event_loop_tick_realm(
       cx,
-      isolate,
+      scope,
       &state,
-      &self.inner.main_realm.as_ref().unwrap().0,
+      &self.inner.main_realm.0,
     )?;
-    if self.additional_realms {
-      let realm_count = state.borrow().known_realms.len();
-      for realm_idx in 1..realm_count {
-        let realm = state.borrow().known_realms.get(realm_idx).unwrap().clone();
-        dispatched_ops |=
-          Self::do_js_event_loop_tick_realm(cx, isolate, &state, &realm)?;
-      }
-    }
 
     Ok(dispatched_ops)
   }
 
   fn do_js_event_loop_tick_realm(
     cx: &mut Context,
-    isolate: &mut ManuallyDrop<v8::OwnedIsolate>,
+    scope: &mut v8::HandleScope,
     state: &Rc<RefCell<JsRuntimeState>>,
     realm: &JsRealmInner,
   ) -> Result<bool, Error> {
     let context_state = realm.state();
     let mut context_state = context_state.borrow_mut();
-    let scope = &mut realm.handle_scope(isolate);
     let mut dispatched_ops = false;
 
     // We return async responses to JS in unbounded batches (may change),
diff --git a/core/runtime/mod.rs b/core/runtime/mod.rs
index 9b700f7..6260fdf 100644
--- a/core/runtime/mod.rs
+++ b/core/runtime/mod.rs
@@ -14,7 +14,7 @@ pub const V8_WRAPPER_TYPE_INDEX: i32 = 0;
 pub const V8_WRAPPER_OBJECT_INDEX: i32 = 1;
 
 pub(crate) use jsrealm::ContextState;
-pub use jsrealm::JsRealm;
+pub(crate) use jsrealm::JsRealm;
 pub use jsruntime::CompiledWasmModuleStore;
 pub use jsruntime::CreateRealmOptions;
 pub use jsruntime::CrossIsolateStore;
diff --git a/ops/Cargo.toml b/ops/Cargo.toml
index f0aa2f7..05a6a90 100644
--- a/ops/Cargo.toml
+++ b/ops/Cargo.toml
@@ -2,7 +2,7 @@
 
 [package]
 name = "deno_ops"
-version = "0.107.0"
+version = "0.108.0"
 authors.workspace = true
 edition.workspace = true
 license.workspace = true
diff --git a/serde_v8/Cargo.toml b/serde_v8/Cargo.toml
index 506e01c..491ccaa 100644
--- a/serde_v8/Cargo.toml
+++ b/serde_v8/Cargo.toml
@@ -2,7 +2,7 @@
 
 [package]
 name = "serde_v8"
-version = "0.140.0"
+version = "0.141.0"
 authors.workspace = true
 edition.workspace = true
 license.workspace = true


Test patch:
diff --git a/core/runtime/tests/error.rs b/core/runtime/tests/error.rs
index 034cebd..c301192 100644
--- a/core/runtime/tests/error.rs
+++ b/core/runtime/tests/error.rs
@@ -179,7 +179,7 @@ if (errMessage !== "higher-level async error: original async error") {
       )
       .unwrap();
 
-    match runtime.poll_value(&promise, cx) {
+    match runtime.poll_value(cx, &promise) {
       Poll::Ready(Ok(_)) => {}
       Poll::Ready(Err(err)) => panic!("{err:?}"),
       _ => panic!(),
diff --git a/core/runtime/tests/jsrealm.rs b/core/runtime/tests/jsrealm.rs
index db6f83d..f353937 100644
--- a/core/runtime/tests/jsrealm.rs
+++ b/core/runtime/tests/jsrealm.rs
@@ -1,104 +1,25 @@
 // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use crate::ascii_str;
 use crate::error;
-use crate::modules::ModuleCode;
 use crate::modules::StaticModuleLoader;
 use crate::op2;
-use crate::runtime::tests::snapshot::generic_es_snapshot_without_runtime_module_loader;
-use crate::CreateRealmOptions;
 use crate::Extension;
 use crate::ExtensionFileSource;
 use crate::ExtensionFileSourceCode;
-use crate::JsRealm;
 use crate::JsRuntime;
 use crate::JsRuntimeForSnapshot;
-use crate::ModuleLoader;
-use crate::ModuleSource;
-use crate::ModuleSourceFuture;
-use crate::ModuleSpecifier;
-use crate::ModuleType;
-use crate::Op;
-use crate::OpState;
-use crate::ResolutionKind;
 use crate::RuntimeOptions;
 use crate::Snapshot;
-use anyhow::Error;
-use futures::channel::oneshot;
 use futures::future::poll_fn;
-use futures::future::Future;
-use futures::FutureExt;
-use serde_v8::ToJsBuffer;
 use std::borrow::Cow;
-use std::cell::RefCell;
-use std::pin::Pin;
 use std::rc::Rc;
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering;
-use std::task::Context;
 use std::task::Poll;
-use url::Url;
-
-use super::snapshot::generic_preserve_snapshotted_modules_test;
-
-#[tokio::test]
-async fn test_set_promise_reject_callback_realms() {
-  let mut runtime = JsRuntime::new(RuntimeOptions::default());
-  let main_realm = runtime.main_realm();
-  let realm1 = runtime.create_realm(Default::default()).unwrap();
-  let realm2 = runtime.create_realm(Default::default()).unwrap();
-
-  let realm_expectations = &[
-    (&main_realm, "main_realm", 42),
-    (&realm1, "realm1", 140),
-    (&realm2, "realm2", 720),
-  ];
-
-  // Set up promise reject callbacks.
-  for (realm, realm_name, number) in realm_expectations {
-    realm
-      .execute_script(
-        runtime.v8_isolate(),
-        "",
-        format!(
-          r#"
-
-            globalThis.rejectValue = undefined;
-            Deno.core.setPromiseRejectCallback((_type, _promise, reason) => {{
-              globalThis.rejectValue = `{realm_name}/${{reason}}`;
-            }});
-            Deno.core.opAsync("op_void_async").then(() => Promise.reject({number}));
-          "#
-        ).into()
-      )
-      .unwrap();
-  }
-
-  runtime.run_event_loop(false).await.unwrap();
-
-  for (realm, realm_name, number) in realm_expectations {
-    let reject_value = realm
-      .execute_script_static(runtime.v8_isolate(), "", "globalThis.rejectValue")
-      .unwrap();
-    let scope = &mut realm.handle_scope(runtime.v8_isolate());
-    let reject_value = v8::Local::new(scope, reject_value);
-    assert!(reject_value.is_string());
-    let reject_value_string = reject_value.to_rust_string_lossy(scope);
-    assert_eq!(reject_value_string, format!("{realm_name}/{number}"));
-  }
-}
 
 #[test]
 fn test_set_format_exception_callback_realms() {
   let mut runtime = JsRuntime::new(RuntimeOptions::default());
   let main_realm = runtime.main_realm();
-  let realm1 = runtime.create_realm(Default::default()).unwrap();
-  let realm2 = runtime.create_realm(Default::default()).unwrap();
 
-  let realm_expectations = &[
-    (&main_realm, "main_realm"),
-    (&realm1, "realm1"),
-    (&realm2, "realm2"),
-  ];
+  let realm_expectations = &[(&main_realm, "main_realm")];
 
   // Set up format exception callbacks.
   for (realm, realm_name) in realm_expectations {
@@ -156,264 +77,6 @@ fn test_set_format_exception_callback_realms() {
   }
 }
 
-#[test]
-fn js_realm_simple() {
-  let mut runtime = JsRuntime::new(Default::default());
-  let main_context = runtime.main_context();
-  let main_global = {
-    let scope = &mut runtime.handle_scope();
-    let local_global = main_context.open(scope).global(scope);
-    v8::Global::new(scope, local_global)
-  };
-
-  let realm = runtime.create_realm(Default::default()).unwrap();
-  assert_ne!(realm.context(), &main_context);
-  assert_ne!(realm.global_object(runtime.v8_isolate()), main_global);
-
-  let main_object = runtime.execute_script_static("", "Object").unwrap();
-  let realm_object = realm
-    .execute_script_static(runtime.v8_isolate(), "", "Object")
-    .unwrap();
-  assert_ne!(main_object, realm_object);
-}
-
-#[test]
-fn js_realm_init() {
-  #[op2]
-  #[string]
-  fn op_test() -> Result<String, Error> {
-    Ok(String::from("Test"))
-  }
-
-  deno_core::extension!(test_ext, ops = [op_test]);
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    extensions: vec![test_ext::init_ops()],
-    ..Default::default()
-  });
-  let realm = runtime.create_realm(Default::default()).unwrap();
-  let ret = realm
-    .execute_script_static(runtime.v8_isolate(), "", "Deno.core.ops.op_test()")
-    .unwrap();
-
-  let op_names = runtime.op_names();
-  assert_eq!(op_names[op_names.len() - 1], "op_test");
-
-  let scope = &mut realm.handle_scope(runtime.v8_isolate());
-  assert_eq!(ret, serde_v8::to_v8(scope, "Test").unwrap());
-}
-
-#[test]
-fn js_realm_init_snapshot() {
-  let snapshot = {
-    let runtime = JsRuntimeForSnapshot::new(Default::default());
-    let snap: &[u8] = &runtime.snapshot();
-    Vec::from(snap).into_boxed_slice()
-  };
-
-  #[op2]
-  #[string]
-  fn op_test() -> Result<String, Error> {
-    Ok(String::from("Test"))
-  }
-
-  deno_core::extension!(test_ext, ops = [op_test]);
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    startup_snapshot: Some(Snapshot::Boxed(snapshot)),
-    extensions: vec![test_ext::init_ops()],
-    skip_op_registration: false,
-    ..Default::default()
-  });
-  let realm = runtime.create_realm(Default::default()).unwrap();
-  let ret = realm
-    .execute_script_static(runtime.v8_isolate(), "", "Deno.core.ops.op_test()")
-    .unwrap();
-
-  let scope = &mut realm.handle_scope(runtime.v8_isolate());
-  assert_eq!(ret, serde_v8::to_v8(scope, "Test").unwrap());
-}
-
-#[test]
-fn js_realm_sync_ops() {
-  // Test that returning a RustToV8Buf and throwing an exception from a sync
-  // op result in objects with prototypes from the right realm. Note that we
-  // don't test the result of returning structs, because they will be
-  // serialized to objects with null prototype.
-
-  #[op2]
-  #[serde]
-  fn op_test(fail: bool) -> Result<ToJsBuffer, Error> {
-    if !fail {
-      Ok(ToJsBuffer::empty())
-    } else {
-      Err(crate::error::type_error("Test"))
-    }
-  }
-
-  deno_core::extension!(test_ext, ops = [op_test]);
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    extensions: vec![test_ext::init_ops()],
-    get_error_class_fn: Some(&|error| {
-      crate::error::get_custom_error_class(error).unwrap()
-    }),
-    ..Default::default()
-  });
-  let new_realm = runtime.create_realm(Default::default()).unwrap();
-
-  // Test in both realms
-  for realm in [runtime.main_realm(), new_realm].into_iter() {
-    let ret = realm
-      .execute_script_static(
-        runtime.v8_isolate(),
-        "",
-        r#"
-          const buf = Deno.core.ops.op_test(false);
-          try {
-            Deno.core.ops.op_test(true);
-          } catch(e) {
-            err = e;
-          }
-          buf instanceof Uint8Array && buf.byteLength === 0 &&
-          err instanceof TypeError && err.message === "Test"
-        "#,
-      )
-      .unwrap();
-    assert!(ret.open(runtime.v8_isolate()).is_true());
-  }
-}
-
-#[tokio::test]
-async fn js_realm_async_ops() {
-  // Test that returning a RustToV8Buf and throwing an exception from a async
-  // op result in objects with prototypes from the right realm. Note that we
-  // don't test the result of returning structs, because they will be
-  // serialized to objects with null prototype.
-
-  #[op2(async)]
-  #[serde]
-  async fn op_test(fail: bool) -> Result<ToJsBuffer, Error> {
-    if !fail {
-      Ok(ToJsBuffer::empty())
-    } else {
-      Err(crate::error::type_error("Test"))
-    }
-  }
-
-  deno_core::extension!(test_ext, ops = [op_test]);
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    extensions: vec![test_ext::init_ops()],
-    get_error_class_fn: Some(&|error| {
-      crate::error::get_custom_error_class(error).unwrap()
-    }),
-    ..Default::default()
-  });
-
-  let main_realm = runtime.main_realm();
-  let new_realm = runtime.create_realm(Default::default()).unwrap();
-
-  let mut rets = vec![];
-
-  // Test in both realms
-  for realm in [main_realm, new_realm].into_iter() {
-    let ret = realm
-      .execute_script_static(
-        runtime.v8_isolate(),
-        "",
-        r#"
-
-          (async function () {
-            const buf = await Deno.core.opAsync("op_test", false);
-            let err;
-            try {
-              await Deno.core.opAsync("op_test", true);
-            } catch(e) {
-              err = e;
-            }
-            return buf instanceof Uint8Array && buf.byteLength === 0 &&
-                    err instanceof TypeError && err.message === "Test" ;
-          })();
-        "#,
-      )
-      .unwrap();
-    rets.push((realm, ret));
-  }
-
-  runtime.run_event_loop(false).await.unwrap();
-
-  for ret in rets {
-    let scope = &mut ret.0.handle_scope(runtime.v8_isolate());
-    let value = v8::Local::new(scope, ret.1);
-    let promise = v8::Local::<v8::Promise>::try_from(value).unwrap();
-    let result = promise.result(scope);
-
-    assert!(result.is_boolean() && result.is_true());
-  }
-}
-
-#[ignore]
-#[tokio::test]
-async fn js_realm_gc() {
-  static INVOKE_COUNT: AtomicUsize = AtomicUsize::new(0);
-  struct PendingFuture {}
-
-  impl Future for PendingFuture {
-    type Output = ();
-    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
-      Poll::Pending
-    }
-  }
-
-  impl Drop for PendingFuture {
-    fn drop(&mut self) {
-      assert_eq!(INVOKE_COUNT.fetch_sub(1, Ordering::SeqCst), 1);
-    }
-  }
-
-  // Never resolves.
-  #[op2(async)]
-  async fn op_pending() {
-    assert_eq!(INVOKE_COUNT.fetch_add(1, Ordering::SeqCst), 0);
-    PendingFuture {}.await
-  }
-
-  deno_core::extension!(test_ext, ops = [op_pending]);
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    extensions: vec![test_ext::init_ops()],
-    ..Default::default()
-  });
-
-  // Detect a drop in OpState
-  let opstate_drop_detect = Rc::new(());
-  runtime
-    .op_state()
-    .borrow_mut()
-    .put(opstate_drop_detect.clone());
-  assert_eq!(Rc::strong_count(&opstate_drop_detect), 2);
-
-  let other_realm = runtime.create_realm(Default::default()).unwrap();
-  other_realm
-    .execute_script(
-      runtime.v8_isolate(),
-      "future",
-      ModuleCode::from_static("Deno.core.opAsync('op_pending')"),
-    )
-    .unwrap();
-  while INVOKE_COUNT.load(Ordering::SeqCst) == 0 {
-    poll_fn(|cx: &mut Context| runtime.poll_event_loop(cx, false))
-      .await
-      .unwrap();
-  }
-  drop(other_realm);
-  while INVOKE_COUNT.load(Ordering::SeqCst) == 1 {
-    poll_fn(|cx| runtime.poll_event_loop(cx, false))
-      .await
-      .unwrap();
-  }
-  drop(runtime);
-
-  // Make sure the OpState was dropped properly when the runtime dropped
-  assert_eq!(Rc::strong_count(&opstate_drop_detect), 1);
-}
-
 #[tokio::test]
 async fn js_realm_ref_unref_ops() {
   // Never resolves.
@@ -430,26 +93,12 @@ async fn js_realm_ref_unref_ops() {
 
   poll_fn(move |cx| {
     let main_realm = runtime.main_realm();
-    let other_realm = runtime.create_realm(Default::default()).unwrap();
 
     main_realm
       .execute_script_static(
         runtime.v8_isolate(),
         "",
-        r#"
-
-          var promise = Deno.core.opAsync("op_pending");
-        "#,
-      )
-      .unwrap();
-    other_realm
-      .execute_script_static(
-        runtime.v8_isolate(),
-        "",
-        r#"
-
-          var promise = Deno.core.opAsync("op_pending");
-        "#,
+        r#"var promise =Deno.core.opAsync("op_pending")"#,
       )
       .unwrap();
     assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
@@ -463,17 +112,7 @@ async fn js_realm_ref_unref_ops() {
         "#,
       )
       .unwrap();
-    assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
 
-    other_realm
-      .execute_script_static(
-        runtime.v8_isolate(),
-        "",
-        r#"
-          Deno.core.unrefOpPromise(promise);
-        "#,
-      )
-      .unwrap();
     assert!(matches!(
       runtime.poll_event_loop(cx, false),
       Poll::Ready(Ok(()))
@@ -483,255 +122,6 @@ async fn js_realm_ref_unref_ops() {
   .await;
 }
 
-#[tokio::test]
-async fn test_realm_modules() {
-  use std::cell::Cell;
-
-  struct Loader(Cell<usize>);
-  impl ModuleLoader for Loader {
-    fn resolve(
-      &self,
-      specifier: &str,
-      referrer: &str,
-      _kind: ResolutionKind,
-    ) -> Result<ModuleSpecifier, Error> {
-      assert_eq!(specifier, "file:///test.js");
-      assert_eq!(referrer, ".");
-      let s = crate::resolve_import(specifier, referrer).unwrap();
-      Ok(s)
-    }
-
-    fn load(
-      &self,
-      module_specifier: &ModuleSpecifier,
-      _maybe_referrer: Option<&ModuleSpecifier>,
-      _is_dyn_import: bool,
-    ) -> Pin<Box<ModuleSourceFuture>> {
-      let code = format!("export default {};", self.0.get());
-      self.0.set(self.0.get() + 1);
-      let module_url = module_specifier.clone();
-      async move {
-        Ok(ModuleSource::new(
-          ModuleType::JavaScript,
-          code.into(),
-          &module_url,
-        ))
-      }
-      .boxed_local()
-    }
-  }
-
-  let loader = Rc::new(Loader(Cell::new(0)));
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    module_loader: Some(loader.clone()),
-    ..Default::default()
-  });
-  let main_realm = runtime.main_realm();
-  let other_realm = runtime
-    .create_realm(CreateRealmOptions {
-      module_loader: Some(loader.clone()),
-    })
-    .unwrap();
-  let other_realm2 = runtime
-    .create_realm(CreateRealmOptions {
-      module_loader: Some(loader),
-    })
-    .unwrap();
-
-  async fn load_test_module(runtime: &mut JsRuntime, realm: JsRealm) -> usize {
-    let id = realm
-      .load_side_module(
-        runtime.v8_isolate(),
-        &crate::resolve_url("file:///test.js").unwrap(),
-        None,
-      )
-      .await
-      .unwrap();
-    let receiver = realm.mod_evaluate(runtime.v8_isolate(), id);
-    runtime.run_event_loop(false).await.unwrap();
-    receiver.await.unwrap().unwrap();
-
-    let namespace = realm
-      .get_module_namespace(runtime.v8_isolate(), id)
-      .unwrap();
-    let mut scope = realm.handle_scope(runtime.v8_isolate());
-    let default_key = v8::String::new(&mut scope, "default").unwrap();
-    let default_value = namespace
-      .open(&mut scope)
-      .get(&mut scope, default_key.into())
-      .unwrap();
-    assert!(default_value.is_uint32());
-    default_value.uint32_value(&mut scope).unwrap() as usize
-  }
-
-  assert_eq!(load_test_module(&mut runtime, other_realm2).await, 0);
-  assert_eq!(load_test_module(&mut runtime, main_realm).await, 1);
-  assert_eq!(load_test_module(&mut runtime, other_realm).await, 2);
-}
-
-#[tokio::test]
-async fn test_cross_realm_imports() {
-  let loader: Rc<dyn ModuleLoader> = Rc::new(StaticModuleLoader::with(
-    Url::parse("file:///test.js").unwrap(),
-    ascii_str!("export default globalThis;"),
-  ));
-
-  let loader = Rc::new(loader);
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    module_loader: Some(Rc::clone(&loader)),
-    ..Default::default()
-  });
-  let main_realm = runtime.main_realm();
-  let other_realm = runtime
-    .create_realm(CreateRealmOptions {
-      module_loader: Some(Rc::clone(&loader)),
-    })
-    .unwrap();
-
-  fn import_wrapper_function(
-    realm: &JsRealm,
-    isolate: &mut v8::Isolate,
-  ) -> v8::Global<v8::Function> {
-    let value = realm
-      .execute_script_static(
-        isolate,
-        "",
-        r#"() => import("file:///test.js").then(ns => ns.default)"#,
-      )
-      .unwrap();
-
-    let mut scope = realm.handle_scope(isolate);
-    let value = v8::Local::new(&mut scope, value);
-    let function: v8::Local<v8::Function> = value.try_into().unwrap();
-    v8::Global::new(&mut scope, function)
-  }
-
-  let main_import_wrapper =
-    import_wrapper_function(&main_realm, runtime.v8_isolate());
-  let other_import_wrapper =
-    import_wrapper_function(&other_realm, runtime.v8_isolate());
-
-  async fn run_fn_test(
-    runtime: &mut JsRuntime,
-    realm: &JsRealm,
-    function: v8::Global<v8::Function>,
-  ) -> v8::Global<v8::Value> {
-    let promise = {
-      let mut scope = realm.handle_scope(runtime.v8_isolate());
-      let undefined = v8::undefined(&mut scope);
-      let promise = function
-        .open(&mut scope)
-        .call(&mut scope, undefined.into(), &[])
-        .unwrap();
-      assert!(promise.is_promise());
-      v8::Global::new(&mut scope, promise)
-    };
-    runtime.resolve_value(promise).await.unwrap()
-  }
-
-  // Same-realm imports.
-  assert_eq!(
-    run_fn_test(&mut runtime, &main_realm, main_import_wrapper.clone()).await,
-    main_realm.global_object(runtime.v8_isolate())
-  );
-  assert_eq!(
-    run_fn_test(&mut runtime, &other_realm, other_import_wrapper.clone()).await,
-    other_realm.global_object(runtime.v8_isolate())
-  );
-
-  // Cross-realm imports.
-  assert_eq!(
-    run_fn_test(&mut runtime, &main_realm, other_import_wrapper.clone()).await,
-    other_realm.global_object(runtime.v8_isolate())
-  );
-  assert_eq!(
-    run_fn_test(&mut runtime, &other_realm, main_import_wrapper.clone()).await,
-    main_realm.global_object(runtime.v8_isolate())
-  );
-}
-
-// Make sure that loading and evaluating top-level-imported modules in
-// different realms at the same time works.
-#[tokio::test]
-async fn test_realms_concurrent_module_evaluations() {
-  let loader: Rc<dyn ModuleLoader> = Rc::new(StaticModuleLoader::with(
-    Url::parse("file:///test.js").unwrap(),
-    ascii_str!(r#"await Deno.core.opAsync("op_wait");"#),
-  ));
-
-  #[op2(async)]
-  async fn op_wait(op_state: Rc<RefCell<OpState>>) {
-    let (sender, receiver) = oneshot::channel::<()>();
-    op_state
-      .borrow_mut()
-      .borrow_mut::<Vec<oneshot::Sender<()>>>()
-      .push(sender);
-    receiver.await.unwrap();
-  }
-  deno_core::extension!(test_ext, ops = [op_wait]);
-
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    extensions: vec![test_ext::init_ops()],
-    module_loader: Some(Rc::clone(&loader)),
-    ..Default::default()
-  });
-  runtime
-    .op_state()
-    .borrow_mut()
-    .put::<Vec<oneshot::Sender<()>>>(vec![]);
-
-  let main_realm = runtime.main_realm();
-  let other_realm = runtime
-    .create_realm(CreateRealmOptions {
-      module_loader: Some(loader),
-    })
-    .unwrap();
-
-  let main_realm_id = main_realm
-    .load_main_module(
-      runtime.v8_isolate(),
-      &crate::resolve_url("file:///test.js").unwrap(),
-      None,
-    )
-    .await
-    .unwrap();
-  let main_realm_receiver =
-    main_realm.mod_evaluate(runtime.v8_isolate(), main_realm_id);
-
-  let other_realm_id = other_realm
-    .load_main_module(
-      runtime.v8_isolate(),
-      &crate::resolve_url("file:///test.js").unwrap(),
-      None,
-    )
-    .await
-    .unwrap();
-  let other_realm_receiver =
-    other_realm.mod_evaluate(runtime.v8_isolate(), other_realm_id);
-
-  poll_fn(|cx| {
-    let res = runtime.poll_event_loop(cx, false);
-    assert!(matches!(res, Poll::Pending));
-    Poll::Ready(())
-  })
-  .await;
-
-  // Resolve the promises
-  {
-    let senders = runtime
-      .op_state()
-      .borrow_mut()
-      .take::<Vec<oneshot::Sender<()>>>();
-    for sender in senders {
-      sender.send(()).unwrap();
-    }
-  }
-
-  runtime.run_event_loop(false).await.unwrap();
-  assert!(matches!(main_realm_receiver.await, Ok(Ok(()))));
-  assert!(matches!(other_realm_receiver.await, Ok(Ok(()))));
-}
-
 #[test]
 fn es_snapshot() {
   let startup_data = {
@@ -749,6 +139,7 @@ fn es_snapshot() {
 
     let runtime = JsRuntimeForSnapshot::new(RuntimeOptions {
       extensions: vec![extension],
+      module_loader: Some(Rc::new(StaticModuleLoader::new([]))),
       ..Default::default()
     });
     runtime.snapshot()
@@ -760,18 +151,12 @@ fn es_snapshot() {
     ..Default::default()
   });
 
-  let realm = runtime
-    .create_realm(CreateRealmOptions {
-      module_loader: Some(Rc::new(StaticModuleLoader::new([]))),
-    })
-    .unwrap();
-
   // The module was evaluated ahead of time
   {
-    let global_test = realm
-      .execute_script_static(runtime.v8_isolate(), "", "globalThis.TEST")
+    let global_test = runtime
+      .execute_script_static("", "globalThis.TEST")
       .unwrap();
-    let scope = &mut realm.handle_scope(runtime.v8_isolate());
+    let scope = &mut runtime.handle_scope();
     let global_test = v8::Local::new(scope, global_test);
     assert!(global_test.is_string());
     assert_eq!(global_test.to_rust_string_lossy(scope).as_str(), "foo");
@@ -779,9 +164,8 @@ fn es_snapshot() {
 
   // The module can be imported
   {
-    let test_export_promise = realm
+    let test_export_promise = runtime
       .execute_script_static(
-        runtime.v8_isolate(),
         "",
         "import('mod:test').then(module => module.TEST)",
       )
@@ -790,69 +174,9 @@ fn es_snapshot() {
       futures::executor::block_on(runtime.resolve_value(test_export_promise))
         .unwrap();
 
-    let scope = &mut realm.handle_scope(runtime.v8_isolate());
+    let scope = &mut runtime.handle_scope();
     let test_export = v8::Local::new(scope, test_export);
     assert!(test_export.is_string());
     assert_eq!(test_export.to_rust_string_lossy(scope).as_str(), "bar");
   }
 }
-
-#[test]
-fn es_snapshot_without_runtime_module_loader_in_realm() {
-  generic_es_snapshot_without_runtime_module_loader(true)
-}
-
-#[test]
-fn preserve_snapshotted_modules() {
-  generic_preserve_snapshotted_modules_test(true, true)
-}
-
-/// Test that `RuntimeOptions::preserve_snapshotted_modules` also works without
-/// a snapshot.
-#[test]
-fn non_snapshot_preserve_snapshotted_modules() {
-  generic_preserve_snapshotted_modules_test(false, true)
-}
-
-/// Test that creating a realm while there are async ops running in another
-/// realm will not block until the async ops are resolved. This used to happen
-/// with non-snapshotted ESM extensions.
-#[tokio::test]
-async fn realm_creation_during_async_op_hang() {
-  #[op2(async)]
-  async fn op_listen(op_state: Rc<RefCell<OpState>>) -> Result<(), Error> {
-    let (sender, receiver) = oneshot::channel::<()>();
-    op_state.borrow_mut().put(sender);
-    receiver.await?;
-    Ok(())
-  }
-
-  let extension = Extension {
-    name: "test_ext",
-    ops: Cow::Borrowed(&[op_listen::DECL]),
-    esm_files: Cow::Borrowed(&[ExtensionFileSource {
-      specifier: "mod:test",
-      code: ExtensionFileSourceCode::IncludedInBinary(""),
-    }]),
-    esm_entry_point: Some("mod:test"),
-    ..Default::default()
-  };
-
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    extensions: vec![extension],
-    ..Default::default()
-  });
-
-  // Start the op in the main realm.
-  {
-    let promise: v8::Local<v8::Promise> = JsRuntime::eval(
-      &mut runtime.handle_scope(),
-      "Deno.core.opAsync('op_listen')",
-    )
-    .unwrap();
-    assert_eq!(promise.state(), v8::PromiseState::Pending);
-  }
-
-  // Create another realm. The test succeeds if this operation doesn't hang.
-  runtime.create_realm(Default::default()).unwrap();
-}
diff --git a/core/runtime/tests/misc.rs b/core/runtime/tests/misc.rs
index d5427f1..9efc43c 100644
--- a/core/runtime/tests/misc.rs
+++ b/core/runtime/tests/misc.rs
@@ -147,7 +147,7 @@ async fn test_poll_value() {
     let value_global = runtime
       .execute_script_static("a.js", "Promise.resolve(1 + 2)")
       .unwrap();
-    let v = runtime.poll_value(&value_global, cx);
+    let v = runtime.poll_value(cx, &value_global);
     {
       let scope = &mut runtime.handle_scope();
       assert!(
@@ -161,7 +161,7 @@ async fn test_poll_value() {
         "Promise.resolve(new Promise(resolve => resolve(2 + 2)))",
       )
       .unwrap();
-    let v = runtime.poll_value(&value_global, cx);
+    let v = runtime.poll_value(cx, &value_global);
     {
       let scope = &mut runtime.handle_scope();
       assert!(
@@ -172,7 +172,7 @@ async fn test_poll_value() {
     let value_global = runtime
       .execute_script_static("a.js", "Promise.reject(new Error('fail'))")
       .unwrap();
-    let v = runtime.poll_value(&value_global, cx);
+    let v = runtime.poll_value(cx, &value_global);
     assert!(
       matches!(v, Poll::Ready(Err(e)) if e.downcast_ref::<JsError>().unwrap().exception_message == "Uncaught Error: fail")
     );
@@ -180,7 +180,7 @@ async fn test_poll_value() {
     let value_global = runtime
       .execute_script_static("a.js", "new Promise(resolve => {})")
       .unwrap();
-    let v = runtime.poll_value(&value_global, cx);
+    let v = runtime.poll_value(cx, &value_global);
     matches!(v, Poll::Ready(Err(e)) if e.to_string() == "Promise resolution is still pending but the event loop has already resolved.");
     Poll::Ready(())
   }).await;
@@ -957,23 +957,16 @@ async fn test_stalled_tla() {
     Url::parse("file:///test.js").unwrap(),
     ascii_str!("await new Promise(() => {});"),
   );
-  let mut runtime = JsRuntime::new(Default::default());
-  let realm = runtime
-    .create_realm(CreateRealmOptions {
-      module_loader: Some(Rc::new(loader)),
-    })
-    .unwrap();
-
-  let module_id = realm
-    .load_main_module(
-      runtime.v8_isolate(),
-      &crate::resolve_url("file:///test.js").unwrap(),
-      None,
-    )
+  let mut runtime = JsRuntime::new(RuntimeOptions {
+    module_loader: Some(Rc::new(loader)),
+    ..Default::default()
+  });
+  let module_id = runtime
+    .load_main_module(&crate::resolve_url("file:///test.js").unwrap(), None)
     .await
     .unwrap();
   #[allow(clippy::let_underscore_future)]
-  let _ = realm.mod_evaluate(runtime.v8_isolate(), module_id);
+  let _ = runtime.mod_evaluate(module_id);
 
   let error = runtime.run_event_loop(false).await.unwrap_err();
   let js_error = error.downcast::<JsError>().unwrap();
diff --git a/core/runtime/tests/snapshot.rs b/core/runtime/tests/snapshot.rs
index c087f53..fbf9b0d 100644
--- a/core/runtime/tests/snapshot.rs
+++ b/core/runtime/tests/snapshot.rs
@@ -3,7 +3,6 @@ use crate::extensions::Op;
 use crate::modules::AssertedModuleType;
 use crate::modules::LoggingModuleLoader;
 use crate::modules::ModuleInfo;
-use crate::modules::ModuleType;
 use crate::*;
 use anyhow::Error;
 use std::borrow::Cow;
@@ -162,7 +161,7 @@ fn es_snapshot() {
         specifier: format!("file:///{prev}.js"),
         asserted_module_type: AssertedModuleType::JavaScriptOrWasm,
       }],
-      module_type: ModuleType::JavaScript,
+      module_type: AssertedModuleType::JavaScriptOrWasm,
     }
   }
 
@@ -199,7 +198,7 @@ fn es_snapshot() {
     main: false,
     name: specifier.into(),
     requests: vec![],
-    module_type: ModuleType::JavaScript,
+    module_type: AssertedModuleType::JavaScriptOrWasm,
   });
 
   modules.extend((1..200).map(|i| create_module(&mut runtime, i, false)));
@@ -253,9 +252,8 @@ fn es_snapshot() {
   }
 }
 
-pub(crate) fn generic_es_snapshot_without_runtime_module_loader(
-  test_realms: bool,
-) {
+#[test]
+pub(crate) fn es_snapshot_without_runtime_module_loader() {
   let startup_data = {
     let extension = Extension {
       name: "module_snapshot",
@@ -277,27 +275,12 @@ pub(crate) fn generic_es_snapshot_without_runtime_module_loader(
     runtime.snapshot()
   };
 
-  let mut runtime;
-  let realm;
-  if test_realms {
-    runtime = JsRuntime::new(RuntimeOptions {
-      module_loader: Some(Rc::new(StaticModuleLoader::new([]))),
-      startup_snapshot: Some(Snapshot::JustCreated(startup_data)),
-      ..Default::default()
-    });
-    realm = runtime
-      .create_realm(CreateRealmOptions {
-        module_loader: None,
-      })
-      .unwrap();
-  } else {
-    runtime = JsRuntime::new(RuntimeOptions {
-      module_loader: None,
-      startup_snapshot: Some(Snapshot::JustCreated(startup_data)),
-      ..Default::default()
-    });
-    realm = runtime.main_realm();
-  }
+  let mut runtime = JsRuntime::new(RuntimeOptions {
+    module_loader: None,
+    startup_snapshot: Some(Snapshot::JustCreated(startup_data)),
+    ..Default::default()
+  });
+  let realm = runtime.main_realm();
 
   // Make sure the module was evaluated.
   {
@@ -339,15 +322,7 @@ pub(crate) fn generic_es_snapshot_without_runtime_module_loader(
   );
 }
 
-#[test]
-fn es_snapshot_without_runtime_module_loader() {
-  generic_es_snapshot_without_runtime_module_loader(false)
-}
-
-pub(crate) fn generic_preserve_snapshotted_modules_test(
-  test_snapshot: bool,
-  test_realms: bool,
-) {
+pub(crate) fn generic_preserve_snapshotted_modules_test(test_snapshot: bool) {
   let extension = Extension {
     name: "module_snapshot",
     esm_files: Cow::Borrowed(&[
@@ -392,15 +367,7 @@ pub(crate) fn generic_preserve_snapshotted_modules_test(
     })
   };
 
-  let realm = if test_realms {
-    runtime
-      .create_realm(CreateRealmOptions {
-        module_loader: Some(loader.clone()),
-      })
-      .unwrap()
-  } else {
-    runtime.main_realm()
-  };
+  let realm = runtime.main_realm();
 
   // We can't import "test:not-preserved"
   {
@@ -452,12 +419,12 @@ pub(crate) fn generic_preserve_snapshotted_modules_test(
 
 #[test]
 fn preserve_snapshotted_modules() {
-  generic_preserve_snapshotted_modules_test(true, false)
+  generic_preserve_snapshotted_modules_test(true)
 }
 
 /// Test that `RuntimeOptions::preserve_snapshotted_modules` also works without
 /// a snapshot.
 #[test]
 fn non_snapshot_preserve_snapshotted_modules() {
-  generic_preserve_snapshotted_modules_test(false, false)
+  generic_preserve_snapshotted_modules_test(false)
 }