diff options
-rw-r--r-- | Cargo.lock | 172 | ||||
-rw-r--r-- | cli/Cargo.toml | 14 | ||||
-rw-r--r-- | cli/ast/mod.rs | 235 | ||||
-rw-r--r-- | cli/http_util.rs | 3 | ||||
-rw-r--r-- | cli/lsp/code_lens.rs | 19 | ||||
-rw-r--r-- | cli/tests/integration/repl_tests.rs | 12 | ||||
-rw-r--r-- | cli/tests/testdata/bundle.test.out | 16 | ||||
-rw-r--r-- | cli/tests/testdata/compiler_api_test.ts | 10 | ||||
-rw-r--r-- | cli/tools/repl/mod.rs | 61 | ||||
-rw-r--r-- | core/Cargo.toml | 3 |
10 files changed, 352 insertions, 193 deletions
diff --git a/Cargo.lock b/Cargo.lock index 6c0702d8c..d9785975c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,9 +44,9 @@ checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" [[package]] name = "ahash" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom 0.2.3", "once_cell", @@ -615,9 +615,9 @@ checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" [[package]] name = "data-url" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d33fe99ccedd6e84bc035f1931bb2e6be79739d6242bd895e7311c886c50dc9c" +checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193" dependencies = [ "matches", ] @@ -694,9 +694,9 @@ dependencies = [ [[package]] name = "deno_ast" -version = "0.5.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee37af956e0efce7863828eb055208965be06f47959b73c47466e0b5f9a1a9e" +checksum = "0f1c58caca74265d1c63a5c26069e037846f8bdf6a3e2dde3da66c6f6f51297d" dependencies = [ "data-url", "dprint-swc-ecma-ast-view", @@ -781,9 +781,9 @@ dependencies = [ [[package]] name = "deno_doc" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "075b0c1b454eaf90cea9c6efc72ff946aa6c855c85a4209cb717c01424b37e5e" +checksum = "366a584bf4486c7d5674e398c7bb8e6c55a871822cea9d217236933d85e25b98" dependencies = [ "cfg-if 1.0.0", "deno_ast", @@ -827,9 +827,9 @@ dependencies = [ [[package]] name = "deno_graph" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee63197c67746c40911cb3082ca13a29cc5adae1ff1b706397b44f7155d7c57" +checksum = "10ec6e60e462d83c3b7c6c482e9c52149e421a6f7f04e2ed32a0749a2655911c" dependencies = [ "anyhow", "cfg-if 1.0.0", @@ -863,9 +863,9 @@ dependencies = [ [[package]] name = "deno_lint" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c031711a48a3c5ea4ca6103c6d6df456ba3b0bb048fb551f07da4f704e1d844" +checksum = "60b82bcc8b48bd19e2755303decf7833e650d5e6743c6331fb462c50ee47adf0" dependencies = [ "anyhow", "deno_ast", @@ -1132,9 +1132,9 @@ dependencies = [ [[package]] name = "dprint-plugin-typescript" -version = "0.59.2" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7eb0e9b299253bcdef030e1df70ee820b13faebee9175b35d78de0bc99c1c9a" +checksum = "b0a43c5093e898d4fc54b14c2583d83e9ab30d68e3bde374ab6a74996af2f1e2" dependencies = [ "deno_ast", "dprint-core", @@ -1145,9 +1145,9 @@ dependencies = [ [[package]] name = "dprint-swc-ecma-ast-view" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac2108f47408837b37dfa645cca2b6c03a8f6c993bc7cd3d17506c2b4dd3326" +checksum = "2d2654eb6e5d6e02096f6969d1370e9e474b43c9ad1a7142556c7d1e9d1afe0a" dependencies = [ "bumpalo", "num-bigint", @@ -1675,7 +1675,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.4", + "ahash 0.7.6", ] [[package]] @@ -1828,9 +1828,9 @@ checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" [[package]] name = "import_map" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d315210af92bcde7a84672d5554fc2b4268c4d40dc9c930ae1d1ed765a8f6381" +checksum = "f91db0bc4eff39727c95caa6e70268df077d7ebde57c1454a9cb8ddeb76b9689" dependencies = [ "indexmap", "log", @@ -1841,12 +1841,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg 1.0.1", - "hashbrown 0.9.1", + "hashbrown 0.11.2", "serde", ] @@ -3560,11 +3560,11 @@ dependencies = [ [[package]] name = "swc_bundler" -version = "0.75.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15b9dfe3beb671044c8237ee921a007255ad6a92c12c119cf29fb7bb7c807ad" +checksum = "7266b804885475a9f2d829946747d72b4806e23be690a44c8b6f7819453fd0bc" dependencies = [ - "ahash 0.7.4", + "ahash 0.7.6", "anyhow", "crc", "indexmap", @@ -3585,16 +3585,18 @@ dependencies = [ "swc_ecma_transforms_optimization", "swc_ecma_utils", "swc_ecma_visit", + "swc_fast_graph", + "swc_graph_analyzer", "tracing", ] [[package]] name = "swc_common" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de8be830f71f62908dae13fd9db66522e77dbf9188bd07d0b86d15f48557b219" +checksum = "560998b621793a613c98ec8cdbd729e46332dd3fbf7619b57e9d98c15e142e2e" dependencies = [ - "ahash 0.7.4", + "ahash 0.7.6", "ast_node", "cfg-if 0.1.10", "either", @@ -3616,9 +3618,9 @@ dependencies = [ [[package]] name = "swc_ecma_ast" -version = "0.55.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e40d99e5376086f6a057202b3889f276c3f5cbcafeead8f536ed088ad0bf36b3" +checksum = "a31826c0275a1062d1e16d5b428c5059d176274c4e6c1c499525ddd2c65fcacc" dependencies = [ "is-macro", "num-bigint", @@ -3630,9 +3632,9 @@ dependencies = [ [[package]] name = "swc_ecma_codegen" -version = "0.77.0" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9679c138f4cfe98c86e0947bdc089c4402b372db064f6aca2636a86c93898052" +checksum = "08ed18a9bf4bca94b2029ed267373b01f4e207f5f617ab403b3bca96a44f5547" dependencies = [ "bitflags", "memchr", @@ -3662,9 +3664,9 @@ dependencies = [ [[package]] name = "swc_ecma_dep_graph" -version = "0.44.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e8d4a5f0136b50a0339e015f77a42a4bbae66c3a82ae399491d4d5caed3d2" +checksum = "a47d0548c1d6fcc44f15462828af696cc335cfa3c36bff98900b851074fad546" dependencies = [ "swc_atoms", "swc_common", @@ -3674,24 +3676,23 @@ dependencies = [ [[package]] name = "swc_ecma_loader" -version = "0.22.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9507f40d574997316948f94423c3c93dcb03bf593bd0a5197b51c34ed09558" +checksum = "b0c9672f7cf71bf2a98fc0c66eed90d43db9252c82e52096c7159ea5521f3478" dependencies = [ - "ahash 0.7.4", + "ahash 0.7.6", "anyhow", + "serde", "swc_atoms", "swc_common", - "swc_ecma_ast", - "swc_ecma_visit", "tracing", ] [[package]] name = "swc_ecma_parser" -version = "0.75.2" +version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf91ac2559e8cb4d5e66ca5b7b71f0bcf9a16289cc0eb31211314bffb1c4f4b" +checksum = "97570156b3eec2e91b43f3adf9526caaf5cdf656c65a7722715b3537c2952261" dependencies = [ "either", "enum_kind", @@ -3710,9 +3711,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms" -version = "0.88.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c38ddf75f012a84fe05ccdbceaf3a57c8657a989ad376ad5a5fd0ec7cf197cf9" +checksum = "15931263dab79ddee709e981b5222d84a684cfaa66d2913394bee6d5b4635cca" dependencies = [ "swc_atoms", "swc_common", @@ -3729,9 +3730,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_base" -version = "0.40.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ce842ee29a2e96647950dba48dddd757ad7e5b392b1902191a16c3e8be22ae" +checksum = "0bfa5fa18d0f7b7f2cf3522049e22ca8c5a77072a30f597c38de1c5f10a69501" dependencies = [ "once_cell", "phf", @@ -3743,13 +3744,14 @@ dependencies = [ "swc_ecma_parser", "swc_ecma_utils", "swc_ecma_visit", + "tracing", ] [[package]] name = "swc_ecma_transforms_classes" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86440b9078c3496db893afb298d20a59baf2fc46caa3298d16fdf3c88f27a250" +checksum = "7305d99e9851ae762e8bca1f7d43a0a1dd6c55b78220b10425b06a5f54c4498f" dependencies = [ "swc_atoms", "swc_common", @@ -3761,9 +3763,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_macros" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063ad8426598df1aad8cdb9e9994a54cecb07fe902190c467bf195f5f553ed8d" +checksum = "18712e4aab969c6508dff3540ade6358f1e013464aa58b3d30da2ab2d9fcbbed" dependencies = [ "pmutil", "proc-macro2 1.0.29", @@ -3774,11 +3776,11 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_optimization" -version = "0.58.1" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8774d32f481b47dec0b0e30765a71d02a1c63919b4ca52f925afbf0dd5b81e6" +checksum = "7d528d813fd0af0c8727b0143b0c60759ff6a1cefb7223ee955da85c90edaaa6" dependencies = [ - "ahash 0.7.4", + "ahash 0.7.6", "dashmap", "indexmap", "once_cell", @@ -3797,9 +3799,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_proposal" -version = "0.51.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4f7cfc191cb5b199bf9aedafd583785ea21662e312ad49d6b5a73dc3c4efe6d" +checksum = "1185431bc8fb9d5460f662effbe4eaa10f1038f4e7fc7cfb2edfef4a7cc1104e" dependencies = [ "either", "serde", @@ -3817,11 +3819,11 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_react" -version = "0.53.0" +version = "0.65.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7a21856bade56164a0da969aacd3ec90c27bed56e82480c92721fca18d1fe8" +checksum = "c0f9a87fba33abfae51b6442c521af5bc607fe81aca98efb131102eff2b3df38" dependencies = [ - "ahash 0.7.4", + "ahash 0.7.6", "base64 0.13.0", "dashmap", "indexmap", @@ -3842,9 +3844,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_typescript" -version = "0.54.0" +version = "0.67.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfbca21d37a9ec2e5de9f92d6dd5ff2d749d741bc0fac832d38ccbcf4bde4f28" +checksum = "33c739f59074fa7b65f43a36c2912a8b92985c2d521ed45649dd0f2c7f5a69ee" dependencies = [ "serde", "swc_atoms", @@ -3859,37 +3861,38 @@ dependencies = [ [[package]] name = "swc_ecma_utils" -version = "0.48.0" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc932d46dabd2250f4bb690cf5eb14a672c6c054caee1a1a9ff3ecf77b472606" +checksum = "f0adfd7c7ebc9133e5d98dbe307c8ef41d43ae9ba9e5f3f690880b057ab0adc3" dependencies = [ "once_cell", - "scoped-tls", "swc_atoms", "swc_common", "swc_ecma_ast", "swc_ecma_visit", + "tracing", "unicode-xid 0.2.2", ] [[package]] name = "swc_ecma_visit" -version = "0.41.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c242ca4236cf826f9d575f27235a049e7e5629b66f130fdc1f333fa23e6a2ff4" +checksum = "f0b3826abd1e68214fe9743437236608a0a22d27912e84a85a53f1e977e10468" dependencies = [ "num-bigint", "swc_atoms", "swc_common", "swc_ecma_ast", "swc_visit", + "tracing", ] [[package]] name = "swc_ecmascript" -version = "0.80.0" +version = "0.95.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc83776796ba1c4602e268ff0a71a325fbaf8b65d312b8fe975ee94865300501" +checksum = "703291bc32dd81c1d73761e02442bdefed5844490f853f9979b8b8cb21e7392b" dependencies = [ "swc_ecma_ast", "swc_ecma_codegen", @@ -3913,6 +3916,31 @@ dependencies = [ ] [[package]] +name = "swc_fast_graph" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4e08c814c7283238c72c61069614b55d58ccfeeb5e4fd9887913e9d34102632" +dependencies = [ + "ahash 0.7.6", + "indexmap", + "petgraph 0.5.1", + "swc_common", +] + +[[package]] +name = "swc_graph_analyzer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13707fe5ba172950c56e16ab206f4d2a7da4e16742e7f527c331c1e0973267d4" +dependencies = [ + "ahash 0.7.6", + "auto_impl", + "petgraph 0.5.1", + "swc_fast_graph", + "tracing", +] + +[[package]] name = "swc_macros_common" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3926,9 +3954,9 @@ dependencies = [ [[package]] name = "swc_visit" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a423caa0b4585118164dbad8f1ad52b592a9a9370b25decc4d84c6b4309132c0" +checksum = "e5c639379dd2a8a0221fa1e12fafbdd594ba53a0cace6560054da52409dfcc1a" dependencies = [ "either", "swc_visit_macros", @@ -3936,9 +3964,9 @@ dependencies = [ [[package]] name = "swc_visit_macros" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b2825fee79f10d0166e8e650e79c7a862fb991db275743083f07555d7641f0" +checksum = "e505bbf8e11898fa05a65aa5e773c827ec743fc15aa3c064c9e06164ed0b6630" dependencies = [ "Inflector", "pmutil", @@ -4054,9 +4082,9 @@ checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a" [[package]] name = "text_lines" -version = "0.3.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b748c1c41162300bfc1748c7458ea66a45aabff1d9202a3267a95db40c7b7c" +checksum = "e49e3c53dd04de8b8e8390bc4fab57f6db7af7d33b086fe411803e6351c9f9f9" dependencies = [ "serde", ] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 4c3997332..dd80d6dfb 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -39,26 +39,26 @@ winapi = "=0.3.9" winres = "=0.1.11" [dependencies] -deno_ast = { version = "0.5.0", features = ["bundler", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] } +deno_ast = { version = "0.7.0", features = ["bundler", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] } deno_core = { version = "0.110.0", path = "../core" } -deno_doc = "0.21.0" -deno_graph = "0.12.0" -deno_lint = { version = "0.19.0", features = ["docs"] } +deno_doc = "0.22.0" +deno_graph = "0.13.0" +deno_lint = { version = "0.20.0", features = ["docs"] } deno_runtime = { version = "0.36.0", path = "../runtime" } atty = "=0.2.14" base64 = "=0.13.0" clap = "=2.33.3" -data-url = "=0.1.0" +data-url = "=0.1.1" dissimilar = "=1.0.2" dprint-plugin-json = "=0.13.2" dprint-plugin-markdown = "=0.11.3" -dprint-plugin-typescript = "=0.59.2" +dprint-plugin-typescript = "=0.60.0" encoding_rs = "=0.8.29" env_logger = "=0.8.4" fancy-regex = "=0.7.1" http = "=0.2.4" -import_map = "=0.3.3" +import_map = "=0.4.0" jsonc-parser = { version = "=0.17.0", features = ["serde"] } lazy_static = "=1.4.0" libc = "=0.2.106" diff --git a/cli/ast/mod.rs b/cli/ast/mod.rs index ac3dd5887..464c89257 100644 --- a/cli/ast/mod.rs +++ b/cli/ast/mod.rs @@ -17,6 +17,8 @@ use deno_ast::swc::common::Globals; use deno_ast::swc::common::Mark; use deno_ast::swc::common::SourceMap; use deno_ast::swc::common::Spanned; +use deno_ast::swc::parser::error::Error as SwcError; +use deno_ast::swc::parser::error::SyntaxError; use deno_ast::swc::parser::lexer::Lexer; use deno_ast::swc::parser::StringInput; use deno_ast::swc::transforms::fixer; @@ -38,6 +40,7 @@ use deno_core::resolve_url_or_path; use deno_core::serde_json; use deno_core::ModuleSpecifier; use std::cell::RefCell; +use std::fmt; use std::rc::Rc; mod bundle_hook; @@ -103,6 +106,25 @@ impl std::fmt::Display for Location { } } +#[derive(Debug)] +pub struct Diagnostics(pub Vec<Diagnostic>); + +impl std::error::Error for Diagnostics {} + +impl fmt::Display for Diagnostics { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, diagnostic) in self.0.iter().enumerate() { + if i > 0 { + write!(f, "\n\n")?; + } + + write!(f, "{}", diagnostic)? + } + + Ok(()) + } +} + #[derive(Debug, Clone)] pub enum ImportsNotUsedAsValues { Remove, @@ -259,6 +281,7 @@ pub fn transpile( parsed_source: &ParsedSource, options: &EmitOptions, ) -> Result<(String, Option<String>), AnyError> { + ensure_no_fatal_diagnostics(parsed_source.diagnostics().iter())?; let program: Program = (*parsed_source.program()).clone(); let source_map = Rc::new(SourceMap::default()); let source_map_config = SourceMapConfig { @@ -333,20 +356,18 @@ pub fn transpile_module( let input = StringInput::from(&*source_file); let comments = SingleThreadedComments::default(); let syntax = get_syntax(media_type); - let lexer = Lexer::new(syntax, deno_ast::TARGET, input, Some(&comments)); + let lexer = Lexer::new(syntax, deno_ast::ES_VERSION, input, Some(&comments)); let mut parser = deno_ast::swc::parser::Parser::new_from(lexer); - let module = parser.parse_module().map_err(|err| { - let location = cm.lookup_char_pos(err.span().lo); - Diagnostic { - specifier: specifier.to_string(), - span: err.span(), - display_position: LineAndColumnDisplay { - line_number: location.line, - column_number: location.col_display + 1, - }, - kind: err.into_kind(), - } - })?; + let module = parser + .parse_module() + .map_err(|e| swc_err_to_diagnostic(&cm, specifier, e))?; + let diagnostics = parser + .take_errors() + .into_iter() + .map(|e| swc_err_to_diagnostic(&cm, specifier, e)) + .collect::<Vec<_>>(); + + ensure_no_fatal_diagnostics(diagnostics.iter())?; let top_level_mark = Mark::fresh(Mark::root()); let program = fold_program( @@ -396,28 +417,25 @@ fn fold_program( comments: &SingleThreadedComments, top_level_mark: Mark, ) -> Result<Program, AnyError> { - let jsx_pass = chain!( - resolver_with_mark(top_level_mark), - react::react( - source_map.clone(), - Some(comments), - react::Options { - pragma: options.jsx_factory.clone(), - pragma_frag: options.jsx_fragment_factory.clone(), - // this will use `Object.assign()` instead of the `_extends` helper - // when spreading props. - use_builtins: true, - runtime: if options.jsx_automatic { - Some(react::Runtime::Automatic) - } else { - None - }, - development: options.jsx_development, - import_source: options.jsx_import_source.clone().unwrap_or_default(), - ..Default::default() + let jsx_pass = react::react( + source_map.clone(), + Some(comments), + react::Options { + pragma: options.jsx_factory.clone(), + pragma_frag: options.jsx_fragment_factory.clone(), + // this will use `Object.assign()` instead of the `_extends` helper + // when spreading props. + use_builtins: true, + runtime: if options.jsx_automatic { + Some(react::Runtime::Automatic) + } else { + None }, - top_level_mark, - ), + development: options.jsx_development, + import_source: options.jsx_import_source.clone().unwrap_or_default(), + ..Default::default() + }, + top_level_mark, ); let mut passes = chain!( Optional::new(transforms::DownlevelImportsFolder, options.repl_imports), @@ -427,10 +445,12 @@ fn fold_program( emit_metadata: options.emit_metadata }), helpers::inject_helpers(), + resolver_with_mark(top_level_mark), Optional::new( - typescript::strip::strip_with_config(strip_config_from_emit_options( - options - )), + typescript::strip::strip_with_config( + strip_config_from_emit_options(options), + top_level_mark + ), !options.transform_jsx ), Optional::new( @@ -457,18 +477,32 @@ fn fold_program( }); let diagnostics = diagnostics_cell.borrow(); - if let Some(diagnostic) = diagnostics.iter().find(|d| is_fatal_diagnostic(d)) - { + ensure_no_fatal_swc_diagnostics(&source_map, diagnostics.iter())?; + Ok(result) +} + +fn ensure_no_fatal_swc_diagnostics<'a>( + source_map: &SourceMap, + diagnostics: impl Iterator<Item = &'a SwcDiagnostic>, +) -> Result<(), AnyError> { + let fatal_diagnostics = diagnostics + .filter(|d| is_fatal_swc_diagnostic(d)) + .collect::<Vec<_>>(); + if !fatal_diagnostics.is_empty() { Err(anyhow!( "{}", - format_swc_diagnostic(&source_map, diagnostic) + fatal_diagnostics + .iter() + .map(|d| format_swc_diagnostic(source_map, d)) + .collect::<Vec<_>>() + .join("\n\n") )) } else { - Ok(result) + Ok(()) } } -fn is_fatal_diagnostic(diagnostic: &SwcDiagnostic) -> bool { +fn is_fatal_swc_diagnostic(diagnostic: &SwcDiagnostic) -> bool { use deno_ast::swc::common::errors::Level; match diagnostic.level { Level::Bug @@ -500,6 +534,51 @@ fn format_swc_diagnostic( } } +fn swc_err_to_diagnostic( + source_map: &SourceMap, + specifier: &ModuleSpecifier, + err: SwcError, +) -> Diagnostic { + let location = source_map.lookup_char_pos(err.span().lo); + Diagnostic { + specifier: specifier.to_string(), + span: err.span(), + display_position: LineAndColumnDisplay { + line_number: location.line, + column_number: location.col_display + 1, + }, + kind: err.into_kind(), + } +} + +fn ensure_no_fatal_diagnostics<'a>( + diagnostics: impl Iterator<Item = &'a Diagnostic>, +) -> Result<(), Diagnostics> { + let fatal_diagnostics = diagnostics + .filter(|d| is_fatal_syntax_error(&d.kind)) + .map(ToOwned::to_owned) + .collect::<Vec<_>>(); + if !fatal_diagnostics.is_empty() { + Err(Diagnostics(fatal_diagnostics)) + } else { + Ok(()) + } +} + +fn is_fatal_syntax_error(error_kind: &SyntaxError) -> bool { + matches!( + error_kind, + // expected identifier + SyntaxError::TS1003 | + // expected semi-colon + SyntaxError::TS1005 | + // expected expression + SyntaxError::TS1109 | + // unterminated string literal + SyntaxError::UnterminatedStrLit + ) +} + #[cfg(test)] mod tests { use super::*; @@ -507,28 +586,37 @@ mod tests { use deno_ast::ParseParams; use deno_ast::SourceTextInfo; + use pretty_assertions::assert_eq; + #[test] fn test_transpile() { let specifier = resolve_url_or_path("https://deno.land/x/mod.ts") .expect("could not resolve specifier"); let source = r#" - enum D { - A, - B, - C, - } +enum D { + A, + B, +} - export class A { - private b: string; - protected c: number = 1; - e: "foo"; - constructor (public d = D.A) { - const e = "foo" as const; - this.e = e; - } - } +namespace N { + export enum D { + A = "value" + } + export const Value = 5; +} + +export class A { + private b: string; + protected c: number = 1; + e: "foo"; + constructor (public d = D.A) { + const e = "foo" as const; + this.e = e; + console.log(N.Value); + } +} "#; - let module = parse_module(ParseParams { + let module = deno_ast::parse_module(ParseParams { specifier: specifier.as_str().to_string(), source: SourceTextInfo::from_string(source.to_string()), media_type: deno_ast::MediaType::TypeScript, @@ -536,10 +624,39 @@ mod tests { maybe_syntax: None, scope_analysis: false, }) - .expect("could not parse module"); + .unwrap(); let (code, maybe_map) = transpile(&module, &EmitOptions::default()) .expect("could not strip types"); - assert!(code.starts_with("var D;\n(function(D) {\n")); + let expected_text = r#"var D; +(function(D) { + D[D["A"] = 0] = "A"; + D[D["B"] = 1] = "B"; +})(D || (D = { +})); +var N; +(function(N1) { + let D; + (function(D) { + D["A"] = "value"; + })(D = N1.D || (N1.D = { + })); + N1.Value = 5; +})(N || (N = { +})); +export class A { + d; + b; + c = 1; + e; + constructor(d = D.A){ + this.d = d; + const e = "foo"; + this.e = e; + console.log(N.Value); + } +} +"#; + assert_eq!(&code[..expected_text.len()], expected_text); assert!( code.contains("\n//# sourceMappingURL=data:application/json;base64,") ); diff --git a/cli/http_util.rs b/cli/http_util.rs index c66fa32d3..87ed7d598 100644 --- a/cli/http_util.rs +++ b/cli/http_util.rs @@ -149,7 +149,6 @@ mod tests { use super::*; use crate::version; use deno_runtime::deno_fetch::create_http_client; - use deno_runtime::deno_tls::rustls::RootCertStore; use std::fs::read; fn create_test_client() -> Client { @@ -409,6 +408,8 @@ mod tests { #[cfg(not(windows))] #[tokio::test] async fn test_fetch_with_empty_certificate_store() { + use deno_runtime::deno_tls::rustls::RootCertStore; + let _http_server_guard = test_util::http_server(); // Relies on external http server with a valid mozilla root CA cert. let url = Url::parse("https://deno.land").unwrap(); diff --git a/cli/lsp/code_lens.rs b/cli/lsp/code_lens.rs index 75f46dba8..852f286ab 100644 --- a/cli/lsp/code_lens.rs +++ b/cli/lsp/code_lens.rs @@ -9,7 +9,6 @@ use super::tsc::NavigationTree; use deno_ast::swc::ast; use deno_ast::swc::common::Span; -use deno_ast::swc::visit::Node; use deno_ast::swc::visit::Visit; use deno_ast::swc::visit::VisitWith; use deno_ast::ParsedSource; @@ -129,7 +128,7 @@ impl DenoTestCollector { } impl Visit for DenoTestCollector { - fn visit_call_expr(&mut self, node: &ast::CallExpr, _parent: &dyn Node) { + fn visit_call_expr(&mut self, node: &ast::CallExpr) { if let ast::ExprOrSuper::Expr(callee_expr) = &node.callee { match callee_expr.as_ref() { ast::Expr::Ident(ident) => { @@ -155,7 +154,7 @@ impl Visit for DenoTestCollector { } } - fn visit_var_decl(&mut self, node: &ast::VarDecl, _parent: &dyn Node) { + fn visit_var_decl(&mut self, node: &ast::VarDecl) { for decl in &node.decls { if let Some(init) = &decl.init { match init.as_ref() { @@ -401,12 +400,7 @@ fn collect_test( if let Some(parsed_source) = parsed_source { let mut collector = DenoTestCollector::new(specifier.clone(), parsed_source.clone()); - parsed_source.module().visit_with( - &ast::Invalid { - span: deno_ast::swc::common::DUMMY_SP, - }, - &mut collector, - ); + parsed_source.module().visit_with(&mut collector); return Ok(collector.take()); } } @@ -564,12 +558,7 @@ mod tests { .unwrap(); let mut collector = DenoTestCollector::new(specifier, parsed_module.clone()); - parsed_module.module().visit_with( - &ast::Invalid { - span: deno_ast::swc::common::DUMMY_SP, - }, - &mut collector, - ); + parsed_module.module().visit_with(&mut collector); assert_eq!( collector.take(), vec![ diff --git a/cli/tests/integration/repl_tests.rs b/cli/tests/integration/repl_tests.rs index 3dd5699c6..18e022cfe 100644 --- a/cli/tests/integration/repl_tests.rs +++ b/cli/tests/integration/repl_tests.rs @@ -63,12 +63,14 @@ fn pty_bad_input() { fn pty_syntax_error_input() { util::with_pty(&["repl"], |mut console| { console.write_line("('\\u')"); - console.write_line("('"); + console.write_line("'"); + console.write_line("[{'a'}];"); console.write_line("close();"); let output = console.read_all_output(); + assert!(output.contains("Expected 4 hex characters")); assert!(output.contains("Unterminated string constant")); - assert!(output.contains("Unexpected eof")); + assert!(output.contains("Expected a semicolon")); }); } @@ -267,7 +269,11 @@ fn typescript_declarations() { Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), false, ); - assert!(out.ends_with("undefined\n0\n2\nundefined\nundefined\n")); + let expected_end_text = "undefined\n0\n2\nundefined\nundefined\n"; + assert_eq!( + &out[out.len() - expected_end_text.len()..], + expected_end_text + ); assert!(err.is_empty()); } diff --git a/cli/tests/testdata/bundle.test.out b/cli/tests/testdata/bundle.test.out index 030c09295..6b1c109d3 100644 --- a/cli/tests/testdata/bundle.test.out +++ b/cli/tests/testdata/bundle.test.out @@ -8,20 +8,20 @@ function returnsFoo() { function printHello2() { printHello(); } -function returnsHi1() { +function returnsHi() { return "Hi"; } -function returnsFoo21() { +function returnsFoo2() { return returnsFoo(); } -function printHello31() { +function printHello3() { printHello2(); } -function throwsError1() { +function throwsError() { throw Error("exception from mod1"); } -export { returnsHi1 as returnsHi }; -export { returnsFoo21 as returnsFoo2 }; -export { printHello31 as printHello3 }; -export { throwsError1 as throwsError }; +export { returnsHi as returnsHi }; +export { returnsFoo2 as returnsFoo2 }; +export { printHello3 as printHello3 }; +export { throwsError as throwsError }; diff --git a/cli/tests/testdata/compiler_api_test.ts b/cli/tests/testdata/compiler_api_test.ts index 42d6f54eb..b9755c29a 100644 --- a/cli/tests/testdata/compiler_api_test.ts +++ b/cli/tests/testdata/compiler_api_test.ts @@ -2,8 +2,8 @@ import { assert, assertEquals, + assertRejects, assertStringIncludes, - assertThrowsAsync, } from "../../../test_util/std/testing/asserts.ts"; Deno.test({ @@ -268,7 +268,7 @@ Deno.test({ Object.keys(files).sort(), ["deno:///bundle.js", "deno:///bundle.js.map"].sort(), ); - assert(files["deno:///bundle.js"].includes(`const bar1 = "bar"`)); + assert(files["deno:///bundle.js"].includes(`const bar = "bar"`)); }, }); @@ -312,7 +312,7 @@ Deno.test({ Object.keys(files).sort(), ["deno:///bundle.js.map", "deno:///bundle.js"].sort(), ); - assert(files["deno:///bundle.js"].includes(`const bar1 = "bar"`)); + assert(files["deno:///bundle.js"].includes(`const bar = "bar"`)); }, }); @@ -430,7 +430,7 @@ Deno.test({ Deno.test({ name: `Deno.emit() - throws descriptive error when unable to load import map`, async fn() { - await assertThrowsAsync( + await assertRejects( async () => { await Deno.emit("/a.ts", { bundle: "classic", @@ -566,7 +566,7 @@ Deno.test({ { sources: { "file:///a.tsx": `/** @jsxImportSource https://example.com/jsx */ - + export function App() { return ( <div><></></div> diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index 925ede654..047b477cf 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -1,6 +1,7 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. use crate::ast::transpile; +use crate::ast::Diagnostics; use crate::ast::ImportsNotUsedAsValues; use crate::colors; use crate::proc_state::ProcState; @@ -507,6 +508,16 @@ impl ReplSession { &mut self, line: &str, ) -> Result<EvaluationOutput, AnyError> { + fn format_diagnostic(diagnostic: &deno_ast::Diagnostic) -> String { + format!( + "{}: {} at {}:{}", + colors::red("parse error"), + diagnostic.message(), + diagnostic.display_position.line_number, + diagnostic.display_position.column_number, + ) + } + match self.evaluate_line_with_object_wrapping(line).await { Ok(evaluate_response) => { let evaluate_result = evaluate_response.get("result").unwrap(); @@ -528,14 +539,20 @@ impl ReplSession { Err(err) => { // handle a parsing diagnostic match err.downcast_ref::<deno_ast::Diagnostic>() { - Some(diagnostic) => Ok(EvaluationOutput::Error(format!( - "{}: {} at {}:{}", - colors::red("parse error"), - diagnostic.message(), - diagnostic.display_position.line_number, - diagnostic.display_position.column_number, - ))), - None => Err(err), + Some(diagnostic) => { + Ok(EvaluationOutput::Error(format_diagnostic(diagnostic))) + } + None => match err.downcast_ref::<Diagnostics>() { + Some(diagnostics) => Ok(EvaluationOutput::Error( + diagnostics + .0 + .iter() + .map(format_diagnostic) + .collect::<Vec<_>>() + .join("\n\n"), + )), + None => Err(err), + }, } } } @@ -545,8 +562,8 @@ impl ReplSession { &mut self, line: &str, ) -> Result<Value, AnyError> { - // It is a bit unexpected that { "foo": "bar" } is interpreted as a block - // statement rather than an object literal so we interpret it as an expression statement + // Expressions like { "foo": "bar" } are interpreted as block expressions at the + // statement level rather than an object literal so we interpret it as an expression statement // to match the behavior found in a typical prompt including browser developer tools. let wrapped_line = if line.trim_start().starts_with('{') && !line.trim_end().ends_with(';') @@ -556,20 +573,22 @@ impl ReplSession { line.to_string() }; - let evaluate_response = self.evaluate_ts_expression(&wrapped_line).await?; + let evaluate_response = self.evaluate_ts_expression(&wrapped_line).await; // If that fails, we retry it without wrapping in parens letting the error bubble up to the // user if it is still an error. - let evaluate_response = - if evaluate_response.get("exceptionDetails").is_some() - && wrapped_line != line - { - self.evaluate_ts_expression(line).await? - } else { - evaluate_response - }; - - Ok(evaluate_response) + if wrapped_line != line + && (evaluate_response.is_err() + || evaluate_response + .as_ref() + .unwrap() + .get("exceptionDetails") + .is_some()) + { + self.evaluate_ts_expression(line).await + } else { + evaluate_response + } } async fn set_last_thrown_error( diff --git a/core/Cargo.toml b/core/Cargo.toml index 760ad2ee5..0bc5f103a 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -15,8 +15,7 @@ path = "lib.rs" [dependencies] anyhow = "1.0.43" futures = "0.3.16" -# TODO(lucacasonato): unlock when https://github.com/tkaitchuck/aHash/issues/95 is resolved -indexmap = "=1.6.2" +indexmap = "1.7.0" lazy_static = "1.4.0" libc = "0.2.106" log = "0.4.14" |