Repository: denoland/deno
Pull request #28737: fix(lsp): url_to_uri() encoding on windows
Author: login: nayeemrmn
Created: 2025-04-04T00:00:03Z | Merged: 2025-04-04T05:24:53Z

Fixes #28736.
Fixes #28743.

Linked issue #28736: Lsp doesn't work on Windows in canary
1. `deno upgrade canary`
1. Clone https://github.com/dsherret/bench-registry
1. Open in vscode on windows

Notice how there's no auto-complete or diagnostics.

Version: Deno 2.2.6+ec05282

Diff:
diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs
index d05200ca046088..68b44dcb99352a 100644
--- a/cli/lsp/diagnostics.rs
+++ b/cli/lsp/diagnostics.rs
@@ -1042,16 +1042,18 @@ async fn generate_ts_diagnostics(
   let mut enabled_modules_by_scope = BTreeMap::<_, Vec<_>>::new();
   let mut disabled_documents = Vec::new();
   for document in snapshot.document_modules.documents.open_docs() {
-    if let Some(module) = snapshot
-      .document_modules
-      .primary_module(&Document::Open(document.clone()))
-    {
-      if config.specifier_enabled(&module.specifier) {
-        enabled_modules_by_scope
-          .entry(module.scope.clone())
-          .or_default()
-          .push(module);
-        continue;
+    if document.is_diagnosable() {
+      if let Some(module) = snapshot
+        .document_modules
+        .primary_module(&Document::Open(document.clone()))
+      {
+        if config.specifier_enabled(&module.specifier) {
+          enabled_modules_by_scope
+            .entry(module.scope.clone())
+            .or_default()
+            .push(module);
+          continue;
+        }
       }
     }
     disabled_documents.push(document.clone());
diff --git a/cli/lsp/urls.rs b/cli/lsp/urls.rs
index 17466de7baa2c4..30df9947ed5861 100644
--- a/cli/lsp/urls.rs
+++ b/cli/lsp/urls.rs
@@ -1,5 +1,7 @@
 // Copyright 2018-2025 the Deno authors. MIT license.
 
+use std::path::Component;
+use std::path::Path;
 use std::path::PathBuf;
 use std::str::FromStr;
 
@@ -82,29 +84,21 @@ pub fn url_to_uri(url: &Url) -> Result<Uri, AnyError> {
   let components = deno_core::url::quirks::internal_components(url);
   let mut input = String::with_capacity(url.as_str().len());
   input.push_str(&url.as_str()[..components.path_start as usize]);
-  if cfg!(windows) && url.scheme() == "file" {
-    let path = url.path();
-    let mut chars = path.chars();
-    let has_drive_letter = chars.next().is_some_and(|c| c == '/')
-      && chars.next().is_some_and(|c| c.is_ascii_alphabetic())
-      && chars.next().is_some_and(|c| c == ':')
-      && chars.next().is_none_or(|c| c == '/');
-    if has_drive_letter {
-      input.push_str(&path[..3]);
-      input.push_str(
-        &percent_encoding::utf8_percent_encode(&path[3..], URL_TO_URI_PATH)
-          .to_string(),
-      );
-    } else {
-      input.push_str(
-        &percent_encoding::utf8_percent_encode(path, URL_TO_URI_PATH)
-          .to_string(),
-      );
-    }
+  let path = url.path();
+  let mut chars = path.chars();
+  let has_drive_letter = chars.next().is_some_and(|c| c == '/')
+    && chars.next().is_some_and(|c| c.is_ascii_alphabetic())
+    && chars.next().is_some_and(|c| c == ':')
+    && chars.next().is_none_or(|c| c == '/');
+  if has_drive_letter {
+    let (dl_part, rest) = path.split_at(2);
+    input.push_str(&dl_part.to_ascii_lowercase());
+    input.push_str(
+      &percent_encoding::utf8_percent_encode(rest, URL_TO_URI_PATH).to_string(),
+    );
   } else {
     input.push_str(
-      &percent_encoding::utf8_percent_encode(url.path(), URL_TO_URI_PATH)
-        .to_string(),
+      &percent_encoding::utf8_percent_encode(path, URL_TO_URI_PATH).to_string(),
     );
   }
   if let Some(query) = url.query() {
@@ -142,8 +136,9 @@ pub fn uri_to_url(uri: &Uri) -> Url {
         .trim_start_matches('/'),
     ))
     .ok()
+    .map(normalize_url)
   })()
-  .unwrap_or_else(|| Url::parse(uri.as_str()).unwrap())
+  .unwrap_or_else(|| normalize_url(Url::parse(uri.as_str()).unwrap()))
 }
 
 pub fn uri_to_file_path(uri: &Uri) -> Result<PathBuf, UrlToFilePathError> {
@@ -160,3 +155,53 @@ pub fn uri_is_file_like(uri: &Uri) -> bool {
     || scheme.eq_lowercase("deno-notebook-cell")
     || scheme.eq_lowercase("vscode-userdata")
 }
+
+fn normalize_url(url: Url) -> Url {
+  let Ok(path) = url_to_file_path(&url) else {
+    return url;
+  };
+  let normalized_path = normalize_path(&path);
+  let Ok(normalized_url) = Url::from_file_path(&normalized_path) else {
+    return url;
+  };
+  normalized_url
+}
+
+// TODO(nayeemrmn): Change the version of this in deno_path_util to force
+// uppercase on drive letters. Then remove this.
+fn normalize_path<P: AsRef<Path>>(path: P) -> PathBuf {
+  fn inner(path: &Path) -> PathBuf {
+    let mut components = path.components().peekable();
+    let mut ret =
+      if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
+        components.next();
+        let s = c.as_os_str();
+        if s.len() == 2 {
+          PathBuf::from(s.to_ascii_uppercase())
+        } else {
+          PathBuf::from(s)
+        }
+      } else {
+        PathBuf::new()
+      };
+
+    for component in components {
+      match component {
+        Component::Prefix(..) => unreachable!(),
+        Component::RootDir => {
+          ret.push(component.as_os_str());
+        }
+        Component::CurDir => {}
+        Component::ParentDir => {
+          ret.pop();
+        }
+        Component::Normal(c) => {
+          ret.push(c);
+        }
+      }
+    }
+    ret
+  }
+
+  inner(path.as_ref())
+}
diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs
index a31fc9ddbdf73c..a4215a03a44219 100644
--- a/tests/integration/lsp_tests.rs
+++ b/tests/integration/lsp_tests.rs
@@ -14,6 +14,7 @@ use test_util::lsp::range_of;
 use test_util::lsp::source_file;
 use test_util::lsp::LspClient;
 use test_util::testdata_path;
+use test_util::url_to_uri;
 use test_util::TestContextBuilder;
 use tower_lsp::lsp_types as lsp;
 use url::Url;
@@ -94,7 +95,7 @@ fn lsp_tsconfig_types() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("test.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("test.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "console.log(a);\n"
@@ -140,7 +141,7 @@ fn lsp_tsconfig_types_config_sub_dir() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("test.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("test.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "console.log(a);\n"
@@ -164,7 +165,7 @@ fn lsp_triple_slash_types() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("test.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("test.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "/// <reference types=\"./a.d.ts\" />\n\nconsole.log(a);\n"
@@ -219,7 +220,7 @@ fn unadded_dependency_message_with_import_map() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("file.ts"),
@@ -280,7 +281,7 @@ fn unadded_dependency_message() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("file.ts"),
@@ -323,7 +324,7 @@ fn lsp_import_map() {
     builder.set_import_map("import-map.json");
   });
 
-  let uri = temp_dir.url().join("a.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("a.ts").unwrap()).unwrap();
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
@@ -396,7 +397,7 @@ fn lsp_import_map_remote() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("file.ts"),
@@ -417,7 +418,7 @@ fn lsp_import_map_data_url() {
   });
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import example from \"example\";\n"
@@ -459,7 +460,7 @@ fn lsp_import_map_config_file() {
     builder.set_config("./deno.import_map.jsonc");
   });
 
-  let uri = temp_dir.url().join("a.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("a.ts").unwrap()).unwrap();
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
@@ -521,7 +522,7 @@ fn lsp_import_map_embedded_in_config_file() {
     builder.set_config("./deno.embedded_import_map.jsonc");
   });
 
-  let uri = temp_dir.url().join("a.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("a.ts").unwrap()).unwrap();
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
@@ -575,7 +576,7 @@ fn lsp_import_map_embedded_in_config_file_after_initialize() {
     builder.set_config("./deno.embedded_import_map.jsonc");
   });
 
-  let uri = temp_dir.url().join("a.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("a.ts").unwrap()).unwrap();
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
@@ -600,7 +601,7 @@ fn lsp_import_map_embedded_in_config_file_after_initialize() {
 
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("deno.embedded_import_map.jsonc").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("deno.embedded_import_map.jsonc").unwrap()).unwrap(),
       "type": 2
     }]
   }));
@@ -649,7 +650,7 @@ fn lsp_import_map_config_file_auto_discovered() {
   temp_dir.write("deno.jsonc", r#"{ "imports": { "/~/": "./lib/" } }"#);
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("deno.jsonc").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("deno.jsonc").unwrap()).unwrap(),
       "type": 2
     }]
   }));
@@ -658,7 +659,7 @@ fn lsp_import_map_config_file_auto_discovered() {
   });
   client.read_diagnostics();
 
-  let uri = temp_dir.url().join("a.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("a.ts").unwrap()).unwrap();
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
@@ -701,7 +702,7 @@ fn lsp_import_map_config_file_auto_discovered() {
   temp_dir.write("deno.jsonc", r#",,#,#,,"#);
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("deno.jsonc").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("deno.jsonc").unwrap()).unwrap(),
       "type": 2
     }]
   }));
@@ -711,7 +712,7 @@ fn lsp_import_map_config_file_auto_discovered() {
   temp_dir.write("deno.jsonc", r#"{ "imports": { "/~/": "./lib/" } }"#);
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("deno.jsonc").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("deno.jsonc").unwrap()).unwrap(),
       "type": 2
     }]
   }));
@@ -776,7 +777,7 @@ fn lsp_import_map_config_file_auto_discovered_symlink() {
   client.did_change_watched_files(json!({
     "changes": [{
       // the client will give a watched file changed event for the symlink's target
-      "uri": temp_dir.path().join("subdir/deno.json").canonicalize().url_file(),
+      "uri": temp_dir.path().join("subdir/deno.json").canonicalize().uri_file(),
       "type": 2
     }]
   }));
@@ -792,7 +793,7 @@ fn lsp_import_map_config_file_auto_discovered_symlink() {
   // now open a file which will cause a diagnostic because the import map is empty
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("a.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("a.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import { b } from \"/~/b.ts\";\n\nconsole.log(b);\n"
@@ -805,7 +806,7 @@ fn lsp_import_map_config_file_auto_discovered_symlink() {
   client.did_change_watched_files(json!({
     "changes": [{
       // now still say that the target path has changed
-      "uri": temp_dir.path().join("subdir/deno.json").canonicalize().url_file(),
+      "uri": temp_dir.path().join("subdir/deno.json").canonicalize().uri_file(),
       "type": 2
     }]
   }));
@@ -851,7 +852,7 @@ fn lsp_deno_json_imports_comments_cache() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("file.ts"),
@@ -884,7 +885,7 @@ fn lsp_import_map_node_specifiers() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("a.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("a.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import fs from \"fs\";\nconsole.log(fs);"
@@ -915,13 +916,13 @@ fn lsp_workspace_enable_paths_no_workspace_configuration() {
       uri: temp_dir.uri(),
       name: "project".to_string(),
     }]);
-    builder.set_root_uri(temp_dir.url());
+    builder.set_root_uri(temp_dir.uri());
     builder.set_enable_paths(vec!["./main_enabled.ts".to_string()]);
   });
 
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("main_disabled.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("main_disabled.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("main_disabled.ts"),
@@ -930,7 +931,7 @@ fn lsp_workspace_enable_paths_no_workspace_configuration() {
 
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("main_enabled.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("main_enabled.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("main_enabled.ts"),
@@ -941,7 +942,7 @@ fn lsp_workspace_enable_paths_no_workspace_configuration() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("main_disabled.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("main_disabled.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 5 }
     }),
@@ -952,7 +953,7 @@ fn lsp_workspace_enable_paths_no_workspace_configuration() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("main_enabled.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("main_enabled.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 5 }
     }),
@@ -1009,37 +1010,37 @@ fn lsp_did_refresh_deno_configuration_tree_notification() {
     json!({
       "data": [
         {
-          "scopeUri": temp_dir.url().join("non_workspace1/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("non_workspace1/").unwrap()).unwrap(),
           "workspaceRootScopeUri": null,
           "denoJson": {
-            "uri": temp_dir.url().join("non_workspace1/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("non_workspace1/deno.json").unwrap()).unwrap(),
           },
           "packageJson": null,
         },
         {
-          "scopeUri": temp_dir.url().join("workspace/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("workspace/").unwrap()).unwrap(),
           "workspaceRootScopeUri": null,
           "denoJson": {
-            "uri": temp_dir.url().join("workspace/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/deno.json").unwrap()).unwrap(),
           },
           "packageJson": null,
         },
         {
-          "scopeUri": temp_dir.url().join("workspace/member1/").unwrap(),
-          "workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("workspace/member1/").unwrap()).unwrap(),
+          "workspaceRootScopeUri": url_to_uri(&temp_dir.url().join("workspace/").unwrap()).unwrap(),
           "denoJson": {
-            "uri": temp_dir.url().join("workspace/member1/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/member1/deno.json").unwrap()).unwrap(),
           },
           "packageJson": {
-            "uri": temp_dir.url().join("workspace/member1/package.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/member1/package.json").unwrap()).unwrap(),
           },
         },
         {
-          "scopeUri": temp_dir.url().join("workspace/member2/").unwrap(),
-          "workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("workspace/member2/").unwrap()).unwrap(),
+          "workspaceRootScopeUri": url_to_uri(&temp_dir.url().join("workspace/").unwrap()).unwrap(),
           "denoJson": null,
           "packageJson": {
-            "uri": temp_dir.url().join("workspace/member2/package.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/member2/package.json").unwrap()).unwrap(),
           },
         },
       ],
@@ -1048,7 +1049,7 @@ fn lsp_did_refresh_deno_configuration_tree_notification() {
   temp_dir.write("non_workspace2/deno.json", json!({}).to_string());
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("non_workspace2/deno.json").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("non_workspace2/deno.json").unwrap()).unwrap(),
       "type": 1,
     }],
   }));
