summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock148
-rw-r--r--cli/Cargo.toml10
-rw-r--r--cli/ast/bundle_hook.rs51
-rw-r--r--cli/ast/mod.rs919
-rw-r--r--cli/ast/transforms.rs524
-rw-r--r--cli/cache.rs8
-rw-r--r--cli/emit.rs180
-rw-r--r--cli/lsp/cache.rs1
-rw-r--r--cli/lsp/code_lens.rs28
-rw-r--r--cli/main.rs4
-rw-r--r--cli/ops/runtime_compiler.rs1
-rw-r--r--cli/proc_state.rs8
-rw-r--r--cli/tools/doc.rs14
-rw-r--r--cli/tools/repl/session.rs19
-rw-r--r--cli/tools/test.rs25
-rw-r--r--cli/tsc.rs4
16 files changed, 302 insertions, 1642 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6a4a971df..27541d0be 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -352,9 +352,9 @@ checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7"
[[package]]
name = "bumpalo"
-version = "3.8.0"
+version = "3.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
+checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
[[package]]
name = "byteorder"
@@ -543,9 +543,9 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
-version = "0.5.1"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
+checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
@@ -553,9 +553,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
+checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120"
dependencies = [
"cfg-if 1.0.0",
"lazy_static",
@@ -763,10 +763,12 @@ dependencies = [
[[package]]
name = "deno_ast"
-version = "0.8.0"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72a3eb87c6fddf68e02f7438728a611ff6ca84a644fc00d3b9ad5a006e212484"
+checksum = "e81ceec755f9e4e270e8d7ef4ade1921eddc1717dea092c726b088f9c074721b"
dependencies = [
+ "anyhow",
+ "base64 0.13.0",
"data-url",
"dprint-swc-ecma-ast-view",
"serde",
@@ -855,9 +857,9 @@ dependencies = [
[[package]]
name = "deno_doc"
-version = "0.25.0"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3fd524cf36cae45b06de577f8f18b6ef786b56a3840fb721923ccddeeb09833"
+checksum = "73ff82ae22a4012a843799f5baadda95ddc67cc3bed21fe5ebcda2c5cff768a1"
dependencies = [
"cfg-if 1.0.0",
"deno_ast",
@@ -901,9 +903,9 @@ dependencies = [
[[package]]
name = "deno_graph"
-version = "0.17.0"
+version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5eda28d50fc84d2b1774829316dcecdce1d41f0923b3a174f88cd599cafd529"
+checksum = "5b2a21feedd2fde8846a8b94855498ff7e1c59bdf972a06a6faf228999c1f7fd"
dependencies = [
"anyhow",
"cfg-if 1.0.0",
@@ -937,9 +939,9 @@ dependencies = [
[[package]]
name = "deno_lint"
-version = "0.21.0"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90b4b3dfb590568c6cb9ff24d4fb36645b47e480059517420fcb5d19758f75c9"
+checksum = "6cf1715d924e6fdf45847868b31742ed305fb6270747c6046dc3c19f67c0d2f5"
dependencies = [
"anyhow",
"deno_ast",
@@ -1212,9 +1214,9 @@ dependencies = [
[[package]]
name = "dprint-plugin-typescript"
-version = "0.61.0"
+version = "0.62.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2cf0922de1556135f425df4de9968fd0b8e424eebc7fdb4001058c678bde475"
+checksum = "b3e9b87d22638bc08075c827ae568e02b07fbf262142db90895383bac3f5a67e"
dependencies = [
"anyhow",
"deno_ast",
@@ -1226,9 +1228,9 @@ dependencies = [
[[package]]
name = "dprint-swc-ecma-ast-view"
-version = "0.47.0"
+version = "0.48.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbbf1d058db8ad7c9790db7dbe852d0cbddd2a314e592387232fa3db02fe0771"
+checksum = "3d189ada8940380247d23993d0ecf13e8b3b5b3a948dffa6fb7291fbd75cf961"
dependencies = [
"bumpalo",
"num-bigint",
@@ -1498,9 +1500,9 @@ dependencies = [
[[package]]
name = "fsevent-sys"
-version = "4.0.0"
+version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c0e564d24da983c053beff1bb7178e237501206840a3e6bf4e267b9e8ae734a"
+checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [
"libc",
]
@@ -1729,9 +1731,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.3.9"
+version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd"
+checksum = "0c9de88456263e249e241fcd211d3954e2c9b0ef7ccfc235a444eb367cae3689"
dependencies = [
"bytes",
"fnv",
@@ -1918,9 +1920,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "1.7.0"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
+checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
dependencies = [
"autocfg 1.0.1",
"hashbrown",
@@ -1985,9 +1987,9 @@ checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
[[package]]
name = "is-macro"
-version = "0.1.9"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a322dd16d960e322c3d92f541b4c1a4f0a2e81e1fdeee430d8cecc8b72e8015f"
+checksum = "94b2c46692aee0d1b3aad44e781ac0f0e7db42ef27adaa0a877b627040019813"
dependencies = [
"Inflector",
"pmutil",
@@ -2361,9 +2363,9 @@ dependencies = [
[[package]]
name = "netif"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c9e642845c332c335e3125759b10145a972c1f413cb48cd6d7b96e81821f281"
+checksum = "c4c80b95aa77797835fccdc22f4c27458c0b04928cf9ab486e826e1dccf36745"
dependencies = [
"libc",
"winapi 0.3.9",
@@ -2528,9 +2530,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "openssl-probe"
-version = "0.1.4"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "os_pipe"
@@ -3088,9 +3090,9 @@ checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157"
[[package]]
name = "reqwest"
-version = "0.11.8"
+version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c4e0a76dc12a116108933f6301b95e83634e0c47b0afbed6abbaa0601e99258"
+checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525"
dependencies = [
"async-compression",
"base64 0.13.0",
@@ -3098,6 +3100,7 @@ dependencies = [
"encoding_rs",
"futures-core",
"futures-util",
+ "h2",
"http",
"http-body",
"hyper",
@@ -3482,9 +3485,9 @@ dependencies = [
[[package]]
name = "sha2"
-version = "0.9.8"
+version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa"
+checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
dependencies = [
"block-buffer",
"cfg-if 1.0.0",
@@ -3694,9 +3697,9 @@ dependencies = [
[[package]]
name = "swc_bundler"
-version = "0.96.0"
+version = "0.101.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4df8e45a1d523403a5f256fca9ab216bcccbd5883b7aba6f8b5a5c1e69bcd31"
+checksum = "7e4ba80b219e651c3eeb830abc7caa391e55c9ff1fd4370e5723a2cbd752ea93"
dependencies = [
"ahash",
"anyhow",
@@ -3726,9 +3729,9 @@ dependencies = [
[[package]]
name = "swc_common"
-version = "0.16.0"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "757c84b893b4b16bbbe983acc8262f52fe5efd9b87b362f4196549e4f798c0a0"
+checksum = "015b0c14152981b1590d05c6073ac602008e5fc414b7cc4b2bbae60220d27ff2"
dependencies = [
"ahash",
"ast_node",
@@ -3753,9 +3756,9 @@ dependencies = [
[[package]]
name = "swc_ecma_ast"
-version = "0.62.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d00427977875928f37e92e260f226a91783812aaf3713562526a920befd6aa39"
+checksum = "accaa4affdc0e2f3693c9d3b325ad97e9d9534e01abe5564b9b85c5d1cacdcbb"
dependencies = [
"is-macro",
"num-bigint",
@@ -3768,9 +3771,9 @@ dependencies = [
[[package]]
name = "swc_ecma_codegen"
-version = "0.86.0"
+version = "0.89.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "025d9bb2d836fac57bf5579f7049ff96e702632c0affb362234b26d587f996d1"
+checksum = "667e9174226b2228b5ddc850f59db0b2689652efa0b5d5d3c072d1caba256cb7"
dependencies = [
"bitflags",
"memchr",
@@ -3800,9 +3803,9 @@ dependencies = [
[[package]]
name = "swc_ecma_dep_graph"
-version = "0.55.0"
+version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3368bafec3d3dd3f19e2108551b9d6dd1362c515cd138a652aff9f911409316"
+checksum = "bf46c8d3c4b34072e2e958b259781d9a94a00f23806c402eba40b8e9865f9dda"
dependencies = [
"swc_atoms",
"swc_common",
@@ -3812,9 +3815,9 @@ dependencies = [
[[package]]
name = "swc_ecma_loader"
-version = "0.26.0"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61e4a236d9fc809d88e8d346381e72936dc8a4e4a2418d1f66ea8acb6ed298be"
+checksum = "764c8e31524d35722aacdbee51e132424798365ddfd75deb81634f342c5fdce3"
dependencies = [
"ahash",
"anyhow",
@@ -3825,9 +3828,9 @@ dependencies = [
[[package]]
name = "swc_ecma_parser"
-version = "0.84.0"
+version = "0.87.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55406a1e109a7c4ad281ee4fe295249553b7fcbfa43b27f7b53d6112b2924af4"
+checksum = "3c454cbd95ab84fd9ffc5059cffad80b7711bd4b8732257a7c83f4b2c809dfa1"
dependencies = [
"either",
"enum_kind",
@@ -3845,9 +3848,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms"
-version = "0.106.1"
+version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4069c5474cfb5f786fa20dd013ab8b8b73f35522f82372e71c2307a2b904e38"
+checksum = "ae472031803e9fddb9f9141edc3ec0c3bff5904cd08e0509f2ad88689678ce7c"
dependencies = [
"swc_atoms",
"swc_common",
@@ -3864,13 +3867,14 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_base"
-version = "0.52.1"
+version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec358dadefdc2a834a623192bc972df7a74443a80b73a538495ebbf652bfc97d"
+checksum = "74824b2df0931ed3d84201e50138b68d1dc78a802aef9dbdec4ea0ffcea8a28b"
dependencies = [
"once_cell",
"phf",
"scoped-tls",
+ "serde",
"smallvec",
"swc_atoms",
"swc_common",
@@ -3883,9 +3887,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_classes"
-version = "0.39.0"
+version = "0.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19ad7eb4fb019fc608ccff8a2ceffb7548ec94018cc2f523367b137b90b1d6a6"
+checksum = "8a972a157b9104b7979a34556841f93e98d18d70b83c9e625b35dd390b57e59f"
dependencies = [
"swc_atoms",
"swc_common",
@@ -3910,9 +3914,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_optimization"
-version = "0.76.0"
+version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb91bd9aea0f0dd57688340306203ec776ed2fd1e2b75871b7135566c5a4e82a"
+checksum = "3af299ad73dc689a0516950613a9262203feff76adc3f2f14307a12bdd5835c9"
dependencies = [
"ahash",
"dashmap",
@@ -3932,9 +3936,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_proposal"
-version = "0.68.0"
+version = "0.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6520f06130f57292dfd986c0484034f37f6a129699a139010a818e4cd164975"
+checksum = "fe1cf222cfe757700ffea622589990b1b0ef0a18c85ffe6e8442ba515257aa98"
dependencies = [
"either",
"serde",
@@ -3952,9 +3956,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_react"
-version = "0.70.0"
+version = "0.75.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ef966c28b0f13412c546ebd777e61b197b2ef8c9214bee8393f25d0027adfef"
+checksum = "cee01d3f5c0f424a199a4d13fc6fbe14cfd88ccff0b778558311075477e25310"
dependencies = [
"ahash",
"base64 0.13.0",
@@ -3977,9 +3981,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_typescript"
-version = "0.72.0"
+version = "0.77.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ca12da83a3ce8fa61defa77256f11bf63048830d45b2e3a67fb7208d5dfa8b5"
+checksum = "50560b92ecbd43ee4dea19ae763d0bde8d753c8401d76115c714cfb51f838e76"
dependencies = [
"serde",
"swc_atoms",
@@ -3994,9 +3998,9 @@ dependencies = [
[[package]]
name = "swc_ecma_utils"
-version = "0.59.0"
+version = "0.63.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4684e029d1c06cd3ee86e83a3cffb7a90acb421b58204ed72c8e3719bc88eca5"
+checksum = "a05826c1edd7d58ec97af8be523c9c15e24e6dc4c1762435bb12573d716dd7ba"
dependencies = [
"once_cell",
"swc_atoms",
@@ -4008,9 +4012,9 @@ dependencies = [
[[package]]
name = "swc_ecma_visit"
-version = "0.48.1"
+version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "decbd767e2630eb650cd97d49c74e4ce32beb9daeccd9602f52c48f32436006c"
+checksum = "95cf6f39cd1c3682885125955e881bec872e0c1743eb1a31735da69b894f065e"
dependencies = [
"num-bigint",
"swc_atoms",
@@ -4022,9 +4026,9 @@ dependencies = [
[[package]]
name = "swc_ecmascript"
-version = "0.103.2"
+version = "0.108.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c47c72500ac5300ab11d5ede08c9bab878ac065c8a9169d34f2f7f28b1ec19f2"
+checksum = "36c59346416fc6010a59c0fa10f19b8ba9a45bed7199005b7c452b68400fc345"
dependencies = [
"swc_ecma_ast",
"swc_ecma_codegen",
@@ -4049,9 +4053,9 @@ dependencies = [
[[package]]
name = "swc_fast_graph"
-version = "0.3.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4857942a9c79e9836f51dca4ca0df89f354acfedc573708006c4365bad07083c"
+checksum = "1d53bbcbb4b055c547f283af1f84211f425b95ac59e02d8b70c94b8a63a4704f"
dependencies = [
"ahash",
"indexmap",
@@ -4061,9 +4065,9 @@ dependencies = [
[[package]]
name = "swc_graph_analyzer"
-version = "0.3.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5f079d9350dee80a59ac2f8be9867ed0a8ac9fb0023461b173e9e42168ff30"
+checksum = "83b42a8b13068dd90dec954ec44576d5922914687bc34277f3b0f8d0bbeb4e83"
dependencies = [
"ahash",
"auto_impl",
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 66fa281ee..10db61bf7 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -40,11 +40,11 @@ winapi = "=0.3.9"
winres = "=0.1.11"
[dependencies]
-deno_ast = { version = "0.8.0", features = ["bundler", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
+deno_ast = { version = "0.9.0", features = ["bundler", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "transpiling", "typescript", "view", "visit"] }
deno_core = { version = "0.113.0", path = "../core" }
-deno_doc = "0.25.0"
-deno_graph = "0.17.0"
-deno_lint = { version = "0.21.0", features = ["docs"] }
+deno_doc = "0.26.0"
+deno_graph = "0.18.0"
+deno_lint = { version = "0.22.0", features = ["docs"] }
deno_runtime = { version = "0.39.0", path = "../runtime" }
atty = "=0.2.14"
@@ -56,7 +56,7 @@ data-url = "=0.1.1"
dissimilar = "=1.0.2"
dprint-plugin-json = "=0.14.0"
dprint-plugin-markdown = "=0.12.0"
-dprint-plugin-typescript = "=0.61.0"
+dprint-plugin-typescript = "=0.62.0"
encoding_rs = "=0.8.29"
env_logger = "=0.8.4"
fancy-regex = "=0.7.1"
diff --git a/cli/ast/bundle_hook.rs b/cli/ast/bundle_hook.rs
deleted file mode 100644
index a2dd658e3..000000000
--- a/cli/ast/bundle_hook.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-use deno_ast::swc::bundler::Hook;
-use deno_ast::swc::bundler::ModuleRecord;
-use deno_ast::swc::common::Span;
-use deno_core::error::AnyError;
-
-/// This contains the logic for Deno to rewrite the `import.meta` when bundling.
-pub struct BundleHook;
-
-impl Hook for BundleHook {
- fn get_import_meta_props(
- &self,
- span: Span,
- module_record: &ModuleRecord,
- ) -> Result<Vec<deno_ast::swc::ast::KeyValueProp>, AnyError> {
- use deno_ast::swc::ast;
-
- Ok(vec![
- ast::KeyValueProp {
- key: ast::PropName::Ident(ast::Ident::new("url".into(), span)),
- value: Box::new(ast::Expr::Lit(ast::Lit::Str(ast::Str {
- span,
- value: module_record.file_name.to_string().into(),
- kind: ast::StrKind::Synthesized,
- has_escape: false,
- }))),
- },
- ast::KeyValueProp {
- key: ast::PropName::Ident(ast::Ident::new("main".into(), span)),
- value: Box::new(if module_record.is_entry {
- ast::Expr::Member(ast::MemberExpr {
- span,
- obj: ast::ExprOrSuper::Expr(Box::new(ast::Expr::MetaProp(
- ast::MetaPropExpr {
- meta: ast::Ident::new("import".into(), span),
- prop: ast::Ident::new("meta".into(), span),
- },
- ))),
- prop: Box::new(ast::Expr::Ident(ast::Ident::new(
- "main".into(),
- span,
- ))),
- computed: false,
- })
- } else {
- ast::Expr::Lit(ast::Lit::Bool(ast::Bool { span, value: false }))
- }),
- },
- ])
- }
-}
diff --git a/cli/ast/mod.rs b/cli/ast/mod.rs
deleted file mode 100644
index 419471daa..000000000
--- a/cli/ast/mod.rs
+++ /dev/null
@@ -1,919 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-
-use crate::config_file;
-use crate::text_encoding::strip_bom;
-
-use deno_ast::get_syntax;
-use deno_ast::swc::ast::Module;
-use deno_ast::swc::ast::Program;
-use deno_ast::swc::codegen::text_writer::JsWriter;
-use deno_ast::swc::codegen::Node;
-use deno_ast::swc::common::chain;
-use deno_ast::swc::common::comments::SingleThreadedComments;
-use deno_ast::swc::common::errors::Diagnostic as SwcDiagnostic;
-use deno_ast::swc::common::BytePos;
-use deno_ast::swc::common::FileName;
-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;
-use deno_ast::swc::transforms::helpers;
-use deno_ast::swc::transforms::hygiene;
-use deno_ast::swc::transforms::pass::Optional;
-use deno_ast::swc::transforms::proposals;
-use deno_ast::swc::transforms::react;
-use deno_ast::swc::transforms::resolver_with_mark;
-use deno_ast::swc::transforms::typescript;
-use deno_ast::swc::visit::FoldWith;
-use deno_ast::Diagnostic;
-use deno_ast::LineAndColumnDisplay;
-use deno_ast::MediaType;
-use deno_ast::ParsedSource;
-use deno_core::anyhow::anyhow;
-use deno_core::error::AnyError;
-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;
-mod transforms;
-
-pub use bundle_hook::BundleHook;
-
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct Location {
- pub specifier: String,
- pub line: usize,
- pub col: usize,
-}
-
-impl Location {
- pub fn from_pos(parsed_source: &ParsedSource, pos: BytePos) -> Self {
- Location::from_line_and_column(
- parsed_source.specifier().to_string(),
- parsed_source.source().line_and_column_index(pos),
- )
- }
-
- pub fn from_line_and_column(
- specifier: String,
- line_and_column: deno_ast::LineAndColumnIndex,
- ) -> Self {
- Location {
- specifier,
- line: line_and_column.line_index + 1,
- col: line_and_column.column_index,
- }
- }
-}
-
-impl From<deno_ast::swc::common::Loc> for Location {
- fn from(swc_loc: deno_ast::swc::common::Loc) -> Self {
- use deno_ast::swc::common::FileName::*;
-
- let filename = match &swc_loc.file.name {
- Real(path_buf) => path_buf.to_string_lossy().to_string(),
- Custom(str_) => str_.to_string(),
- Url(url) => url.to_string(),
- _ => panic!("invalid filename"),
- };
-
- Location {
- specifier: filename,
- line: swc_loc.line,
- col: swc_loc.col.0,
- }
- }
-}
-
-impl From<Location> for ModuleSpecifier {
- fn from(loc: Location) -> Self {
- resolve_url_or_path(&loc.specifier).unwrap()
- }
-}
-
-impl std::fmt::Display for Location {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- write!(f, "{}:{}:{}", self.specifier, self.line, self.col)
- }
-}
-
-#[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,
- Preserve,
- Error,
-}
-
-/// Options which can be adjusted when transpiling a module.
-#[derive(Debug, Clone)]
-pub struct EmitOptions {
- /// When emitting a legacy decorator, also emit experimental decorator meta
- /// data. Defaults to `false`.
- pub emit_metadata: bool,
- /// What to do with import statements that only import types i.e. whether to
- /// remove them (`Remove`), keep them as side-effect imports (`Preserve`)
- /// or error (`Error`). Defaults to `Remove`.
- pub imports_not_used_as_values: ImportsNotUsedAsValues,
- /// Should the source map be inlined in the emitted code file, or provided
- /// as a separate file. Defaults to `true`.
- pub inline_source_map: bool,
- /// Should the sources be inlined in the source map. Defaults to `true`.
- pub inline_sources: bool,
- /// Should a corresponding .map file be created for the output. This should be
- /// false if inline_source_map is true. Defaults to `false`.
- pub source_map: bool,
- /// `true` if the program should use an implicit JSX import source/the "new"
- /// JSX transforms.
- pub jsx_automatic: bool,
- /// If JSX is automatic, if it is in development mode, meaning that it should
- /// import `jsx-dev-runtime` and transform JSX using `jsxDEV` import from the
- /// JSX import source as well as provide additional debug information to the
- /// JSX factory.
- pub jsx_development: bool,
- /// When transforming JSX, what value should be used for the JSX factory.
- /// Defaults to `React.createElement`.
- pub jsx_factory: String,
- /// When transforming JSX, what value should be used for the JSX fragment
- /// factory. Defaults to `React.Fragment`.
- pub jsx_fragment_factory: String,
- /// The string module specifier to implicitly import JSX factories from when
- /// transpiling JSX.
- pub jsx_import_source: Option<String>,
- /// Should JSX be transformed or preserved. Defaults to `true`.
- pub transform_jsx: bool,
- /// Should import declarations be transformed to variable declarations.
- /// This should only be set to true for the REPL. Defaults to `false`.
- pub repl_imports: bool,
-}
-
-impl Default for EmitOptions {
- fn default() -> Self {
- EmitOptions {
- emit_metadata: false,
- imports_not_used_as_values: ImportsNotUsedAsValues::Remove,
- inline_source_map: true,
- inline_sources: true,
- source_map: false,
- jsx_automatic: false,
- jsx_development: false,
- jsx_factory: "React.createElement".into(),
- jsx_fragment_factory: "React.Fragment".into(),
- jsx_import_source: None,
- transform_jsx: true,
- repl_imports: false,
- }
- }
-}
-
-impl From<config_file::TsConfig> for EmitOptions {
- fn from(config: config_file::TsConfig) -> Self {
- let options: config_file::EmitConfigOptions =
- serde_json::from_value(config.0).unwrap();
- let imports_not_used_as_values =
- match options.imports_not_used_as_values.as_str() {
- "preserve" => ImportsNotUsedAsValues::Preserve,
- "error" => ImportsNotUsedAsValues::Error,
- _ => ImportsNotUsedAsValues::Remove,
- };
- let (transform_jsx, jsx_automatic, jsx_development) =
- match options.jsx.as_str() {
- "react" => (true, false, false),
- "react-jsx" => (true, true, false),
- "react-jsxdev" => (true, true, true),
- _ => (false, false, false),
- };
- EmitOptions {
- emit_metadata: options.emit_decorator_metadata,
- imports_not_used_as_values,
- inline_source_map: options.inline_source_map,
- inline_sources: options.inline_sources,
- source_map: options.source_map,
- jsx_automatic,
- jsx_development,
- jsx_factory: options.jsx_factory,
- jsx_fragment_factory: options.jsx_fragment_factory,
- jsx_import_source: options.jsx_import_source,
- transform_jsx,
- repl_imports: false,
- }
- }
-}
-
-fn strip_config_from_emit_options(
- options: &EmitOptions,
-) -> typescript::strip::Config {
- typescript::strip::Config {
- pragma: Some(options.jsx_factory.clone()),
- pragma_frag: Some(options.jsx_fragment_factory.clone()),
- import_not_used_as_values: match options.imports_not_used_as_values {
- ImportsNotUsedAsValues::Remove => {
- typescript::strip::ImportsNotUsedAsValues::Remove
- }
- ImportsNotUsedAsValues::Preserve => {
- typescript::strip::ImportsNotUsedAsValues::Preserve
- }
- // `Error` only affects the type-checking stage. Fall back to `Remove` here.
- ImportsNotUsedAsValues::Error => {
- typescript::strip::ImportsNotUsedAsValues::Remove
- }
- },
- use_define_for_class_fields: true,
- // TODO(bartlomieju): this could be changed to `false` to provide `export {}`
- // in Typescript files without manual changes
- no_empty_export: true,
- }
-}
-
-/// Implements a configuration trait for source maps that reflects the logic
-/// to embed sources in the source map or not.
-#[derive(Debug)]
-pub(crate) struct SourceMapConfig {
- pub inline_sources: bool,
-}
-
-impl deno_ast::swc::common::source_map::SourceMapGenConfig for SourceMapConfig {
- fn file_name_to_source(&self, f: &FileName) -> String {
- f.to_string()
- }
-
- fn inline_sources_content(&self, f: &FileName) -> bool {
- match f {
- FileName::Real(..) | FileName::Custom(..) => false,
- FileName::Url(..) => self.inline_sources,
- _ => true,
- }
- }
-}
-
-/// Transform a TypeScript file into a JavaScript file, based on the supplied
-/// options.
-///
-/// The result is a tuple of the code and optional source map as strings.
-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 {
- inline_sources: options.inline_sources,
- };
- let specifier = resolve_url_or_path(parsed_source.specifier())?;
- let file_name = FileName::Url(specifier);
- source_map
- .new_source_file(file_name, parsed_source.source().text().to_string());
- let comments = parsed_source.comments().as_single_threaded(); // needs to be mutable
- let globals = Globals::new();
- deno_ast::swc::common::GLOBALS.set(&globals, || {
- let top_level_mark = Mark::fresh(Mark::root());
- let module = fold_program(
- program,
- options,
- source_map.clone(),
- &comments,
- top_level_mark,
- )?;
-
- let mut src_map_buf = vec![];
- let mut buf = vec![];
- {
- let writer = Box::new(JsWriter::new(
- source_map.clone(),
- "\n",
- &mut buf,
- Some(&mut src_map_buf),
- ));
- let config = deno_ast::swc::codegen::Config { minify: false };
- let mut emitter = deno_ast::swc::codegen::Emitter {
- cfg: config,
- comments: Some(&comments),
- cm: source_map.clone(),
- wr: writer,
- };
- module.emit_with(&mut emitter)?;
- }
- let mut src = String::from_utf8(buf)?;
- let mut map: Option<String> = None;
- {
- let mut buf = Vec::new();
- source_map
- .build_source_map_with_config(&mut src_map_buf, None, source_map_config)
- .to_writer(&mut buf)?;
-
- if options.inline_source_map {
- src.push_str("//# sourceMappingURL=data:application/json;base64,");
- let encoded_map = base64::encode(buf);
- src.push_str(&encoded_map);
- } else {
- map = Some(String::from_utf8(buf)?);
- }
- }
- Ok((src, map))
- })
-}
-
-/// A low level function which transpiles a source module into an swc
-/// SourceFile.
-pub fn transpile_module(
- specifier: &ModuleSpecifier,
- source: &str,
- media_type: MediaType,
- options: &EmitOptions,
- cm: Rc<SourceMap>,
-) -> Result<(Rc<deno_ast::swc::common::SourceFile>, Module), AnyError> {
- let source = strip_bom(source);
- let source = if media_type == MediaType::Json {
- format!(
- "export default JSON.parse(`{}`);",
- source.replace("${", "\\${").replace('`', "\\`")
- )
- } else {
- source.to_string()
- };
- let source_file =
- cm.new_source_file(FileName::Url(specifier.clone()), source);
- let input = StringInput::from(&*source_file);
- let comments = SingleThreadedComments::default();
- let syntax = if media_type == MediaType::Json {
- get_syntax(MediaType::JavaScript)
- } else {
- get_syntax(media_type)
- };
- 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(|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(
- Program::Module(module),
- options,
- cm,
- &comments,
- top_level_mark,
- )?;
- let module = match program {
- Program::Module(module) => module,
- _ => unreachable!(),
- };
-
- Ok((source_file, module))
-}
-
-#[derive(Default, Clone)]
-struct DiagnosticCollector {
- diagnostics_cell: Rc<RefCell<Vec<SwcDiagnostic>>>,
-}
-
-impl DiagnosticCollector {
- pub fn into_handler(self) -> deno_ast::swc::common::errors::Handler {
- deno_ast::swc::common::errors::Handler::with_emitter(
- true,
- false,
- Box::new(self),
- )
- }
-}
-
-impl deno_ast::swc::common::errors::Emitter for DiagnosticCollector {
- fn emit(
- &mut self,
- db: &deno_ast::swc::common::errors::DiagnosticBuilder<'_>,
- ) {
- use std::ops::Deref;
- self.diagnostics_cell.borrow_mut().push(db.deref().clone());
- }
-}
-
-fn fold_program(
- program: Program,
- options: &EmitOptions,
- source_map: Rc<SourceMap>,
- comments: &SingleThreadedComments,
- top_level_mark: Mark,
-) -> Result<Program, AnyError> {
- 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
- },
- 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),
- Optional::new(transforms::StripExportsFolder, options.repl_imports),
- proposals::decorators::decorators(proposals::decorators::Config {
- legacy: true,
- 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),
- top_level_mark
- ),
- !options.transform_jsx
- ),
- Optional::new(
- typescript::strip::strip_with_jsx(
- source_map.clone(),
- strip_config_from_emit_options(options),
- comments,
- top_level_mark
- ),
- options.transform_jsx
- ),
- Optional::new(jsx_pass, options.transform_jsx),
- fixer(Some(comments)),
- hygiene(),
- );
-
- let emitter = DiagnosticCollector::default();
- let diagnostics_cell = emitter.diagnostics_cell.clone();
- let handler = emitter.into_handler();
- let result = deno_ast::swc::utils::HANDLER.set(&handler, || {
- helpers::HELPERS.set(&helpers::Helpers::new(false), || {
- program.fold_with(&mut passes)
- })
- });
-
- let diagnostics = diagnostics_cell.borrow();
- 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!(
- "{}",
- fatal_diagnostics
- .iter()
- .map(|d| format_swc_diagnostic(source_map, d))
- .collect::<Vec<_>>()
- .join("\n\n")
- ))
- } else {
- Ok(())
- }
-}
-
-fn is_fatal_swc_diagnostic(diagnostic: &SwcDiagnostic) -> bool {
- use deno_ast::swc::common::errors::Level;
- match diagnostic.level {
- Level::Bug
- | Level::Cancelled
- | Level::FailureNote
- | Level::Fatal
- | Level::PhaseFatal
- | Level::Error => true,
- Level::Help | Level::Note | Level::Warning => false,
- }
-}
-
-fn format_swc_diagnostic(
- source_map: &SourceMap,
- diagnostic: &SwcDiagnostic,
-) -> String {
- if let Some(span) = &diagnostic.span.primary_span() {
- let file_name = source_map.span_to_filename(*span);
- let loc = source_map.lookup_char_pos(span.lo);
- format!(
- "{} at {}:{}:{}",
- diagnostic.message(),
- file_name.to_string(),
- loc.line,
- loc.col_display + 1,
- )
- } else {
- diagnostic.message()
- }
-}
-
-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::*;
- use deno_ast::parse_module;
- 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").unwrap();
- let source = r#"
-enum D {
- A,
- B,
-}
-
-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 = deno_ast::parse_module(ParseParams {
- specifier: specifier.as_str().to_string(),
- source: SourceTextInfo::from_string(source.to_string()),
- media_type: deno_ast::MediaType::TypeScript,
- capture_tokens: false,
- maybe_syntax: None,
- scope_analysis: false,
- })
- .unwrap();
- let (code, maybe_map) =
- transpile(&module, &EmitOptions::default()).unwrap();
- 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 = {}));
- var Value = 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,")
- );
- assert!(maybe_map.is_none());
- }
-
- #[test]
- fn test_transpile_tsx() {
- let specifier = resolve_url_or_path("https://deno.land/x/mod.ts").unwrap();
- let source = r#"
- export class A {
- render() {
- return <div><span></span></div>
- }
- }
- "#;
- let module = parse_module(ParseParams {
- specifier: specifier.as_str().to_string(),
- source: SourceTextInfo::from_string(source.to_string()),
- media_type: deno_ast::MediaType::Tsx,
- capture_tokens: false,
- maybe_syntax: None,
- scope_analysis: true, // ensure scope analysis doesn't conflict with a second resolver pass
- })
- .unwrap();
- let (code, _) = transpile(&module, &EmitOptions::default()).unwrap();
- assert!(code.contains("React.createElement(\"div\", null"));
- }
-
- #[test]
- fn test_transpile_jsx_pragma() {
- let specifier = resolve_url_or_path("https://deno.land/x/mod.ts").unwrap();
- let source = r#"
-/** @jsx h */
-/** @jsxFrag Fragment */
-import { h, Fragment } from "https://deno.land/x/mod.ts";
-
-function App() {
- return (
- <div><></></div>
- );
-}"#;
- let module = parse_module(ParseParams {
- specifier: specifier.as_str().to_string(),
- source: SourceTextInfo::from_string(source.to_string()),
- media_type: deno_ast::MediaType::Jsx,
- capture_tokens: false,
- maybe_syntax: None,
- scope_analysis: true,
- })
- .unwrap();
- let (code, _) = transpile(&module, &EmitOptions::default()).unwrap();
- let expected = r#"/** @jsx h */ /** @jsxFrag Fragment */ import { h, Fragment } from "https://deno.land/x/mod.ts";
-function App() {
- return(/*#__PURE__*/ h("div", null, /*#__PURE__*/ h(Fragment, null)));
-}"#;
- assert_eq!(&code[..expected.len()], expected);
- }
-
- #[test]
- fn test_transpile_jsx_import_source_pragma() {
- let specifier = resolve_url_or_path("https://deno.land/x/mod.tsx").unwrap();
- let source = r#"
-/** @jsxImportSource jsx_lib */
-
-function App() {
- return (
- <div><></></div>
- );
-}"#;
- let module = parse_module(ParseParams {
- specifier: specifier.as_str().to_string(),
- source: SourceTextInfo::from_string(source.to_string()),
- media_type: deno_ast::MediaType::Jsx,
- capture_tokens: false,
- maybe_syntax: None,
- scope_analysis: true,
- })
- .unwrap();
- let (code, _) = transpile(&module, &EmitOptions::default()).unwrap();
- let expected = r#"import { jsx as _jsx, Fragment as _Fragment } from "jsx_lib/jsx-runtime";
-/** @jsxImportSource jsx_lib */ function App() {
- return(/*#__PURE__*/ _jsx("div", {
- children: /*#__PURE__*/ _jsx(_Fragment, {})
- }));
-"#;
- assert_eq!(&code[..expected.len()], expected);
- }
-
- #[test]
- fn test_transpile_jsx_import_source_no_pragma() {
- let specifier = resolve_url_or_path("https://deno.land/x/mod.tsx").unwrap();
- let source = r#"
-function App() {
- return (
- <div><></></div>
- );
-}"#;
- let module = parse_module(ParseParams {
- specifier: specifier.as_str().to_string(),
- source: SourceTextInfo::from_string(source.to_string()),
- media_type: deno_ast::MediaType::Jsx,
- capture_tokens: false,
- maybe_syntax: None,
- scope_analysis: true,
- })
- .unwrap();
- let emit_options = EmitOptions {
- jsx_automatic: true,
- jsx_import_source: Some("jsx_lib".to_string()),
- ..Default::default()
- };
- let (code, _) = transpile(&module, &emit_options).unwrap();
- let expected = r#"import { jsx as _jsx, Fragment as _Fragment } from "jsx_lib/jsx-runtime";
-function App() {
- return(/*#__PURE__*/ _jsx("div", {
- children: /*#__PURE__*/ _jsx(_Fragment, {})
- }));
-}
-"#;
- assert_eq!(&code[..expected.len()], expected);
- }
-
- // TODO(@kitsonk) https://github.com/swc-project/swc/issues/2656
- // #[test]
- // fn test_transpile_jsx_import_source_no_pragma_dev() {
- // let specifier = resolve_url_or_path("https://deno.land/x/mod.tsx").unwrap();
- // let source = r#"
- // function App() {
- // return (
- // <div><></></div>
- // );
- // }"#;
- // let module = parse_module(ParseParams {
- // specifier: specifier.as_str().to_string(),
- // source: SourceTextInfo::from_string(source.to_string()),
- // media_type: deno_ast::MediaType::Jsx,
- // capture_tokens: false,
- // maybe_syntax: None,
- // scope_analysis: true,
- // })
- // .unwrap();
- // let emit_options = EmitOptions {
- // jsx_automatic: true,
- // jsx_import_source: Some("jsx_lib".to_string()),
- // jsx_development: true,
- // ..Default::default()
- // };
- // let (code, _) = transpile(&module, &emit_options).unwrap();
- // let expected = r#"import { jsx as _jsx, Fragment as _Fragment } from "jsx_lib/jsx-dev-runtime";
- // function App() {
- // return(/*#__PURE__*/ _jsx("div", {
- // children: /*#__PURE__*/ _jsx(_Fragment, {
- // })
- // }));
- // }
- // "#;
- // assert_eq!(&code[..expected.len()], expected);
- // }
-
- #[test]
- fn test_transpile_decorators() {
- let specifier = resolve_url_or_path("https://deno.land/x/mod.ts").unwrap();
- let source = r#"
- function enumerable(value: boolean) {
- return function (
- _target: any,
- _propertyKey: string,
- descriptor: PropertyDescriptor,
- ) {
- descriptor.enumerable = value;
- };
- }
-
- export class A {
- @enumerable(false)
- a() {
- Test.value;
- }
- }
- "#;
- let module = parse_module(ParseParams {
- specifier: specifier.as_str().to_string(),
- source: SourceTextInfo::from_string(source.to_string()),
- media_type: deno_ast::MediaType::TypeScript,
- capture_tokens: false,
- maybe_syntax: None,
- scope_analysis: false,
- })
- .unwrap();
- let (code, _) = transpile(&module, &EmitOptions::default()).unwrap();
- assert!(code.contains("_applyDecoratedDescriptor("));
- }
-
- #[test]
- fn transpile_handle_code_nested_in_ts_nodes_with_jsx_pass() {
- // from issue 12409
- let specifier = resolve_url_or_path("https://deno.land/x/mod.ts").unwrap();
- let source = r#"
-export function g() {
- let algorithm: any
- algorithm = {}
-
- return <Promise>(
- test(algorithm, false, keyUsages)
- )
-}
- "#;
- let module = parse_module(ParseParams {
- specifier: specifier.as_str().to_string(),
- source: SourceTextInfo::from_string(source.to_string()),
- media_type: deno_ast::MediaType::TypeScript,
- capture_tokens: false,
- maybe_syntax: None,
- scope_analysis: false,
- })
- .unwrap();
- let emit_options = EmitOptions {
- transform_jsx: true,
- ..Default::default()
- };
- let (code, _) = transpile(&module, &emit_options).unwrap();
- let expected = r#"export function g() {
- let algorithm;
- algorithm = {};
- return test(algorithm, false, keyUsages);
-}"#;
- assert_eq!(&code[..expected.len()], expected);
- }
-
- #[test]
- fn diagnostic_jsx_spread_instead_of_panic() {
- let specifier = resolve_url_or_path("https://deno.land/x/mod.ts").unwrap();
- let source = r#"const A = () => {
- return <div>{...[]}</div>;
-};"#;
- let parsed_source = parse_module(ParseParams {
- specifier: specifier.as_str().to_string(),
- source: SourceTextInfo::from_string(source.to_string()),
- media_type: deno_ast::MediaType::Tsx,
- capture_tokens: false,
- maybe_syntax: None,
- scope_analysis: false,
- })
- .unwrap();
- let err = transpile(&parsed_source, &Default::default())
- .err()
- .unwrap();
-
- assert_eq!(err.to_string(), "Spread children are not supported in React. at https://deno.land/x/mod.ts:2:15");
- }
-}
diff --git a/cli/ast/transforms.rs b/cli/ast/transforms.rs
deleted file mode 100644
index a89edc01d..000000000
--- a/cli/ast/transforms.rs
+++ /dev/null
@@ -1,524 +0,0 @@
-use deno_ast::swc::ast as swc_ast;
-use deno_ast::swc::common::DUMMY_SP;
-use deno_ast::swc::visit::noop_fold_type;
-use deno_ast::swc::visit::Fold;
-
-/// Transforms import declarations to variable declarations
-/// with a dynamic import. This is used to provide import
-/// declaration support in the REPL.
-pub struct DownlevelImportsFolder;
-
-impl Fold for DownlevelImportsFolder {
- noop_fold_type!(); // skip typescript specific nodes
-
- fn fold_module_item(
- &mut self,
- module_item: swc_ast::ModuleItem,
- ) -> swc_ast::ModuleItem {
- use deno_ast::swc::ast::*;
-
- match module_item {
- ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) => {
- // Handle type only imports
- if import_decl.type_only {
- // should have no side effects
- return create_empty_stmt();
- }
-
- // The initializer (ex. `await import('./mod.ts')`)
- let initializer =
- create_await_import_expr(&import_decl.src.value, import_decl.asserts);
-
- // Handle imports for the side effects
- // ex. `import "module.ts"` -> `await import("module.ts");`
- if import_decl.specifiers.is_empty() {
- return ModuleItem::Stmt(Stmt::Expr(ExprStmt {
- span: DUMMY_SP,
- expr: initializer,
- }));
- }
-
- // Collect the specifiers and create the variable statement
- let named_import_props = import_decl
- .specifiers
- .iter()
- .filter_map(|specifier| match specifier {
- ImportSpecifier::Default(specifier) => Some(create_key_value(
- "default".to_string(),
- specifier.local.sym.to_string(),
- )),
- ImportSpecifier::Named(specifier) => {
- Some(match specifier.imported.as_ref() {
- Some(name) => create_key_value(
- match name {
- ModuleExportName::Ident(ident) => ident.sym.to_string(),
- ModuleExportName::Str(str) => str.value.to_string(),
- },
- specifier.local.sym.to_string(),
- ),
- None => create_assignment(specifier.local.sym.to_string()),
- })
- }
- ImportSpecifier::Namespace(_) => None,
- })
- .collect::<Vec<_>>();
- let namespace_import_name =
- import_decl
- .specifiers
- .iter()
- .find_map(|specifier| match specifier {
- ImportSpecifier::Namespace(specifier) => {
- Some(create_binding_ident(specifier.local.sym.to_string()))
- }
- _ => None,
- });
-
- ModuleItem::Stmt(Stmt::Decl(Decl::Var(VarDecl {
- span: DUMMY_SP,
- kind: VarDeclKind::Const,
- declare: false,
- decls: {
- let mut decls = Vec::new();
-
- if !named_import_props.is_empty() {
- decls.push(VarDeclarator {
- span: DUMMY_SP,
- name: Pat::Object(ObjectPat {
- span: DUMMY_SP,
- optional: false,
- props: named_import_props,
- type_ann: None,
- }),
- definite: false,
- init: Some(initializer.clone()),
- });
- }
- if let Some(namespace_import) = namespace_import_name {
- decls.push(VarDeclarator {
- span: DUMMY_SP,
- name: Pat::Ident(namespace_import),
- definite: false,
- init: Some(initializer),
- });
- }
-
- decls
- },
- })))
- }
- _ => module_item,
- }
- }
-}
-
-/// Strips export declarations and exports on named exports for the REPL.
-pub struct StripExportsFolder;
-
-impl Fold for StripExportsFolder {
- noop_fold_type!(); // skip typescript specific nodes
-
- fn fold_module_item(
- &mut self,
- module_item: swc_ast::ModuleItem,
- ) -> swc_ast::ModuleItem {
- use deno_ast::swc::ast::*;
-
- match module_item {
- ModuleItem::ModuleDecl(ModuleDecl::ExportAll(export_all)) => {
- ModuleItem::Stmt(Stmt::Expr(ExprStmt {
- span: DUMMY_SP,
- expr: create_await_import_expr(
- &export_all.src.value,
- export_all.asserts,
- ),
- }))
- }
- ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(export_named)) => {
- if let Some(src) = export_named.src {
- ModuleItem::Stmt(Stmt::Expr(ExprStmt {
- span: DUMMY_SP,
- expr: create_await_import_expr(&src.value, export_named.asserts),
- }))
- } else {
- create_empty_stmt()
- }
- }
- ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(default_expr)) => {
- // transform a default export expression to its expression
- ModuleItem::Stmt(Stmt::Expr(ExprStmt {
- span: DUMMY_SP,
- expr: default_expr.expr,
- }))
- }
- ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(export_decl)) => {
- // strip the export keyword on an exported declaration
- ModuleItem::Stmt(Stmt::Decl(export_decl.decl))
- }
- ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(default_decl)) => {
- // only keep named default exports
- match default_decl.decl {
- DefaultDecl::Fn(FnExpr {
- ident: Some(ident),
- function,
- }) => ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl {
- declare: false,
- ident,
- function,
- }))),
- DefaultDecl::Class(ClassExpr {
- ident: Some(ident),
- class,
- }) => ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl {
- declare: false,
- ident,
- class,
- }))),
- _ => create_empty_stmt(),
- }
- }
- _ => module_item,
- }
- }
-}
-
-fn create_empty_stmt() -> swc_ast::ModuleItem {
- use swc_ast::*;
- ModuleItem::Stmt(Stmt::Empty(EmptyStmt { span: DUMMY_SP }))
-}
-
-fn create_binding_ident(name: String) -> swc_ast::BindingIdent {
- swc_ast::BindingIdent {
- id: create_ident(name),
- type_ann: None,
- }
-}
-
-fn create_ident(name: String) -> swc_ast::Ident {
- swc_ast::Ident {
- span: DUMMY_SP,
- sym: name.into(),
- optional: false,
- }
-}
-
-fn create_key_value(key: String, value: String) -> swc_ast::ObjectPatProp {
- swc_ast::ObjectPatProp::KeyValue(swc_ast::KeyValuePatProp {
- // use a string literal because it will work in more scenarios than an identifier
- key: swc_ast::PropName::Str(swc_ast::Str {
- span: DUMMY_SP,
- value: key.into(),
- has_escape: false,
- kind: swc_ast::StrKind::Synthesized,
- }),
- value: Box::new(swc_ast::Pat::Ident(swc_ast::BindingIdent {
- id: swc_ast::Ident {
- span: DUMMY_SP,
- sym: value.into(),
- optional: false,
- },
- type_ann: None,
- })),
- })
-}
-
-fn create_await_import_expr(
- module_specifier: &str,
- maybe_asserts: Option<swc_ast::ObjectLit>,
-) -> Box<swc_ast::Expr> {
- use swc_ast::*;
- let mut args = vec![ExprOrSpread {
- spread: None,
- expr: Box::new(Expr::Lit(Lit::Str(Str {
- span: DUMMY_SP,
- has_escape: false,
- kind: StrKind::Normal {
- contains_quote: false,
- },
- value: module_specifier.into(),
- }))),
- }];
-
- // add assert object if it exists
- if let Some(asserts) = maybe_asserts {
- args.push(ExprOrSpread {
- spread: None,
- expr: Box::new(Expr::Object(ObjectLit {
- span: DUMMY_SP,
- props: vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(
- KeyValueProp {
- key: PropName::Ident(create_ident("assert".to_string())),
- value: Box::new(Expr::Object(asserts)),
- },
- )))],
- })),
- })
- }
-
- Box::new(Expr::Await(AwaitExpr {
- span: DUMMY_SP,
- arg: Box::new(Expr::Call(CallExpr {
- span: DUMMY_SP,
- callee: ExprOrSuper::Expr(Box::new(Expr::Ident(Ident {
- span: DUMMY_SP,
- sym: "import".into(),
- optional: false,
- }))),
- args,
- type_args: None,
- })),
- }))
-}
-
-fn create_assignment(key: String) -> swc_ast::ObjectPatProp {
- swc_ast::ObjectPatProp::Assign(swc_ast::AssignPatProp {
- span: DUMMY_SP,
- key: create_ident(key),
- value: None,
- })
-}
-
-#[cfg(test)]
-mod test {
- use deno_ast::swc::ast::Module;
- use deno_ast::swc::codegen::text_writer::JsWriter;
- use deno_ast::swc::codegen::Node;
- use deno_ast::swc::common::FileName;
- use deno_ast::swc::common::SourceMap;
- use deno_ast::swc::parser::Parser;
- use deno_ast::swc::parser::StringInput;
- use deno_ast::swc::parser::Syntax;
- use deno_ast::swc::parser::TsConfig;
- use deno_ast::swc::visit::Fold;
- use deno_ast::swc::visit::FoldWith;
- use deno_ast::ModuleSpecifier;
- use pretty_assertions::assert_eq;
- use std::rc::Rc;
-
- use super::*;
-
- #[test]
- fn test_downlevel_imports_type_only() {
- test_transform(
- DownlevelImportsFolder,
- r#"import type { test } from "./mod.ts";"#,
- ";",
- );
- }
-
- #[test]
- fn test_downlevel_imports_specifier_only() {
- test_transform(
- DownlevelImportsFolder,
- r#"import "./mod.ts";"#,
- r#"await import("./mod.ts");"#,
- );
-
- test_transform(
- DownlevelImportsFolder,
- r#"import {} from "./mod.ts";"#,
- r#"await import("./mod.ts");"#,
- );
- }
-
- #[test]
- fn test_downlevel_imports_default() {
- test_transform(
- DownlevelImportsFolder,
- r#"import mod from "./mod.ts";"#,
- r#"const { "default": mod } = await import("./mod.ts");"#,
- );
- }
-
- #[test]
- fn test_downlevel_imports_named() {
- test_transform(
- DownlevelImportsFolder,
- r#"import { A } from "./mod.ts";"#,
- r#"const { A } = await import("./mod.ts");"#,
- );
-
- test_transform(
- DownlevelImportsFolder,
- r#"import { A, B, C } from "./mod.ts";"#,
- r#"const { A , B , C } = await import("./mod.ts");"#,
- );
-
- test_transform(
- DownlevelImportsFolder,
- r#"import { A as LocalA, B, C as LocalC } from "./mod.ts";"#,
- r#"const { "A": LocalA , B , "C": LocalC } = await import("./mod.ts");"#,
- );
- }
-
- #[test]
- fn test_downlevel_imports_namespace() {
- test_transform(
- DownlevelImportsFolder,
- r#"import * as mod from "./mod.ts";"#,
- r#"const mod = await import("./mod.ts");"#,
- );
- }
-
- #[test]
- fn test_downlevel_imports_mixed() {
- test_transform(
- DownlevelImportsFolder,
- r#"import myDefault, { A, B as LocalB } from "./mod.ts";"#,
- r#"const { "default": myDefault , A , "B": LocalB } = await import("./mod.ts");"#,
- );
-
- test_transform(
- DownlevelImportsFolder,
- r#"import myDefault, * as mod from "./mod.ts";"#,
- r#"const { "default": myDefault } = await import("./mod.ts"), mod = await import("./mod.ts");"#,
- );
- }
-
- #[test]
- fn test_downlevel_imports_assertions() {
- test_transform(
- DownlevelImportsFolder,
- r#"import data from "./mod.json" assert { type: "json" };"#,
- "const { \"default\": data } = await import(\"./mod.json\", {\n assert: {\n type: \"json\"\n }\n});",
- );
- }
-
- #[test]
- fn test_strip_exports_export_all() {
- test_transform(
- StripExportsFolder,
- r#"export * from "./test.ts";"#,
- r#"await import("./test.ts");"#,
- );
- }
-
- #[test]
- fn test_strip_exports_export_named() {
- test_transform(
- StripExportsFolder,
- r#"export { test } from "./test.ts";"#,
- r#"await import("./test.ts");"#,
- );
-
- test_transform(StripExportsFolder, r#"export { test };"#, ";");
- }
-
- #[test]
- fn test_strip_exports_assertions() {
- test_transform(
- StripExportsFolder,
- r#"export { default as data } from "./mod.json" assert { type: "json" };"#,
- "await import(\"./mod.json\", {\n assert: {\n type: \"json\"\n }\n});",
- );
- }
-
- #[test]
- fn test_strip_exports_export_all_assertions() {
- // even though this doesn't really make sense for someone to do
- test_transform(
- StripExportsFolder,
- r#"export * from "./mod.json" assert { type: "json" };"#,
- "await import(\"./mod.json\", {\n assert: {\n type: \"json\"\n }\n});",
- );
- }
-
- #[test]
- fn test_strip_exports_export_default_expr() {
- test_transform(StripExportsFolder, "export default 5;", "5;");
- }
-
- #[test]
- fn test_strip_exports_export_default_decl_name() {
- test_transform(
- StripExportsFolder,
- "export default class Test {}",
- "class Test {\n}",
- );
-
- test_transform(
- StripExportsFolder,
- "export default function test() {}",
- "function test() {}",
- );
- }
-
- #[test]
- fn test_strip_exports_export_default_decl_no_name() {
- test_transform(StripExportsFolder, "export default class {}", ";");
-
- test_transform(StripExportsFolder, "export default function() {}", ";");
- }
-
- #[test]
- fn test_strip_exports_export_named_decls() {
- test_transform(
- StripExportsFolder,
- "export class Test {}",
- "class Test {\n}",
- );
-
- test_transform(
- StripExportsFolder,
- "export function test() {}",
- "function test() {}",
- );
-
- test_transform(StripExportsFolder, "export enum Test {}", "enum Test {\n}");
-
- test_transform(
- StripExportsFolder,
- "export namespace Test {}",
- "module Test {\n}",
- );
- }
-
- #[test]
- fn test_strip_exports_not_in_namespace() {
- test_transform(
- StripExportsFolder,
- "namespace Test { export class Test {} }",
- "module Test {\n export class Test {\n }\n}",
- );
- }
-
- fn test_transform(
- mut transform: impl Fold,
- src: &str,
- expected_output: &str,
- ) {
- let (source_map, module) = parse(src);
- let output = print(source_map, module.fold_with(&mut transform));
- assert_eq!(output, format!("{}\n", expected_output));
- }
-
- fn parse(src: &str) -> (Rc<SourceMap>, Module) {
- let source_map = Rc::new(SourceMap::default());
- let source_file = source_map.new_source_file(
- FileName::Url(ModuleSpecifier::parse("file:///test.ts").unwrap()),
- src.to_string(),
- );
- let input = StringInput::from(&*source_file);
- let syntax = Syntax::Typescript(TsConfig {
- ..Default::default()
- });
- let mut parser = Parser::new(syntax, input, None);
- (source_map, parser.parse_module().unwrap())
- }
-
- fn print(source_map: Rc<SourceMap>, module: Module) -> String {
- let mut buf = vec![];
- {
- let writer =
- Box::new(JsWriter::new(source_map.clone(), "\n", &mut buf, None));
- let config = deno_ast::swc::codegen::Config { minify: false };
- let mut emitter = deno_ast::swc::codegen::Emitter {
- cfg: config,
- comments: None,
- cm: source_map,
- wr: writer,
- };
- module.emit_with(&mut emitter).unwrap();
- }
- String::from_utf8(buf).unwrap()
- }
-}
diff --git a/cli/cache.rs b/cli/cache.rs
index 218c699a1..1075230d1 100644
--- a/cli/cache.rs
+++ b/cli/cache.rs
@@ -149,7 +149,7 @@ impl Loader for FetchCacher {
let file_fetcher = self.file_fetcher.clone();
async move {
- let load_result = file_fetcher
+ file_fetcher
.fetch(&specifier, &mut permissions)
.await
.map_or_else(
@@ -170,9 +170,7 @@ impl Loader for FetchCacher {
content: file.source,
}))
},
- );
-
- (specifier, load_result)
+ )
}
.boxed()
}
@@ -295,7 +293,7 @@ impl Loader for MemoryCacher {
maybe_headers: None,
content: c.to_owned(),
});
- Box::pin(future::ready((specifier.clone(), Ok(response))))
+ Box::pin(future::ready(Ok(response)))
}
}
diff --git a/cli/emit.rs b/cli/emit.rs
index 35d6f1110..e21013b61 100644
--- a/cli/emit.rs
+++ b/cli/emit.rs
@@ -4,10 +4,10 @@
//! populate a cache, emit files, and transform a graph into the structures for
//! loading into an isolate.
-use crate::ast;
use crate::cache::CacheType;
use crate::cache::Cacher;
use crate::colors;
+use crate::config_file;
use crate::config_file::ConfigFile;
use crate::config_file::IgnoredCompilerOptions;
use crate::config_file::TsConfig;
@@ -15,10 +15,25 @@ use crate::diagnostics::Diagnostics;
use crate::flags;
use crate::graph_util::GraphData;
use crate::graph_util::ModuleEntry;
+use crate::text_encoding::strip_bom;
use crate::tsc;
use crate::version;
+use deno_ast::get_syntax;
use deno_ast::swc;
+use deno_ast::swc::bundler::Hook;
+use deno_ast::swc::bundler::ModuleRecord;
+use deno_ast::swc::common::comments::SingleThreadedComments;
+use deno_ast::swc::common::FileName;
+use deno_ast::swc::common::Mark;
+use deno_ast::swc::common::SourceMap;
+use deno_ast::swc::common::Span;
+use deno_ast::swc::common::Spanned;
+use deno_ast::swc::parser::error::Error as SwcError;
+use deno_ast::swc::parser::lexer::Lexer;
+use deno_ast::swc::parser::StringInput;
+use deno_ast::Diagnostic;
+use deno_ast::LineAndColumnDisplay;
use deno_core::anyhow::anyhow;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
@@ -27,6 +42,7 @@ use deno_core::serde::Deserialize;
use deno_core::serde::Deserializer;
use deno_core::serde::Serialize;
use deno_core::serde::Serializer;
+use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use deno_core::ModuleSpecifier;
@@ -517,7 +533,7 @@ pub(crate) struct BundleOptions {
/// of modules from the graph.
struct BundleLoader<'a> {
cm: Rc<swc::common::SourceMap>,
- emit_options: &'a ast::EmitOptions,
+ emit_options: &'a deno_ast::EmitOptions,
graph: &'a ModuleGraph,
}
@@ -529,7 +545,7 @@ impl swc::bundler::Load for BundleLoader<'_> {
match file_name {
swc::common::FileName::Url(specifier) => {
if let Some(m) = self.graph.get(specifier) {
- let (fm, module) = ast::transpile_module(
+ let (fm, module) = transpile_module(
specifier,
m.maybe_source().unwrap_or(""),
*m.media_type(),
@@ -556,6 +572,77 @@ impl swc::bundler::Load for BundleLoader<'_> {
}
}
+/// Transpiles a source module into an swc SourceFile.
+fn transpile_module(
+ specifier: &ModuleSpecifier,
+ source: &str,
+ media_type: MediaType,
+ options: &deno_ast::EmitOptions,
+ cm: Rc<swc::common::SourceMap>,
+) -> Result<(Rc<swc::common::SourceFile>, swc::ast::Module), AnyError> {
+ let source = strip_bom(source);
+ let source = if media_type == MediaType::Json {
+ format!(
+ "export default JSON.parse(`{}`);",
+ source.replace("${", "\\${").replace('`', "\\`")
+ )
+ } else {
+ source.to_string()
+ };
+ let source_file =
+ cm.new_source_file(FileName::Url(specifier.clone()), source);
+ let input = StringInput::from(&*source_file);
+ let comments = SingleThreadedComments::default();
+ let syntax = if media_type == MediaType::Json {
+ get_syntax(MediaType::JavaScript)
+ } else {
+ get_syntax(media_type)
+ };
+ let lexer = Lexer::new(syntax, deno_ast::ES_VERSION, input, Some(&comments));
+ let mut parser = swc::parser::Parser::new_from(lexer);
+ 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<_>>();
+
+ let top_level_mark = Mark::fresh(Mark::root());
+ let program = deno_ast::fold_program(
+ swc::ast::Program::Module(module),
+ options,
+ cm,
+ &comments,
+ top_level_mark,
+ &diagnostics,
+ )?;
+ let module = match program {
+ swc::ast::Program::Module(module) => module,
+ _ => unreachable!(),
+ };
+
+ Ok((source_file, module))
+}
+
+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(),
+ }
+}
+
/// A resolver implementation for swc that resolves specifiers from the graph.
struct BundleResolver<'a>(&'a ModuleGraph);
@@ -597,8 +684,8 @@ pub(crate) fn bundle(
) -> Result<(String, Option<String>), AnyError> {
let globals = swc::common::Globals::new();
deno_ast::swc::common::GLOBALS.set(&globals, || {
- let emit_options: ast::EmitOptions = options.ts_config.into();
- let source_map_config = ast::SourceMapConfig {
+ let emit_options: deno_ast::EmitOptions = options.ts_config.into();
+ let source_map_config = deno_ast::SourceMapConfig {
inline_sources: emit_options.inline_sources,
};
@@ -617,7 +704,7 @@ pub(crate) fn bundle(
};
// This hook will rewrite the `import.meta` when bundling to give a consistent
// behavior between bundled and unbundled code.
- let hook = Box::new(ast::BundleHook);
+ let hook = Box::new(BundleHook);
let mut bundler = swc::bundler::Bundler::new(
&globals,
cm.clone(),
@@ -722,11 +809,10 @@ pub(crate) fn emit(
if is_valid && !needs_reload {
continue;
}
- let (emit, maybe_map) =
- ast::transpile(&module.parsed_source, &emit_options)?;
+ let transpiled_source = module.parsed_source.transpile(&emit_options)?;
emit_count += 1;
- cache.set(CacheType::Emit, &module.specifier, emit)?;
- if let Some(map) = maybe_map {
+ cache.set(CacheType::Emit, &module.specifier, transpiled_source.text)?;
+ if let Some(map) = transpiled_source.source_map {
cache.set(CacheType::SourceMap, &module.specifier, map)?;
}
if !is_valid {
@@ -861,6 +947,80 @@ pub(crate) fn to_file_map(
files
}
+/// This contains the logic for Deno to rewrite the `import.meta` when bundling.
+pub struct BundleHook;
+
+impl Hook for BundleHook {
+ fn get_import_meta_props(
+ &self,
+ span: Span,
+ module_record: &ModuleRecord,
+ ) -> Result<Vec<deno_ast::swc::ast::KeyValueProp>, AnyError> {
+ use deno_ast::swc::ast;
+
+ Ok(vec![
+ ast::KeyValueProp {
+ key: ast::PropName::Ident(ast::Ident::new("url".into(), span)),
+ value: Box::new(ast::Expr::Lit(ast::Lit::Str(ast::Str {
+ span,
+ value: module_record.file_name.to_string().into(),
+ kind: ast::StrKind::Synthesized,
+ has_escape: false,
+ }))),
+ },
+ ast::KeyValueProp {
+ key: ast::PropName::Ident(ast::Ident::new("main".into(), span)),
+ value: Box::new(if module_record.is_entry {
+ ast::Expr::Member(ast::MemberExpr {
+ span,
+ obj: Box::new(ast::Expr::MetaProp(ast::MetaPropExpr {
+ span,
+ kind: ast::MetaPropKind::ImportMeta,
+ })),
+ prop: ast::MemberProp::Ident(ast::Ident::new("main".into(), span)),
+ })
+ } else {
+ ast::Expr::Lit(ast::Lit::Bool(ast::Bool { span, value: false }))
+ }),
+ },
+ ])
+ }
+}
+
+impl From<config_file::TsConfig> for deno_ast::EmitOptions {
+ fn from(config: config_file::TsConfig) -> Self {
+ let options: config_file::EmitConfigOptions =
+ serde_json::from_value(config.0).unwrap();
+ let imports_not_used_as_values =
+ match options.imports_not_used_as_values.as_str() {
+ "preserve" => deno_ast::ImportsNotUsedAsValues::Preserve,
+ "error" => deno_ast::ImportsNotUsedAsValues::Error,
+ _ => deno_ast::ImportsNotUsedAsValues::Remove,
+ };
+ let (transform_jsx, jsx_automatic, jsx_development) =
+ match options.jsx.as_str() {
+ "react" => (true, false, false),
+ "react-jsx" => (true, true, false),
+ "react-jsxdev" => (true, true, true),
+ _ => (false, false, false),
+ };
+ deno_ast::EmitOptions {
+ emit_metadata: options.emit_decorator_metadata,
+ imports_not_used_as_values,
+ inline_source_map: options.inline_source_map,
+ inline_sources: options.inline_sources,
+ source_map: options.source_map,
+ jsx_automatic,
+ jsx_development,
+ jsx_factory: options.jsx_factory,
+ jsx_fragment_factory: options.jsx_fragment_factory,
+ jsx_import_source: options.jsx_import_source,
+ transform_jsx,
+ var_decl_imports: false,
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/cli/lsp/cache.rs b/cli/lsp/cache.rs
index 16ad76451..562ad78b0 100644
--- a/cli/lsp/cache.rs
+++ b/cli/lsp/cache.rs
@@ -80,6 +80,7 @@ impl CacheServer {
maybe_resolver,
None,
None,
+ None,
)
.await;
diff --git a/cli/lsp/code_lens.rs b/cli/lsp/code_lens.rs
index d0034069d..853a16f1f 100644
--- a/cli/lsp/code_lens.rs
+++ b/cli/lsp/code_lens.rs
@@ -157,7 +157,7 @@ impl DenoTestCollector {
impl Visit for DenoTestCollector {
fn visit_call_expr(&mut self, node: &ast::CallExpr) {
- if let ast::ExprOrSuper::Expr(callee_expr) = &node.callee {
+ if let ast::Callee::Expr(callee_expr) = &node.callee {
match callee_expr.as_ref() {
ast::Expr::Ident(ident) => {
if self.test_vars.contains(&ident.sym.to_string()) {
@@ -165,13 +165,11 @@ impl Visit for DenoTestCollector {
}
}
ast::Expr::Member(member_expr) => {
- if let ast::Expr::Ident(ns_prop_ident) = member_expr.prop.as_ref() {
+ if let ast::MemberProp::Ident(ns_prop_ident) = &member_expr.prop {
if ns_prop_ident.sym.to_string() == "test" {
- if let ast::ExprOrSuper::Expr(obj_expr) = &member_expr.obj {
- if let ast::Expr::Ident(ident) = obj_expr.as_ref() {
- if ident.sym.to_string() == "Deno" {
- self.check_call_expr(node, &ns_prop_ident.span);
- }
+ if let ast::Expr::Ident(ident) = member_expr.obj.as_ref() {
+ if ident.sym.to_string() == "Deno" {
+ self.check_call_expr(node, &ns_prop_ident.span);
}
}
}
@@ -219,16 +217,12 @@ impl Visit for DenoTestCollector {
}
// Identify variable assignments where the init is `Deno.test`
ast::Expr::Member(member_expr) => {
- if let ast::ExprOrSuper::Expr(expr) = &member_expr.obj {
- if let ast::Expr::Ident(obj_ident) = expr.as_ref() {
- if obj_ident.sym.to_string() == "Deno" {
- if let ast::Expr::Ident(prop_ident) =
- &member_expr.prop.as_ref()
- {
- if prop_ident.sym.to_string() == "test" {
- if let ast::Pat::Ident(binding_ident) = &decl.name {
- self.test_vars.insert(binding_ident.id.sym.to_string());
- }
+ if let ast::Expr::Ident(obj_ident) = member_expr.obj.as_ref() {
+ if obj_ident.sym.to_string() == "Deno" {
+ if let ast::MemberProp::Ident(prop_ident) = &member_expr.prop {
+ if prop_ident.sym.to_string() == "test" {
+ if let ast::Pat::Ident(binding_ident) = &decl.name {
+ self.test_vars.insert(binding_ident.id.sym.to_string());
}
}
}
diff --git a/cli/main.rs b/cli/main.rs
index d1fda4727..b845a4f49 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -1,6 +1,5 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-mod ast;
mod auth_tokens;
mod cache;
mod checksum;
@@ -475,6 +474,7 @@ async fn info_command(
maybe_resolver,
maybe_locker,
None,
+ None,
)
.await;
@@ -654,6 +654,7 @@ async fn create_graph_and_maybe_check(
maybe_resolver,
maybe_locker,
None,
+ None,
)
.await,
);
@@ -999,6 +1000,7 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<i32, AnyError> {
maybe_resolver,
maybe_locker,
None,
+ None,
)
.await;
let check_js = ps
diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs
index 50268b7eb..3d079e2fb 100644
--- a/cli/ops/runtime_compiler.rs
+++ b/cli/ops/runtime_compiler.rs
@@ -217,6 +217,7 @@ async fn op_emit(
maybe_resolver,
None,
None,
+ None,
)
.await,
);
diff --git a/cli/proc_state.rs b/cli/proc_state.rs
index ceff64c54..253878872 100644
--- a/cli/proc_state.rs
+++ b/cli/proc_state.rs
@@ -382,10 +382,9 @@ impl ProcState {
let graph_data = self.graph_data.read();
let found_specifier = graph_data.follow_redirect(specifier);
match graph_data.get(&found_specifier) {
- Some(_) if !self.reload => Box::pin(futures::future::ready((
- specifier.clone(),
- Err(anyhow!("")),
- ))),
+ Some(_) if !self.reload => {
+ Box::pin(futures::future::ready(Err(anyhow!(""))))
+ }
_ => self.inner.load(specifier, is_dynamic),
}
}
@@ -403,6 +402,7 @@ impl ProcState {
maybe_resolver,
maybe_locker,
None,
+ None,
)
.await;
// If there was a locker, validate the integrity of all the modules in the
diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs
index 5b258a540..1ef2e29eb 100644
--- a/cli/tools/doc.rs
+++ b/cli/tools/doc.rs
@@ -30,10 +30,10 @@ struct StubDocLoader;
impl Loader for StubDocLoader {
fn load(
&mut self,
- specifier: &ModuleSpecifier,
+ _specifier: &ModuleSpecifier,
_is_dynamic: bool,
) -> LoadFuture {
- Box::pin(future::ready((specifier.clone(), Ok(None))))
+ Box::pin(future::ready(Ok(None)))
}
}
@@ -74,18 +74,16 @@ impl Loader for DocLoader {
let specifier = specifier.clone();
let ps = self.ps.clone();
async move {
- let result = ps
- .file_fetcher
+ ps.file_fetcher
.fetch(&specifier, &mut Permissions::allow_all())
.await
.map(|file| {
Some(LoadResponse {
- specifier: specifier.clone(),
+ specifier,
content: file.source.clone(),
maybe_headers: file.maybe_headers,
})
- });
- (specifier.clone(), result)
+ })
}
.boxed_local()
}
@@ -113,6 +111,7 @@ pub async fn print_docs(
None,
None,
None,
+ None,
)
.await;
let doc_parser =
@@ -152,6 +151,7 @@ pub async fn print_docs(
Some(&resolver),
None,
None,
+ None,
)
.await;
let doc_parser =
diff --git a/cli/tools/repl/session.rs b/cli/tools/repl/session.rs
index d8276396a..5d458189f 100644
--- a/cli/tools/repl/session.rs
+++ b/cli/tools/repl/session.rs
@@ -1,10 +1,9 @@
// Copyright 2018-2022 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::lsp::ReplLanguageServer;
+use deno_ast::DiagnosticsError;
+use deno_ast::ImportsNotUsedAsValues;
use deno_core::error::AnyError;
use deno_core::futures::FutureExt;
use deno_core::serde_json::json;
@@ -184,7 +183,7 @@ impl ReplSession {
Some(diagnostic) => {
Ok(EvaluationOutput::Error(format_diagnostic(diagnostic)))
}
- None => match err.downcast_ref::<Diagnostics>() {
+ None => match err.downcast_ref::<DiagnosticsError>() {
Some(diagnostics) => Ok(EvaluationOutput::Error(
diagnostics
.0
@@ -311,9 +310,8 @@ impl ReplSession {
scope_analysis: false,
})?;
- let transpiled_src = transpile(
- &parsed_module,
- &crate::ast::EmitOptions {
+ let transpiled_src = parsed_module
+ .transpile(&deno_ast::EmitOptions {
emit_metadata: false,
source_map: false,
inline_source_map: false,
@@ -326,10 +324,9 @@ impl ReplSession {
jsx_factory: "React.createElement".into(),
jsx_fragment_factory: "React.Fragment".into(),
jsx_import_source: None,
- repl_imports: true,
- },
- )?
- .0;
+ var_decl_imports: true,
+ })?
+ .text;
let value = self
.evaluate_expression(&format!(
diff --git a/cli/tools/test.rs b/cli/tools/test.rs
index e5f03a19c..d991ef1ec 100644
--- a/cli/tools/test.rs
+++ b/cli/tools/test.rs
@@ -1,6 +1,5 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-use crate::ast::Location;
use crate::cache;
use crate::cache::CacherLoader;
use crate::colors;
@@ -535,9 +534,10 @@ async fn test_specifier(
}
fn extract_files_from_regex_blocks(
- location: &Location,
+ specifier: &ModuleSpecifier,
source: &str,
media_type: MediaType,
+ file_line_index: usize,
blocks_regex: &Regex,
lines_regex: &Regex,
) -> Result<Vec<File>, AnyError> {
@@ -594,9 +594,9 @@ fn extract_files_from_regex_blocks(
let file_specifier = deno_core::resolve_url_or_path(&format!(
"{}${}-{}{}",
- location.specifier,
- location.line + line_offset,
- location.line + line_offset + line_count,
+ specifier,
+ file_line_index + line_offset + 1,
+ file_line_index + line_offset + line_count + 1,
file_media_type.as_ts_extension(),
))
.unwrap();
@@ -642,12 +642,11 @@ fn extract_files_from_source_comments(
true
})
.flat_map(|comment| {
- let location = Location::from_pos(&parsed_source, comment.span.lo);
-
extract_files_from_regex_blocks(
- &location,
+ specifier,
&comment.text,
media_type,
+ parsed_source.source().line_index(comment.span.lo),
&blocks_regex,
&lines_regex,
)
@@ -663,19 +662,14 @@ fn extract_files_from_fenced_blocks(
source: &str,
media_type: MediaType,
) -> Result<Vec<File>, AnyError> {
- let location = Location {
- specifier: specifier.to_string(),
- line: 1,
- col: 0,
- };
-
let blocks_regex = Regex::new(r"```([^\r\n]*)\r?\n([\S\s]*?)```")?;
let lines_regex = Regex::new(r"(?:\# ?)?(.*)")?;
extract_files_from_regex_blocks(
- &location,
+ specifier,
source,
media_type,
+ /* file line index */ 0,
&blocks_regex,
&lines_regex,
)
@@ -1150,6 +1144,7 @@ pub async fn run_tests_with_watch(
maybe_resolver,
maybe_locker,
None,
+ None,
)
.await;
graph_valid(&graph, !no_check, check_js)?;
diff --git a/cli/tsc.rs b/cli/tsc.rs
index a2265e36f..001cfaf5d 100644
--- a/cli/tsc.rs
+++ b/cli/tsc.rs
@@ -689,7 +689,7 @@ mod tests {
})
})
.map_err(|err| err.into());
- Box::pin(future::ready((specifier.clone(), response)))
+ Box::pin(future::ready(response))
}
}
@@ -711,6 +711,7 @@ mod tests {
None,
None,
None,
+ None,
)
.await;
State::new(
@@ -737,6 +738,7 @@ mod tests {
None,
None,
None,
+ None,
)
.await;
let config = TsConfig::new(json!({