2021-01-11 12:13:41 -05:00
|
|
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
2018-11-29 22:03:00 -05:00
|
|
|
|
2020-11-01 21:51:56 -05:00
|
|
|
use deno_core::ModuleSpecifier;
|
2020-05-18 06:59:29 -04:00
|
|
|
use serde::Serialize;
|
2020-06-19 06:27:15 -04:00
|
|
|
use serde::Serializer;
|
2020-10-11 22:25:27 -04:00
|
|
|
use std::fmt;
|
2020-09-14 08:27:44 -04:00
|
|
|
use std::path::Path;
|
|
|
|
use std::path::PathBuf;
|
2020-05-18 06:59:29 -04:00
|
|
|
|
2020-09-14 08:27:44 -04:00
|
|
|
// Warning! The values in this enum are duplicated in tsc/99_main_compiler.js
|
|
|
|
// Update carefully!
|
2019-08-26 17:02:34 -04:00
|
|
|
#[allow(non_camel_case_types)]
|
2020-06-19 06:27:15 -04:00
|
|
|
#[repr(i32)]
|
2020-10-13 19:52:49 -04:00
|
|
|
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
2019-08-26 17:02:34 -04:00
|
|
|
pub enum MediaType {
|
|
|
|
JavaScript = 0,
|
2019-10-02 10:46:36 -04:00
|
|
|
JSX = 1,
|
|
|
|
TypeScript = 2,
|
2020-09-14 08:27:44 -04:00
|
|
|
Dts = 3,
|
|
|
|
TSX = 4,
|
|
|
|
Json = 5,
|
|
|
|
Wasm = 6,
|
2020-10-13 19:52:49 -04:00
|
|
|
TsBuildInfo = 7,
|
|
|
|
SourceMap = 8,
|
|
|
|
Unknown = 9,
|
2020-09-14 08:27:44 -04:00
|
|
|
}
|
|
|
|
|
2020-10-11 22:25:27 -04:00
|
|
|
impl fmt::Display for MediaType {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
let value = match self {
|
|
|
|
MediaType::JavaScript => "JavaScript",
|
|
|
|
MediaType::JSX => "JSX",
|
|
|
|
MediaType::TypeScript => "TypeScript",
|
|
|
|
MediaType::Dts => "Dts",
|
|
|
|
MediaType::TSX => "TSX",
|
|
|
|
MediaType::Json => "Json",
|
|
|
|
MediaType::Wasm => "Wasm",
|
2020-10-13 19:52:49 -04:00
|
|
|
MediaType::TsBuildInfo => "TsBuildInfo",
|
|
|
|
MediaType::SourceMap => "SourceMap",
|
2020-10-11 22:25:27 -04:00
|
|
|
MediaType::Unknown => "Unknown",
|
|
|
|
};
|
|
|
|
write!(f, "{}", value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-14 08:27:44 -04:00
|
|
|
impl<'a> From<&'a Path> for MediaType {
|
|
|
|
fn from(path: &'a Path) -> Self {
|
|
|
|
MediaType::from_path(path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> From<&'a PathBuf> for MediaType {
|
|
|
|
fn from(path: &'a PathBuf) -> Self {
|
|
|
|
MediaType::from_path(path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> From<&'a String> for MediaType {
|
|
|
|
fn from(specifier: &'a String) -> Self {
|
|
|
|
MediaType::from_path(&PathBuf::from(specifier))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-01 21:51:56 -05:00
|
|
|
impl<'a> From<&'a ModuleSpecifier> for MediaType {
|
|
|
|
fn from(specifier: &'a ModuleSpecifier) -> Self {
|
|
|
|
let url = specifier.as_url();
|
|
|
|
let path = if url.scheme() == "file" {
|
|
|
|
if let Ok(path) = url.to_file_path() {
|
|
|
|
path
|
|
|
|
} else {
|
|
|
|
PathBuf::from(url.path())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PathBuf::from(url.path())
|
|
|
|
};
|
|
|
|
MediaType::from_path(&path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-13 19:52:49 -04:00
|
|
|
impl Default for MediaType {
|
|
|
|
fn default() -> Self {
|
|
|
|
MediaType::Unknown
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-14 08:27:44 -04:00
|
|
|
impl MediaType {
|
|
|
|
fn from_path(path: &Path) -> Self {
|
|
|
|
match path.extension() {
|
2020-10-13 19:52:49 -04:00
|
|
|
None => match path.file_name() {
|
|
|
|
None => MediaType::Unknown,
|
|
|
|
Some(os_str) => match os_str.to_str() {
|
|
|
|
Some(".tsbuildinfo") => MediaType::TsBuildInfo,
|
|
|
|
_ => MediaType::Unknown,
|
|
|
|
},
|
|
|
|
},
|
2020-09-14 08:27:44 -04:00
|
|
|
Some(os_str) => match os_str.to_str() {
|
2020-11-09 18:10:41 -05:00
|
|
|
Some("ts") => {
|
|
|
|
if let Some(os_str) = path.file_stem() {
|
|
|
|
if let Some(file_name) = os_str.to_str() {
|
2020-10-22 20:50:15 -04:00
|
|
|
if file_name.ends_with(".d") {
|
2020-11-09 18:10:41 -05:00
|
|
|
return MediaType::Dts;
|
2020-10-22 20:50:15 -04:00
|
|
|
}
|
|
|
|
}
|
2020-11-09 18:10:41 -05:00
|
|
|
}
|
|
|
|
MediaType::TypeScript
|
|
|
|
}
|
2020-09-14 08:27:44 -04:00
|
|
|
Some("tsx") => MediaType::TSX,
|
|
|
|
Some("js") => MediaType::JavaScript,
|
|
|
|
Some("jsx") => MediaType::JSX,
|
|
|
|
Some("mjs") => MediaType::JavaScript,
|
|
|
|
Some("cjs") => MediaType::JavaScript,
|
|
|
|
Some("json") => MediaType::Json,
|
|
|
|
Some("wasm") => MediaType::Wasm,
|
2020-10-13 19:52:49 -04:00
|
|
|
Some("tsbuildinfo") => MediaType::TsBuildInfo,
|
|
|
|
Some("map") => MediaType::SourceMap,
|
2020-09-14 08:27:44 -04:00
|
|
|
_ => MediaType::Unknown,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2020-10-13 19:52:49 -04:00
|
|
|
|
|
|
|
/// Convert a MediaType to a `ts.Extension`.
|
|
|
|
///
|
|
|
|
/// *NOTE* This is defined in TypeScript as a string based enum. Changes to
|
|
|
|
/// that enum in TypeScript should be reflected here.
|
|
|
|
pub fn as_ts_extension(&self) -> String {
|
|
|
|
let ext = match self {
|
|
|
|
MediaType::JavaScript => ".js",
|
|
|
|
MediaType::JSX => ".jsx",
|
|
|
|
MediaType::TypeScript => ".ts",
|
|
|
|
MediaType::Dts => ".d.ts",
|
|
|
|
MediaType::TSX => ".tsx",
|
|
|
|
MediaType::Json => ".json",
|
|
|
|
// TypeScript doesn't have an "unknown", so we will treat WASM as JS for
|
|
|
|
// mapping purposes, though in reality, it is unlikely to ever be passed
|
|
|
|
// to the compiler.
|
|
|
|
MediaType::Wasm => ".js",
|
|
|
|
MediaType::TsBuildInfo => ".tsbuildinfo",
|
|
|
|
// TypeScript doesn't have an "source map", so we will treat SourceMap as
|
|
|
|
// JS for mapping purposes, though in reality, it is unlikely to ever be
|
|
|
|
// passed to the compiler.
|
|
|
|
MediaType::SourceMap => ".js",
|
|
|
|
// TypeScript doesn't have an "unknown", so we will treat WASM as JS for
|
|
|
|
// mapping purposes, though in reality, it is unlikely to ever be passed
|
|
|
|
// to the compiler.
|
|
|
|
MediaType::Unknown => ".js",
|
|
|
|
};
|
|
|
|
|
|
|
|
ext.into()
|
|
|
|
}
|
2020-10-22 20:50:15 -04:00
|
|
|
|
|
|
|
/// Map the media type to a `ts.ScriptKind`
|
|
|
|
pub fn as_ts_script_kind(&self) -> i32 {
|
|
|
|
match self {
|
|
|
|
MediaType::JavaScript => 1,
|
|
|
|
MediaType::JSX => 2,
|
|
|
|
MediaType::TypeScript => 3,
|
|
|
|
MediaType::Dts => 3,
|
|
|
|
MediaType::TSX => 4,
|
|
|
|
MediaType::Json => 5,
|
|
|
|
_ => 0,
|
|
|
|
}
|
|
|
|
}
|
2019-08-26 17:02:34 -04:00
|
|
|
}
|
|
|
|
|
2020-06-19 06:27:15 -04:00
|
|
|
impl Serialize for MediaType {
|
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
where
|
|
|
|
S: Serializer,
|
|
|
|
{
|
2020-09-14 08:27:44 -04:00
|
|
|
let value = match self {
|
2020-11-27 14:47:35 -05:00
|
|
|
MediaType::JavaScript => 0_i32,
|
|
|
|
MediaType::JSX => 1_i32,
|
|
|
|
MediaType::TypeScript => 2_i32,
|
|
|
|
MediaType::Dts => 3_i32,
|
|
|
|
MediaType::TSX => 4_i32,
|
|
|
|
MediaType::Json => 5_i32,
|
|
|
|
MediaType::Wasm => 6_i32,
|
|
|
|
MediaType::TsBuildInfo => 7_i32,
|
|
|
|
MediaType::SourceMap => 8_i32,
|
|
|
|
MediaType::Unknown => 9_i32,
|
2020-06-19 06:27:15 -04:00
|
|
|
};
|
|
|
|
Serialize::serialize(&value, serializer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-11 22:25:27 -04:00
|
|
|
/// Serialize a `MediaType` enum into a human readable string. The default
|
|
|
|
/// serialization for media types is and integer.
|
|
|
|
///
|
|
|
|
/// TODO(@kitsonk) remove this once we stop sending MediaType into tsc.
|
|
|
|
pub fn serialize_media_type<S>(mt: &MediaType, s: S) -> Result<S::Ok, S::Error>
|
|
|
|
where
|
|
|
|
S: Serializer,
|
|
|
|
{
|
2020-11-09 09:38:29 -05:00
|
|
|
s.serialize_str(&mt.to_string())
|
2019-08-26 17:02:34 -04:00
|
|
|
}
|
2019-11-13 10:35:56 -05:00
|
|
|
|
2020-10-11 22:25:27 -04:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use deno_core::serde_json::json;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_map_file_extension() {
|
|
|
|
assert_eq!(
|
|
|
|
MediaType::from(Path::new("foo/bar.ts")),
|
|
|
|
MediaType::TypeScript
|
|
|
|
);
|
|
|
|
assert_eq!(MediaType::from(Path::new("foo/bar.tsx")), MediaType::TSX);
|
2020-10-22 20:50:15 -04:00
|
|
|
assert_eq!(MediaType::from(Path::new("foo/bar.d.ts")), MediaType::Dts);
|
2020-10-11 22:25:27 -04:00
|
|
|
assert_eq!(
|
|
|
|
MediaType::from(Path::new("foo/bar.js")),
|
|
|
|
MediaType::JavaScript
|
|
|
|
);
|
|
|
|
assert_eq!(MediaType::from(Path::new("foo/bar.jsx")), MediaType::JSX);
|
|
|
|
assert_eq!(MediaType::from(Path::new("foo/bar.json")), MediaType::Json);
|
|
|
|
assert_eq!(MediaType::from(Path::new("foo/bar.wasm")), MediaType::Wasm);
|
|
|
|
assert_eq!(
|
|
|
|
MediaType::from(Path::new("foo/bar.cjs")),
|
|
|
|
MediaType::JavaScript
|
|
|
|
);
|
2020-10-13 19:52:49 -04:00
|
|
|
assert_eq!(
|
|
|
|
MediaType::from(Path::new("foo/.tsbuildinfo")),
|
|
|
|
MediaType::TsBuildInfo
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
MediaType::from(Path::new("foo/bar.js.map")),
|
|
|
|
MediaType::SourceMap
|
|
|
|
);
|
2020-10-11 22:25:27 -04:00
|
|
|
assert_eq!(
|
|
|
|
MediaType::from(Path::new("foo/bar.txt")),
|
|
|
|
MediaType::Unknown
|
|
|
|
);
|
|
|
|
assert_eq!(MediaType::from(Path::new("foo/bar")), MediaType::Unknown);
|
|
|
|
}
|
|
|
|
|
2020-11-05 19:38:21 -05:00
|
|
|
#[test]
|
|
|
|
fn test_from_specifier() {
|
|
|
|
let fixtures = vec![
|
|
|
|
("file:///a/b/c.ts", MediaType::TypeScript),
|
|
|
|
("file:///a/b/c.js", MediaType::JavaScript),
|
|
|
|
("file:///a/b/c.txt", MediaType::Unknown),
|
|
|
|
("https://deno.land/x/mod.ts", MediaType::TypeScript),
|
|
|
|
("https://deno.land/x/mod.js", MediaType::JavaScript),
|
|
|
|
("https://deno.land/x/mod.txt", MediaType::Unknown),
|
|
|
|
];
|
|
|
|
|
|
|
|
for (specifier, expected) in fixtures {
|
|
|
|
let actual = ModuleSpecifier::resolve_url_or_path(specifier).unwrap();
|
|
|
|
assert_eq!(MediaType::from(&actual), expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-11 22:25:27 -04:00
|
|
|
#[test]
|
|
|
|
fn test_serialization() {
|
|
|
|
assert_eq!(json!(MediaType::JavaScript), json!(0));
|
|
|
|
assert_eq!(json!(MediaType::JSX), json!(1));
|
|
|
|
assert_eq!(json!(MediaType::TypeScript), json!(2));
|
|
|
|
assert_eq!(json!(MediaType::Dts), json!(3));
|
|
|
|
assert_eq!(json!(MediaType::TSX), json!(4));
|
|
|
|
assert_eq!(json!(MediaType::Json), json!(5));
|
|
|
|
assert_eq!(json!(MediaType::Wasm), json!(6));
|
2020-10-13 19:52:49 -04:00
|
|
|
assert_eq!(json!(MediaType::TsBuildInfo), json!(7));
|
|
|
|
assert_eq!(json!(MediaType::SourceMap), json!(8));
|
|
|
|
assert_eq!(json!(MediaType::Unknown), json!(9));
|
2020-10-11 22:25:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_display() {
|
2020-11-09 09:38:29 -05:00
|
|
|
assert_eq!(MediaType::JavaScript.to_string(), "JavaScript");
|
|
|
|
assert_eq!(MediaType::JSX.to_string(), "JSX");
|
|
|
|
assert_eq!(MediaType::TypeScript.to_string(), "TypeScript");
|
|
|
|
assert_eq!(MediaType::Dts.to_string(), "Dts");
|
|
|
|
assert_eq!(MediaType::TSX.to_string(), "TSX");
|
|
|
|
assert_eq!(MediaType::Json.to_string(), "Json");
|
|
|
|
assert_eq!(MediaType::Wasm.to_string(), "Wasm");
|
|
|
|
assert_eq!(MediaType::TsBuildInfo.to_string(), "TsBuildInfo");
|
|
|
|
assert_eq!(MediaType::SourceMap.to_string(), "SourceMap");
|
|
|
|
assert_eq!(MediaType::Unknown.to_string(), "Unknown");
|
2020-10-11 22:25:27 -04:00
|
|
|
}
|
2020-09-14 08:27:44 -04:00
|
|
|
}
|