Repository: denoland/deno (language: rust)

Issue:
`deno check` occasionally fails on `fetch` signature with no http client
Version: Deno 2.2.0

This is a regression in 2.2.0, where `deno check` checks against the `fetch` in `lib.deno.shared_globals.d.ts` instead of `lib.deno.fetch.d.ts`. I suspect a broken cache causing this because it does not always happen.

The most minimal repro case I could produce:

```ts
// bug.ts
import { stub } from "jsr:@std/testing@1.0.9/mock";
const stubbed = stub(globalThis, "fetch");
await stubbed.original.call(globalThis, "https://www.example.com", {});
```

```sh
> deno check -r bug.ts
Check file:///Users/tugrul/Code/bug-deno-fetch-check-signature/bug.ts
TS2345 [ERROR]: Argument of type '{}' is not assignable to parameter of type 'RequestInit & { client: HttpClient; }'.
  Property 'client' is missing in type '{}' but required in type '{ client: HttpClient; }'.
await stubbed.original.call(globalThis, "https://www.example.com", {});
                                                                   ~~
    at file:///Users/tugrul/Code/bug-deno-fetch-check-signature/bug.ts:4:68

    'client' is declared here.
      init?: RequestInit & { client: Deno.HttpClient },
                             ~~~~~~
        at asset:///lib.deno.shared_globals.d.ts:754:26

error: Type checking failed.
```