@@ -1064,45 +1065,45 @@ fn lsp_did_refresh_deno_configuration_tree_notification() {
     json!({
       "data": [
         {
-          "scopeUri": temp_dir.url().join("non_workspace1/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("non_workspace1/").unwrap()).unwrap(),
           "workspaceRootScopeUri": null,
           "denoJson": {
-            "uri": temp_dir.url().join("non_workspace1/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("non_workspace1/deno.json").unwrap()).unwrap(),
           },
           "packageJson": null,
         },
         {
-          "scopeUri": temp_dir.url().join("non_workspace2/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("non_workspace2/").unwrap()).unwrap(),
           "workspaceRootScopeUri": null,
           "denoJson": {
-            "uri": temp_dir.url().join("non_workspace2/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("non_workspace2/deno.json").unwrap()).unwrap(),
           },
           "packageJson": null,
         },
         {
-          "scopeUri": temp_dir.url().join("workspace/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("workspace/").unwrap()).unwrap(),
           "workspaceRootScopeUri": null,
           "denoJson": {
-            "uri": temp_dir.url().join("workspace/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/deno.json").unwrap()).unwrap(),
           },
           "packageJson": null,
         },
         {
-          "scopeUri": temp_dir.url().join("workspace/member1/").unwrap(),
-          "workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("workspace/member1/").unwrap()).unwrap(),
+          "workspaceRootScopeUri": url_to_uri(&temp_dir.url().join("workspace/").unwrap()).unwrap(),
           "denoJson": {
-            "uri": temp_dir.url().join("workspace/member1/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/member1/deno.json").unwrap()).unwrap(),
           },
           "packageJson": {
-            "uri": temp_dir.url().join("workspace/member1/package.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/member1/package.json").unwrap()).unwrap(),
           },
         },
         {
-          "scopeUri": temp_dir.url().join("workspace/member2/").unwrap(),
-          "workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("workspace/member2/").unwrap()).unwrap(),
+          "workspaceRootScopeUri": url_to_uri(&temp_dir.url().join("workspace/").unwrap()).unwrap(),
           "denoJson": null,
           "packageJson": {
-            "uri": temp_dir.url().join("workspace/member2/package.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/member2/package.json").unwrap()).unwrap(),
           },
         },
       ],
@@ -1124,37 +1125,37 @@ fn lsp_did_refresh_deno_configuration_tree_notification() {
     json!({
       "data": [
         {
-          "scopeUri": temp_dir.url().join("non_workspace2/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("non_workspace2/").unwrap()).unwrap(),
           "workspaceRootScopeUri": null,
           "denoJson": {
-            "uri": temp_dir.url().join("non_workspace2/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("non_workspace2/deno.json").unwrap()).unwrap(),
           },
           "packageJson": null,
         },
         {
-          "scopeUri": temp_dir.url().join("workspace/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("workspace/").unwrap()).unwrap(),
           "workspaceRootScopeUri": null,
           "denoJson": {
-            "uri": temp_dir.url().join("workspace/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/deno.json").unwrap()).unwrap(),
           },
           "packageJson": null,
         },
         {
-          "scopeUri": temp_dir.url().join("workspace/member1/").unwrap(),
-          "workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("workspace/member1/").unwrap()).unwrap(),
+          "workspaceRootScopeUri": url_to_uri(&temp_dir.url().join("workspace/").unwrap()).unwrap(),
           "denoJson": {
-            "uri": temp_dir.url().join("workspace/member1/deno.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/member1/deno.json").unwrap()).unwrap(),
           },
           "packageJson": {
-            "uri": temp_dir.url().join("workspace/member1/package.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/member1/package.json").unwrap()).unwrap(),
           },
         },
         {
-          "scopeUri": temp_dir.url().join("workspace/member2/").unwrap(),
-          "workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
+          "scopeUri": url_to_uri(&temp_dir.url().join("workspace/member2/").unwrap()).unwrap(),
+          "workspaceRootScopeUri": url_to_uri(&temp_dir.url().join("workspace/").unwrap()).unwrap(),
           "denoJson": null,
           "packageJson": {
-            "uri": temp_dir.url().join("workspace/member2/package.json").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("workspace/member2/package.json").unwrap()).unwrap(),
           },
         },
       ],
@@ -1180,14 +1181,14 @@ fn lsp_did_change_deno_configuration_notification() {
     Some(json!({
       "changes": [
         {
-          "scopeUri": temp_dir.url(),
-          "fileUri": temp_dir.url().join("deno.json").unwrap(),
+          "scopeUri": temp_dir.uri(),
+          "fileUri": url_to_uri(&temp_dir.url().join("deno.json").unwrap()).unwrap(),
           "type": "added",
           "configurationType": "denoJson"
         },
         {
-          "scopeUri": temp_dir.url(),
-          "fileUri": temp_dir.url().join("package.json").unwrap(),
+          "scopeUri": temp_dir.uri(),
+          "fileUri": url_to_uri(&temp_dir.url().join("package.json").unwrap()).unwrap(),
           "type": "added",
           "configurationType": "packageJson"
         },
@@ -1201,7 +1202,7 @@ fn lsp_did_change_deno_configuration_notification() {
   );
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("deno.json").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("deno.json").unwrap()).unwrap(),
       "type": 2,
     }],
   }));
@@ -1212,8 +1213,8 @@ fn lsp_did_change_deno_configuration_notification() {
     res,
     Some(json!({
       "changes": [{
-        "scopeUri": temp_dir.url(),
-        "fileUri": temp_dir.url().join("deno.json").unwrap(),
+        "scopeUri": temp_dir.uri(),
+        "fileUri": url_to_uri(&temp_dir.url().join("deno.json").unwrap()).unwrap(),
         "type": "changed",
         "configurationType": "denoJson"
       }],
@@ -1223,7 +1224,7 @@ fn lsp_did_change_deno_configuration_notification() {
   temp_dir.remove_file("deno.json");
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("deno.json").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("deno.json").unwrap()).unwrap(),
       "type": 3,
     }],
   }));
@@ -1234,8 +1235,8 @@ fn lsp_did_change_deno_configuration_notification() {
     res,
     Some(json!({
       "changes": [{
-        "scopeUri": temp_dir.url(),
-        "fileUri": temp_dir.url().join("deno.json").unwrap(),
+        "scopeUri": temp_dir.uri(),
+        "fileUri": url_to_uri(&temp_dir.url().join("deno.json").unwrap()).unwrap(),
         "type": "removed",
         "configurationType": "denoJson"
       }],
@@ -1245,7 +1246,7 @@ fn lsp_did_change_deno_configuration_notification() {
   temp_dir.write("package.json", json!({ "type": "module" }).to_string());
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("package.json").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("package.json").unwrap()).unwrap(),
       "type": 2,
     }],
   }));
@@ -1256,8 +1257,8 @@ fn lsp_did_change_deno_configuration_notification() {
     res,
     Some(json!({
       "changes": [{
-        "scopeUri": temp_dir.url(),
-        "fileUri": temp_dir.url().join("package.json").unwrap(),
+        "scopeUri": temp_dir.uri(),
+        "fileUri": url_to_uri(&temp_dir.url().join("package.json").unwrap()).unwrap(),
         "type": "changed",
         "configurationType": "packageJson"
       }],
@@ -1267,7 +1268,7 @@ fn lsp_did_change_deno_configuration_notification() {
   temp_dir.remove_file("package.json");
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("package.json").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("package.json").unwrap()).unwrap(),
       "type": 3,
     }],
   }));
@@ -1278,8 +1279,8 @@ fn lsp_did_change_deno_configuration_notification() {
     res,
     Some(json!({
       "changes": [{
-        "scopeUri": temp_dir.url(),
-        "fileUri": temp_dir.url().join("package.json").unwrap(),
+        "scopeUri": temp_dir.uri(),
+        "fileUri": url_to_uri(&temp_dir.url().join("package.json").unwrap()).unwrap(),
         "type": "removed",
         "configurationType": "packageJson"
       }],
@@ -1315,12 +1316,12 @@ fn lsp_deno_task() {
       {
         "name": "build",
         "command": "deno test",
-        "sourceUri": temp_dir.url().join("deno.jsonc").unwrap(),
+        "sourceUri": url_to_uri(&temp_dir.url().join("deno.jsonc").unwrap()).unwrap(),
       },
       {
         "name": "serve",
         "command": "deno run -RN server.ts",
-        "sourceUri": temp_dir.url().join("deno.jsonc").unwrap(),
+        "sourceUri": url_to_uri(&temp_dir.url().join("deno.jsonc").unwrap()).unwrap(),
       }
     ])
   );
@@ -1485,7 +1486,7 @@ fn lsp_import_map_import_completions() {
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
 
-  let uri = temp_dir.url().join("a.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("a.ts").unwrap()).unwrap();
 
   client.did_open(json!({
     "textDocument": {
@@ -1501,7 +1502,7 @@ fn lsp_import_map_import_completions() {
   }));
 
   let res = client.get_completion(
-    &uri,
+    uri.as_str(),
     (1, 28),
     json!({ "triggerKind": 2, "triggerCharacter": "\"" }),
   );
@@ -1572,7 +1573,7 @@ fn lsp_import_map_import_completions() {
   );
 
   let res = client.get_completion(
-    &uri,
+    uri.as_str(),
     (2, 31),
     json!({ "triggerKind": 2, "triggerCharacter": "/" }),
   );
@@ -1601,7 +1602,7 @@ fn lsp_import_map_import_completions() {
   );
 
   let res = client.get_completion(
-    &uri,
+    uri.as_str(),
     (3, 32),
     json!({ "triggerKind": 2, "triggerCharacter": "/" }),
   );
@@ -1685,7 +1686,7 @@ fn lsp_hover_asset() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "console.log(Date.now());\n"
@@ -1695,7 +1696,7 @@ fn lsp_hover_asset() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap()
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap()
       },
       "position": { "line": 0, "character": 14 }
     }),
@@ -2044,7 +2045,7 @@ fn lsp_suggestion_actions_disabled() {
   }));
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -2079,7 +2080,7 @@ fn lsp_suggestion_actions_disabled() {
         "relatedInformation": [
           {
             "location": {
-              "uri": temp_dir.url().join("file.ts").unwrap(),
+              "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
               "range": {
                 "start": { "line": 8, "character": 12 },
                 "end": { "line": 8, "character": 24 },
@@ -2116,23 +2117,19 @@ fn lsp_workspace_disable_enable_paths() {
     temp_dir.write("worker/other.ts", "import { a } from './shared.ts';\na;");
     temp_dir.write("worker/node.ts", "Buffer.alloc(1);");
 
-    let root_specifier = temp_dir.url();
-
     let mut client = context.new_lsp_command().build();
     client.initialize_with_config(
       |builder| {
         builder
           .set_disable_paths(vec!["./worker/node.ts".to_string()])
           .set_enable_paths(vec!["./worker".to_string()])
-          .set_root_uri(root_specifier.clone())
+          .set_root_uri(temp_dir.uri())
           .set_workspace_folders(vec![lsp::WorkspaceFolder {
             uri: if use_trailing_slash {
-              lsp::Uri::from_str(root_specifier.as_str()).unwrap()
+              temp_dir.uri()
             } else {
-              lsp::Uri::from_str(
-                root_specifier.as_str().strip_suffix('/').unwrap(),
-              )
-              .unwrap()
+              url_to_uri(&Url::from_file_path(temp_dir.path()).unwrap())
+                .unwrap()
             },
             name: "project".to_string(),
           }]);
@@ -2145,7 +2142,7 @@ fn lsp_workspace_disable_enable_paths() {
 
     client.did_open(json!({
       "textDocument": {
-        "uri": root_specifier.join("./file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./file.ts").unwrap()).unwrap(),
         "languageId": "typescript",
         "version": 1,
         "text": "console.log(Date.now());\n"
@@ -2154,7 +2151,7 @@ fn lsp_workspace_disable_enable_paths() {
 
     client.did_open(json!({
       "textDocument": {
-        "uri": root_specifier.join("./other/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./other/file.ts").unwrap()).unwrap(),
         "languageId": "typescript",
         "version": 1,
         "text": "console.log(Date.now());\n"
@@ -2163,7 +2160,7 @@ fn lsp_workspace_disable_enable_paths() {
 
     client.did_open(json!({
       "textDocument": {
-        "uri": root_specifier.join("./worker/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
         "languageId": "typescript",
         "version": 1,
         "text": concat!(
@@ -2176,7 +2173,7 @@ fn lsp_workspace_disable_enable_paths() {
 
     client.did_open(json!({
       "textDocument": {
-        "uri": root_specifier.join("./worker/subdir/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./worker/subdir/file.ts").unwrap()).unwrap(),
         "languageId": "typescript",
         "version": 1,
         "text": "console.log(Date.now());\n"
@@ -2187,7 +2184,7 @@ fn lsp_workspace_disable_enable_paths() {
       "textDocument/hover",
       json!({
         "textDocument": {
-          "uri": root_specifier.join("./file.ts").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("./file.ts").unwrap()).unwrap(),
         },
         "position": { "line": 0, "character": 19 }
       }),
@@ -2198,7 +2195,7 @@ fn lsp_workspace_disable_enable_paths() {
       "textDocument/hover",
       json!({
         "textDocument": {
-          "uri": root_specifier.join("./other/file.ts").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("./other/file.ts").unwrap()).unwrap(),
         },
         "position": { "line": 0, "character": 19 }
       }),
@@ -2209,7 +2206,7 @@ fn lsp_workspace_disable_enable_paths() {
       "textDocument/hover",
       json!({
         "textDocument": {
-          "uri": root_specifier.join("./worker/node.ts").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("./worker/node.ts").unwrap()).unwrap(),
         },
         "position": { "line": 0, "character": 0 }
       }),
@@ -2220,7 +2217,7 @@ fn lsp_workspace_disable_enable_paths() {
       "textDocument/hover",
       json!({
         "textDocument": {
-          "uri": root_specifier.join("./worker/file.ts").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
         },
         "position": { "line": 0, "character": 19 }
       }),
@@ -2246,7 +2243,7 @@ fn lsp_workspace_disable_enable_paths() {
       "textDocument/hover",
       json!({
         "textDocument": {
-          "uri": root_specifier.join("./worker/subdir/file.ts").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("./worker/subdir/file.ts").unwrap()).unwrap(),
         },
         "position": { "line": 0, "character": 19 }
       }),
@@ -2274,7 +2271,7 @@ fn lsp_workspace_disable_enable_paths() {
       "textDocument/references",
       json!({
         "textDocument": {
-          "uri": root_specifier.join("./worker/file.ts").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
         },
         "position": { "line": 2, "character": 0 },
         "context": {
@@ -2286,31 +2283,31 @@ fn lsp_workspace_disable_enable_paths() {
     assert_eq!(
       res,
       json!([{
-        "uri": root_specifier.join("./worker/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
         "range": {
           "start": { "line": 1, "character": 9 },
           "end": { "line": 1, "character": 10 }
         }
       }, {
-        "uri": root_specifier.join("./worker/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
         "range": {
           "start": { "line": 2, "character": 0 },
           "end": { "line": 2, "character": 1 }
         }
       }, {
-        "uri": root_specifier.join("./worker/shared.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./worker/shared.ts").unwrap()).unwrap(),
         "range": {
           "start": { "line": 0, "character": 13 },
           "end": { "line": 0, "character": 14 }
         }
       }, {
-        "uri": root_specifier.join("./worker/other.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./worker/other.ts").unwrap()).unwrap(),
         "range": {
           "start": { "line": 0, "character": 9 },
           "end": { "line": 0, "character": 10 }
         }
       }, {
-        "uri": root_specifier.join("./worker/other.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./worker/other.ts").unwrap()).unwrap(),
         "range": {
           "start": { "line": 1, "character": 0 },
           "end": { "line": 1, "character": 1 }
@@ -2342,14 +2339,12 @@ fn lsp_exclude_config() {
   "exclude": ["other"],
 }"#,
   );
-  let root_specifier = temp_dir.url();
-
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
 
   client.did_open(json!({
     "textDocument": {
-      "uri": root_specifier.join("./other/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("./other/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "console.log(Date.now());\n"
@@ -2358,7 +2353,7 @@ fn lsp_exclude_config() {
 
   client.did_open(json!({
     "textDocument": {
-      "uri": root_specifier.join("./worker/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": concat!(
@@ -2371,7 +2366,7 @@ fn lsp_exclude_config() {
 
   client.did_open(json!({
     "textDocument": {
-      "uri": root_specifier.join("./worker/subdir/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("./worker/subdir/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "console.log(Date.now());\n"
@@ -2382,7 +2377,7 @@ fn lsp_exclude_config() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": root_specifier.join("./other/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./other/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 19 }
     }),
@@ -2393,7 +2388,7 @@ fn lsp_exclude_config() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": root_specifier.join("./worker/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 19 }
     }),
@@ -2420,7 +2415,7 @@ fn lsp_exclude_config() {
     "textDocument/references",
     json!({
       "textDocument": {
-        "uri": root_specifier.join("./worker/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 2, "character": 0 },
       "context": {
@@ -2432,19 +2427,19 @@ fn lsp_exclude_config() {
   assert_eq!(
     res,
     json!([{
-      "uri": root_specifier.join("./worker/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
       "range": {
         "start": { "line": 1, "character": 9 },
         "end": { "line": 1, "character": 10 }
       }
     }, {
-      "uri": root_specifier.join("./worker/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("./worker/file.ts").unwrap()).unwrap(),
       "range": {
         "start": { "line": 2, "character": 0 },
         "end": { "line": 2, "character": 1 }
       }
     }, {
-      "uri": root_specifier.join("./worker/shared.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("./worker/shared.ts").unwrap()).unwrap(),
       "range": {
         "start": { "line": 0, "character": 13 },
         "end": { "line": 0, "character": 14 }
@@ -2622,14 +2617,14 @@ fn lsp_hover_closed_document() {
   temp_dir.write("b.ts", r#"export * from "./a.ts";"#);
   temp_dir.write("c.ts", "import { a } from \"./b.ts\";\nconsole.log(a);\n");
 
-  let b_specifier = temp_dir.url().join("b.ts").unwrap();
-  let c_specifier = temp_dir.url().join("c.ts").unwrap();
+  let b_uri = url_to_uri(&temp_dir.url().join("b.ts").unwrap()).unwrap();
+  let c_uri = url_to_uri(&temp_dir.url().join("c.ts").unwrap()).unwrap();
 
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": b_specifier,
+      "uri": b_uri,
       "languageId": "typescript",
       "version": 1,
       "text": r#"export * from "./a.ts";"#
@@ -2638,7 +2633,7 @@ fn lsp_hover_closed_document() {
 
   client.did_open(json!({
     "textDocument": {
-      "uri": c_specifier,
+      "uri": c_uri,
       "languageId": "typescript",
       "version": 1,
       "text": "import { a } from \"./b.ts\";\nconsole.log(a);\n",
@@ -2649,7 +2644,7 @@ fn lsp_hover_closed_document() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": c_specifier,
+        "uri": c_uri,
       },
       "position": { "line": 0, "character": 10 }
     }),
@@ -2674,7 +2669,7 @@ fn lsp_hover_closed_document() {
     "textDocument/didClose",
     json!({
       "textDocument": {
-        "uri": b_specifier,
+        "uri": b_uri,
       }
     }),
   );
@@ -2682,7 +2677,7 @@ fn lsp_hover_closed_document() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": c_specifier,
+        "uri": c_uri,
       },
       "position": { "line": 0, "character": 10 }
     }),
@@ -2984,7 +2979,7 @@ fn lsp_rename_synbol_file_scheme_edits_only() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -2997,7 +2992,7 @@ fn lsp_rename_synbol_file_scheme_edits_only() {
     "textDocument/rename",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 1, "character": 17 },
       "newName": "PATH_SEPARATOR",
@@ -3009,7 +3004,7 @@ fn lsp_rename_synbol_file_scheme_edits_only() {
       "documentChanges": [
         {
           "textDocument": {
-            "uri": temp_dir.url().join("file.ts").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
             "version": 1,
           },
           "edits": [
@@ -3055,8 +3050,8 @@ fn lsp_document_preload_limit_zero_deno_json_detection() {
     res,
     Some(json!({
       "changes": [{
-        "scopeUri": temp_dir.url(),
-        "fileUri": temp_dir.url().join("deno.json").unwrap(),
+        "scopeUri": temp_dir.uri(),
+        "fileUri": url_to_uri(&temp_dir.url().join("deno.json").unwrap()).unwrap(),
         "type": "added",
         "configurationType": "denoJson",
       }],
@@ -3091,7 +3086,7 @@ fn lsp_import_map_setting_with_deno_json() {
   });
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"file2\";\n",
@@ -3168,7 +3163,7 @@ fn lsp_hover_jsr() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"jsr:@denotest/add@1.0.0\";\n",
@@ -3186,7 +3181,7 @@ fn lsp_hover_jsr() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -5573,7 +5568,7 @@ fn lsp_code_actions_deno_cache_jsr() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -5585,7 +5580,7 @@ fn lsp_code_actions_deno_cache_jsr() {
   assert_eq!(
     json!(diagnostics.messages_with_source("deno")),
     json!({
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "diagnostics": [{
         "range": {
           "start": { "line": 1, "character": 28 },
@@ -5603,7 +5598,7 @@ fn lsp_code_actions_deno_cache_jsr() {
   let res = client.write_request(
     "textDocument/codeAction",
     json!({
-      "textDocument": { "uri": temp_dir.url().join("file.ts").unwrap() },
+      "textDocument": { "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap() },
       "range": {
         "start": { "line": 1, "character": 28 },
         "end": { "line": 1, "character": 49 },
@@ -5693,7 +5688,7 @@ fn lsp_jsr_lockfile() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -5746,14 +5741,16 @@ fn lsp_jsr_auto_import_completion() {
   client.read_diagnostics();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"add"#,
     }
   }));
   let list = client.get_completion_list(
-    temp_dir.url().join("file.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (0, 3),
     json!({ "triggerKind": 1 }),
   );
@@ -5827,14 +5824,16 @@ fn lsp_jsr_auto_import_completion_import_map() {
   client.read_diagnostics();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"add"#,
     }
   }));
   let list = client.get_completion_list(
-    temp_dir.url().join("file.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (0, 3),
     json!({ "triggerKind": 1 }),
   );
@@ -5904,7 +5903,7 @@ fn lsp_jsr_auto_import_completion_import_map_sub_path() {
   client.read_diagnostics();
   client.did_open_file(&file);
   let list = client.get_completion_list(
-    file.url(),
+    file.uri().as_str(),
     (3, 15),
     json!({ "triggerKind": 1 }),
   );
@@ -5972,7 +5971,7 @@ fn lsp_jsr_code_action_missing_declaration() {
     "textDocument/codeAction",
     json!({
       "textDocument": {
-        "uri": file.url(),
+        "uri": file.uri(),
       },
       "range": {
         "start": { "line": 2, "character": 6 },
@@ -6025,7 +6024,7 @@ fn lsp_jsr_code_action_missing_declaration() {
           "documentChanges": [
             {
               "textDocument": {
-                "uri": file.url(),
+                "uri": file.uri(),
                 "version": 1,
               },
               "edits": [
@@ -6094,7 +6093,7 @@ fn lsp_jsr_code_action_move_to_new_file() {
     .write_request_with_res_as::<Option<lsp::CodeActionResponse>>(
       "textDocument/codeAction",
       json!({
-        "textDocument": { "uri": file.url() },
+        "textDocument": { "uri": file.uri() },
         "range": {
           "start": { "line": 2, "character": 19 },
           "end": { "line": 2, "character": 28 },
@@ -6123,7 +6122,7 @@ fn lsp_jsr_code_action_move_to_new_file() {
       "edit": {
         "documentChanges": [
           {
-            "textDocument": { "uri": file.url(), "version": 1 },
+            "textDocument": { "uri": file.uri(), "version": 1 },
             "edits": [
               {
                 "range": {
@@ -6143,14 +6142,14 @@ fn lsp_jsr_code_action_move_to_new_file() {
           },
           {
             "kind": "create",
-            "uri": file.url().join("someValue.ts").unwrap(),
+            "uri": url_to_uri(&file.url().join("someValue.ts").unwrap()).unwrap(),
             "options": {
               "ignoreIfExists": true,
             },
           },
           {
             "textDocument": {
-              "uri": file.url().join("someValue.ts").unwrap(),
+              "uri": url_to_uri(&file.url().join("someValue.ts").unwrap()).unwrap(),
               "version": null,
             },
             "edits": [
@@ -6167,7 +6166,7 @@ fn lsp_jsr_code_action_move_to_new_file() {
       },
       "isPreferred": false,
       "data": {
-        "uri": file.url(),
+        "uri": file.uri(),
         "range": {
           "start": { "line": 2, "character": 19 },
           "end": { "line": 2, "character": 28 },
@@ -6446,7 +6445,7 @@ fn lsp_cache_on_save() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("file.ts"),
@@ -6455,7 +6454,7 @@ fn lsp_cache_on_save() {
   assert_eq!(
     diagnostics.messages_with_source("deno"),
     serde_json::from_value(json!({
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "diagnostics": [{
         "range": {
           "start": { "line": 1, "character": 33 },
@@ -6472,7 +6471,7 @@ fn lsp_cache_on_save() {
     .unwrap()
   );
   client.did_save(json!({
-    "textDocument": { "uri": temp_dir.url().join("file.ts").unwrap() },
+    "textDocument": { "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap() },
   }));
   assert_eq!(client.read_diagnostics().all(), vec![]);
 
@@ -6498,7 +6497,7 @@ fn lsp_asset_document_dom_code_action() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#""#,
@@ -6532,7 +6531,7 @@ fn lsp_cache_then_definition() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"import "http://localhost:4545/run/002_hello.ts";"#,
@@ -6556,7 +6555,7 @@ fn lsp_cache_then_definition() {
   let res = client.write_request(
     "textDocument/definition",
     json!({
-      "textDocument": { "uri": temp_dir.url().join("file.ts").unwrap() },
+      "textDocument": { "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap() },
       "position": { "line": 0, "character": 8 },
     }),
   );
@@ -6854,7 +6853,7 @@ fn lsp_code_actions_imports_dts() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -6867,7 +6866,7 @@ fn lsp_code_actions_imports_dts() {
     "textDocument/codeAction",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
       "range": {
         "start": { "line": 1, "character": 17 },
@@ -6897,7 +6896,7 @@ fn lsp_code_actions_imports_dts() {
       "edit": {
         "documentChanges": [{
           "textDocument": {
-            "uri": temp_dir.url().join("file.ts").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
             "version": 1,
           },
           "edits": [{
@@ -6935,7 +6934,7 @@ fn lsp_code_actions_import_map_remap() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -6947,7 +6946,7 @@ fn lsp_code_actions_import_map_remap() {
   let res = client.write_request(
     "textDocument/codeAction",
     json!({
-      "textDocument": { "uri": temp_dir.url().join("file.ts").unwrap() },
+      "textDocument": { "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap() },
       "range": {
         "start": { "line": 0, "character": 0 },
         "end": { "line": 3, "character": 0 },
@@ -6979,7 +6978,7 @@ fn lsp_code_actions_import_map_remap() {
         ],
         "edit": {
           "changes": {
-            temp_dir.url().join("file.ts").unwrap(): [
+            url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap().as_str(): [
               {
                 "range": {
                   "start": { "line": 1, "character": 15 },
@@ -7009,7 +7008,7 @@ fn lsp_code_actions_import_map_remap() {
         ],
         "edit": {
           "changes": {
-            temp_dir.url().join("file.ts").unwrap(): [
+            url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap().as_str(): [
               {
                 "range": {
                   "start": { "line": 2, "character": 28 },
@@ -7273,7 +7272,7 @@ fn lsp_code_actions_imports_respects_fmt_config() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file00.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file00.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("file00.ts"),
@@ -7281,7 +7280,7 @@ fn lsp_code_actions_imports_respects_fmt_config() {
   }));
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file01.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file01.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("file01.ts"),
@@ -7292,7 +7291,7 @@ fn lsp_code_actions_imports_respects_fmt_config() {
     "textDocument/codeAction",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file00.ts").unwrap()
+        "uri": url_to_uri(&temp_dir.url().join("file00.ts").unwrap()).unwrap()
       },
       "range": {
         "start": { "line": 0, "character": 0 },
@@ -7331,7 +7330,7 @@ fn lsp_code_actions_imports_respects_fmt_config() {
       "edit": {
         "documentChanges": [{
           "textDocument": {
-            "uri": temp_dir.url().join("file00.ts").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("file00.ts").unwrap()).unwrap(),
             "version": 1
           },
           "edits": [{
@@ -7361,7 +7360,7 @@ fn lsp_code_actions_imports_respects_fmt_config() {
         "message": "Cannot find name 'DuckConfigOptions'."
       }],
       "data": {
-        "uri": temp_dir.url().join("file00.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file00.ts").unwrap()).unwrap(),
         "fixId": "fixMissingImport"
       }
     }),
@@ -7384,7 +7383,7 @@ fn lsp_code_actions_imports_respects_fmt_config() {
       "edit": {
         "documentChanges": [{
           "textDocument": {
-            "uri": temp_dir.url().join("file00.ts").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("file00.ts").unwrap()).unwrap(),
             "version": 1
           },
           "edits": [{
@@ -7397,7 +7396,7 @@ fn lsp_code_actions_imports_respects_fmt_config() {
         }]
       },
       "data": {
-        "uri": temp_dir.url().join("file00.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file00.ts").unwrap()).unwrap(),
         "fixId": "fixMissingImport"
       }
     })
@@ -7443,7 +7442,7 @@ fn lsp_quote_style_from_workspace_settings() {
 
   let code_action_params = json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file00.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file00.ts").unwrap()).unwrap(),
     },
     "range": {
       "start": { "line": 0, "character": 0 },
@@ -7485,7 +7484,7 @@ fn lsp_quote_style_from_workspace_settings() {
       "edit": {
         "documentChanges": [{
           "textDocument": {
-            "uri": temp_dir.url().join("file00.ts").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("file00.ts").unwrap()).unwrap(),
             "version": null,
           },
           "edits": [{
@@ -7504,7 +7503,7 @@ fn lsp_quote_style_from_workspace_settings() {
   temp_dir.write("./deno.json", json!({}).to_string());
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("deno.json").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("deno.json").unwrap()).unwrap(),
       "type": 1,
     }],
   }));
@@ -7530,7 +7529,7 @@ fn lsp_quote_style_from_workspace_settings() {
       "edit": {
         "documentChanges": [{
           "textDocument": {
-            "uri": temp_dir.url().join("file00.ts").unwrap(),
+            "uri": url_to_uri(&temp_dir.url().join("file00.ts").unwrap()).unwrap(),
             "version": null,
           },
           "edits": [{
@@ -7984,7 +7983,7 @@ fn lsp_completions_auto_import_node_builtin() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -8002,7 +8001,9 @@ fn lsp_completions_auto_import_node_builtin() {
   );
   client.read_diagnostics();
   let list = client.get_completion_list(
-    temp_dir.url().join("file.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (2, 21),
     json!({ "triggerKind": 2 }),
   );
@@ -8324,14 +8325,16 @@ fn lsp_npm_auto_import_and_quick_fix_byonm() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "think({ text: \"foo\" });\n",
     },
   }));
   let list = client.get_completion_list(
-    temp_dir.url().join("file.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (0, 5),
     json!({ "triggerKind": 1 }),
   );
@@ -8369,7 +8372,9 @@ fn lsp_npm_auto_import_and_quick_fix_byonm() {
   );
   let diagnostics = diagnostics
     .messages_with_file_and_source(
-      temp_dir.url().join("file.ts").unwrap().as_str(),
+      url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+        .unwrap()
+        .as_str(),
       "deno-ts",
     )
     .diagnostics;
@@ -8377,7 +8382,7 @@ fn lsp_npm_auto_import_and_quick_fix_byonm() {
     "textDocument/codeAction",
     json!(json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
       "range": {
         "start": { "line": 0, "character": 0 },
@@ -8399,7 +8404,7 @@ fn lsp_npm_auto_import_and_quick_fix_byonm() {
         "edit": {
           "documentChanges": [{
             "textDocument": {
-              "uri": temp_dir.url().join("file.ts").unwrap(),
+              "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
               "version": 1,
             },
             "edits": [{
@@ -8420,7 +8425,7 @@ fn lsp_npm_auto_import_and_quick_fix_byonm() {
           "documentChanges": [
             {
               "textDocument": {
-                "uri": temp_dir.url().join("file.ts").unwrap(),
+                "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
                 "version": 1,
               },
               "edits": [
@@ -8485,7 +8490,7 @@ fn lsp_npm_auto_import_with_deno_types() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -8495,7 +8500,9 @@ fn lsp_npm_auto_import_with_deno_types() {
     },
   }));
   let list = client.get_completion_list(
-    temp_dir.url().join("file.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (1, 24),
     json!({ "triggerKind": 1 }),
   );
@@ -8531,7 +8538,9 @@ fn lsp_npm_auto_import_with_deno_types() {
     }),
   );
   let list = client.get_completion_list(
-    temp_dir.url().join("file.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (2, 17),
     json!({ "triggerKind": 1 }),
   );
@@ -8575,14 +8584,16 @@ fn lsp_completions_node_specifier() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import fs from \"node:as\";\n",
     },
   }));
   let list = client.get_completion_list(
-    temp_dir.url().join("file.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (0, 23),
     json!({
       "triggerKind": 2,
@@ -8707,7 +8718,7 @@ fn lsp_infer_return_type() {
   let res = client.write_request(
     "textDocument/codeAction",
     json!({
-      "textDocument": { "uri": file.url() },
+      "textDocument": { "uri": file.uri() },
       "range": {
         "start": { "line": 1, "character": 15 },
         "end": { "line": 1, "character": 18 },
@@ -8726,7 +8737,7 @@ fn lsp_infer_return_type() {
         "kind": "refactor.rewrite.function.returnType",
         "isPreferred": false,
         "data": {
-          "uri": file.url(),
+          "uri": file.uri(),
           "range": {
             "start": { "line": 1, "character": 15 },
             "end": { "line": 1, "character": 18 },
@@ -8746,7 +8757,7 @@ fn lsp_infer_return_type() {
       "kind": "refactor.rewrite.function.returnType",
       "isPreferred": false,
       "data": {
-        "uri": file.url(),
+        "uri": file.uri(),
         "range": {
           "start": { "line": 1, "character": 15 },
           "end": { "line": 1, "character": 18 },
@@ -8757,7 +8768,7 @@ fn lsp_infer_return_type() {
       "edit": {
         "documentChanges": [
           {
-            "textDocument": { "uri": file.url(), "version": null },
+            "textDocument": { "uri": file.uri(), "version": null },
             "edits": [
               {
                 "range": {
@@ -8882,7 +8893,8 @@ fn lsp_npm_always_caches() {
   // create the lsp and cache a different npm specifier
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
-  let opened_file_uri = temp_dir_path.join("file.ts").url_file();
+  let opened_file_uri = temp_dir_path.join("file.ts").uri_file();
+  let opened_file_url = temp_dir_path.join("file.ts").url_file();
   client.did_open(
     json!({
       "textDocument": {
@@ -8899,14 +8911,14 @@ fn lsp_npm_always_caches() {
       "command": "deno.cache",
       "arguments": [
         ["npm:@denotest/types-exports-subpaths@1/client"],
-        opened_file_uri,
+        opened_file_url,
       ],
     }),
   );
   client.read_diagnostics();
 
   // now open a new file and chalk should be working
-  let new_file_uri = temp_dir_path.join("new_file.ts").url_file();
+  let new_file_uri = temp_dir_path.join("new_file.ts").uri_file();
   client.did_open(json!({
     "textDocument": {
       "uri": new_file_uri,
@@ -8917,7 +8929,7 @@ fn lsp_npm_always_caches() {
   }));
 
   let list = client.get_completion_list(
-    new_file_uri,
+    new_file_uri.as_str(),
     (1, 6),
     json!({
       "triggerKind": 2,
@@ -8997,7 +9009,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   client.did_open(
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
         "languageId": "typescript",
         "version": 1,
         "text": concat!(
@@ -9033,14 +9045,16 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   // try auto-import with path
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("a.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("a.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "getClie",
     }
   }));
   let list = client.get_completion_list(
-    temp_dir.url().join("a.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("a.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (0, 7),
     json!({ "triggerKind": 1 }),
   );
@@ -9081,7 +9095,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   // try quick fix with path
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("b.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("b.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "getClient",
@@ -9089,7 +9103,9 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   }));
   let diagnostics = diagnostics
     .messages_with_file_and_source(
-      temp_dir.url().join("b.ts").unwrap().as_str(),
+      url_to_uri(&temp_dir.url().join("b.ts").unwrap())
+        .unwrap()
+        .as_str(),
       "deno-ts",
     )
     .diagnostics;
@@ -9097,7 +9113,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
     "textDocument/codeAction",
     json!(json!({
       "textDocument": {
-        "uri": temp_dir.url().join("b.ts").unwrap()
+        "uri": url_to_uri(&temp_dir.url().join("b.ts").unwrap()).unwrap()
       },
       "range": {
         "start": { "line": 0, "character": 0 },
@@ -9129,7 +9145,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
       "edit": {
         "documentChanges": [{
             "textDocument": {
-              "uri": temp_dir.url().join("b.ts").unwrap(),
+              "uri": url_to_uri(&temp_dir.url().join("b.ts").unwrap()).unwrap(),
               "version": 1,
             },
             "edits": [{
@@ -9147,7 +9163,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   // try auto-import without path
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("c.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("c.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "chal",
@@ -9155,7 +9171,9 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   }));
 
   let list = client.get_completion_list(
-    temp_dir.url().join("c.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("c.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (0, 4),
     json!({ "triggerKind": 1 }),
   );
@@ -9194,7 +9212,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   // try quick fix without path
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("d.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("d.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "chalk",
@@ -9202,7 +9220,9 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   }));
   let diagnostics = diagnostics
     .messages_with_file_and_source(
-      temp_dir.url().join("d.ts").unwrap().as_str(),
+      url_to_uri(&temp_dir.url().join("d.ts").unwrap())
+        .unwrap()
+        .as_str(),
       "deno-ts",
     )
     .diagnostics;
@@ -9210,7 +9230,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
     "textDocument/codeAction",
     json!(json!({
       "textDocument": {
-        "uri": temp_dir.url().join("d.ts").unwrap()
+        "uri": url_to_uri(&temp_dir.url().join("d.ts").unwrap()).unwrap()
       },
       "range": {
         "start": { "line": 0, "character": 0 },
@@ -9242,7 +9262,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
       "edit": {
         "documentChanges": [{
             "textDocument": {
-              "uri": temp_dir.url().join("d.ts").unwrap(),
+              "uri": url_to_uri(&temp_dir.url().join("d.ts").unwrap()).unwrap(),
               "version": 1,
             },
             "edits": [{
@@ -9260,7 +9280,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   // try auto-import with http import map
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("e.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("e.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "printH",
@@ -9268,7 +9288,9 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   }));
 
   let list = client.get_completion_list(
-    temp_dir.url().join("e.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("e.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (0, 6),
     json!({ "triggerKind": 1 }),
   );
@@ -9307,7 +9329,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   // try quick fix with http import
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("f.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("f.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "printHello",
@@ -9315,7 +9337,9 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   }));
   let diagnostics = diagnostics
     .messages_with_file_and_source(
-      temp_dir.url().join("f.ts").unwrap().as_str(),
+      url_to_uri(&temp_dir.url().join("f.ts").unwrap())
+        .unwrap()
+        .as_str(),
       "deno-ts",
     )
     .diagnostics;
@@ -9323,7 +9347,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
     "textDocument/codeAction",
     json!(json!({
       "textDocument": {
-        "uri": temp_dir.url().join("f.ts").unwrap()
+        "uri": url_to_uri(&temp_dir.url().join("f.ts").unwrap()).unwrap()
       },
       "range": {
         "start": { "line": 0, "character": 0 },
@@ -9355,7 +9379,7 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
       "edit": {
         "documentChanges": [{
             "textDocument": {
-              "uri": temp_dir.url().join("f.ts").unwrap(),
+              "uri": url_to_uri(&temp_dir.url().join("f.ts").unwrap()).unwrap(),
               "version": 1,
             },
             "edits": [{
@@ -9373,14 +9397,16 @@ fn lsp_completions_auto_import_and_quick_fix_with_import_map() {
   // try auto-import with npm package with sub-path on value side of import map
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("nested_path.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("nested_path.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "entry",
     }
   }));
   let list = client.get_completion_list(
-    temp_dir.url().join("nested_path.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("nested_path.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (0, 5),
     json!({ "triggerKind": 1 }),
   );
@@ -9444,7 +9470,7 @@ fn lsp_quick_fix_missing_import_exclude_bare_node_builtins() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       // Include node:buffer import to ensure @types/node is in the dep graph.
@@ -9460,7 +9486,7 @@ fn lsp_quick_fix_missing_import_exclude_bare_node_builtins() {
     "textDocument/codeAction",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
       "range": {
         "start": { "line": 1, "character": 0 },
@@ -9812,7 +9838,7 @@ fn lsp_auto_import_npm_export_node_modules_dir_auto() {
   context.run_deno("cache mod.ts");
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
-  let file_uri = temp_dir_path.join("file.ts").url_file();
+  let file_uri = temp_dir_path.join("file.ts").uri_file();
   let mut diagnostics = client
     .did_open(json!({
       "textDocument": {
@@ -9889,7 +9915,7 @@ fn lsp_auto_import_npm_export_node_modules_dir_manual() {
   let diagnostics = client
     .did_open(json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
         "languageId": "typescript",
         "version": 1,
         "text": "useEffect",
@@ -9902,7 +9928,7 @@ fn lsp_auto_import_npm_export_node_modules_dir_manual() {
     "textDocument/codeAction",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
       "range": {
         "start": { "line": 0, "character": 0 },
@@ -9944,7 +9970,7 @@ fn lsp_auto_imports_remote_dts() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -9962,7 +9988,9 @@ fn lsp_auto_imports_remote_dts() {
   );
   client.read_diagnostics();
   let list = client.get_completion_list(
-    temp_dir.url().join("file.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (2, 21),
     json!({ "triggerKind": 2 }),
   );
@@ -10030,7 +10058,7 @@ fn lsp_npm_specifier_unopened_file() {
   // open main.ts, which imports other.ts (unopened)
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("main.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("main.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import { chalk } from './other.ts';\n\n",
@@ -10041,7 +10069,7 @@ fn lsp_npm_specifier_unopened_file() {
     "textDocument/didChange",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("main.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("main.ts").unwrap()).unwrap(),
         "version": 2
       },
       "contentChanges": [
@@ -10059,7 +10087,9 @@ fn lsp_npm_specifier_unopened_file() {
 
   // now ensure completions work
   let list = client.get_completion_list(
-    temp_dir.url().join("main.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("main.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (2, 6),
     json!({
       "triggerKind": 2,
@@ -10312,7 +10342,7 @@ fn lsp_completions_node_specifier_node_modules_dir() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import fs from \"node:fs\";\n",
@@ -10330,7 +10360,7 @@ fn lsp_completions_node_specifier_node_modules_dir() {
     "textDocument/didChange",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
         "version": 2,
       },
       "contentChanges": [
@@ -10345,7 +10375,9 @@ fn lsp_completions_node_specifier_node_modules_dir() {
     }),
   );
   let list = client.get_completion_list(
-    temp_dir.url().join("file.ts").unwrap(),
+    url_to_uri(&temp_dir.url().join("file.ts").unwrap())
+      .unwrap()
+      .as_str(),
     (1, 3),
     json!({
       "triggerKind": 2,
@@ -10972,7 +11004,7 @@ fn lsp_lockfile_redirect_resolution() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"http://localhost:4545/subdir/mod1.ts\";\n",
@@ -10989,7 +11021,7 @@ fn lsp_lockfile_redirect_resolution() {
   let res = client.write_request(
     "textDocument/definition",
     json!({
-      "textDocument": { "uri": temp_dir.url().join("file.ts").unwrap() },
+      "textDocument": { "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap() },
       "position": { "line": 0, "character": 7 },
     }),
   );
@@ -11257,7 +11289,7 @@ fn lsp_ts_diagnostics_refresh_on_lsp_version_reset() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("file.ts"),
@@ -11268,7 +11300,7 @@ fn lsp_ts_diagnostics_refresh_on_lsp_version_reset() {
     "textDocument/didClose",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
     }),
   );
@@ -11277,7 +11309,7 @@ fn lsp_ts_diagnostics_refresh_on_lsp_version_reset() {
   // diagnostics are still refreshed.
   client.did_open_raw(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "",
@@ -11286,7 +11318,7 @@ fn lsp_ts_diagnostics_refresh_on_lsp_version_reset() {
   temp_dir.write("file.ts", r#""#);
   client.did_save(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
     },
   }));
   let diagnostics = client.read_diagnostics();
@@ -11314,7 +11346,7 @@ fn lsp_diagnostics_none_for_resolving_types() {
   // run in Deno or Node.
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": context.temp_dir().path().join("file.ts").url_file(),
+      "uri": context.temp_dir().path().join("file.ts").uri_file(),
       "languageId": "typescript",
       "version": 1,
       "text": concat!(
@@ -11630,7 +11662,8 @@ fn lsp_format_exclude_with_config() {
     builder.set_config("./deno.fmt.jsonc");
   });
 
-  let file_uri = temp_dir.url().join("ignored.ts").unwrap();
+  let file_uri =
+    url_to_uri(&temp_dir.url().join("ignored.ts").unwrap()).unwrap();
   client.did_open(json!({
     "textDocument": {
       "uri": file_uri,
@@ -11682,7 +11715,8 @@ fn lsp_format_exclude_default_config() {
     builder.set_config("./deno.fmt.jsonc");
   });
 
-  let file_uri = temp_dir.url().join("ignored.ts").unwrap();
+  let file_uri =
+    url_to_uri(&temp_dir.url().join("ignored.ts").unwrap()).unwrap();
   client.did_open(json!({
     "textDocument": {
       "uri": file_uri,
@@ -11762,7 +11796,7 @@ fn lsp_format_json() {
     "textDocument/formatting",
     json!({
       "textDocument": {
-        "uri": json_file.url(),
+        "uri": json_file.uri(),
       },
       "options": {
         "tabSize": 2,
@@ -11854,7 +11888,7 @@ fn lsp_format_editor_options() {
     "textDocument/formatting",
     json!({
       "textDocument": {
-        "uri": file.url(),
+        "uri": file.uri(),
       },
       "options": {
         "tabSize": 4,
@@ -11878,7 +11912,7 @@ fn lsp_format_editor_options() {
     "textDocument/formatting",
     json!({
       "textDocument": {
-        "uri": file.url(),
+        "uri": file.uri(),
       },
       "options": {
         "tabSize": 2,
@@ -11957,7 +11991,7 @@ fn lsp_json_import_with_query_string() {
   client.initialize_default();
   client.did_open_raw(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("data.json").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("data.json").unwrap()).unwrap(),
       "languageId": "json",
       "version": 1,
       "text": temp_dir.read_to_string("data.json"),
@@ -11965,7 +11999,7 @@ fn lsp_json_import_with_query_string() {
   }));
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("main.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("main.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.read_to_string("main.ts"),
@@ -11988,7 +12022,7 @@ fn lsp_format_markdown() {
     "textDocument/formatting",
     json!({
       "textDocument": {
-        "uri": file.url()
+        "uri": file.uri(),
       },
       "options": {
         "tabSize": 2,
@@ -12029,7 +12063,7 @@ fn lsp_format_html() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": file.url() },
+      "textDocument": { "uri": file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12078,7 +12112,7 @@ fn lsp_format_css() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": css_file.url() },
+      "textDocument": { "uri": css_file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12100,7 +12134,7 @@ fn lsp_format_css() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": scss_file.url() },
+      "textDocument": { "uri": scss_file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12122,7 +12156,7 @@ fn lsp_format_css() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": sass_file.url() },
+      "textDocument": { "uri": sass_file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12144,7 +12178,7 @@ fn lsp_format_css() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": less_file.url() },
+      "textDocument": { "uri": less_file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12177,7 +12211,7 @@ fn lsp_format_yaml() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": file.url() },
+      "textDocument": { "uri": file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12227,7 +12261,7 @@ fn lsp_format_sql() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": file.url() },
+      "textDocument": { "uri": file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12293,7 +12327,7 @@ fn lsp_format_component() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": svelte_file.url() },
+      "textDocument": { "uri": svelte_file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12315,7 +12349,7 @@ fn lsp_format_component() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": vue_file.url() },
+      "textDocument": { "uri": vue_file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12337,7 +12371,7 @@ fn lsp_format_component() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": astro_file.url() },
+      "textDocument": { "uri": astro_file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12359,7 +12393,7 @@ fn lsp_format_component() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": vento_file.url() },
+      "textDocument": { "uri": vento_file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12381,7 +12415,7 @@ fn lsp_format_component() {
   let res = client.write_request(
     "textDocument/formatting",
     json!({
-      "textDocument": { "uri": nunjucks_file.url() },
+      "textDocument": { "uri": nunjucks_file.uri() },
       "options": {
         "tabSize": 2,
         "insertSpaces": true,
@@ -12434,7 +12468,7 @@ fn lsp_format_with_config() {
     .did_open(
       json!({
         "textDocument": {
-          "uri": ts_file.url_file(),
+          "uri": ts_file.uri_file(),
           "languageId": "typescript",
           "version": 1,
           "text": "export async function someVeryLongFunctionName() {\nconst response = fetch(\"http://localhost:4545/some/non/existent/path.json\");\nconsole.log(response.text());\nconsole.log(\"finished!\")\n}"
@@ -12447,7 +12481,7 @@ fn lsp_format_with_config() {
     "textDocument/formatting",
     json!({
       "textDocument": {
-        "uri": ts_file.url_file()
+        "uri": ts_file.uri_file()
       },
       "options": {
         "tabSize": 2,
@@ -13286,7 +13320,7 @@ fn lsp_lint_with_config() {
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "// TODO: fixme\nexport async function non_camel_case() {\nconsole.log(\"finished!\")\n}"
@@ -13427,7 +13461,7 @@ fn lsp_jsx_import_source_config_file_automatic_cache() {
   client.initialize_default();
   let mut diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.tsx").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.tsx").unwrap()).unwrap(),
       "languageId": "typescriptreact",
       "version": 1,
       "text": "
@@ -13450,7 +13484,7 @@ fn lsp_jsx_import_source_config_file_automatic_cache() {
       "textDocument/didChange",
       json!({
         "textDocument": {
-          "uri": temp_dir.url().join("file.tsx").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("file.tsx").unwrap()).unwrap(),
           "version": version,
         },
         "contentChanges": [
@@ -13503,7 +13537,7 @@ fn lsp_jsx_import_source_package_json_automatic_cache() {
   client.initialize_default();
   let mut diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.tsx").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.tsx").unwrap()).unwrap(),
       "languageId": "typescriptreact",
       "version": 1,
       "text": "
@@ -13526,7 +13560,7 @@ fn lsp_jsx_import_source_package_json_automatic_cache() {
       "textDocument/didChange",
       json!({
         "textDocument": {
-          "uri": temp_dir.url().join("file.tsx").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("file.tsx").unwrap()).unwrap(),
           "version": version,
         },
         "contentChanges": [
@@ -13584,7 +13618,7 @@ fn lsp_jsx_import_source_byonm_preact() {
   let res = client.write_request(
     "textDocument/hover",
     json!({
-      "textDocument": { "uri": file.url() },
+      "textDocument": { "uri": file.uri() },
       "position": { "line": 0, "character": 1 },
     }),
   );
@@ -13733,7 +13767,7 @@ Deno.test({
 "#;
   temp_dir.write("./test.ts", contents);
   temp_dir.write("./deno.jsonc", "{}");
-  let specifier = temp_dir.url().join("test.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("test.ts").unwrap()).unwrap();
 
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
@@ -13746,7 +13780,7 @@ Deno.test({
 
   client.did_open(json!({
     "textDocument": {
-      "uri": specifier,
+      "uri": uri,
       "languageId": "typescript",
       "version": 1,
       "text": contents,
@@ -13757,7 +13791,7 @@ Deno.test({
     client.read_notification_with_method::<Value>("deno/testModule");
   let params: TestModuleNotificationParams =
     serde_json::from_value(notification.unwrap()).unwrap();
-  assert_eq!(params.text_document.uri.as_str(), specifier.as_str());
+  assert_eq!(params.text_document.uri.as_str(), uri.as_str());
   assert_eq!(params.kind, TestModuleNotificationKind::Replace);
   assert_eq!(params.label, "test.ts");
   assert_eq!(params.tests.len(), 1);
@@ -13802,10 +13836,7 @@ Deno.test({
     }),
   );
   assert_eq!(res.enqueued.len(), 1);
-  assert_eq!(
-    res.enqueued[0].text_document.uri.as_str(),
-    specifier.as_str()
-  );
+  assert_eq!(res.enqueued[0].text_document.uri.as_str(), uri.as_str());
   assert_eq!(res.enqueued[0].ids.len(), 1);
   let id = res.enqueued[0].ids[0].clone();
   let notification =
@@ -13818,7 +13849,7 @@ Deno.test({
         "type": "started",
         "test": {
           "textDocument": {
-            "uri": specifier,
+            "uri": uri,
           },
           "id": id,
         },
@@ -13854,7 +13885,7 @@ Deno.test({
         "value": notification_value,
         "test": {
           "textDocument": {
-            "uri": specifier,
+            "uri": uri,
           },
           "id": id,
         },
@@ -13872,7 +13903,7 @@ Deno.test({
         "type": "started",
         "test": {
           "textDocument": {
-            "uri": specifier,
+            "uri": uri,
           },
           "id": id,
           "stepId": step.id,
@@ -13901,7 +13932,7 @@ Deno.test({
         "type": "passed",
         "test": {
           "textDocument": {
-            "uri": specifier,
+            "uri": uri,
           },
           "id": id,
           "stepId": step.id,
@@ -13922,7 +13953,7 @@ Deno.test({
         message.get("test"),
         Some(&json!({
           "textDocument": {
-            "uri": specifier
+            "uri": uri
           },
           "id": id,
         }))
@@ -13954,7 +13985,7 @@ Deno.test({
     "textDocument/didChange",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("test.ts").unwrap(),
+        "uri": uri,
         "version": 2
       },
       "contentChanges": [{ "text": "" }],
@@ -13969,9 +14000,9 @@ Deno.test({
     notification,
     Some(json!({
       "textDocument": {
-        "uri": temp_dir.url().join("test.ts").unwrap()
-      }
-    }))
+        "uri": uri,
+      },
+    })),
   );
 
   client.shutdown();
@@ -13987,12 +14018,11 @@ fn lsp_closed_file_find_references() {
     "./mod.test.ts",
     "import { a } from './mod.ts'; console.log(a);",
   );
-  let temp_dir_url = temp_dir.url();
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir_url.join("mod.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("mod.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"export const a = 5;"#
@@ -14002,7 +14032,7 @@ fn lsp_closed_file_find_references() {
     "textDocument/references",
     json!({
       "textDocument": {
-        "uri": temp_dir_url.join("mod.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("mod.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 13 },
       "context": {
@@ -14014,13 +14044,13 @@ fn lsp_closed_file_find_references() {
   assert_eq!(
     res,
     json!([{
-      "uri": temp_dir_url.join("mod.test.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("mod.test.ts").unwrap()).unwrap(),
       "range": {
         "start": { "line": 0, "character": 9 },
         "end": { "line": 0, "character": 10 }
       }
     }, {
-      "uri": temp_dir_url.join("mod.test.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("mod.test.ts").unwrap()).unwrap(),
       "range": {
         "start": { "line": 0, "character": 42 },
         "end": { "line": 0, "character": 43 }
@@ -14042,14 +14072,13 @@ fn lsp_closed_file_find_references_low_document_pre_load() {
     "./sub_dir/mod.test.ts",
     "import { a } from './mod.ts'; console.log(a);",
   );
-  let temp_dir_url = temp_dir.url();
   let mut client = context.new_lsp_command().build();
   client.initialize(|builder| {
     builder.set_preload_limit(1);
   });
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir_url.join("sub_dir/mod.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("sub_dir/mod.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"export const a = 5;"#
@@ -14059,7 +14088,7 @@ fn lsp_closed_file_find_references_low_document_pre_load() {
     "textDocument/references",
     json!({
       "textDocument": {
-        "uri": temp_dir_url.join("sub_dir/mod.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("sub_dir/mod.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 13 },
       "context": {
@@ -14099,12 +14128,11 @@ fn lsp_closed_file_find_references_excluded_path() {
   ]
 }"#,
   );
-  let temp_dir_url = temp_dir.url();
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir_url.join("sub_dir/mod.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("sub_dir/mod.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"export const a = 5;"#
@@ -14114,7 +14142,7 @@ fn lsp_closed_file_find_references_excluded_path() {
     "textDocument/references",
     json!({
       "textDocument": {
-        "uri": temp_dir_url.join("sub_dir/mod.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("sub_dir/mod.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 13 },
       "context": {
@@ -14142,7 +14170,7 @@ fn lsp_data_urls_with_jsx_compiler_option() {
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
 
-  let uri = temp_dir.url().join("main.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("main.ts").unwrap()).unwrap();
 
   let diagnostics = client.did_open(json!({
     "textDocument": {
@@ -14216,7 +14244,8 @@ fn lsp_node_modules_dir() {
 
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
-  let file_uri = temp_dir.url().join("file.ts").unwrap();
+  let file_url = temp_dir.url().join("file.ts").unwrap();
+  let file_uri = url_to_uri(&file_url).unwrap();
   client.did_open(json!({
     "textDocument": {
       "uri": file_uri,
@@ -14230,7 +14259,7 @@ fn lsp_node_modules_dir() {
       "workspace/executeCommand",
       json!({
         "command": "deno.cache",
-        "arguments": [["npm:chalk", "npm:@types/node"], file_uri],
+        "arguments": [["npm:chalk", "npm:@types/node"], file_url],
       }),
     );
     client.read_diagnostics()
@@ -14316,7 +14345,12 @@ fn lsp_node_modules_dir() {
     .unwrap();
   // canonicalize for mac
   let path = temp_dir.path().join("node_modules").canonicalize();
-  assert_starts_with!(uri, Url::from_file_path(&path).unwrap().as_str());
+  assert_starts_with!(
+    uri,
+    url_to_uri(&Url::from_file_path(&path).unwrap())
+      .unwrap()
+      .as_str()
+  );
 
   client.shutdown();
 }
@@ -14332,7 +14366,8 @@ fn lsp_vendor_dir() {
 
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
-  let local_file_uri = temp_dir.url().join("file.ts").unwrap();
+  let local_file_url = temp_dir.url().join("file.ts").unwrap();
+  let local_file_uri = url_to_uri(&local_file_url).unwrap();
   client.did_open(json!({
     "textDocument": {
       "uri": local_file_uri,
@@ -14346,7 +14381,7 @@ fn lsp_vendor_dir() {
       "workspace/executeCommand",
       json!({
         "command": "deno.cache",
-        "arguments": [["http://localhost:4545/subdir/mod1.ts"], local_file_uri],
+        "arguments": [["http://localhost:4545/subdir/mod1.ts"], local_file_url],
       }),
     );
   };
@@ -14436,7 +14471,7 @@ fn lsp_vendor_dir() {
   let file_path = temp_dir
     .path()
     .join("vendor/http_localhost_4545/subdir/mod1.ts");
-  let remote_file_uri = file_path.url_file();
+  let remote_file_uri = file_path.uri_file();
   assert_eq!(uri, remote_file_uri.as_str());
 
   let file_text = file_path.read_to_string();
@@ -14596,7 +14631,7 @@ fn lsp_deno_json_scopes_import_map() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"foo\";\n",
@@ -14606,7 +14641,7 @@ fn lsp_deno_json_scopes_import_map() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -14626,7 +14661,7 @@ fn lsp_deno_json_scopes_import_map() {
   );
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"foo\";\n",
@@ -14636,7 +14671,7 @@ fn lsp_deno_json_scopes_import_map() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -14656,7 +14691,7 @@ fn lsp_deno_json_scopes_import_map() {
   );
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/project3/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/project3/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"foo\";\n",
@@ -14666,7 +14701,7 @@ fn lsp_deno_json_scopes_import_map() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project2/project3/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project2/project3/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -14720,7 +14755,7 @@ fn lsp_deno_json_scopes_vendor_dir() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"http://localhost:4545/subdir/mod1.ts\";\n",
@@ -14738,7 +14773,7 @@ fn lsp_deno_json_scopes_vendor_dir() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -14746,7 +14781,7 @@ fn lsp_deno_json_scopes_vendor_dir() {
   assert_eq!(
     res,
     json!([{
-      "targetUri": temp_dir.url().join("project1/vendor/http_localhost_4545/subdir/mod1.ts").unwrap(),
+      "targetUri": url_to_uri(&temp_dir.url().join("project1/vendor/http_localhost_4545/subdir/mod1.ts").unwrap()).unwrap(),
       "targetRange": {
         "start": {
           "line": 0,
@@ -14771,7 +14806,7 @@ fn lsp_deno_json_scopes_vendor_dir() {
   );
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"http://localhost:4545/subdir/mod2.ts\";\n",
@@ -14789,7 +14824,7 @@ fn lsp_deno_json_scopes_vendor_dir() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -14797,7 +14832,7 @@ fn lsp_deno_json_scopes_vendor_dir() {
   assert_eq!(
     res,
     json!([{
-      "targetUri": temp_dir.url().join("project2/vendor/http_localhost_4545/subdir/mod2.ts").unwrap(),
+      "targetUri": url_to_uri(&temp_dir.url().join("project2/vendor/http_localhost_4545/subdir/mod2.ts").unwrap()).unwrap(),
       "targetRange": {
         "start": {
           "line": 0,
@@ -14822,7 +14857,7 @@ fn lsp_deno_json_scopes_vendor_dir() {
   );
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/project3/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/project3/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"http://localhost:4545/subdir/mod3.js\";\n",
@@ -14840,7 +14875,7 @@ fn lsp_deno_json_scopes_vendor_dir() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project2/project3/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project2/project3/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -14848,7 +14883,7 @@ fn lsp_deno_json_scopes_vendor_dir() {
   assert_eq!(
     res,
     json!([{
-      "targetUri": temp_dir.url().join("project2/project3/vendor/http_localhost_4545/subdir/mod3.js").unwrap(),
+      "targetUri": url_to_uri(&temp_dir.url().join("project2/project3/vendor/http_localhost_4545/subdir/mod3.js").unwrap()).unwrap(),
       "targetRange": {
         "start": {
           "line": 0,
@@ -14907,7 +14942,7 @@ fn lsp_deno_json_scopes_node_modules_dir() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"npm:@denotest/add@1\";\n",
@@ -14925,7 +14960,7 @@ fn lsp_deno_json_scopes_node_modules_dir() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -14936,7 +14971,7 @@ fn lsp_deno_json_scopes_node_modules_dir() {
   assert_eq!(
     res,
     json!([{
-      "targetUri": canon_temp_dir.join("project1/node_modules/.deno/%40denotest%2Badd%401.0.0/node_modules/%40denotest/add/index.d.ts").unwrap(),
+      "targetUri": url_to_uri(&canon_temp_dir.join("project1/node_modules/.deno/%40denotest%2Badd%401.0.0/node_modules/%40denotest/add/index.d.ts").unwrap()).unwrap(),
       "targetRange": {
         "start": {
           "line": 0,
@@ -14961,7 +14996,7 @@ fn lsp_deno_json_scopes_node_modules_dir() {
   );
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"npm:@denotest/add@1\";\n",
@@ -14979,7 +15014,7 @@ fn lsp_deno_json_scopes_node_modules_dir() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -14987,7 +15022,7 @@ fn lsp_deno_json_scopes_node_modules_dir() {
   assert_eq!(
     res,
     json!([{
-      "targetUri": canon_temp_dir.join("project2/node_modules/.deno/%40denotest%2Badd%401.0.0/node_modules/%40denotest/add/index.d.ts").unwrap(),
+      "targetUri": url_to_uri(&canon_temp_dir.join("project2/node_modules/.deno/%40denotest%2Badd%401.0.0/node_modules/%40denotest/add/index.d.ts").unwrap()).unwrap(),
       "targetRange": {
         "start": {
           "line": 0,
@@ -15012,7 +15047,7 @@ fn lsp_deno_json_scopes_node_modules_dir() {
   );
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/project3/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/project3/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"npm:@denotest/add@1\";\n",
@@ -15030,7 +15065,7 @@ fn lsp_deno_json_scopes_node_modules_dir() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project2/project3/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project2/project3/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -15038,7 +15073,7 @@ fn lsp_deno_json_scopes_node_modules_dir() {
   assert_eq!(
     res,
     json!([{
-      "targetUri": canon_temp_dir.join("project2/project3/node_modules/.deno/%40denotest%2Badd%401.0.0/node_modules/%40denotest/add/index.d.ts").unwrap(),
+      "targetUri": url_to_uri(&canon_temp_dir.join("project2/project3/node_modules/.deno/%40denotest%2Badd%401.0.0/node_modules/%40denotest/add/index.d.ts").unwrap()).unwrap(),
       "targetRange": {
         "start": {
           "line": 0,
@@ -15083,7 +15118,7 @@ fn lsp_deno_json_scopes_ts_config() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "Window;\nWorkerGlobalScope;\n",
@@ -15091,7 +15126,7 @@ fn lsp_deno_json_scopes_ts_config() {
   }));
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "Window;\nWorkerGlobalScope;\n",
@@ -15101,7 +15136,7 @@ fn lsp_deno_json_scopes_ts_config() {
     json!(diagnostics.all_messages()),
     json!([
       {
-        "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
         "version": 1,
         "diagnostics": [
           {
@@ -15117,7 +15152,7 @@ fn lsp_deno_json_scopes_ts_config() {
         ],
       },
       {
-        "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
         "version": 1,
         "diagnostics": [
           {
@@ -15150,7 +15185,7 @@ fn lsp_deno_json_scopes_declaration_files() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "export const foo: Foo = 1;\nexport const bar: Bar = 1;\n",
@@ -15158,7 +15193,7 @@ fn lsp_deno_json_scopes_declaration_files() {
   }));
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "export const foo: Foo = 1;\nexport const bar: Bar = 1;\n",
@@ -15168,7 +15203,7 @@ fn lsp_deno_json_scopes_declaration_files() {
     json!(diagnostics.all_messages()),
     json!([
       {
-        "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
         "version": 1,
         "diagnostics": [
           {
@@ -15184,7 +15219,7 @@ fn lsp_deno_json_scopes_declaration_files() {
         ],
       },
       {
-        "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
         "version": 1,
         "diagnostics": [
           {
@@ -15235,11 +15270,11 @@ fn lsp_deno_json_scopes_find_references() {
     res,
     json!([
       {
-        "uri": file1.url(),
+        "uri": file1.uri(),
         "range": file1.range_of("foo"),
       },
       {
-        "uri": file2.url(),
+        "uri": file2.uri(),
         "range": file2.range_of("foo"),
       },
     ]),
@@ -15267,8 +15302,8 @@ fn lsp_deno_json_scopes_file_rename_import_edits() {
     json!({
       "files": [
         {
-          "oldUri": file1.url(),
-          "newUri": file1.url().join("file_renamed.ts").unwrap(),
+          "oldUri": file1.uri(),
+          "newUri": url_to_uri(&file1.url().join("file_renamed.ts").unwrap()).unwrap(),
         },
       ],
     }),
@@ -15279,7 +15314,7 @@ fn lsp_deno_json_scopes_file_rename_import_edits() {
       "documentChanges": [
         {
           "textDocument": {
-            "uri": file2.url(),
+            "uri": file2.uri(),
             "version": null,
           },
           "edits": [
@@ -15326,7 +15361,7 @@ fn lsp_deno_json_scopes_goto_implementations() {
     res,
     json!([
       {
-        "targetUri": file2.url(),
+        "targetUri": file2.uri(),
         "targetRange": file2.range_of("export class SomeFoo implements Foo {}"),
         "targetSelectionRange": file2.range_of("SomeFoo"),
       },
@@ -15381,7 +15416,7 @@ fn lsp_deno_json_scopes_call_hierarchy() {
         "name": "bar",
         "kind": 12,
         "detail": "",
-        "uri": file2.url(),
+        "uri": file2.uri(),
         "range": {
           "start": { "line": 2, "character": 6 },
           "end": { "line": 4, "character": 7 },
@@ -15401,7 +15436,7 @@ fn lsp_deno_json_scopes_call_hierarchy() {
           "name": "file.ts",
           "kind": 2,
           "detail": "project3",
-          "uri": file3.url(),
+          "uri": file3.uri(),
           "range": {
             "start": { "line": 1, "character": 6 },
             "end": { "line": 3, "character": 4 },
@@ -15430,7 +15465,7 @@ fn lsp_deno_json_scopes_call_hierarchy() {
           "name": "foo",
           "kind": 12,
           "detail": "",
-          "uri": file1.url(),
+          "uri": file1.uri(),
           "range": file1.range_of("export function foo() {}"),
           "selectionRange": file1.range_of("foo"),
         },
@@ -15477,7 +15512,7 @@ fn lsp_deno_json_scopes_rename_symbol() {
       "documentChanges": [
         {
           "textDocument": {
-            "uri": file1.url(),
+            "uri": file1.uri(),
             "version": null,
           },
           "edits": [
@@ -15489,7 +15524,7 @@ fn lsp_deno_json_scopes_rename_symbol() {
         },
         {
           "textDocument": {
-            "uri": file2.url(),
+            "uri": file2.uri(),
             "version": null,
           },
           "edits": [
@@ -15532,7 +15567,7 @@ fn lsp_deno_json_scopes_search_symbol() {
         "name": "someSymbol1",
         "kind": 13,
         "location": {
-          "uri": file1.url(),
+          "uri": file1.uri(),
           "range": file1.range_of("someSymbol1 = 1"),
         },
         "containerName": "",
@@ -15541,7 +15576,7 @@ fn lsp_deno_json_scopes_search_symbol() {
         "name": "someSymbol2",
         "kind": 13,
         "location": {
-          "uri": file2.url(),
+          "uri": file2.uri(),
           "range": file2.range_of("someSymbol2 = 2"),
         },
         "containerName": "",
@@ -15580,7 +15615,7 @@ fn lsp_deno_json_workspace_fmt_config() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "console.log(\"\");\n",
@@ -15590,7 +15625,7 @@ fn lsp_deno_json_workspace_fmt_config() {
     "textDocument/formatting",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
       "options": {
         "tabSize": 2,
@@ -15610,7 +15645,7 @@ fn lsp_deno_json_workspace_fmt_config() {
   );
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "console.log(\"\");\n",
@@ -15620,7 +15655,7 @@ fn lsp_deno_json_workspace_fmt_config() {
     "textDocument/formatting",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       },
       "options": {
         "tabSize": 2,
@@ -15642,7 +15677,7 @@ fn lsp_deno_json_workspace_fmt_config() {
   // has no fmt field.
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "console.log(\"\");\n",
@@ -15652,7 +15687,7 @@ fn lsp_deno_json_workspace_fmt_config() {
     "textDocument/formatting",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       },
       "options": {
         "tabSize": 2,
@@ -15706,7 +15741,7 @@ fn lsp_deno_json_workspace_lint_config() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -15719,7 +15754,7 @@ fn lsp_deno_json_workspace_lint_config() {
   assert_eq!(
     json!(diagnostics.messages_with_source("deno-lint")),
     json!({
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "diagnostics": [{
         "range": {
           "start": { "line": 2, "character": 14 },
@@ -15737,13 +15772,13 @@ fn lsp_deno_json_workspace_lint_config() {
     "textDocument/didClose",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
     }),
   );
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -15756,7 +15791,7 @@ fn lsp_deno_json_workspace_lint_config() {
   assert_eq!(
     json!(diagnostics.messages_with_source("deno-lint")),
     json!({
-      "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       "diagnostics": [{
         "range": {
           "start": { "line": 1, "character": 8 },
@@ -15783,7 +15818,7 @@ fn lsp_deno_json_workspace_lint_config() {
     "textDocument/didClose",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
       },
     }),
   );
@@ -15791,7 +15826,7 @@ fn lsp_deno_json_workspace_lint_config() {
   // has no lint field.
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -15804,7 +15839,7 @@ fn lsp_deno_json_workspace_lint_config() {
   assert_eq!(
     json!(diagnostics.messages_with_source("deno-lint")),
     json!({
-      "uri": temp_dir.url().join("project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project2/file.ts").unwrap()).unwrap(),
       "diagnostics": [{
         "range": {
           "start": { "line": 2, "character": 14 },
@@ -15855,7 +15890,7 @@ fn lsp_deno_json_workspace_import_map() {
   {
     client.did_open(json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
         "languageId": "typescript",
         "version": 1,
         "text": "import \"foo\";\n",
@@ -15865,7 +15900,7 @@ fn lsp_deno_json_workspace_import_map() {
       "textDocument/hover",
       json!({
         "textDocument": {
-          "uri": temp_dir.url().join("project1/file.ts").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("project1/file.ts").unwrap()).unwrap(),
         },
         "position": { "line": 0, "character": 7 },
       }),
@@ -15889,7 +15924,7 @@ fn lsp_deno_json_workspace_import_map() {
   {
     client.did_open(json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project1/project2/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/project2/file.ts").unwrap()).unwrap(),
         "languageId": "typescript",
         "version": 1,
         "text": "import \"foo\";\n",
@@ -15899,7 +15934,7 @@ fn lsp_deno_json_workspace_import_map() {
       "textDocument/hover",
       json!({
         "textDocument": {
-          "uri": temp_dir.url().join("project1/project2/file.ts").unwrap(),
+          "uri": url_to_uri(&temp_dir.url().join("project1/project2/file.ts").unwrap()).unwrap(),
         },
         "position": { "line": 0, "character": 7 },
       }),
@@ -15948,7 +15983,7 @@ fn lsp_workspace_lockfile() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"http://localhost:4545/subdir/mod1.ts\";\n",
@@ -15965,7 +16000,7 @@ fn lsp_workspace_lockfile() {
   let res = client.write_request(
     "textDocument/definition",
     json!({
-      "textDocument": { "uri": temp_dir.url().join("project1/project2/file.ts").unwrap() },
+      "textDocument": { "uri": url_to_uri(&temp_dir.url().join("project1/project2/file.ts").unwrap()).unwrap() },
       "position": { "line": 0, "character": 7 },
     }),
   );
@@ -16007,7 +16042,7 @@ fn lsp_deno_json_workspace_vendor_dir() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"http://localhost:4545/subdir/mod1.ts\";\n",
@@ -16025,7 +16060,7 @@ fn lsp_deno_json_workspace_vendor_dir() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project1/project2/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/project2/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -16033,7 +16068,7 @@ fn lsp_deno_json_workspace_vendor_dir() {
   assert_eq!(
     res,
     json!([{
-      "targetUri": temp_dir.url().join("project1/vendor/http_localhost_4545/subdir/mod1.ts").unwrap(),
+      "targetUri": url_to_uri(&temp_dir.url().join("project1/vendor/http_localhost_4545/subdir/mod1.ts").unwrap()).unwrap(),
       "targetRange": {
         "start": {
           "line": 0,
@@ -16080,7 +16115,7 @@ fn lsp_deno_json_workspace_node_modules_dir() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("project1/project2/file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("project1/project2/file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"npm:@denotest/add@1\";\n",
@@ -16098,7 +16133,7 @@ fn lsp_deno_json_workspace_node_modules_dir() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("project1/project2/file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("project1/project2/file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -16109,7 +16144,7 @@ fn lsp_deno_json_workspace_node_modules_dir() {
   assert_eq!(
     res,
     json!([{
-      "targetUri": canon_temp_dir.join("project1/node_modules/.deno/%40denotest%2Badd%401.0.0/node_modules/%40denotest/add/index.d.ts").unwrap(),
+      "targetUri": url_to_uri(&canon_temp_dir.join("project1/node_modules/.deno/%40denotest%2Badd%401.0.0/node_modules/%40denotest/add/index.d.ts").unwrap()).unwrap(),
       "targetRange": {
         "start": {
           "line": 0,
@@ -16162,7 +16197,7 @@ fn lsp_deno_json_workspace_jsr_resolution() {
   client.initialize_default();
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import \"jsr:@org/project1@^1.0.0\";\n",
@@ -16172,7 +16207,7 @@ fn lsp_deno_json_workspace_jsr_resolution() {
     "textDocument/hover",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("file.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 7 },
     }),
@@ -16314,7 +16349,7 @@ fn lsp_npm_workspace() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("packages/subtract/index.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("packages/subtract/index.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": "import { add } from 'add';\nexport function subtract(a: number, b: number): number { return add(a, -b); }",
@@ -16325,7 +16360,7 @@ fn lsp_npm_workspace() {
     "textDocument/definition",
     json!({
       "textDocument": {
-        "uri": temp_dir.url().join("packages/subtract/index.ts").unwrap(),
+        "uri": url_to_uri(&temp_dir.url().join("packages/subtract/index.ts").unwrap()).unwrap(),
       },
       "position": { "line": 0, "character": 9 },
     }),
@@ -16334,7 +16369,7 @@ fn lsp_npm_workspace() {
   assert_eq!(
     res,
     json!([{
-      "targetUri": temp_dir.url().join("packages/add/index.ts").unwrap(),
+      "targetUri": url_to_uri(&temp_dir.url().join("packages/add/index.ts").unwrap()).unwrap(),
       "targetRange": {
         "start": {
           "line": 0,
@@ -16369,13 +16404,13 @@ fn lsp_import_unstable_bare_node_builtins_auto_discovered() {
   let contents = r#"import path from "path";"#;
   temp_dir.write("main.ts", contents);
   temp_dir.write("deno.json", r#"{ "unstable": ["bare-node-builtins"] }"#);
-  let main_script = temp_dir.url().join("main.ts").unwrap();
+  let main_uri = url_to_uri(&temp_dir.url().join("main.ts").unwrap()).unwrap();
 
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": main_script,
+      "uri": main_uri,
       "languageId": "typescript",
       "version": 1,
       "text": contents,
@@ -16383,7 +16418,7 @@ fn lsp_import_unstable_bare_node_builtins_auto_discovered() {
   }));
 
   let diagnostics = diagnostics
-    .messages_with_file_and_source(main_script.as_ref(), "deno")
+    .messages_with_file_and_source(main_uri.as_str(), "deno")
     .diagnostics
     .into_iter()
     .filter(|d| {
@@ -16399,7 +16434,7 @@ fn lsp_import_unstable_bare_node_builtins_auto_discovered() {
     "textDocument/codeAction",
     json!({
       "textDocument": {
-        "uri": main_script
+        "uri": main_uri
       },
       "range": {
         "start": { "line": 0, "character": 16 },
@@ -16433,7 +16468,7 @@ fn lsp_import_unstable_bare_node_builtins_auto_discovered() {
       ],
       "edit": {
         "changes": {
-          main_script: [
+          main_uri.as_str(): [
             {
               "range": {
                 "start": { "line": 0, "character": 17 },
@@ -16466,10 +16501,10 @@ fn lsp_jupyter_byonm_diagnostics() {
   context.run_npm("install");
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
-  let notebook_specifier = temp_dir.join("notebook.ipynb").url_file();
+  let notebook_uri = temp_dir.join("notebook.ipynb").uri_file();
   let notebook_specifier = format!(
     "{}#abc",
-    notebook_specifier
+    notebook_uri
       .to_string()
       .replace("file://", "deno-notebook-cell:")
   );
@@ -16525,7 +16560,7 @@ fn lsp_byonm() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("file.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("file.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": r#"
@@ -16574,7 +16609,7 @@ fn lsp_byonm() {
   context.run_npm("install");
   client.did_change_watched_files(json!({
     "changes": [{
-      "uri": temp_dir.url().join("node_modules/.package-lock.json").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("node_modules/.package-lock.json").unwrap()).unwrap(),
       "type": 1,
     }],
   }));
@@ -16620,11 +16655,11 @@ fn lsp_sloppy_imports() {
   temp_dir.join("c.d.ts").write("export class C {}");
   let mut client = context.new_lsp_command().build();
   client.initialize(|builder| {
-    builder.set_root_uri(temp_dir.url_dir());
+    builder.set_root_uri(temp_dir.uri_dir());
   });
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.join("b.ts").url_file(),
+      "uri": temp_dir.join("b.ts").uri_file(),
       "languageId": "typescript",
       "version": 1,
       "text": "export class B {}",
@@ -16632,7 +16667,7 @@ fn lsp_sloppy_imports() {
   }));
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.join("c.js").url_file(),
+      "uri": temp_dir.join("c.js").uri_file(),
       "languageId": "typescript",
       "version": 1,
       "text": "export class C {}",
@@ -16640,7 +16675,7 @@ fn lsp_sloppy_imports() {
   }));
   client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.join("c.d.ts").url_file(),
+      "uri": temp_dir.join("c.d.ts").uri_file(),
       "languageId": "typescript",
       "version": 1,
       "text": "export class C {}",
@@ -16648,7 +16683,7 @@ fn lsp_sloppy_imports() {
   }));
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.join("file.ts").url_file(),
+      "uri": temp_dir.join("file.ts").uri_file(),
       "languageId": "typescript",
       "version": 1,
       "text": concat!(
@@ -16779,7 +16814,7 @@ fn lsp_sloppy_imports_prefers_dts() {
   );
 
   let diagnostics = client.did_open_file(&a_dts);
-  assert_eq!(json!(diagnostics.for_file(&a_dts.url())), json!([]));
+  assert_eq!(json!(diagnostics.for_file(&a_dts.uri())), json!([]));
 
   let response = client.write_request(
     "textDocument/references",
@@ -16795,12 +16830,12 @@ fn lsp_sloppy_imports_prefers_dts() {
     response,
     json!([
       {
-        "uri": file.url(),
+        "uri": file.uri(),
         // the import
         "range": file.range_of("foo"),
       },
       {
-        "uri": file.url(),
+        "uri": file.uri(),
         // the usage
         "range": file.range_of_nth(1, "foo"),
       }
@@ -16821,11 +16856,11 @@ fn sloppy_imports_not_enabled() {
   temp_dir.join("a.ts").write("export class A {}");
   let mut client = context.new_lsp_command().build();
   client.initialize(|builder| {
-    builder.set_root_uri(temp_dir.url_dir());
+    builder.set_root_uri(temp_dir.uri_dir());
   });
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.join("file.ts").url_file(),
+      "uri": temp_dir.join("file.ts").uri_file(),
       "languageId": "typescript",
       "version": 1,
       "text": "import * as a from './a';\nconsole.log(a)\n",
@@ -16867,7 +16902,7 @@ fn sloppy_imports_not_enabled() {
     "textDocument/codeAction",
     json!({
       "textDocument": {
-        "uri": temp_dir.join("file.ts").url_file()
+        "uri": temp_dir.join("file.ts").uri_file()
       },
       "range": {
         "start": { "line": 0, "character": 19 },
@@ -16887,7 +16922,7 @@ fn sloppy_imports_not_enabled() {
             temp_dir.join("a").url_file(),
           ),
           "data": {
-            "uri": temp_dir.join("a").url_file(),
+            "uri": temp_dir.join("a").uri_file(),
             "to": temp_dir.join("a.ts").url_file(),
             "message": "Add a '.ts' extension.",
           },
@@ -16914,14 +16949,14 @@ fn sloppy_imports_not_enabled() {
           temp_dir.join("a").url_file(),
         ),
         "data": {
-          "uri": temp_dir.join("a").url_file(),
+          "uri": temp_dir.join("a").uri_file(),
           "to": temp_dir.join("a.ts").url_file(),
           "message": "Add a '.ts' extension.",
         },
       }],
       "edit": {
         "changes": {
-          temp_dir.join("file.ts").url_file(): [{
+          temp_dir.join("file.ts").uri_file().as_str(): [{
             "range": {
               "start": { "line": 0, "character": 19 },
               "end": { "line": 0, "character": 24 }
@@ -16966,7 +17001,7 @@ fn lsp_byonm_js_import_resolves_to_dts() {
   client.initialize_default();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": temp_dir.url().join("node_modules/postcss/lib/comment.d.ts").unwrap(),
+      "uri": url_to_uri(&temp_dir.url().join("node_modules/postcss/lib/comment.d.ts").unwrap()).unwrap(),
       "languageId": "typescript",
       "version": 1,
       "text": temp_dir.path().join("node_modules/postcss/lib/comment.d.ts").read_to_string(),
@@ -16986,7 +17021,7 @@ fn decorators_tc39() {
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
 
-  let uri = temp_dir.url().join("main.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("main.ts").unwrap()).unwrap();
 
   let diagnostics = client
     .did_open(json!({
@@ -17038,7 +17073,7 @@ fn decorators_ts() {
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
 
-  let uri = temp_dir.url().join("main.ts").unwrap();
+  let uri = url_to_uri(&temp_dir.url().join("main.ts").unwrap()).unwrap();
 
   let diagnostics = client
     .did_open(json!({
@@ -17139,17 +17174,17 @@ fn lsp_cjs_internal_types_default_export() {
   );
   client.did_open(json!({
     "textDocument": {
-      "uri": node_modules_index_d_ts.url_file(),
+      "uri": node_modules_index_d_ts.uri_file(),
       "languageId": "typescript",
       "version": 1,
       "text": node_modules_index_d_ts.read_to_string(),
     }
   }));
-  let main_url = temp_dir.path().join("main.ts").url_file();
+  let main_uri = temp_dir.path().join("main.ts").uri_file();
   let diagnostics = client.did_open(
     json!({
       "textDocument": {
-        "uri": main_url,
+        "uri": main_uri,
         "languageId": "typescript",
         "version": 1,
         "text": "import * as mod from '@denotest/cjs-internal-types-default-export';\nmod.add(1, 2);",
@@ -17182,11 +17217,11 @@ fn lsp_cjs_import_dual() {
 
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
-  let main_url = temp_dir.path().join("main.ts").url_file();
+  let main_uri = temp_dir.path().join("main.ts").uri_file();
   let diagnostics = client.did_open(
     json!({
       "textDocument": {
-        "uri": main_url,
+        "uri": main_uri,
         "languageId": "typescript",
         "version": 1,
         // getKind() should resolve as "cjs" and cause a type checker error
@@ -17232,11 +17267,11 @@ fn lsp_type_commonjs() {
 
   let mut client = context.new_lsp_command().build();
   client.initialize_default();
-  let main_url = temp_dir.path().join("main.ts").url_file();
+  let main_uri = temp_dir.path().join("main.ts").uri_file();
   let diagnostics = client.did_open(
     json!({
       "textDocument": {
-        "uri": main_url,
+        "uri": main_uri,
         "languageId": "typescript",
         "version": 1,
         // getKind() should resolve as "cjs" and cause a type checker error
@@ -17272,10 +17307,10 @@ fn lsp_ts_code_fix_any_param() {
 
   let param_def = range_of("param", src);
 
-  let main_url = temp_dir.path().join("main.ts").url_file();
+  let main_uri = temp_dir.path().join("main.ts").uri_file();
   let diagnostics = client.did_open(json!({
     "textDocument": {
-      "uri": main_url,
+      "uri": main_uri,
       "languageId": "typescript",
       "version": 1,
       "text": src,
@@ -17296,7 +17331,7 @@ fn lsp_ts_code_fix_any_param() {
     "textDocument/codeAction",
     json!({
       "textDocument": {
-        "uri": main_url,
+        "uri": main_uri,
       },
       "range": lsp::Range {
         start: param_def.end,
@@ -17581,7 +17616,7 @@ fn compiler_options_types() {
     context.run_deno("install");
     client.did_change_watched_files(json!({
       "changes": [{
-        "uri": temp.url().join("deno.json").unwrap(),
+        "uri": url_to_uri(&temp.url().join("deno.json").unwrap()).unwrap(),
         "type": 2,
       }],
     }));
@@ -17656,7 +17691,7 @@ fn type_reference_import_meta() {
     context.run_deno("install");
     client.did_change_watched_files(json!({
       "changes": [{
-        "uri": temp.url().join("deno.json").unwrap(),
+        "uri": url_to_uri(&temp.url().join("deno.json").unwrap()).unwrap(),
         "type": 2,
       }],
     }));
@@ -17752,7 +17787,7 @@ fn definitely_typed_fallback() {
     context.run_deno("install");
     client.did_change_watched_files(json!({
       "changes": [{
-        "uri": temp.url().join("deno.json").unwrap(),
+        "uri": url_to_uri(&temp.url().join("deno.json").unwrap()).unwrap(),
         "type": 2,
       }],
     }));
@@ -17827,7 +17862,7 @@ fn do_not_auto_import_from_definitely_typed() {
     temp.write("deno.json", deno_json.to_string());
     client.did_change_watched_files(json!({
       "changes": [{
-        "uri": temp.url().join("deno.json").unwrap(),
+        "uri": url_to_uri(&temp.url().join("deno.json").unwrap()).unwrap(),
         "type": 2,
       }],
     }));
diff --git a/tests/util/server/src/fs.rs b/tests/util/server/src/fs.rs
index 062ca59ef3a202..01ea502df61d2d 100644
--- a/tests/util/server/src/fs.rs
+++ b/tests/util/server/src/fs.rs
@@ -22,6 +22,79 @@ use url::Url;
 use crate::assertions::assert_wildcard_match;
 use crate::testdata_path;
 
+/// Characters that are left unencoded in a `Url` path but will be encoded in a
+/// VSCode URI.
+const URL_TO_URI_PATH: &percent_encoding::AsciiSet =
+  &percent_encoding::CONTROLS
+    .add(b' ')
+    .add(b'!')
+    .add(b'$')
+    .add(b'&')
+    .add(b'\'')
+    .add(b'(')
+    .add(b')')
+    .add(b'*')
+    .add(b'+')
+    .add(b',')
+    .add(b':')
+    .add(b';')
+    .add(b'=')
+    .add(b'@')
+    .add(b'[')
+    .add(b']')
+    .add(b'^')
+    .add(b'|');
+
+/// Characters that may be left unencoded in a `Url` query but not valid in a
+/// `Uri` query.
+const URL_TO_URI_QUERY: &percent_encoding::AsciiSet =
+  &URL_TO_URI_PATH.add(b'\\').add(b'`').add(b'{').add(b'}');
+
+/// Characters that may be left unencoded in a `Url` fragment but not valid in
+/// a `Uri` fragment.
+const URL_TO_URI_FRAGMENT: &percent_encoding::AsciiSet =
+  &URL_TO_URI_PATH.add(b'#').add(b'\\').add(b'{').add(b'}');
+
+pub fn url_to_uri(url: &Url) -> Result<Uri, anyhow::Error> {
+  let components = url::quirks::internal_components(url);
+  let mut input = String::with_capacity(url.as_str().len());
+  input.push_str(&url.as_str()[..components.path_start as usize]);
+  let path = url.path();
+  let mut chars = path.chars();
+  let has_drive_letter = chars.next().is_some_and(|c| c == '/')
+    && chars.next().is_some_and(|c| c.is_ascii_alphabetic())
+    && chars.next().is_some_and(|c| c == ':')
+    && chars.next().is_none_or(|c| c == '/');
+  if has_drive_letter {
+    let (dl_part, rest) = path.split_at(2);
+    input.push_str(&dl_part.to_ascii_lowercase());
+    input.push_str(
+      &percent_encoding::utf8_percent_encode(rest, URL_TO_URI_PATH).to_string(),
+    );
+  } else {
+    input.push_str(
+      &percent_encoding::utf8_percent_encode(path, URL_TO_URI_PATH).to_string(),
+    );
+  }
+  if let Some(query) = url.query() {
+    input.push('?');
+    input.push_str(
+      &percent_encoding::utf8_percent_encode(query, URL_TO_URI_QUERY)
+        .to_string(),
+    );
+  }
+  if let Some(fragment) = url.fragment() {
+    input.push('#');
+    input.push_str(
+      &percent_encoding::utf8_percent_encode(fragment, URL_TO_URI_FRAGMENT)
+        .to_string(),
+    );
+  }
+  Uri::from_str(&input).map_err(|err| {
+    anyhow::anyhow!("Could not convert URL \"{url}\" to URI: {err}")
+  })
+}
+
 /// Represents a path on the file system, which can be used
 /// to perform specific actions.
 #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
@@ -63,11 +136,11 @@ impl PathRef {
   }
 
   pub fn uri_dir(&self) -> Uri {
-    Uri::from_str(self.url_dir().as_str()).unwrap()
+    url_to_uri(&self.url_dir()).unwrap()
   }
 
   pub fn uri_file(&self) -> Uri {
-    Uri::from_str(self.url_file().as_str()).unwrap()
+    url_to_uri(&self.url_file()).unwrap()
   }
 
   pub fn as_path(&self) -> &Path {
@@ -475,7 +548,7 @@ impl TempDir {
   }
 
   pub fn uri(&self) -> Uri {
-    Uri::from_str(self.url().as_str()).unwrap()
+    url_to_uri(&self.url()).unwrap()
   }
 
   pub fn path(&self) -> &PathRef {
diff --git a/tests/util/server/src/lib.rs b/tests/util/server/src/lib.rs
index c3d5909ff9d6d2..6465e4cdd3e0f2 100644
--- a/tests/util/server/src/lib.rs
+++ b/tests/util/server/src/lib.rs
@@ -40,6 +40,7 @@ pub use builders::TestCommandBuilder;
 pub use builders::TestCommandOutput;
 pub use builders::TestContext;
 pub use builders::TestContextBuilder;
+pub use fs::url_to_uri;
 pub use fs::PathRef;
 pub use fs::TempDir;
 
diff --git a/tests/util/server/src/lsp.rs b/tests/util/server/src/lsp.rs
index 917074cfc79978..b788960dd7950d 100644
--- a/tests/util/server/src/lsp.rs
+++ b/tests/util/server/src/lsp.rs
@@ -14,7 +14,6 @@ use std::process::ChildStdin;
 use std::process::ChildStdout;
 use std::process::Command;
 use std::process::Stdio;
-use std::str::FromStr;
 use std::sync::mpsc;
 use std::sync::Arc;
 use std::time::Duration;
@@ -34,6 +33,7 @@ use lsp_types::FoldingRangeClientCapabilities;
 use lsp_types::InitializeParams;
 use lsp_types::TextDocumentClientCapabilities;
 use lsp_types::TextDocumentSyncClientCapabilities;
+use lsp_types::Uri;
 use lsp_types::WorkspaceClientCapabilities;
 use once_cell::sync::Lazy;
 use parking_lot::Condvar;
@@ -291,13 +291,12 @@ impl InitializeParamsBuilder {
   }
 
   #[allow(deprecated)]
-  pub fn set_maybe_root_uri(&mut self, value: Option<Url>) -> &mut Self {
-    self.params.root_uri =
-      value.map(|v| lsp::Uri::from_str(v.as_str()).unwrap());
+  pub fn set_maybe_root_uri(&mut self, value: Option<Uri>) -> &mut Self {
+    self.params.root_uri = value;
     self
   }
 
-  pub fn set_root_uri(&mut self, value: Url) -> &mut Self {
+  pub fn set_root_uri(&mut self, value: Uri) -> &mut Self {
     self.set_maybe_root_uri(Some(value))
   }
 
@@ -854,7 +853,7 @@ impl LspClient {
     mut config: Value,
   ) {
     let mut builder = InitializeParamsBuilder::new(config.clone());
-    builder.set_root_uri(self.root_dir.url_dir());
+    builder.set_root_uri(self.root_dir.uri_dir());
     do_build(&mut builder);
     let params: InitializeParams = builder.build();
     // `config` must be updated to account for the builder changes.
@@ -1228,11 +1227,11 @@ impl CollectedDiagnostics {
       .collect()
   }
 
-  pub fn for_file(&self, specifier: &Url) -> Vec<lsp::Diagnostic> {
+  pub fn for_file(&self, uri: &Uri) -> Vec<lsp::Diagnostic> {
     self
       .all_messages()
       .iter()
-      .filter(|p| p.uri.as_str() == specifier.as_str())
+      .filter(|p| p.uri.as_str() == uri.as_str())
       .flat_map(|p| p.diagnostics.iter())
       .cloned()
       .collect()


Reviews:
user: login: nayeemrmn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-04T00:00:37Z
user: login: nathanwhit
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-04T00:17:12Z
user: login: littledivy
body: RSLGTM
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-04T04:20:15Z

Review comments:
path: .github/workflows/ci.yml
user: login: nayeemrmn
body: Revert before landing
created_at: 2025-04-04T00:00:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -82,31 +82,10 @@ pub fn url_to_uri(url: &Url) -> Result<Uri, AnyError> {
   let components = deno_core::url::quirks::internal_components(url);
   let mut input = String::with_capacity(url.as_str().len());
   input.push_str(&url.as_str()[..components.path_start as usize]);
-  if cfg!(windows) && url.scheme() == "file" {
-    let path = url.path();
-    let mut chars = path.chars();
-    let has_drive_letter = chars.next().is_some_and(|c| c == '/')
-      && chars.next().is_some_and(|c| c.is_ascii_alphabetic())
-      && chars.next().is_some_and(|c| c == ':')
-      && chars.next().is_none_or(|c| c == '/');
-    if has_drive_letter {
-      input.push_str(&path[..3]);
-      input.push_str(
-        &percent_encoding::utf8_percent_encode(&path[3..], URL_TO_URI_PATH)
-          .to_string(),
-      );
-    } else {
-      input.push_str(
-        &percent_encoding::utf8_percent_encode(path, URL_TO_URI_PATH)
-          .to_string(),
-      );
-    }
-  } else {
-    input.push_str(
-      &percent_encoding::utf8_percent_encode(url.path(), URL_TO_URI_PATH)
-        .to_string(),
-    );
-  }
+  input.push_str(
path: cli/lsp/urls.rs
user: login: nathanwhit
body: these functions (`url_to_uri`, `uri_to_url`) could use some unit tests
created_at: 2025-04-04T00:17:12Z
author_association: MEMBER

PR comments:
user: login: dsherret
created_at: 2025-04-04T01:10:06Z
body: Tried it out and it unfortunately it doesn't fix it for me. I can look into this more tomorrow if needed.
author_association: CONTRIBUTOR
user: login: dsherret
created_at: 2025-04-04T03:00:55Z
body: This seems to be working now for me. It would be good to retest on a windows machine once all the tests are passing though.
author_association: CONTRIBUTOR