mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
refactor: move transpiling to deno_ast (#13332)
This commit is contained in:
parent
5e2d7737f5
commit
f12164646b
16 changed files with 302 additions and 1642 deletions
148
Cargo.lock
generated
148
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 }))
|
||||
}),
|
||||
},
|
||||
])
|
||||
}
|
||||
}
|
919
cli/ast/mod.rs
919
cli/ast/mod.rs
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
180
cli/emit.rs
180
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::*;
|
||||
|
|
|
@ -80,6 +80,7 @@ impl CacheServer {
|
|||
maybe_resolver,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -217,6 +217,7 @@ async fn op_emit(
|
|||
maybe_resolver,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await,
|
||||
);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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!({
|
||||
|
|
Loading…
Reference in a new issue