From 212fbf0c4a27f55796ae0f31a9f77d0fbd99b4da Mon Sep 17 00:00:00 2001 From: raashidanwar Date: Wed, 23 Oct 2024 00:25:57 +0530 Subject: [PATCH 1/6] Added new compiler option to support TsConfig runtime option with values ["deno", "browser"]. --- src/deno_json/ts.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/deno_json/ts.rs b/src/deno_json/ts.rs index 88bdbe2..650a8d3 100644 --- a/src/deno_json/ts.rs +++ b/src/deno_json/ts.rs @@ -7,6 +7,7 @@ use serde::Serializer; use serde_json::json; use serde_json::Value; use std::collections::BTreeMap; +use std::collections::HashSet; use std::fmt; use url::Url; @@ -120,6 +121,7 @@ static ALLOWED_COMPILER_OPTIONS: phf::Set<&'static str> = phf::phf_set! { "noUncheckedIndexedAccess", "noUnusedLocals", "noUnusedParameters", + "runtime", "strict", "strictBindCallApply", "strictBuiltinIteratorReturn", @@ -146,6 +148,24 @@ pub fn parse_compiler_options( let mut ignored: Vec = Vec::with_capacity(compiler_options.len()); for (key, value) in compiler_options { + if key == "runtime" { + if let Value::Array(ref v) = value { + let mut runtime_set = HashSet::new(); + for val in v { + if let Value::String(ref s) = val { + runtime_set.insert(s.as_str()); + } + } + + if runtime_set.contains("browser") && runtime_set.contains("deno") { + allowed.insert(String::from("lib"), json!(["deno.ns", "esnext", "dom", "dom.iterable"])); + } else if runtime_set.contains("deno") { + allowed.insert(String::from("lib"), json!(["deno.ns"])); + } else if runtime_set.contains("browser") { + allowed.insert(String::from("lib"), json!(["esnext", "dom", "dom.iterable"])); + } + } + } // We don't pass "types" entries to typescript via the compiler // options and instead provide those to tsc as "roots". This is // because our "types" behavior is at odds with how TypeScript's From e729de9619c9b5223f8ed2140c735d33d7008517 Mon Sep 17 00:00:00 2001 From: raashidanwar Date: Wed, 23 Oct 2024 00:32:41 +0530 Subject: [PATCH 2/6] fmt fix --- src/deno_json/ts.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/deno_json/ts.rs b/src/deno_json/ts.rs index 650a8d3..df8821a 100644 --- a/src/deno_json/ts.rs +++ b/src/deno_json/ts.rs @@ -152,13 +152,16 @@ pub fn parse_compiler_options( if let Value::Array(ref v) = value { let mut runtime_set = HashSet::new(); for val in v { - if let Value::String(ref s) = val { - runtime_set.insert(s.as_str()); - } + if let Value::String(ref s) = val { + runtime_set.insert(s.as_str()); + } } if runtime_set.contains("browser") && runtime_set.contains("deno") { - allowed.insert(String::from("lib"), json!(["deno.ns", "esnext", "dom", "dom.iterable"])); + allowed.insert( + String::from("lib"), + json!(["deno.ns", "esnext", "dom", "dom.iterable"]) + ); } else if runtime_set.contains("deno") { allowed.insert(String::from("lib"), json!(["deno.ns"])); } else if runtime_set.contains("browser") { From 3d6a4505c67a0b22aadc1a7ec03b2e4168d60036 Mon Sep 17 00:00:00 2001 From: raashidanwar Date: Wed, 23 Oct 2024 00:34:18 +0530 Subject: [PATCH 3/6] fmt fix --- src/deno_json/ts.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/deno_json/ts.rs b/src/deno_json/ts.rs index df8821a..7d6fa84 100644 --- a/src/deno_json/ts.rs +++ b/src/deno_json/ts.rs @@ -153,19 +153,22 @@ pub fn parse_compiler_options( let mut runtime_set = HashSet::new(); for val in v { if let Value::String(ref s) = val { - runtime_set.insert(s.as_str()); + runtime_set.insert(s.as_str()); } } if runtime_set.contains("browser") && runtime_set.contains("deno") { allowed.insert( String::from("lib"), - json!(["deno.ns", "esnext", "dom", "dom.iterable"]) + json!(["deno.ns", "esnext", "dom", "dom.iterable"]), ); } else if runtime_set.contains("deno") { allowed.insert(String::from("lib"), json!(["deno.ns"])); } else if runtime_set.contains("browser") { - allowed.insert(String::from("lib"), json!(["esnext", "dom", "dom.iterable"])); + allowed.insert( + String::from("lib"), + json!(["esnext", "dom", "dom.iterable"]), + ); } } } From de1dd8d68edaf312c1b89b31eb5f92345c3593e1 Mon Sep 17 00:00:00 2001 From: raashidanwar Date: Wed, 23 Oct 2024 16:34:20 +0530 Subject: [PATCH 4/6] Added the runtime option to config. --- src/deno_json/mod.rs | 59 +++++++++++++++++++++++++++++++++++++++++--- src/deno_json/ts.rs | 26 ------------------- 2 files changed, 55 insertions(+), 30 deletions(-) diff --git a/src/deno_json/mod.rs b/src/deno_json/mod.rs index 8ac2d5f..6a55005 100644 --- a/src/deno_json/mod.rs +++ b/src/deno_json/mod.rs @@ -594,6 +594,7 @@ impl NodeModulesDirMode { #[serde(rename_all = "camelCase")] pub struct ConfigFileJson { pub compiler_options: Option, + pub runtime: Vec, pub import_map: Option, pub imports: Option, pub scopes: Option, @@ -914,16 +915,64 @@ impl ConfigFile { /// Parse `compilerOptions` and return a serde `Value`. /// The result also contains any options that were ignored. pub fn to_compiler_options(&self) -> Result { - if let Some(compiler_options) = self.json.compiler_options.clone() { - let options: serde_json::Map = + let compiler_options_exists = self.json.compiler_options.is_some(); + let runtime_exists = !self.json.runtime.is_empty(); + + if compiler_options_exists || runtime_exists { + let mut options: serde_json::Map = if let Some(compiler_options) = self.json.compiler_options.clone() { serde_json::from_value(compiler_options) - .context("compilerOptions should be an object")?; + .context("compilerOptions should be an object")? + } else { + serde_json::Map::new() + }; + + if runtime_exists { + self.resolve_runtime_libs(&mut options); + } + parse_compiler_options(options, Some(&self.specifier)) } else { Ok(Default::default()) } } + /// Resolves and updates the `lib` field in `compilerOptions` based on the `runtime` configuration. + fn resolve_runtime_libs(&self, options: &mut serde_json::Map) { + let runtime = &self.json.runtime; + let contains_deno = runtime.contains(&"deno".to_string()); + let contains_browser = runtime.contains(&"browser".to_string()); + + if contains_deno && contains_browser { + self.insert_libs(options, vec![ + "deno.ns".to_string(), + "esnext".to_string(), + "dom".to_string(), + "dom.iterable".to_string(), + ]); + } else if contains_deno { + self.insert_libs(options, vec!["deno.ns".to_string()]); + } else if contains_browser { + self.insert_libs(options, vec![ + "esnext".to_string(), + "dom".to_string(), + "dom.iterable".to_string(), + ]); + } + } + + /// Inserts the values into the `lib` field of `compilerOptions`. + fn insert_libs(&self, options: &mut serde_json::Map, libs: Vec) { + let lib_array = options + .entry("lib".to_string()) + .or_insert(Value::Array(Vec::new())) // Ensure "lib" key exists as an array + .as_array_mut() + .unwrap(); + + for lib in libs { + lib_array.push(Value::String(lib)); + } + } + pub fn to_import_map_path(&self) -> Result, AnyError> { let Some(value) = self.json.import_map.as_ref() else { return Ok(None); @@ -1705,6 +1754,7 @@ mod tests { // comments are allowed "strict": true }, + "runtime": ["deno", "browser"], "lint": { "include": ["src/"], "exclude": ["src/testdata/"], @@ -1741,7 +1791,8 @@ mod tests { maybe_ignored, } = config_file.to_compiler_options().unwrap(); assert!(options.contains_key("strict")); - assert_eq!(options.len(), 1); + assert!(options.contains_key("lib")); + assert_eq!(options.len(), 2); assert_eq!( maybe_ignored, Some(IgnoredCompilerOptions { diff --git a/src/deno_json/ts.rs b/src/deno_json/ts.rs index 7d6fa84..88bdbe2 100644 --- a/src/deno_json/ts.rs +++ b/src/deno_json/ts.rs @@ -7,7 +7,6 @@ use serde::Serializer; use serde_json::json; use serde_json::Value; use std::collections::BTreeMap; -use std::collections::HashSet; use std::fmt; use url::Url; @@ -121,7 +120,6 @@ static ALLOWED_COMPILER_OPTIONS: phf::Set<&'static str> = phf::phf_set! { "noUncheckedIndexedAccess", "noUnusedLocals", "noUnusedParameters", - "runtime", "strict", "strictBindCallApply", "strictBuiltinIteratorReturn", @@ -148,30 +146,6 @@ pub fn parse_compiler_options( let mut ignored: Vec = Vec::with_capacity(compiler_options.len()); for (key, value) in compiler_options { - if key == "runtime" { - if let Value::Array(ref v) = value { - let mut runtime_set = HashSet::new(); - for val in v { - if let Value::String(ref s) = val { - runtime_set.insert(s.as_str()); - } - } - - if runtime_set.contains("browser") && runtime_set.contains("deno") { - allowed.insert( - String::from("lib"), - json!(["deno.ns", "esnext", "dom", "dom.iterable"]), - ); - } else if runtime_set.contains("deno") { - allowed.insert(String::from("lib"), json!(["deno.ns"])); - } else if runtime_set.contains("browser") { - allowed.insert( - String::from("lib"), - json!(["esnext", "dom", "dom.iterable"]), - ); - } - } - } // We don't pass "types" entries to typescript via the compiler // options and instead provide those to tsc as "roots". This is // because our "types" behavior is at odds with how TypeScript's From 608295f3eea4d84e6dd26a3e6f53aba831100082 Mon Sep 17 00:00:00 2001 From: raashidanwar Date: Wed, 23 Oct 2024 16:38:59 +0530 Subject: [PATCH 5/6] fmt fix --- src/deno_json/mod.rs | 55 ++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/deno_json/mod.rs b/src/deno_json/mod.rs index 6a55005..9132508 100644 --- a/src/deno_json/mod.rs +++ b/src/deno_json/mod.rs @@ -919,12 +919,13 @@ impl ConfigFile { let runtime_exists = !self.json.runtime.is_empty(); if compiler_options_exists || runtime_exists { - let mut options: serde_json::Map = if let Some(compiler_options) = self.json.compiler_options.clone() { - serde_json::from_value(compiler_options) - .context("compilerOptions should be an object")? - } else { - serde_json::Map::new() - }; + let mut options: serde_json::Map = + if let Some(compiler_options) = self.json.compiler_options.clone() { + serde_json::from_value(compiler_options) + .context("compilerOptions should be an object")? + } else { + serde_json::Map::new() + }; if runtime_exists { self.resolve_runtime_libs(&mut options); @@ -943,30 +944,40 @@ impl ConfigFile { let contains_browser = runtime.contains(&"browser".to_string()); if contains_deno && contains_browser { - self.insert_libs(options, vec![ - "deno.ns".to_string(), - "esnext".to_string(), - "dom".to_string(), - "dom.iterable".to_string(), - ]); + self.insert_libs( + options, + vec![ + "deno.ns".to_string(), + "esnext".to_string(), + "dom".to_string(), + "dom.iterable".to_string(), + ], + ); } else if contains_deno { self.insert_libs(options, vec!["deno.ns".to_string()]); } else if contains_browser { - self.insert_libs(options, vec![ - "esnext".to_string(), - "dom".to_string(), - "dom.iterable".to_string(), - ]); + self.insert_libs( + options, + vec![ + "esnext".to_string(), + "dom".to_string(), + "dom.iterable".to_string(), + ], + ); } } /// Inserts the values into the `lib` field of `compilerOptions`. - fn insert_libs(&self, options: &mut serde_json::Map, libs: Vec) { + fn insert_libs( + &self, + options: &mut serde_json::Map, + libs: Vec, + ) { let lib_array = options - .entry("lib".to_string()) - .or_insert(Value::Array(Vec::new())) // Ensure "lib" key exists as an array - .as_array_mut() - .unwrap(); + .entry("lib".to_string()) + .or_insert(Value::Array(Vec::new())) // Ensure "lib" key exists as an array + .as_array_mut() + .unwrap(); for lib in libs { lib_array.push(Value::String(lib)); From 14ce1b4b3f9bbb816cc98e1b480894a333544302 Mon Sep 17 00:00:00 2001 From: raashidanwar Date: Wed, 23 Oct 2024 16:48:05 +0530 Subject: [PATCH 6/6] runtime is Option --- src/deno_json/mod.rs | 55 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/src/deno_json/mod.rs b/src/deno_json/mod.rs index 9132508..bd772f4 100644 --- a/src/deno_json/mod.rs +++ b/src/deno_json/mod.rs @@ -594,7 +594,7 @@ impl NodeModulesDirMode { #[serde(rename_all = "camelCase")] pub struct ConfigFileJson { pub compiler_options: Option, - pub runtime: Vec, + pub runtime: Option>, pub import_map: Option, pub imports: Option, pub scopes: Option, @@ -916,7 +916,7 @@ impl ConfigFile { /// The result also contains any options that were ignored. pub fn to_compiler_options(&self) -> Result { let compiler_options_exists = self.json.compiler_options.is_some(); - let runtime_exists = !self.json.runtime.is_empty(); + let runtime_exists = self.json.runtime.is_some(); if compiler_options_exists || runtime_exists { let mut options: serde_json::Map = @@ -939,31 +939,32 @@ impl ConfigFile { /// Resolves and updates the `lib` field in `compilerOptions` based on the `runtime` configuration. fn resolve_runtime_libs(&self, options: &mut serde_json::Map) { - let runtime = &self.json.runtime; - let contains_deno = runtime.contains(&"deno".to_string()); - let contains_browser = runtime.contains(&"browser".to_string()); - - if contains_deno && contains_browser { - self.insert_libs( - options, - vec![ - "deno.ns".to_string(), - "esnext".to_string(), - "dom".to_string(), - "dom.iterable".to_string(), - ], - ); - } else if contains_deno { - self.insert_libs(options, vec!["deno.ns".to_string()]); - } else if contains_browser { - self.insert_libs( - options, - vec![ - "esnext".to_string(), - "dom".to_string(), - "dom.iterable".to_string(), - ], - ); + if let Some(runtime) = self.json.runtime.clone() { + let contains_deno = runtime.contains(&"deno".to_string()); + let contains_browser = runtime.contains(&"browser".to_string()); + + if contains_deno && contains_browser { + self.insert_libs( + options, + vec![ + "deno.ns".to_string(), + "esnext".to_string(), + "dom".to_string(), + "dom.iterable".to_string(), + ], + ); + } else if contains_deno { + self.insert_libs(options, vec!["deno.ns".to_string()]); + } else if contains_browser { + self.insert_libs( + options, + vec![ + "esnext".to_string(), + "dom".to_string(), + "dom.iterable".to_string(), + ], + ); + } } }