diff options
author | Kitson Kelly <me@kitsonkelly.com> | 2021-04-06 21:45:53 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-06 21:45:53 +1000 |
commit | 2c86ca1d643add802f0140aa5598d1bc8b05082e (patch) | |
tree | 22af3c4d274ff8a2c5ce4f12a1ef841c80da6bdd /cli/lsp/urls.rs | |
parent | 00e63306cbcc295a87ba662f9f63311a3c6c49ce (diff) |
fix(lsp): properly handle encoding URLs from lsp client (#10033)
Fixes #9741
Diffstat (limited to 'cli/lsp/urls.rs')
-rw-r--r-- | cli/lsp/urls.rs | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/cli/lsp/urls.rs b/cli/lsp/urls.rs index a4af7d7b9..62b7dd277 100644 --- a/cli/lsp/urls.rs +++ b/cli/lsp/urls.rs @@ -4,14 +4,28 @@ use crate::file_fetcher::map_content_type; use crate::media_type::MediaType; use deno_core::error::AnyError; +use deno_core::url::Position; use deno_core::url::Url; use deno_core::ModuleSpecifier; use std::collections::HashMap; -/// This is a partial guess as how URLs get encoded from the LSP. We want to -/// encode URLs sent to the LSP in the same way that they would be encoded back -/// so that we have the same return encoding. -const LSP_ENCODING: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS +/// Matches the `encodeURIComponent()` encoding from JavaScript, which matches +/// the component percent encoding set. +/// +/// See: https://url.spec.whatwg.org/#component-percent-encode-set +/// +// TODO(@kitsonk) - refactor when #9934 is landed. +const COMPONENT: &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'=') @@ -20,7 +34,11 @@ const LSP_ENCODING: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS .add(b'\\') .add(b']') .add(b'^') - .add(b'|'); + .add(b'|') + .add(b'$') + .add(b'&') + .add(b'+') + .add(b','); fn hash_data_specifier(specifier: &ModuleSpecifier) -> String { let mut file_name_str = specifier.path().to_string(); @@ -90,8 +108,15 @@ impl LspUrlMap { extension ) } else { - let path = specifier.as_str().replacen("://", "/", 1); - let path = percent_encoding::utf8_percent_encode(&path, LSP_ENCODING); + let mut path = + specifier[..Position::BeforePath].replacen("://", "/", 1); + let parts: Vec<String> = specifier[Position::BeforePath..] + .split('/') + .map(|p| { + percent_encoding::utf8_percent_encode(p, COMPONENT).to_string() + }) + .collect(); + path.push_str(&parts.join("/")); format!("deno:/{}", path) }; let url = Url::parse(&specifier_str)?; @@ -159,6 +184,21 @@ mod tests { } #[test] + fn test_lsp_url_map_complex_encoding() { + // Test fix for #9741 - not properly encoding certain URLs + let mut map = LspUrlMap::default(); + let fixture = resolve_url("https://cdn.skypack.dev/-/postcss@v8.2.9-E4SktPp9c0AtxrJHp8iV/dist=es2020,mode=types/lib/postcss.d.ts").unwrap(); + let actual_url = map + .normalize_specifier(&fixture) + .expect("could not handle specifier"); + let expected_url = Url::parse("deno:/https/cdn.skypack.dev/-/postcss%40v8.2.9-E4SktPp9c0AtxrJHp8iV/dist%3Des2020%2Cmode%3Dtypes/lib/postcss.d.ts").unwrap(); + assert_eq!(actual_url, expected_url); + + let actual_specifier = map.normalize_url(&actual_url); + assert_eq!(actual_specifier, fixture); + } + + #[test] fn test_lsp_url_map_data() { let mut map = LspUrlMap::default(); let fixture = resolve_url("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap(); |