1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-25 16:49:18 -05:00

refactor: use 'data-url' crate to process data URLs in lsp & file_fetcher (#10196)

Closes: #10118
This commit is contained in:
Satya Rohith 2021-04-24 00:13:13 +05:30 committed by GitHub
parent feb6af7732
commit 13f7592b8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 22 additions and 96 deletions

1
Cargo.lock generated
View file

@ -516,6 +516,7 @@ dependencies = [
"byteorder", "byteorder",
"chrono", "chrono",
"clap", "clap",
"data-url",
"deno_core", "deno_core",
"deno_doc", "deno_doc",
"deno_lint", "deno_lint",

View file

@ -43,6 +43,7 @@ atty = "0.2.14"
base64 = "0.13.0" base64 = "0.13.0"
byteorder = "1.4.3" byteorder = "1.4.3"
clap = "2.33.3" clap = "2.33.3"
data-url = "0.1.0"
dissimilar = "1.0.2" dissimilar = "1.0.2"
dprint-plugin-json = "0.10.1" dprint-plugin-json = "0.10.1"
dprint-plugin-markdown = "0.6.2" dprint-plugin-markdown = "0.6.2"

View file

@ -10,6 +10,7 @@ use crate::http_util::FetchOnceResult;
use crate::media_type::MediaType; use crate::media_type::MediaType;
use crate::text_encoding; use crate::text_encoding;
use crate::version::get_user_agent; use crate::version::get_user_agent;
use data_url::DataUrl;
use deno_core::error::custom_error; use deno_core::error::custom_error;
use deno_core::error::generic_error; use deno_core::error::generic_error;
use deno_core::error::uri_error; use deno_core::error::uri_error;
@ -153,40 +154,6 @@ pub fn get_source_from_bytes(
Ok(source) Ok(source)
} }
fn get_source_from_data_url(
specifier: &ModuleSpecifier,
) -> Result<(String, MediaType, String), AnyError> {
if specifier.scheme() != "data" {
return Err(custom_error(
"BadScheme",
format!("Unexpected scheme of \"{}\"", specifier.scheme()),
));
}
let path = specifier.path();
let mut parts = path.splitn(2, ',');
let media_type_part =
percent_encoding::percent_decode_str(parts.next().unwrap())
.decode_utf8()?;
let data_part = if let Some(data) = parts.next() {
data
} else {
return Err(custom_error(
"BadUrl",
"The data URL is badly formed, missing a comma.",
));
};
let (media_type, maybe_charset) =
map_content_type(specifier, Some(media_type_part.to_string()));
let is_base64 = media_type_part.rsplit(';').any(|p| p == "base64");
let bytes = if is_base64 {
base64::decode(data_part)?
} else {
percent_encoding::percent_decode_str(data_part).collect()
};
let source = strip_shebang(get_source_from_bytes(bytes, maybe_charset)?);
Ok((source, media_type, media_type_part.to_string()))
}
/// Return a validated scheme for a given module specifier. /// Return a validated scheme for a given module specifier.
fn get_validated_scheme( fn get_validated_scheme(
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
@ -430,8 +397,18 @@ impl FileFetcher {
)); ));
} }
let (source, media_type, content_type) = let data_url = DataUrl::process(specifier.as_str())
get_source_from_data_url(specifier)?; .map_err(|e| uri_error(format!("{:?}", e)))?;
let mime = data_url.mime_type();
let charset = mime.get_parameter("charset").map(|v| v.to_string());
let (bytes, _) = data_url
.decode_to_vec()
.map_err(|e| uri_error(format!("{:?}", e)))?;
let source = strip_shebang(get_source_from_bytes(bytes, charset)?);
let content_type = format!("{}", mime);
let (media_type, _) =
map_content_type(specifier, Some(content_type.clone()));
let local = let local =
self self
.http_cache .http_cache
@ -762,39 +739,6 @@ mod tests {
assert_eq!(file.source, expected); assert_eq!(file.source, expected);
} }
#[test]
fn test_get_source_from_data_url() {
let fixtures = vec![
("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=", true, MediaType::TypeScript, "application/typescript;base64", "export const a = \"a\";\n\nexport enum A {\n A,\n B,\n C,\n}\n"),
("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=?a=b&b=c", true, MediaType::TypeScript, "application/typescript;base64", "export const a = \"a\";\n\nexport enum A {\n A,\n B,\n C,\n}\n"),
("data:text/plain,Hello%2C%20Deno!", true, MediaType::Unknown, "text/plain", "Hello, Deno!"),
("data:,Hello%2C%20Deno!", true, MediaType::Unknown, "", "Hello, Deno!"),
("data:application/javascript,console.log(\"Hello, Deno!\");%0A", true, MediaType::JavaScript, "application/javascript", "console.log(\"Hello, Deno!\");\n"),
("data:text/jsx;base64,ZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oKSB7CiAgcmV0dXJuIDxkaXY+SGVsbG8gRGVubyE8L2Rpdj4KfQo=", true, MediaType::Jsx, "text/jsx;base64", "export default function() {\n return <div>Hello Deno!</div>\n}\n"),
("data:text/tsx;base64,ZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oKSB7CiAgcmV0dXJuIDxkaXY+SGVsbG8gRGVubyE8L2Rpdj4KfQo=", true, MediaType::Tsx, "text/tsx;base64", "export default function() {\n return <div>Hello Deno!</div>\n}\n"),
];
for (
url_str,
expected_ok,
expected_media_type,
expected_media_type_str,
expected,
) in fixtures
{
let specifier = resolve_url(url_str).unwrap();
let actual = get_source_from_data_url(&specifier);
assert_eq!(actual.is_ok(), expected_ok);
if expected_ok {
let (actual, actual_media_type, actual_media_type_str) =
actual.unwrap();
assert_eq!(actual, expected);
assert_eq!(actual_media_type, expected_media_type);
assert_eq!(actual_media_type_str, expected_media_type_str);
}
}
}
#[test] #[test]
fn test_get_validated_scheme() { fn test_get_validated_scheme() {
let fixtures = vec![ let fixtures = vec![

View file

@ -3,6 +3,8 @@
use crate::file_fetcher::map_content_type; use crate::file_fetcher::map_content_type;
use crate::media_type::MediaType; use crate::media_type::MediaType;
use data_url::DataUrl;
use deno_core::error::uri_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::url::Position; use deno_core::url::Position;
use deno_core::url::Url; use deno_core::url::Url;
@ -49,17 +51,6 @@ fn hash_data_specifier(specifier: &ModuleSpecifier) -> String {
crate::checksum::gen(&[file_name_str.as_bytes()]) crate::checksum::gen(&[file_name_str.as_bytes()])
} }
fn data_url_media_type(specifier: &ModuleSpecifier) -> MediaType {
let path = specifier.path();
let mut parts = path.splitn(2, ',');
let media_type_part =
percent_encoding::percent_decode_str(parts.next().unwrap())
.decode_utf8_lossy();
let (media_type, _) =
map_content_type(specifier, Some(media_type_part.into()));
media_type
}
/// A bi-directional map of URLs sent to the LSP client and internal module /// A bi-directional map of URLs sent to the LSP client and internal module
/// specifiers. We need to map internal specifiers into `deno:` schema URLs /// specifiers. We need to map internal specifiers into `deno:` schema URLs
/// to allow the Deno language server to manage these as virtual documents. /// to allow the Deno language server to manage these as virtual documents.
@ -96,7 +87,11 @@ impl LspUrlMap {
specifier.clone() specifier.clone()
} else { } else {
let specifier_str = if specifier.scheme() == "data" { let specifier_str = if specifier.scheme() == "data" {
let media_type = data_url_media_type(specifier); let data_url = DataUrl::process(specifier.as_str())
.map_err(|e| uri_error(format!("{:?}", e)))?;
let mime = data_url.mime_type();
let (media_type, _) =
map_content_type(specifier, Some(format!("{}", mime)));
let extension = if media_type == MediaType::Unknown { let extension = if media_type == MediaType::Unknown {
"" ""
} else { } else {
@ -159,21 +154,6 @@ mod tests {
); );
} }
#[test]
fn test_data_url_media_type() {
let fixture = resolve_url("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap();
let actual = data_url_media_type(&fixture);
assert_eq!(actual, MediaType::TypeScript);
let fixture = resolve_url("data:application/javascript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap();
let actual = data_url_media_type(&fixture);
assert_eq!(actual, MediaType::JavaScript);
let fixture = resolve_url("data:text/plain;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap();
let actual = data_url_media_type(&fixture);
assert_eq!(actual, MediaType::Unknown);
}
#[test] #[test]
fn test_lsp_url_map() { fn test_lsp_url_map() {
let mut map = LspUrlMap::default(); let mut map = LspUrlMap::default();