I was able to find the culprit commit as well (#28056).

```
2.2.0,                                     # fail
33bccf9090e8764790be84e56fe0988600ffe31a,  # fail: perf(check): use v8 code cache for extension sources in deno check (#28089)
a2afae46b616e9ca087ce09539a56c2fc159f49d,  # fail
23540c2825ddf838444279a394909d0888bd3dcb,  # fail: refactor: remove tsc snapshot (#28056)
07410d19cf30d102f7aa1874c4f716934d0d0137,  # pass
b9183c737ffe727b24c141bb0ffb13df39ed126b,  # pass
a5a1cce50d7c48a373ac2381b309e253601a2321,  # pass: feat(ext/cache): support lscache (#27628)
2.1.10                                     # pass
```

You can find the repro code, and bisecting results [here](https://github.com/tugrulates/deno-bug-28201/actions/runs/13436815644).


Discussion / hints:
Yeah, weird. When I run with `--reload` it goes away (edit: it sometimes goes away. I see the issue and will open a PR in a second).

Fix patch:
diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs
index c25269d8dc640d..9bea10ef300577 100644
--- a/cli/lsp/documents.rs
+++ b/cli/lsp/documents.rs
@@ -23,7 +23,6 @@ use deno_core::futures::future;
 use deno_core::futures::future::Shared;
 use deno_core::futures::FutureExt;
 use deno_core::parking_lot::Mutex;
-use deno_core::parking_lot::RwLock;
 use deno_core::resolve_url;
 use deno_core::ModuleSpecifier;
 use deno_error::JsErrorBox;
@@ -52,7 +51,6 @@ use super::testing::TestModule;
 use super::text::LineIndex;
 use super::tsc;
 use crate::graph_util::CliJsrUrlProvider;
-use crate::tsc::MaybeStaticSource;
 
 pub const DOCUMENT_SCHEMES: [&str; 5] =
   ["data", "blob", "file", "http", "https"];
@@ -188,14 +186,14 @@ impl IndexValid {
 #[derive(Debug)]
 pub struct AssetDocument {
   specifier: ModuleSpecifier,
-  text: MaybeStaticSource,
+  text: &'static str,
   line_index: Arc<LineIndex>,
   maybe_navigation_tree: Mutex<Option<Arc<tsc::NavigationTree>>>,
 }
 
 impl AssetDocument {
-  pub fn new(specifier: ModuleSpecifier, text: MaybeStaticSource) -> Self {
-    let line_index = Arc::new(LineIndex::new(text.as_ref()));
+  pub fn new(specifier: ModuleSpecifier, text: &'static str) -> Self {
+    let line_index = Arc::new(LineIndex::new(text));
     Self {
       specifier,
       text,
@@ -215,8 +213,8 @@ impl AssetDocument {
     *self.maybe_navigation_tree.lock() = Some(navigation_tree);
   }
 
-  pub fn text(&self) -> MaybeStaticSource {
-    self.text.clone()
+  pub fn text(&self) -> &'static str {
+    self.text
   }
 
   pub fn line_index(&self) -> Arc<LineIndex> {
@@ -230,32 +228,30 @@ impl AssetDocument {
 
 #[derive(Debug)]
 pub struct AssetDocuments {
-  inner: RwLock<HashMap<ModuleSpecifier, Arc<AssetDocument>>>,
+  inner: HashMap<ModuleSpecifier, Arc<AssetDocument>>,
 }
 
 impl AssetDocuments {
   pub fn contains_key(&self, k: &ModuleSpecifier) -> bool {
-    self.inner.read().contains_key(k)
+    self.inner.contains_key(k)
   }
 
   pub fn get(&self, k: &ModuleSpecifier) -> Option<Arc<AssetDocument>> {
-    self.inner.read().get(k).cloned()
+    self.inner.get(k).cloned()
   }
 }
 
 pub static ASSET_DOCUMENTS: Lazy<AssetDocuments> =
   Lazy::new(|| AssetDocuments {
-    inner: RwLock::new(
-      crate::tsc::LAZILY_LOADED_STATIC_ASSETS
-        .iter()
-        .map(|(k, v)| {
-          let url_str = format!("asset:///{k}");
-          let specifier = resolve_url(&url_str).unwrap();
-          let asset = Arc::new(AssetDocument::new(specifier.clone(), v.get()));
-          (specifier, asset)
-        })
-        .collect(),
-    ),
+    inner: crate::tsc::LAZILY_LOADED_STATIC_ASSETS
+      .iter()
+      .map(|(k, v)| {
+        let url_str = format!("asset:///{k}");
+        let specifier = resolve_url(&url_str).unwrap();
+        let asset = Arc::new(AssetDocument::new(specifier.clone(), v.as_str()));
+        (specifier, asset)
+      })
+      .collect(),
   });
 
 #[derive(Debug, Clone)]
@@ -296,12 +292,17 @@ impl AssetOrDocument {
     }
   }
 
-  pub fn text(&self) -> MaybeStaticSource {
+  pub fn text_str(&self) -> &str {
     match self {
       AssetOrDocument::Asset(a) => a.text(),
-      AssetOrDocument::Document(d) => {
-        MaybeStaticSource::Computed(d.text.clone())
-      }
+      AssetOrDocument::Document(d) => d.text.as_ref(),
+    }
+  }
+
+  pub fn text_fast_string(&self) -> deno_core::FastString {
+    match self {
+      AssetOrDocument::Asset(a) => deno_core::FastString::from_static(a.text()),
+      AssetOrDocument::Document(d) => d.text.clone().into(),
     }
   }
 
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 724e8f9bfa4154..df7c00d3bdb218 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -2786,7 +2786,7 @@ impl Inner {
             }
             Ok(span.to_folding_range(
               asset_or_doc.line_index(),
-              asset_or_doc.text().as_ref().as_bytes(),
+              asset_or_doc.text_str().as_bytes(),
               self.config.line_folding_only_capable(),
             ))
           })
@@ -4403,12 +4403,9 @@ impl Inner {
       && specifier.path() == "/status.md"
     {
       let mut contents = String::new();
-      let mut documents_specifiers = self
-        .documents
-        .documents(DocumentsFilter::All)
-        .into_iter()
-        .map(|d| d.specifier().clone())
-        .collect::<Vec<_>>();
+      let documents = self.documents.documents(DocumentsFilter::All);
+      let mut documents_specifiers =
+        documents.iter().map(|d| d.specifier()).collect::<Vec<_>>();
       documents_specifiers.sort();
       let measures = self.performance.to_vec();
       let workspace_settings = self.config.workspace_settings();
@@ -4445,8 +4442,8 @@ impl Inner {
         documents_specifiers.len(),
         documents_specifiers
           .into_iter()
-          .map(|s| s.to_string())
-          .collect::<Vec<String>>()
+          .map(|s| s.as_str())
+          .collect::<Vec<&str>>()
           .join("\n    - "),
         measures.len(),
         measures
@@ -4484,7 +4481,7 @@ impl Inner {
     } else {
       let asset_or_doc = self.get_maybe_asset_or_document(&specifier);
       if let Some(asset_or_doc) = asset_or_doc {
-        Some(asset_or_doc.text().to_string())
+        Some(asset_or_doc.text_str().to_string())
       } else {
         error!("The source was not found: {}", specifier);
         None
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index 5771301f058e49..29bd0c3ba60c18 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -97,7 +97,6 @@ use super::urls::INVALID_URI;
 use crate::args::jsr_url;
 use crate::args::FmtOptionsConfig;
 use crate::lsp::logging::lsp_warn;
-use crate::tsc::MaybeStaticSource;
 use crate::tsc::ResolveArgs;
 use crate::tsc::MISSING_DEPENDENCY_SPECIFIER;
 use crate::util::path::relative_specifier;
@@ -4504,7 +4503,7 @@ enum LoadError {
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 struct LoadResponse {
-  data: MaybeStaticSource,
+  data: deno_core::FastString,
   script_kind: i32,
   version: Option<String>,
   is_cjs: bool,
@@ -4522,22 +4521,23 @@ fn op_load<'s>(
     .performance
     .mark_with_args("tsc.op.op_load", specifier);
   let specifier = state.specifier_map.normalize(specifier)?;
+  let asset_or_document = if specifier.as_str() == MISSING_DEPENDENCY_SPECIFIER
+  {
+    None
+  } else {
+    state.get_asset_or_document(&specifier)
+  };
   let maybe_load_response =
-    if specifier.as_str() == MISSING_DEPENDENCY_SPECIFIER {
-      None
-    } else {
-      let asset_or_document = state.get_asset_or_document(&specifier);
-      asset_or_document.map(|doc| LoadResponse {
-        data: doc.text(),
-        script_kind: crate::tsc::as_ts_script_kind(doc.media_type()),
-        version: state.script_version(&specifier),
-        is_cjs: doc
-          .document()
-          .map(|d| d.resolution_mode())
-          .unwrap_or(ResolutionMode::Import)
-          == ResolutionMode::Require,
-      })
-    };
+    asset_or_document.as_ref().map(|doc| LoadResponse {
+      data: doc.text_fast_string(),
+      script_kind: crate::tsc::as_ts_script_kind(doc.media_type()),
+      version: state.script_version(&specifier),
+      is_cjs: doc
+        .document()
+        .map(|d| d.resolution_mode())
+        .unwrap_or(ResolutionMode::Import)
+        == ResolutionMode::Require,
+    });
   let serialized = serde_v8::to_v8(scope, maybe_load_response)?;
   state.performance.measure(mark);
   Ok(serialized)
@@ -5074,10 +5074,10 @@ deno_core::extension!(deno_tsc,
   },
   customizer = |ext: &mut deno_core::Extension| {
     use deno_core::ExtensionFileSource;
-    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_tsc/99_main_compiler.js", crate::tsc::MAIN_COMPILER_SOURCE.get().into()));
-    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_tsc/97_ts_host.js", crate::tsc::TS_HOST_SOURCE.get().into()));
-    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_tsc/98_lsp.js", crate::tsc::LSP_SOURCE.get().into()));
-    ext.js_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/00_typescript.js", crate::tsc::TYPESCRIPT_SOURCE.get().into()));
+    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_tsc/99_main_compiler.js", crate::tsc::MAIN_COMPILER_SOURCE.as_str().into()));
+    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_tsc/97_ts_host.js", crate::tsc::TS_HOST_SOURCE.as_str().into()));
+    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_tsc/98_lsp.js", crate::tsc::LSP_SOURCE.as_str().into()));
+    ext.js_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/00_typescript.js", crate::tsc::TYPESCRIPT_SOURCE.as_str().into()));
     ext.esm_entry_point = Some("ext:deno_tsc/99_main_compiler.js");
   }
 );
diff --git a/cli/tsc/dts/lib.deno.shared_globals.d.ts b/cli/tsc/dts/lib.deno.shared_globals.d.ts
index a469525270b588..6fe18b2379e26c 100644
--- a/cli/tsc/dts/lib.deno.shared_globals.d.ts
+++ b/cli/tsc/dts/lib.deno.shared_globals.d.ts
@@ -750,6 +750,6 @@ interface ErrorConstructor {
  * @category Fetch
  */
 declare function fetch(
-  input: Request | URL | string,
-  init?: RequestInit & { client: Deno.HttpClient },
+  input: RequestInfo | URL,
+  init?: RequestInit & { client?: Deno.HttpClient },
 ): Promise<Response>;
diff --git a/cli/tsc/dts/lib.deno_fetch.d.ts b/cli/tsc/dts/lib.deno_fetch.d.ts
index 2be844f0f8f92d..2a51259d1a7f90 100644
--- a/cli/tsc/dts/lib.deno_fetch.d.ts
+++ b/cli/tsc/dts/lib.deno_fetch.d.ts
@@ -408,7 +408,7 @@ declare var Response: {
  * @category Fetch
  */
 declare function fetch(
-  input: URL | Request | string,
+  input: RequestInfo | URL,
   init?: RequestInit,
 ): Promise<Response>;
 
diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs
index a62fb4dd70054a..d6fb26b24c9af3 100644
--- a/cli/tsc/mod.rs
+++ b/cli/tsc/mod.rs
@@ -10,7 +10,6 @@ use std::sync::OnceLock;
 
 use deno_ast::MediaType;
 use deno_core::anyhow::Context;
-use deno_core::error::AnyError;
 use deno_core::located_script_name;
 use deno_core::op2;
 use deno_core::resolve_url_or_path;
@@ -20,6 +19,7 @@ use deno_core::serde::Serialize;
 use deno_core::serde::Serializer;
 use deno_core::serde_json::json;
 use deno_core::url::Url;
+use deno_core::FastString;
 use deno_core::JsRuntime;
 use deno_core::ModuleSpecifier;
 use deno_core::OpState;
@@ -34,6 +34,7 @@ use deno_lib::worker::create_isolate_create_params;
 use deno_resolver::npm::managed::ResolvePkgFolderFromDenoModuleError;
 use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
 use deno_semver::npm::NpmPackageReqReference;
+use indexmap::IndexMap;
 use node_resolver::errors::NodeJsErrorCode;
 use node_resolver::errors::NodeJsErrorCoded;
 use node_resolver::errors::PackageSubpathResolveError;
@@ -60,12 +61,6 @@ pub use self::diagnostics::Diagnostics;
 pub use self::diagnostics::Position;
 
 pub fn get_types_declaration_file_text() -> String {
-  let mut assets = get_asset_texts()
-    .unwrap()
-    .into_iter()
-    .map(|a| (a.specifier, a.text))
-    .collect::<HashMap<_, _>>();
-
   let lib_names = vec![
     "deno.ns",
     "deno.console",
@@ -88,24 +83,16 @@ pub fn get_types_declaration_file_text() -> String {
   lib_names
     .into_iter()
     .map(|name| {
-      let asset_url = format!("asset:///lib.{name}.d.ts");
-      assets.remove(&asset_url).unwrap()
+      let lib_name = format!("lib.{name}.d.ts");
+      LAZILY_LOADED_STATIC_ASSETS
+        .get(lib_name.as_str())
+        .unwrap()
+        .as_str()
     })
     .collect::<Vec<_>>()
     .join("\n")
 }
 
-fn get_asset_texts() -> Result<Vec<AssetText>, AnyError> {
-  let mut out = Vec::with_capacity(LAZILY_LOADED_STATIC_ASSETS.len());
-  for (name, text) in LAZILY_LOADED_STATIC_ASSETS.iter() {
-    out.push(AssetText {
-      specifier: format!("asset:///{name}"),
-      text: text.to_string(),
-    });
-  }
-  Ok(out)
-}
-
 macro_rules! maybe_compressed_source {
   ($file: expr) => {{
     maybe_compressed_source!(compressed = $file, uncompressed = $file)
@@ -156,78 +143,20 @@ pub enum StaticAssetSource {
   Owned(&'static str, std::sync::OnceLock<Arc<str>>),
 }
 
-/// Like a `Cow` but the owned form is an `Arc<str>` instead of `String`
-#[derive(Debug, Clone, Serialize)]
-#[serde(untagged)]
-pub enum MaybeStaticSource {
-  Computed(Arc<str>),
-  Static(&'static str),
-}
-
-impl std::fmt::Display for MaybeStaticSource {
-  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    match self {
-      MaybeStaticSource::Computed(arc) => write!(f, "{}", arc),
-      MaybeStaticSource::Static(s) => write!(f, "{}", s),
-    }
-  }
-}
-
-impl From<MaybeStaticSource> for Cow<'static, str> {
-  fn from(value: MaybeStaticSource) -> Self {
-    match value {
-      MaybeStaticSource::Computed(arc) => Cow::Owned(arc.to_string()),
-      MaybeStaticSource::Static(s) => Cow::Borrowed(s),
-    }
-  }
-}
-
-impl AsRef<str> for MaybeStaticSource {
-  fn as_ref(&self) -> &str {
-    match self {
-      MaybeStaticSource::Computed(arc) => arc.as_ref(),
-      MaybeStaticSource::Static(s) => s,
-    }
-  }
-}
-
-impl From<MaybeStaticSource> for String {
-  fn from(value: MaybeStaticSource) -> Self {
-    match value {
-      MaybeStaticSource::Computed(arc) => arc.to_string(),
-      MaybeStaticSource::Static(s) => s.into(),
-    }
-  }
-}
-
-impl From<MaybeStaticSource> for Arc<str> {
-  fn from(value: MaybeStaticSource) -> Self {
-    match value {
-      MaybeStaticSource::Computed(arc) => arc,
-      MaybeStaticSource::Static(s) => Arc::from(s),
-    }
-  }
-}
-
 impl StaticAssetSource {
-  pub fn get(&self) -> MaybeStaticSource {
+  pub fn as_str(&'static self) -> &'static str {
     match self {
       StaticAssetSource::Compressed(compressed_source) => {
-        MaybeStaticSource::Computed(compressed_source.get())
+        compressed_source.get()
       }
-      StaticAssetSource::Uncompressed(src) => MaybeStaticSource::Static(src),
+      StaticAssetSource::Uncompressed(src) => src,
       StaticAssetSource::Owned(path, cell) => {
         let str =
           cell.get_or_init(|| std::fs::read_to_string(path).unwrap().into());
-        MaybeStaticSource::Computed((*str).clone())
+        str.as_ref()
       }
     }
   }
-
-  #[allow(clippy::inherent_to_string)]
-  pub fn to_string(&self) -> String {
-    self.get().into()
-  }
 }
 
 /// Contains static assets that are not preloaded in the compiler snapshot.
@@ -235,9 +164,9 @@ impl StaticAssetSource {
 /// We lazily load these because putting them in the compiler snapshot will
 /// increase memory usage when not used (last time checked by about 0.5MB).
 pub static LAZILY_LOADED_STATIC_ASSETS: Lazy<
-  HashMap<&'static str, StaticAssetSource>,
+  IndexMap<&'static str, StaticAssetSource>,
 > = Lazy::new(|| {
-  ([
+  IndexMap::from([
     // compressed in build.rs
     maybe_compressed_lib!("lib.deno.console.d.ts", "lib.deno_console.d.ts"),
     maybe_compressed_lib!("lib.deno.url.d.ts", "lib.deno_url.d.ts"),
@@ -367,9 +296,6 @@ pub static LAZILY_LOADED_STATIC_ASSETS: Lazy<
       ),
     ),
   ])
-  .iter()
-  .cloned()
-  .collect()
 });
 
 /// A structure representing stats from a type check operation for a graph.
@@ -406,16 +332,9 @@ impl fmt::Display for Stats {
   }
 }
 
-#[derive(Debug, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct AssetText {
-  pub specifier: String,
-  pub text: String,
-}
-
 /// Retrieve a static asset that are included in the binary.
-fn get_lazily_loaded_asset(asset: &str) -> Option<MaybeStaticSource> {
-  LAZILY_LOADED_STATIC_ASSETS.get(asset).map(|s| s.get())
+fn get_lazily_loaded_asset(asset: &str) -> Option<&'static str> {
+  LAZILY_LOADED_STATIC_ASSETS.get(asset).map(|s| s.as_str())
 }
 
 fn get_maybe_hash(
@@ -713,7 +632,7 @@ pub enum LoadError {
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 struct LoadResponse {
-  data: String,
+  data: FastString,
   version: Option<String>,
   script_kind: i32,
   is_cjs: bool,
@@ -737,7 +656,7 @@ fn op_load_inner(
     npm_state: Option<&RequestNpmState>,
     media_type: &mut MediaType,
     is_cjs: &mut bool,
-  ) -> Result<String, LoadError> {
+  ) -> Result<FastString, LoadError> {
     *media_type = MediaType::from_specifier(specifier);
     let file_path = specifier.to_file_path().unwrap();
     let code = std::fs::read_to_string(&file_path).map_err(|err| {
@@ -752,8 +671,7 @@ fn op_load_inner(
         npm_state.cjs_tracker.is_cjs(specifier, *media_type, &code)
       })
       .unwrap_or(false);
-    // todo(dsherret): how to avoid cloning here?
-    Ok(code.to_string())
+    Ok(code.into())
   }
 
   let state = state.borrow_mut::<State>();
@@ -766,16 +684,19 @@ fn op_load_inner(
   let mut is_cjs = false;
 
   let data = if load_specifier == "internal:///.tsbuildinfo" {
-    state.maybe_tsbuildinfo.as_deref().map(Cow::Borrowed)
+    state
+      .maybe_tsbuildinfo
+      .as_deref()
+      .map(|s| s.to_string().into())
   // in certain situations we return a "blank" module to tsc and we need to
   // handle the request for that module here.
   } else if load_specifier == MISSING_DEPENDENCY_SPECIFIER {
     None
   } else if let Some(name) = load_specifier.strip_prefix("asset:///") {
-    let maybe_source = get_lazily_loaded_asset(name).map(Cow::from);
-    hash = get_maybe_hash(maybe_source.as_deref(), state.hash_data);
+    let maybe_source = get_lazily_loaded_asset(name);
+    hash = get_maybe_hash(maybe_source, state.hash_data);
     media_type = MediaType::from_str(load_specifier);
-    maybe_source
+    maybe_source.map(FastString::from_static)
   } else {
     let specifier = if let Some(remapped_specifier) =
       state.maybe_remapped_specifier(load_specifier)
@@ -789,7 +710,7 @@ fn op_load_inner(
       Err(err) => match err {
         deno_graph::ModuleError::UnsupportedMediaType(_, media_type, _) => {
           return Ok(Some(LoadResponse {
-            data: "".to_string(),
+            data: FastString::from_static(""),
             version: Some("1".to_string()),
             script_kind: as_ts_script_kind(*media_type),
             is_cjs: false,
@@ -809,19 +730,20 @@ fn op_load_inner(
               module.is_script,
             )?;
           }
-          let source = module
-            .fast_check_module()
-            .map(|m| &*m.source)
-            .unwrap_or(&*module.source);
-          Some(Cow::Borrowed(source))
+          Some(
+            module
+              .fast_check_module()
+              .map(|m| FastString::from(m.source.clone()))
+              .unwrap_or(module.source.clone().into()),
+          )
         }
         Module::Json(module) => {
           media_type = MediaType::Json;
-          Some(Cow::Borrowed(&*module.source))
+          Some(FastString::from(module.source.clone()))
         }
         Module::Wasm(module) => {
           media_type = MediaType::Dts;
-          Some(Cow::Borrowed(&*module.source_dts))
+          Some(FastString::from(module.source_dts.clone()))
         }
         Module::Npm(_) | Module::Node(_) => None,
         Module::External(module) => {
@@ -833,12 +755,12 @@ fn op_load_inner(
               &CliSys::default(),
               &module.specifier,
             );
-            Some(Cow::Owned(load_from_node_modules(
+            Some(load_from_node_modules(
               &specifier,
               state.maybe_npm.as_ref(),
               &mut media_type,
               &mut is_cjs,
-            )?))
+            )?)
           }
         }
       }
@@ -847,12 +769,12 @@ fn op_load_inner(
       .as_ref()
       .filter(|npm| npm.node_resolver.in_npm_package(specifier))
     {
-      Some(Cow::Owned(load_from_node_modules(
+      Some(load_from_node_modules(
         specifier,
         Some(npm),
         &mut media_type,
         &mut is_cjs,
-      )?))
+      )?)
     } else {
       None
     };
@@ -863,7 +785,7 @@ fn op_load_inner(
     return Ok(None);
   };
   Ok(Some(LoadResponse {
-    data: data.into_owned(),
+    data,
     version: hash,
     script_kind: as_ts_script_kind(media_type),
     is_cjs,
@@ -1318,11 +1240,11 @@ impl CompressedSource {
       uncompressed: OnceLock::new(),
     }
   }
-  pub(crate) fn get(&self) -> Arc<str> {
+  pub(crate) fn get(&self) -> &str {
     self
       .uncompressed
       .get_or_init(|| decompress_source(self.bytes))
-      .clone()
+      .as_ref()
   }
 }
 
@@ -1374,10 +1296,10 @@ deno_core::extension!(deno_cli_tsc,
   },
   customizer = |ext: &mut deno_core::Extension| {
     use deno_core::ExtensionFileSource;
-    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/99_main_compiler.js", crate::tsc::MAIN_COMPILER_SOURCE.get().into()));
-    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/97_ts_host.js", crate::tsc::TS_HOST_SOURCE.get().into()));
-    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/98_lsp.js", crate::tsc::LSP_SOURCE.get().into()));
-    ext.js_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/00_typescript.js", crate::tsc::TYPESCRIPT_SOURCE.get().into()));
+    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/99_main_compiler.js", crate::tsc::MAIN_COMPILER_SOURCE.as_str().into()));
+    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/97_ts_host.js", crate::tsc::TS_HOST_SOURCE.as_str().into()));
+    ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/98_lsp.js", crate::tsc::LSP_SOURCE.as_str().into()));
+    ext.js_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/00_typescript.js", crate::tsc::TYPESCRIPT_SOURCE.as_str().into()));
     ext.esm_entry_point = Some("ext:deno_cli_tsc/99_main_compiler.js");
   }
 );
@@ -1727,7 +1649,7 @@ mod tests {
       .expect("should have invoked op")
       .expect("load should have succeeded");
     let expected = get_lazily_loaded_asset("lib.dom.d.ts").unwrap();
-    assert_eq!(actual.data, expected.to_string());
+    assert_eq!(actual.data.to_string(), expected.to_string());
     assert!(actual.version.is_some());
     assert_eq!(actual.script_kind, 3);
   }


Test patch:
diff --git a/tests/specs/check/instability_fetch/__test__.jsonc b/tests/specs/check/instability_fetch/__test__.jsonc
new file mode 100644
index 00000000000000..58c84ac573853a
--- /dev/null
+++ b/tests/specs/check/instability_fetch/__test__.jsonc
@@ -0,0 +1,5 @@
+{
+  "args": "check main.ts",
+  "output": "[WILDCARD]",
+  "exitCode": 0 // should be successful
+}
diff --git a/tests/specs/check/instability_fetch/main.ts b/tests/specs/check/instability_fetch/main.ts
new file mode 100644
index 00000000000000..3bf8aeccc863de
--- /dev/null
+++ b/tests/specs/check/instability_fetch/main.ts
@@ -0,0 +1,2 @@
+const fetch2 = globalThis["fetch"];
+await fetch2.call(globalThis, "https://www.example.com", {});