0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

fix(cli): restore tripleslash lib refs support (#8157)

Fixes #8147
This commit is contained in:
Kitson Kelly 2020-10-28 11:52:20 +11:00 committed by GitHub
parent dd01f206da
commit 6844caa9a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 140 additions and 98 deletions

View file

@ -343,8 +343,19 @@ impl fmt::Display for Diagnostic {
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Diagnostics(pub Vec<Diagnostic>);
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Diagnostics(Vec<Diagnostic>);
impl Diagnostics {
#[cfg(test)]
pub fn new(diagnostics: Vec<Diagnostic>) -> Self {
Diagnostics(diagnostics)
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl<'de> Deserialize<'de> for Diagnostics {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>

View file

@ -353,7 +353,7 @@ async fn bundle_command(
if let Some(ignored_options) = maybe_ignored_options {
eprintln!("{}", ignored_options);
}
if !diagnostics.0.is_empty() {
if !diagnostics.is_empty() {
return Err(generic_error(diagnostics.to_string()));
}
}

View file

@ -747,7 +747,7 @@ impl Graph2 {
debug!("graph does not need to be checked or emitted.");
return Ok((
Stats(Vec::new()),
Diagnostics(Vec::new()),
Diagnostics::default(),
maybe_ignored_options,
));
}
@ -786,7 +786,7 @@ impl Graph2 {
graph.maybe_tsbuildinfo = response.maybe_tsbuildinfo;
// Only process changes to the graph if there are no diagnostics and there
// were files emitted.
if response.diagnostics.0.is_empty() && !response.emitted_files.is_empty() {
if response.diagnostics.is_empty() && !response.emitted_files.is_empty() {
let mut codes = HashMap::new();
let mut maps = HashMap::new();
let check_js = config.get_check_js();
@ -1694,7 +1694,7 @@ pub mod tests {
.expect("should have checked");
assert!(maybe_ignored_options.is_none());
assert_eq!(stats.0.len(), 12);
assert!(diagnostics.0.is_empty());
assert!(diagnostics.is_empty());
let h = handler.borrow();
assert_eq!(h.cache_calls.len(), 2);
assert_eq!(h.tsbuildinfo_calls.len(), 1);
@ -1717,7 +1717,7 @@ pub mod tests {
.expect("should have checked");
assert!(maybe_ignored_options.is_none());
assert_eq!(stats.0.len(), 12);
assert!(diagnostics.0.is_empty());
assert!(diagnostics.is_empty());
let h = handler.borrow();
assert_eq!(h.cache_calls.len(), 0);
assert_eq!(h.tsbuildinfo_calls.len(), 1);

View file

@ -10,7 +10,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use std::rc::Rc;
fn get_asset(name: &str) -> Option<&'static str> {
pub fn get_asset(name: &str) -> Option<&'static str> {
macro_rules! inc {
($e:expr) => {
Some(include_str!(concat!("dts/", $e)))

View file

@ -182,7 +182,7 @@ impl ProgramState {
if let Some(ignored_options) = maybe_ignored_options {
eprintln!("{}", ignored_options);
}
if !diagnostics.0.is_empty() {
if !diagnostics.is_empty() {
return Err(generic_error(diagnostics.to_string()));
}
};

View file

@ -0,0 +1,7 @@
/// <reference no-default-lib="true"/>
/// <reference lib="dom" />
/// <reference lib="deno.ns" />
export const div = document.createElement("div");
div.innerHTML = `<span>Hello World!</span>`;
console.log(Deno.args);

View file

@ -613,7 +613,7 @@ pub async fn runtime_compile(
execute_in_tsc(program_state.clone(), req_msg).map_err(extract_js_error)?;
let response: RuntimeCompileResponse = serde_json::from_str(&json_str)?;
if response.diagnostics.0.is_empty() && sources.is_none() {
if response.diagnostics.is_empty() && sources.is_none() {
compiler.cache_emitted_files(response.emit_map)?;
}

View file

@ -369,7 +369,7 @@ delete Object.prototype.__proto__;
return sourceFile;
}
/** @type {{ data: string; hash: string; }} */
/** @type {{ data: string; hash?: string; scriptKind: ts.ScriptKind }} */
const { data, hash, scriptKind } = core.jsonOpSync(
"op_load",
{ specifier },

View file

@ -4,6 +4,8 @@ use crate::diagnostics::Diagnostics;
use crate::media_type::MediaType;
use crate::module_graph2::Graph2;
use crate::module_graph2::Stats;
// TODO(@kitsonk) this needs to be refactored when we drop MG1
use crate::op_fetch_asset::get_asset;
use crate::tsc_config::TsConfig;
use deno_core::error::anyhow;
@ -24,6 +26,19 @@ use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
fn get_maybe_hash(
maybe_source: &Option<String>,
hash_data: &[Vec<u8>],
) -> Option<String> {
if let Some(source) = maybe_source {
let mut data = vec![source.as_bytes().to_owned()];
data.extend_from_slice(hash_data);
Some(crate::checksum::gen(&data))
} else {
None
}
}
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct EmittedFile {
pub data: String,
@ -177,6 +192,12 @@ fn load(state: &mut State, args: Value) -> Result<Value, AnyError> {
hash = Some("1".to_string());
media_type = MediaType::TypeScript;
Some("declare var a: any;\nexport = a;\n".to_string())
} else if v.specifier.starts_with("asset:///") {
let name = v.specifier.replace("asset:///", "");
let maybe_source = get_asset(&name).map(|s| s.to_string());
hash = get_maybe_hash(&maybe_source, &state.hash_data);
media_type = MediaType::from(&v.specifier);
maybe_source
} else {
let graph = state.graph.borrow();
let specifier =
@ -191,11 +212,7 @@ fn load(state: &mut State, args: Value) -> Result<Value, AnyError> {
} else {
MediaType::Unknown
};
if let Some(source) = &maybe_source {
let mut data = vec![source.as_bytes().to_owned()];
data.extend_from_slice(&state.hash_data);
hash = Some(crate::checksum::gen(&data));
}
hash = get_maybe_hash(&maybe_source, &state.hash_data);
maybe_source
};
@ -396,6 +413,47 @@ mod tests {
State::new(graph, hash_data, maybe_tsbuildinfo, HashMap::new())
}
async fn test_exec(
specifier: &ModuleSpecifier,
) -> Result<Response, AnyError> {
let hash_data = vec![b"something".to_vec()];
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
let fixtures = c.join("tests/tsc2");
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
fixtures,
..Default::default()
}));
let mut builder = GraphBuilder2::new(handler.clone(), None, None);
builder.add(&specifier, false).await?;
let graph = Rc::new(RefCell::new(builder.get_graph()));
let config = TsConfig::new(json!({
"allowJs": true,
"checkJs": false,
"esModuleInterop": true,
"emitDecoratorMetadata": false,
"incremental": true,
"jsx": "react",
"jsxFactory": "React.createElement",
"jsxFragmentFactory": "React.Fragment",
"lib": ["deno.window"],
"module": "esnext",
"noEmit": true,
"outDir": "deno:///",
"strict": true,
"target": "esnext",
"tsBuildInfoFile": "deno:///.tsbuildinfo",
}));
let request = Request {
config,
debug: false,
graph,
hash_data,
maybe_tsbuildinfo: None,
root_names: vec![(specifier.clone(), MediaType::TypeScript)],
};
exec(js::compiler_isolate_init(), request)
}
#[tokio::test]
async fn test_create_hash() {
let mut state = setup(None, Some(vec![b"something".to_vec()]), None).await;
@ -481,6 +539,36 @@ mod tests {
);
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct LoadResponse {
data: String,
hash: Option<String>,
script_kind: i64,
}
#[tokio::test]
async fn test_load_asset() {
let mut state = setup(
Some(
ModuleSpecifier::resolve_url_or_path("https://deno.land/x/mod.ts")
.unwrap(),
),
None,
Some("some content".to_string()),
)
.await;
let value =
load(&mut state, json!({ "specifier": "asset:///lib.dom.d.ts" }))
.expect("should have invoked op");
let actual: LoadResponse =
serde_json::from_value(value).expect("failed to deserialize");
let expected = get_asset("lib.dom.d.ts").unwrap();
assert_eq!(actual.data, expected);
assert!(actual.hash.is_some());
assert_eq!(actual.script_kind, 3);
}
#[tokio::test]
async fn test_load_tsbuildinfo() {
let mut state = setup(
@ -581,7 +669,7 @@ mod tests {
assert_eq!(
state.maybe_response,
Some(RespondArgs {
diagnostics: Diagnostics(vec![Diagnostic {
diagnostics: Diagnostics::new(vec![Diagnostic {
category: DiagnosticCategory::Error,
code: 5023,
start: None,
@ -601,50 +689,13 @@ mod tests {
}
#[tokio::test]
async fn test_exec() {
async fn test_exec_basic() {
let specifier =
ModuleSpecifier::resolve_url_or_path("https://deno.land/x/a.ts").unwrap();
let hash_data = vec![b"something".to_vec()];
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
let fixtures = c.join("tests/tsc2");
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
fixtures,
..MockSpecifierHandler::default()
}));
let mut builder = GraphBuilder2::new(handler.clone(), None, None);
builder
.add(&specifier, false)
let actual = test_exec(&specifier)
.await
.expect("module not inserted");
let graph = Rc::new(RefCell::new(builder.get_graph()));
let config = TsConfig::new(json!({
"allowJs": true,
"checkJs": false,
"esModuleInterop": true,
"emitDecoratorMetadata": false,
"incremental": true,
"jsx": "react",
"jsxFactory": "React.createElement",
"jsxFragmentFactory": "React.Fragment",
"lib": ["deno.window"],
"module": "esnext",
"noEmit": true,
"outDir": "deno:///",
"strict": true,
"target": "esnext",
"tsBuildInfoFile": "deno:///.tsbuildinfo",
}));
let request = Request {
config,
debug: false,
graph,
hash_data,
maybe_tsbuildinfo: None,
root_names: vec![(specifier, MediaType::TypeScript)],
};
let actual = exec(js::compiler_isolate_init(), request)
.expect("exec should have not errored");
assert!(actual.diagnostics.0.is_empty());
.expect("exec should not have errored");
assert!(actual.diagnostics.is_empty());
assert!(actual.emitted_files.is_empty());
assert!(actual.maybe_tsbuildinfo.is_some());
assert_eq!(actual.stats.0.len(), 12);
@ -654,49 +705,22 @@ mod tests {
async fn test_exec_reexport_dts() {
let specifier =
ModuleSpecifier::resolve_url_or_path("file:///reexports.ts").unwrap();
let hash_data = vec![b"something".to_vec()];
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
let fixtures = c.join("tests/tsc2");
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
fixtures,
..MockSpecifierHandler::default()
}));
let mut builder = GraphBuilder2::new(handler.clone(), None, None);
builder
.add(&specifier, false)
let actual = test_exec(&specifier)
.await
.expect("module not inserted");
let graph = Rc::new(RefCell::new(builder.get_graph()));
let config = TsConfig::new(json!({
"allowJs": true,
"checkJs": false,
"esModuleInterop": true,
"emitDecoratorMetadata": false,
"incremental": true,
"jsx": "react",
"jsxFactory": "React.createElement",
"jsxFragmentFactory": "React.Fragment",
"lib": ["deno.window"],
"module": "esnext",
"noEmit": true,
"outDir": "deno:///",
"strict": true,
"target": "esnext",
"tsBuildInfoFile": "deno:///.tsbuildinfo",
}));
let request = Request {
config,
debug: false,
graph,
hash_data,
maybe_tsbuildinfo: None,
root_names: vec![(specifier, MediaType::TypeScript)],
};
let actual = exec(js::compiler_isolate_init(), request)
.expect("exec should have not errored");
assert!(actual.diagnostics.0.is_empty());
.expect("exec should not have errored");
assert!(actual.diagnostics.is_empty());
assert!(actual.emitted_files.is_empty());
assert!(actual.maybe_tsbuildinfo.is_some());
assert_eq!(actual.stats.0.len(), 12);
}
#[tokio::test]
async fn fix_lib_ref() {
let specifier =
ModuleSpecifier::resolve_url_or_path("file:///libref.ts").unwrap();
let actual = test_exec(&specifier)
.await
.expect("exec should not have errored");
assert!(actual.diagnostics.is_empty());
}
}