diff --git a/.dprint.json b/.dprint.json index 3b2376f786..b9c2d1ebc1 100644 --- a/.dprint.json +++ b/.dprint.json @@ -31,6 +31,8 @@ "cli/tsc/dts/lib.scripthost.d.ts", "cli/tsc/dts/lib.webworker*.d.ts", "cli/tsc/dts/typescript.d.ts", + "cli/tools/doc/prism.css", + "cli/tools/doc/prism.js", "ext/websocket/autobahn/reports", "gh-pages", "target", diff --git a/Cargo.lock b/Cargo.lock index 56d2417419..52bb39ee83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,6 +128,19 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "ammonia" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459" +dependencies = [ + "html5ever", + "maplit", + "once_cell", + "tendril", + "url", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -882,9 +895,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comrak" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c93ab3577cca16b4a1d80a88c2e0cd8b6e969e51696f0bbb0d1dcb0157109832" +checksum = "d8c32ff8b21372fab0e9ecc4e42536055702dc5faa418362bffd1544f9d12637" dependencies = [ "caseless", "derive_builder", @@ -1278,6 +1291,7 @@ dependencies = [ "sha2", "shell-escape", "spki", + "sqlformat", "strsim", "tar", "tempfile", @@ -1452,9 +1466,9 @@ dependencies = [ [[package]] name = "deno_core" -version = "0.319.0" +version = "0.321.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dbb841f9850534320d8927dce53ca8d64bafbab5576c2a98f03f9e08534215" +checksum = "cd2a54cda74cdc187d5fc2d23370a45cf09f912caf566dd1cd24a50157d809c7" dependencies = [ "anyhow", "bincode", @@ -1466,6 +1480,7 @@ dependencies = [ "deno_ops", "deno_unsync", "futures", + "indexmap 2.3.0", "libc", "memoffset", "parking_lot", @@ -1480,6 +1495,7 @@ dependencies = [ "tokio", "url", "v8", + "wasm_dep_analyzer", ] [[package]] @@ -1540,27 +1556,33 @@ dependencies = [ [[package]] name = "deno_doc" -version = "0.156.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2585b98d6ad76dae30bf2d7b6d71b8363cae041158b8780d14a2f4fe17590a61" +checksum = "db2baa33e5d1ed235209c2990f5fe9644bac6b9e7bcb789dd92894f907b09ad7" dependencies = [ + "ammonia", "anyhow", "cfg-if", "comrak", "deno_ast", "deno_graph", + "deno_path_util", "futures", "handlebars", "html-escape", "import_map", "indexmap 2.3.0", "itoa", + "js-sys", "lazy_static", + "percent-encoding", "regex", "serde", + "serde-wasm-bindgen", "serde_json", - "syntect", "termcolor", + "url", + "wasm-bindgen", ] [[package]] @@ -1642,9 +1664,9 @@ dependencies = [ [[package]] name = "deno_graph" -version = "0.84.1" +version = "0.85.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd4f4a14aa069087be41c2998077b0453f0191747898f96e6343f700abfc2c18" +checksum = "9d097305aba3f119781fe82b4d5a85a1ad10c586a388ee4d754e5bf82901cc5c" dependencies = [ "anyhow", "async-trait", @@ -1667,6 +1689,7 @@ dependencies = [ "thiserror", "twox-hash", "url", + "wasm_dep_analyzer", ] [[package]] @@ -1929,6 +1952,7 @@ dependencies = [ "stable_deref_trait", "thiserror", "tokio", + "tokio-eld", "url", "webpki-root-certs", "winapi", @@ -1959,13 +1983,14 @@ dependencies = [ [[package]] name = "deno_ops" -version = "0.195.0" +version = "0.197.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "797f348c38c07a5398bf790b280077c698e13fb49252f61ca6f6c5c616060292" +checksum = "37a8825d92301cf445727c43f17fee2a20fcdf4370004339965156ae7c56c97e" dependencies = [ "proc-macro-rules", "proc-macro2", "quote", + "stringcase", "strum", "strum_macros", "syn 2.0.87", @@ -3224,6 +3249,16 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.30" @@ -3560,6 +3595,20 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" +dependencies = [ + "base64 0.21.7", + "byteorder", + "crossbeam-channel", + "flate2", + "nom 7.1.3", + "num-traits", +] + [[package]] name = "heck" version = "0.4.1" @@ -3737,6 +3786,20 @@ dependencies = [ "utf8-width", ] +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "http" version = "0.2.12" @@ -4449,6 +4512,12 @@ dependencies = [ "serde_repr", ] +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + [[package]] name = "malloc_buf" version = "0.0.6" @@ -4471,6 +4540,26 @@ dependencies = [ "tiny_pretty", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", + "tendril", +] + [[package]] name = "markup_fmt" version = "0.15.0" @@ -4883,28 +4972,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "onig" -version = "6.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" -dependencies = [ - "bitflags 1.3.2", - "libc", - "once_cell", - "onig_sys", -] - -[[package]] -name = "onig_sys" -version = "69.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "opaque-debug" version = "0.3.1" @@ -5250,7 +5317,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_macros", - "phf_shared", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", ] [[package]] @@ -5259,7 +5346,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ - "phf_shared", + "phf_shared 0.11.2", "rand", ] @@ -5269,13 +5356,22 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.2", + "phf_shared 0.11.2", "proc-macro2", "quote", "syn 2.0.87", ] +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "phf_shared" version = "0.11.2" @@ -5398,6 +5494,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "pretty_assertions" version = "1.4.0" @@ -6348,6 +6450,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.14" @@ -6406,9 +6519,9 @@ dependencies = [ [[package]] name = "serde_v8" -version = "0.228.0" +version = "0.230.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe23e75c9a167f4e9d67a90d9fcaa622d1eec9aecad526c270e99a92f6915ff" +checksum = "b5a783242d2af51d6955cc04bf2b64adb643ab588b61e9573c908a69dabf8c2f" dependencies = [ "num-bigint", "serde", @@ -6684,6 +6797,17 @@ dependencies = [ "der", ] +[[package]] +name = "sqlformat" +version = "0.3.1" +source = "git+https://github.com/shssoichiro/sqlformat-rs.git?rev=827d639#827d639bef94d8e5a5a0e29b41185c8d572f24e6" +dependencies = [ + "nom 7.1.3", + "once_cell", + "regex", + "unicode_categories", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -6709,6 +6833,32 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + [[package]] name = "string_enum" version = "0.4.4" @@ -6721,6 +6871,12 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "stringcase" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04028eeb851ed08af6aba5caa29f2d59a13ed168cee4d6bd753aeefcf1d636b0" + [[package]] name = "strip-ansi-escapes" version = "0.2.0" @@ -7261,26 +7417,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "syntect" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" -dependencies = [ - "bincode", - "bitflags 1.3.2", - "flate2", - "fnv", - "once_cell", - "onig", - "regex-syntax", - "serde", - "serde_derive", - "serde_json", - "thiserror", - "walkdir", -] - [[package]] name = "tap" version = "1.0.1" @@ -7310,6 +7446,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -7522,6 +7669,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "tokio-eld" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9166030f05d6bc5642bdb8f8c2be31eb3c02cd465d662bcdc2df82d4aa41a584" +dependencies = [ + "hdrhistogram", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.2.0" @@ -8135,6 +8292,15 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm_dep_analyzer" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f270206a91783fd90625c8bb0d8fbd459d0b1d1bf209b656f713f01ae7c04b8" +dependencies = [ + "thiserror", +] + [[package]] name = "web-sys" version = "0.3.69" diff --git a/Cargo.toml b/Cargo.toml index 9d625f082a..cf7e2610bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ repository = "https://github.com/denoland/deno" [workspace.dependencies] deno_ast = { version = "=0.43.3", features = ["transpiling"] } -deno_core = { version = "0.319.0" } +deno_core = { version = "0.321.0" } deno_bench_util = { version = "0.171.0", path = "./bench_util" } deno_config = { version = "=0.39.1", features = ["workspace", "sync"] } diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 374f3dae5e..16f39e9d48 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -72,8 +72,8 @@ deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposa deno_cache_dir.workspace = true deno_config.workspace = true deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] } -deno_doc = { version = "0.156.0", default-features = false, features = ["rust", "html", "syntect"] } -deno_graph = { version = "=0.84.1" } +deno_doc = { version = "0.160.0", features = ["rust", "comrak"] } +deno_graph = { version = "=0.85.0" } deno_lint = { version = "=0.68.0", features = ["docs"] } deno_lockfile.workspace = true deno_npm.workspace = true @@ -151,6 +151,8 @@ serde_repr.workspace = true sha2.workspace = true shell-escape = "=0.1.5" spki = { version = "0.7", features = ["pem"] } +# NOTE(bartlomieju): for now using github URL, because 0.3.2 with important fixes hasn't been released yet. +sqlformat = { git = "https://github.com/shssoichiro/sqlformat-rs.git", rev = "827d639" } strsim = "0.11.1" tar.workspace = true tempfile.workspace = true diff --git a/cli/args/deno_json.rs b/cli/args/deno_json.rs index e9ab0189f5..a82289e67d 100644 --- a/cli/args/deno_json.rs +++ b/cli/args/deno_json.rs @@ -70,7 +70,41 @@ pub fn deno_json_deps( let values = imports_values(config.json.imports.as_ref()) .into_iter() .chain(scope_values(config.json.scopes.as_ref())); - values_to_set(values) + let mut set = values_to_set(values); + + if let Some(serde_json::Value::Object(compiler_options)) = + &config.json.compiler_options + { + // add jsxImportSource + if let Some(serde_json::Value::String(value)) = + compiler_options.get("jsxImportSource") + { + if let Some(dep_req) = value_to_dep_req(value) { + set.insert(dep_req); + } + } + // add jsxImportSourceTypes + if let Some(serde_json::Value::String(value)) = + compiler_options.get("jsxImportSourceTypes") + { + if let Some(dep_req) = value_to_dep_req(value) { + set.insert(dep_req); + } + } + // add the dependencies in the types array + if let Some(serde_json::Value::Array(types)) = compiler_options.get("types") + { + for value in types { + if let serde_json::Value::String(value) = value { + if let Some(dep_req) = value_to_dep_req(value) { + set.insert(dep_req); + } + } + } + } + } + + set } fn imports_values(value: Option<&serde_json::Value>) -> Vec<&String> { @@ -98,15 +132,23 @@ fn values_to_set<'a>( ) -> HashSet { let mut entries = HashSet::new(); for value in values { - if let Ok(req_ref) = JsrPackageReqReference::from_str(value) { - entries.insert(JsrDepPackageReq::jsr(req_ref.into_inner().req)); - } else if let Ok(req_ref) = NpmPackageReqReference::from_str(value) { - entries.insert(JsrDepPackageReq::npm(req_ref.into_inner().req)); + if let Some(dep_req) = value_to_dep_req(value) { + entries.insert(dep_req); } } entries } +fn value_to_dep_req(value: &str) -> Option { + if let Ok(req_ref) = JsrPackageReqReference::from_str(value) { + Some(JsrDepPackageReq::jsr(req_ref.into_inner().req)) + } else if let Ok(req_ref) = NpmPackageReqReference::from_str(value) { + Some(JsrDepPackageReq::npm(req_ref.into_inner().req)) + } else { + None + } +} + pub fn check_warn_tsconfig(ts_config: &TsConfigForEmit) { if let Some(ignored_options) = &ts_config.maybe_ignored_options { log::warn!("{}", ignored_options); diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 39db12b5f1..5d85f2861c 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -210,6 +210,7 @@ pub struct FmtFlags { pub no_semicolons: Option, pub watch: Option, pub unstable_component: bool, + pub unstable_sql: bool, } impl FmtFlags { @@ -379,6 +380,7 @@ pub struct TaskFlags { pub cwd: Option, pub task: Option, pub is_run: bool, + pub eval: bool, } #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] @@ -427,6 +429,7 @@ pub struct PublishFlags { pub allow_slow_types: bool, pub allow_dirty: bool, pub no_provenance: bool, + pub set_version: Option, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -1384,13 +1387,13 @@ pub fn flags_from_vec(args: Vec) -> clap::error::Result { "repl" => repl_parse(&mut flags, &mut m)?, "run" => run_parse(&mut flags, &mut m, app, false)?, "serve" => serve_parse(&mut flags, &mut m, app)?, - "task" => task_parse(&mut flags, &mut m), + "task" => task_parse(&mut flags, &mut m, app)?, "test" => test_parse(&mut flags, &mut m)?, "types" => types_parse(&mut flags, &mut m), "uninstall" => uninstall_parse(&mut flags, &mut m), "upgrade" => upgrade_parse(&mut flags, &mut m), "vendor" => vendor_parse(&mut flags, &mut m), - "publish" => publish_parse(&mut flags, &mut m), + "publish" => publish_parse(&mut flags, &mut m)?, _ => unreachable!(), } } else { @@ -1908,10 +1911,10 @@ On the first invocation with deno will download the proper binary and cache it i Arg::new("include") .long("include") .help( - cstr!("Includes an additional module in the compiled executable's module graph. + cstr!("Includes an additional module or file/directory in the compiled executable. Use this flag if a dynamically imported module or a web worker main module - fails to load in the executable. This flag can be passed multiple times, - to include multiple additional modules.", + fails to load in the executable or to embed a file or directory in the executable. + This flag can be passed multiple times, to include multiple additional modules.", )) .action(ArgAction::Append) .value_hint(ValueHint::FilePath) @@ -2291,7 +2294,7 @@ Ignore formatting a file by adding an ignore comment at the top of the file: .value_parser([ "ts", "tsx", "js", "jsx", "md", "json", "jsonc", "css", "scss", "sass", "less", "html", "svelte", "vue", "astro", "yml", "yaml", - "ipynb", + "ipynb", "sql" ]) .help_heading(FMT_HEADING).requires("files"), ) @@ -2410,6 +2413,14 @@ Ignore formatting a file by adding an ignore comment at the top of the file: .help_heading(FMT_HEADING) .hide(true), ) + .arg( + Arg::new("unstable-sql") + .long("unstable-sql") + .help("Enable formatting SQL files.") + .value_parser(FalseyValueParser::new()) + .action(ArgAction::SetTrue) + .help_heading(FMT_HEADING), + ) }) } @@ -2921,7 +2932,10 @@ fn task_subcommand() -> Command { deno task build List all available tasks: - deno task" + deno task + +Evaluate a task from string + deno task --eval \"echo $(pwd)\"" ), UnstableArgsConfig::ResolutionAndRuntime, ) @@ -2937,6 +2951,13 @@ List all available tasks: .help("Specify the directory to run the task in") .value_hint(ValueHint::DirPath), ) + .arg( + Arg::new("eval") + .long("eval") + .help( + "Evaluate the passed value as if, it was a task in a configuration file", + ).action(ArgAction::SetTrue) + ) .arg(node_modules_dir_arg()) }) } @@ -3216,12 +3237,12 @@ fn publish_subcommand() -> Command { command("publish", "Publish the current working directory's package or workspace to JSR", UnstableArgsConfig::ResolutionOnly) .defer(|cmd| { cmd - .arg( - Arg::new("token") - .long("token") - .help("The API token to use when publishing. If unset, interactive authentication is be used") - .help_heading(PUBLISH_HEADING) - ) + .arg( + Arg::new("token") + .long("token") + .help("The API token to use when publishing. If unset, interactive authentication is be used") + .help_heading(PUBLISH_HEADING) + ) .arg(config_arg()) .arg(no_config_arg()) .arg( @@ -3229,29 +3250,38 @@ fn publish_subcommand() -> Command { .long("dry-run") .help("Prepare the package for publishing performing all checks and validations without uploading") .action(ArgAction::SetTrue) - .help_heading(PUBLISH_HEADING), + .help_heading(PUBLISH_HEADING), ) .arg( Arg::new("allow-slow-types") .long("allow-slow-types") .help("Allow publishing with slow types") .action(ArgAction::SetTrue) - .help_heading(PUBLISH_HEADING), + .help_heading(PUBLISH_HEADING), ) .arg( Arg::new("allow-dirty") .long("allow-dirty") .help("Allow publishing if the repository has uncommitted changed") .action(ArgAction::SetTrue) - .help_heading(PUBLISH_HEADING), - ).arg( - Arg::new("no-provenance") - .long("no-provenance") - .help(cstr!("Disable provenance attestation. + .help_heading(PUBLISH_HEADING), + ) + .arg( + Arg::new("no-provenance") + .long("no-provenance") + .help(cstr!("Disable provenance attestation. Enabled by default on Github actions, publicly links the package to where it was built and published from.")) - .action(ArgAction::SetTrue) - .help_heading(PUBLISH_HEADING) - ) + .action(ArgAction::SetTrue) + .help_heading(PUBLISH_HEADING) + ) + .arg( + Arg::new("set-version") + .long("set-version") + .help("Set version for a package to be published. + This flag can be used while publishing individual packages and cannot be used in a workspace.") + .value_name("VERSION") + .help_heading(PUBLISH_HEADING) + ) .arg(check_arg(/* type checks by default */ true)) .arg(no_check_arg()) }) @@ -4634,6 +4664,7 @@ fn fmt_parse( let prose_wrap = matches.remove_one::("prose-wrap"); let no_semicolons = matches.remove_one::("no-semicolons"); let unstable_component = matches.get_flag("unstable-component"); + let unstable_sql = matches.get_flag("unstable-sql"); flags.subcommand = DenoSubcommand::Fmt(FmtFlags { check: matches.get_flag("check"), @@ -4646,6 +4677,7 @@ fn fmt_parse( no_semicolons, watch: watch_arg_parse(matches)?, unstable_component, + unstable_sql, }); Ok(()) } @@ -5045,7 +5077,11 @@ fn serve_parse( Ok(()) } -fn task_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn task_parse( + flags: &mut Flags, + matches: &mut ArgMatches, + mut app: Command, +) -> clap::error::Result<()> { flags.config_flag = matches .remove_one::("config") .map(ConfigFlag::Path) @@ -5058,6 +5094,7 @@ fn task_parse(flags: &mut Flags, matches: &mut ArgMatches) { cwd: matches.remove_one::("cwd"), task: None, is_run: false, + eval: matches.get_flag("eval"), }; if let Some((task, mut matches)) = matches.remove_subcommand() { @@ -5070,9 +5107,15 @@ fn task_parse(flags: &mut Flags, matches: &mut ArgMatches) { .flatten() .filter_map(|arg| arg.into_string().ok()), ); + } else if task_flags.eval { + return Err(app.find_subcommand_mut("task").unwrap().error( + clap::error::ErrorKind::MissingRequiredArgument, + "[TASK] must be specified when using --eval", + )); } flags.subcommand = DenoSubcommand::Task(task_flags); + Ok(()) } fn parallel_arg_parse(matches: &mut ArgMatches) -> Option { @@ -5218,7 +5261,10 @@ fn vendor_parse(flags: &mut Flags, _matches: &mut ArgMatches) { flags.subcommand = DenoSubcommand::Vendor } -fn publish_parse(flags: &mut Flags, matches: &mut ArgMatches) { +fn publish_parse( + flags: &mut Flags, + matches: &mut ArgMatches, +) -> clap::error::Result<()> { flags.type_check_mode = TypeCheckMode::Local; // local by default unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly); no_check_arg_parse(flags, matches); @@ -5231,7 +5277,10 @@ fn publish_parse(flags: &mut Flags, matches: &mut ArgMatches) { allow_slow_types: matches.get_flag("allow-slow-types"), allow_dirty: matches.get_flag("allow-dirty"), no_provenance: matches.get_flag("no-provenance"), + set_version: matches.remove_one::("set-version"), }); + + Ok(()) } fn compile_args_parse( @@ -6565,6 +6614,7 @@ mod tests { prose_wrap: None, no_semicolons: None, unstable_component: false, + unstable_sql: false, watch: Default::default(), }), ..Flags::default() @@ -6588,6 +6638,7 @@ mod tests { prose_wrap: None, no_semicolons: None, unstable_component: false, + unstable_sql: false, watch: Default::default(), }), ..Flags::default() @@ -6611,6 +6662,7 @@ mod tests { prose_wrap: None, no_semicolons: None, unstable_component: false, + unstable_sql: false, watch: Default::default(), }), ..Flags::default() @@ -6634,6 +6686,7 @@ mod tests { prose_wrap: None, no_semicolons: None, unstable_component: false, + unstable_sql: false, watch: Some(Default::default()), }), ..Flags::default() @@ -6648,7 +6701,8 @@ mod tests { "--unstable-css", "--unstable-html", "--unstable-component", - "--unstable-yaml" + "--unstable-yaml", + "--unstable-sql" ]); assert_eq!( r.unwrap(), @@ -6666,6 +6720,7 @@ mod tests { prose_wrap: None, no_semicolons: None, unstable_component: true, + unstable_sql: true, watch: Some(WatchFlags { hmr: false, no_clear_screen: true, @@ -6700,6 +6755,7 @@ mod tests { prose_wrap: None, no_semicolons: None, unstable_component: false, + unstable_sql: false, watch: Some(Default::default()), }), ..Flags::default() @@ -6723,6 +6779,7 @@ mod tests { prose_wrap: None, no_semicolons: None, unstable_component: false, + unstable_sql: false, watch: Default::default(), }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), @@ -6754,6 +6811,7 @@ mod tests { prose_wrap: None, no_semicolons: None, unstable_component: false, + unstable_sql: false, watch: Some(Default::default()), }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), @@ -6790,6 +6848,7 @@ mod tests { prose_wrap: Some("never".to_string()), no_semicolons: Some(true), unstable_component: false, + unstable_sql: false, watch: Default::default(), }), ..Flags::default() @@ -6820,6 +6879,7 @@ mod tests { prose_wrap: None, no_semicolons: Some(false), unstable_component: false, + unstable_sql: false, watch: Default::default(), }), ..Flags::default() @@ -6845,6 +6905,7 @@ mod tests { prose_wrap: None, no_semicolons: None, unstable_component: false, + unstable_sql: false, watch: Default::default(), }), ext: Some("html".to_string()), @@ -10235,6 +10296,7 @@ mod tests { cwd: None, task: Some("build".to_string()), is_run: false, + eval: false, }), argv: svec!["hello", "world"], ..Flags::default() @@ -10249,6 +10311,7 @@ mod tests { cwd: None, task: Some("build".to_string()), is_run: false, + eval: false, }), ..Flags::default() } @@ -10262,10 +10325,28 @@ mod tests { cwd: Some("foo".to_string()), task: Some("build".to_string()), is_run: false, + eval: false, }), ..Flags::default() } ); + + let r = flags_from_vec(svec!["deno", "task", "--eval", "echo 1"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Task(TaskFlags { + cwd: None, + task: Some("echo 1".to_string()), + is_run: false, + eval: true, + }), + ..Flags::default() + } + ); + + let r = flags_from_vec(svec!["deno", "task", "--eval"]); + assert!(r.is_err()); } #[test] @@ -10287,6 +10368,7 @@ mod tests { cwd: None, task: Some("build".to_string()), is_run: false, + eval: false, }), argv: svec!["--", "hello", "world"], config_flag: ConfigFlag::Path("deno.json".to_owned()), @@ -10304,6 +10386,7 @@ mod tests { cwd: Some("foo".to_string()), task: Some("build".to_string()), is_run: false, + eval: false, }), argv: svec!["--", "hello", "world"], ..Flags::default() @@ -10322,6 +10405,7 @@ mod tests { cwd: None, task: Some("build".to_string()), is_run: false, + eval: false, }), argv: svec!["--"], ..Flags::default() @@ -10339,6 +10423,7 @@ mod tests { cwd: None, task: Some("build".to_string()), is_run: false, + eval: false, }), argv: svec!["-1", "--test"], ..Flags::default() @@ -10356,6 +10441,7 @@ mod tests { cwd: None, task: Some("build".to_string()), is_run: false, + eval: false, }), argv: svec!["--test"], ..Flags::default() @@ -10374,6 +10460,7 @@ mod tests { cwd: None, task: Some("build".to_string()), is_run: false, + eval: false, }), log_level: Some(log::Level::Error), ..Flags::default() @@ -10391,6 +10478,7 @@ mod tests { cwd: None, task: None, is_run: false, + eval: false, }), ..Flags::default() } @@ -10407,6 +10495,7 @@ mod tests { cwd: None, task: None, is_run: false, + eval: false, }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), ..Flags::default() @@ -10424,6 +10513,7 @@ mod tests { cwd: None, task: None, is_run: false, + eval: false, }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), ..Flags::default() @@ -10746,6 +10836,7 @@ mod tests { "--allow-slow-types", "--allow-dirty", "--token=asdf", + "--set-version=1.0.1", ]); assert_eq!( r.unwrap(), @@ -10756,6 +10847,7 @@ mod tests { allow_slow_types: true, allow_dirty: true, no_provenance: true, + set_version: Some("1.0.1".to_string()), }), type_check_mode: TypeCheckMode::Local, ..Flags::default() diff --git a/cli/args/lockfile.rs b/cli/args/lockfile.rs index 1805d26426..a9eb8a0d7c 100644 --- a/cli/args/lockfile.rs +++ b/cli/args/lockfile.rs @@ -126,11 +126,7 @@ impl CliLockfile { maybe_deno_json: Option<&ConfigFile>, ) -> HashSet { maybe_deno_json - .map(|c| { - crate::args::deno_json::deno_json_deps(c) - .into_iter() - .collect() - }) + .map(crate::args::deno_json::deno_json_deps) .unwrap_or_default() } diff --git a/cli/args/mod.rs b/cli/args/mod.rs index ec75d7a100..21df6cf115 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -289,6 +289,7 @@ impl BenchOptions { #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] pub struct UnstableFmtOptions { pub component: bool, + pub sql: bool, } #[derive(Clone, Debug)] @@ -322,6 +323,7 @@ impl FmtOptions { options: resolve_fmt_options(fmt_flags, fmt_config.options), unstable: UnstableFmtOptions { component: unstable.component || fmt_flags.unstable_component, + sql: unstable.sql || fmt_flags.unstable_sql, }, files: fmt_config.files, } @@ -1319,6 +1321,7 @@ impl CliOptions { let workspace = self.workspace(); UnstableFmtOptions { component: workspace.has_unstable("fmt-component"), + sql: workspace.has_unstable("fmt-sql"), } } @@ -1545,6 +1548,10 @@ impl CliOptions { }) => Url::parse(&flags.module_url) .ok() .map(|url| vec![Cow::Owned(url)]), + DenoSubcommand::Doc(DocFlags { + source_files: DocSourceFileFlag::Paths(paths), + .. + }) => Some(files_to_urls(paths)), _ => None, }) .unwrap_or_default(); @@ -1667,6 +1674,7 @@ impl CliOptions { "byonm", "bare-node-builtins", "fmt-component", + "fmt-sql", ]) .collect(); diff --git a/cli/errors.rs b/cli/errors.rs index b1808f7339..38dc8259e3 100644 --- a/cli/errors.rs +++ b/cli/errors.rs @@ -38,6 +38,7 @@ fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str { ModuleGraphError::ModuleError(err) => match err { ModuleError::InvalidTypeAssertion { .. } => "SyntaxError", ModuleError::ParseErr(_, diagnostic) => get_diagnostic_class(diagnostic), + ModuleError::WasmParseErr(..) => "SyntaxError", ModuleError::UnsupportedMediaType { .. } | ModuleError::UnsupportedImportAttributeType { .. } => "TypeError", ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => { diff --git a/cli/factory.rs b/cli/factory.rs index 7949a83a55..98149982f0 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -884,6 +884,7 @@ impl CliFactory { let cli_options = self.cli_options()?; Ok(DenoCompileBinaryWriter::new( self.cjs_tracker()?, + self.cli_options()?, self.deno_dir()?, self.emitter()?, self.file_fetcher()?, diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index b01544ddf9..cdc25f3ac3 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -883,8 +883,13 @@ impl FileSystemDocuments { let doc = if specifier.scheme() == "file" { let path = url_to_file_path(specifier).ok()?; let bytes = fs::read(path).ok()?; - let content = - deno_graph::source::decode_owned_source(specifier, bytes, None).ok()?; + let content = bytes_to_content( + specifier, + MediaType::from_specifier(specifier), + bytes, + None, + ) + .ok()?; Document::new( specifier.clone(), content.into(), @@ -923,19 +928,24 @@ impl FileSystemDocuments { specifier, Some(&cached_file.metadata.headers), ); - let content = deno_graph::source::decode_owned_source( + let media_type = resolve_media_type( specifier, + Some(&cached_file.metadata.headers), + None, + ); + let content = bytes_to_content( + specifier, + media_type, cached_file.content, maybe_charset, ) .ok()?; - let maybe_headers = Some(cached_file.metadata.headers); Document::new( specifier.clone(), content.into(), None, None, - maybe_headers, + Some(cached_file.metadata.headers), is_cjs_resolver, resolver.clone(), config.clone(), @@ -1706,6 +1716,24 @@ fn analyze_module( } } +fn bytes_to_content( + specifier: &ModuleSpecifier, + media_type: MediaType, + bytes: Vec, + maybe_charset: Option<&str>, +) -> Result { + if media_type == MediaType::Wasm { + // we use the dts representation for Wasm modules + Ok(deno_graph::source::wasm::wasm_module_to_dts(&bytes)?) + } else { + Ok(deno_graph::source::decode_owned_source( + specifier, + bytes, + maybe_charset, + )?) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 2ce26c1f2e..cbe194e14e 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -1405,6 +1405,9 @@ impl Inner { component: config_data .map(|d| d.unstable.contains("fmt-component")) .unwrap_or(false), + sql: config_data + .map(|d| d.unstable.contains("fmt-sql")) + .unwrap_or(false), }; let document = document.clone(); move || { diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index fc7ff57948..c221a6097b 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -5609,7 +5609,7 @@ mod tests { let (_tx, rx) = mpsc::unbounded_channel(); let state = State::new(state_snapshot, Default::default(), Default::default(), rx); - let mut op_state = OpState::new(None); + let mut op_state = OpState::new(None, None); op_state.put(state); op_state } diff --git a/cli/main.rs b/cli/main.rs index 7d3ef0e6a0..3dd2692f05 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -238,6 +238,7 @@ async fn run_subcommand(flags: Arc) -> Result { cwd: None, task: Some(run_flags.script.clone()), is_run: true, + eval: false, }; new_flags.subcommand = DenoSubcommand::Task(task_flags.clone()); let result = tools::task::execute_script(Arc::new(new_flags), task_flags.clone()).await; diff --git a/cli/module_loader.rs b/cli/module_loader.rs index b9adfe642c..035ae4264b 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -66,6 +66,7 @@ use deno_graph::JsonModule; use deno_graph::Module; use deno_graph::ModuleGraph; use deno_graph::Resolution; +use deno_graph::WasmModule; use deno_runtime::code_cache; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node::create_host_defined_options; @@ -368,7 +369,9 @@ impl requested_module_type: RequestedModuleType, ) -> Result { let code_source = self.load_code_source(specifier, maybe_referrer).await?; - let code = if self.shared.is_inspecting { + let code = if self.shared.is_inspecting + || code_source.media_type == MediaType::Wasm + { // we need the code with the source map in order for // it to work with --inspect or --inspect-brk code_source.code @@ -378,6 +381,7 @@ impl }; let module_type = match code_source.media_type { MediaType::Json => ModuleType::Json, + MediaType::Wasm => ModuleType::Wasm, _ => ModuleType::JavaScript, }; @@ -474,21 +478,6 @@ impl raw_specifier: &str, referrer: &ModuleSpecifier, ) -> Result { - if self.shared.in_npm_pkg_checker.in_npm_package(referrer) { - return Ok( - self - .shared - .node_resolver - .resolve( - raw_specifier, - referrer, - self.shared.cjs_tracker.get_referrer_kind(referrer), - NodeResolutionMode::Execution, - )? - .into_url(), - ); - } - let graph = self.graph_container.graph(); let resolution = match graph.get(referrer) { Some(Module::Js(module)) => module @@ -560,6 +549,7 @@ impl Some(Module::Node(module)) => module.specifier.clone(), Some(Module::Js(module)) => module.specifier.clone(), Some(Module::Json(module)) => module.specifier.clone(), + Some(Module::Wasm(module)) => module.specifier.clone(), Some(Module::External(module)) => { node::resolve_specifier_into_node_modules( &module.specifier, @@ -731,6 +721,13 @@ impl media_type: *media_type, }))) } + Some(deno_graph::Module::Wasm(WasmModule { + source, specifier, .. + })) => Ok(Some(CodeOrDeferredEmit::Code(ModuleCodeStringSource { + code: ModuleSourceCode::Bytes(source.clone().into()), + found_url: specifier.clone(), + media_type: MediaType::Wasm, + }))), Some( deno_graph::Module::External(_) | deno_graph::Module::Node(_) diff --git a/cli/schemas/config-file.v1.json b/cli/schemas/config-file.v1.json index 56a8090f9b..ccd773efbf 100644 --- a/cli/schemas/config-file.v1.json +++ b/cli/schemas/config-file.v1.json @@ -448,6 +448,13 @@ "type": "string", "required": true, "description": "The task to execute" + }, + "dependencies": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tasks that should be executed before this task" } } } @@ -550,6 +557,7 @@ "ffi", "fs", "fmt-component", + "fmt-sql", "http", "kv", "net", diff --git a/cli/standalone/binary.rs b/cli/standalone/binary.rs index 37753bafc8..e35119e0aa 100644 --- a/cli/standalone/binary.rs +++ b/cli/standalone/binary.rs @@ -201,7 +201,8 @@ fn write_binary_bytes( compile_flags: &CompileFlags, ) -> Result<(), AnyError> { let data_section_bytes = - serialize_binary_data_section(metadata, npm_snapshot, remote_modules, vfs)?; + serialize_binary_data_section(metadata, npm_snapshot, remote_modules, vfs) + .context("Serializing binary data section.")?; let target = compile_flags.resolve_target(); if target.contains("linux") { @@ -364,6 +365,7 @@ pub fn extract_standalone( pub struct DenoCompileBinaryWriter<'a> { cjs_tracker: &'a CjsTracker, + cli_options: &'a CliOptions, deno_dir: &'a DenoDir, emitter: &'a Emitter, file_fetcher: &'a FileFetcher, @@ -377,6 +379,7 @@ impl<'a> DenoCompileBinaryWriter<'a> { #[allow(clippy::too_many_arguments)] pub fn new( cjs_tracker: &'a CjsTracker, + cli_options: &'a CliOptions, deno_dir: &'a DenoDir, emitter: &'a Emitter, file_fetcher: &'a FileFetcher, @@ -387,6 +390,7 @@ impl<'a> DenoCompileBinaryWriter<'a> { ) -> Self { Self { cjs_tracker, + cli_options, deno_dir, emitter, file_fetcher, @@ -403,8 +407,8 @@ impl<'a> DenoCompileBinaryWriter<'a> { graph: &ModuleGraph, root_dir_url: StandaloneRelativeFileBaseUrl<'_>, entrypoint: &ModuleSpecifier, + include_files: &[ModuleSpecifier], compile_flags: &CompileFlags, - cli_options: &CliOptions, ) -> Result<(), AnyError> { // Select base binary based on target let mut original_binary = self.get_base_binary(compile_flags).await?; @@ -417,7 +421,8 @@ impl<'a> DenoCompileBinaryWriter<'a> { target, ) } - set_windows_binary_to_gui(&mut original_binary)?; + set_windows_binary_to_gui(&mut original_binary) + .context("Setting windows binary to GUI.")?; } if compile_flags.icon.is_some() { let target = compile_flags.resolve_target(); @@ -435,7 +440,7 @@ impl<'a> DenoCompileBinaryWriter<'a> { graph, root_dir_url, entrypoint, - cli_options, + include_files, compile_flags, ) .await @@ -478,10 +483,14 @@ impl<'a> DenoCompileBinaryWriter<'a> { if !binary_path.exists() { self .download_base_binary(&download_directory, &binary_path_suffix) - .await?; + .await + .context("Setting up base binary.")?; } - let archive_data = std::fs::read(binary_path)?; + let read_file = |path: &Path| -> Result, AnyError> { + std::fs::read(path).with_context(|| format!("Reading {}", path.display())) + }; + let archive_data = read_file(&binary_path)?; let temp_dir = tempfile::TempDir::new()?; let base_binary_path = archive::unpack_into_dir(archive::UnpackArgs { exe_name: "denort", @@ -490,7 +499,7 @@ impl<'a> DenoCompileBinaryWriter<'a> { is_windows: target.contains("windows"), dest_path: temp_dir.path(), })?; - let base_binary = std::fs::read(base_binary_path)?; + let base_binary = read_file(&base_binary_path)?; drop(temp_dir); // delete the temp dir Ok(base_binary) } @@ -518,15 +527,19 @@ impl<'a> DenoCompileBinaryWriter<'a> { let bytes = match maybe_bytes { Some(bytes) => bytes, None => { - log::info!("Download could not be found, aborting"); - deno_runtime::exit(1); + bail!("Download could not be found, aborting"); } }; - std::fs::create_dir_all(output_directory)?; + let create_dir_all = |dir: &Path| { + std::fs::create_dir_all(dir) + .with_context(|| format!("Creating {}", dir.display())) + }; + create_dir_all(output_directory)?; let output_path = output_directory.join(binary_path_suffix); - std::fs::create_dir_all(output_path.parent().unwrap())?; - tokio::fs::write(output_path, bytes).await?; + create_dir_all(output_path.parent().unwrap())?; + std::fs::write(&output_path, bytes) + .with_context(|| format!("Writing {}", output_path.display()))?; Ok(()) } @@ -540,73 +553,87 @@ impl<'a> DenoCompileBinaryWriter<'a> { graph: &ModuleGraph, root_dir_url: StandaloneRelativeFileBaseUrl<'_>, entrypoint: &ModuleSpecifier, - cli_options: &CliOptions, + include_files: &[ModuleSpecifier], compile_flags: &CompileFlags, ) -> Result<(), AnyError> { - let ca_data = match cli_options.ca_data() { + let ca_data = match self.cli_options.ca_data() { Some(CaData::File(ca_file)) => Some( - std::fs::read(ca_file) - .with_context(|| format!("Reading: {ca_file}"))?, + std::fs::read(ca_file).with_context(|| format!("Reading {ca_file}"))?, ), Some(CaData::Bytes(bytes)) => Some(bytes.clone()), None => None, }; let root_path = root_dir_url.inner().to_file_path().unwrap(); - let (maybe_npm_vfs, node_modules, npm_snapshot) = match self - .npm_resolver - .as_inner() - { - InnerCliNpmResolverRef::Managed(managed) => { - let snapshot = - managed.serialized_valid_snapshot_for_system(&self.npm_system_info); - if !snapshot.as_serialized().packages.is_empty() { - let npm_vfs_builder = self.build_npm_vfs(&root_path, cli_options)?; + let (maybe_npm_vfs, node_modules, npm_snapshot) = + match self.npm_resolver.as_inner() { + InnerCliNpmResolverRef::Managed(managed) => { + let snapshot = + managed.serialized_valid_snapshot_for_system(&self.npm_system_info); + if !snapshot.as_serialized().packages.is_empty() { + let npm_vfs_builder = self + .build_npm_vfs(&root_path) + .context("Building npm vfs.")?; + ( + Some(npm_vfs_builder), + Some(NodeModules::Managed { + node_modules_dir: self + .npm_resolver + .root_node_modules_path() + .map(|path| { + root_dir_url + .specifier_key( + &ModuleSpecifier::from_directory_path(path).unwrap(), + ) + .into_owned() + }), + }), + Some(snapshot), + ) + } else { + (None, None, None) + } + } + InnerCliNpmResolverRef::Byonm(resolver) => { + let npm_vfs_builder = self.build_npm_vfs(&root_path)?; ( Some(npm_vfs_builder), - Some(NodeModules::Managed { - node_modules_dir: self.npm_resolver.root_node_modules_path().map( - |path| { + Some(NodeModules::Byonm { + root_node_modules_dir: resolver.root_node_modules_path().map( + |node_modules_dir| { root_dir_url .specifier_key( - &ModuleSpecifier::from_directory_path(path).unwrap(), + &ModuleSpecifier::from_directory_path(node_modules_dir) + .unwrap(), ) .into_owned() }, ), }), - Some(snapshot), + None, ) - } else { - (None, None, None) } - } - InnerCliNpmResolverRef::Byonm(resolver) => { - let npm_vfs_builder = self.build_npm_vfs(&root_path, cli_options)?; - ( - Some(npm_vfs_builder), - Some(NodeModules::Byonm { - root_node_modules_dir: resolver.root_node_modules_path().map( - |node_modules_dir| { - root_dir_url - .specifier_key( - &ModuleSpecifier::from_directory_path(node_modules_dir) - .unwrap(), - ) - .into_owned() - }, - ), - }), - None, - ) - } - }; + }; let mut vfs = if let Some(npm_vfs) = maybe_npm_vfs { npm_vfs } else { VfsBuilder::new(root_path.clone())? }; + for include_file in include_files { + let path = deno_path_util::url_to_file_path(include_file)?; + if path.is_dir() { + // TODO(#26941): we should analyze if any of these are + // modules in order to include their dependencies + vfs + .add_dir_recursive(&path) + .with_context(|| format!("Including {}", path.display()))?; + } else { + vfs + .add_file_at_path(&path) + .with_context(|| format!("Including {}", path.display()))?; + } + } let mut remote_modules_store = RemoteModulesStoreBuilder::default(); - let mut code_cache_key_hasher = if cli_options.code_cache_enabled() { + let mut code_cache_key_hasher = if self.cli_options.code_cache_enabled() { Some(FastInsecureHasher::new_deno_versioned()) } else { None @@ -648,6 +675,9 @@ impl<'a> DenoCompileBinaryWriter<'a> { deno_graph::Module::Json(m) => { (Some(m.source.as_bytes().to_vec()), m.media_type) } + deno_graph::Module::Wasm(m) => { + (Some(m.source.to_vec()), MediaType::Wasm) + } deno_graph::Module::Npm(_) | deno_graph::Module::Node(_) | deno_graph::Module::External(_) => (None, MediaType::Unknown), @@ -671,7 +701,7 @@ impl<'a> DenoCompileBinaryWriter<'a> { } remote_modules_store.add_redirects(&graph.redirects); - let env_vars_from_env_file = match cli_options.env_file_name() { + let env_vars_from_env_file = match self.cli_options.env_file_name() { Some(env_filenames) => { let mut aggregated_env_vars = IndexMap::new(); for env_filename in env_filenames.iter().rev() { @@ -687,16 +717,17 @@ impl<'a> DenoCompileBinaryWriter<'a> { let metadata = Metadata { argv: compile_flags.args.clone(), - seed: cli_options.seed(), + seed: self.cli_options.seed(), code_cache_key: code_cache_key_hasher.map(|h| h.finish()), - location: cli_options.location_flag().clone(), - permissions: cli_options.permission_flags().clone(), - v8_flags: cli_options.v8_flags().clone(), - unsafely_ignore_certificate_errors: cli_options + location: self.cli_options.location_flag().clone(), + permissions: self.cli_options.permission_flags().clone(), + v8_flags: self.cli_options.v8_flags().clone(), + unsafely_ignore_certificate_errors: self + .cli_options .unsafely_ignore_certificate_errors() .clone(), - log_level: cli_options.log_level(), - ca_stores: cli_options.ca_stores().clone(), + log_level: self.cli_options.log_level(), + ca_stores: self.cli_options.ca_stores().clone(), ca_data, env_vars_from_env_file, entrypoint_key: root_dir_url.specifier_key(entrypoint).into_owned(), @@ -739,11 +770,11 @@ impl<'a> DenoCompileBinaryWriter<'a> { node_modules, unstable_config: UnstableConfig { legacy_flag_enabled: false, - bare_node_builtins: cli_options.unstable_bare_node_builtins(), - sloppy_imports: cli_options.unstable_sloppy_imports(), - features: cli_options.unstable_features(), + bare_node_builtins: self.cli_options.unstable_bare_node_builtins(), + sloppy_imports: self.cli_options.unstable_sloppy_imports(), + features: self.cli_options.unstable_features(), }, - otel_config: cli_options.otel_config(), + otel_config: self.cli_options.otel_config(), }; write_binary_bytes( @@ -755,13 +786,10 @@ impl<'a> DenoCompileBinaryWriter<'a> { vfs, compile_flags, ) + .context("Writing binary bytes") } - fn build_npm_vfs( - &self, - root_path: &Path, - cli_options: &CliOptions, - ) -> Result { + fn build_npm_vfs(&self, root_path: &Path) -> Result { fn maybe_warn_different_system(system_info: &NpmSystemInfo) { if system_info != &NpmSystemInfo::default() { log::warn!("{} The node_modules directory may be incompatible with the target system.", crate::colors::yellow("Warning")); @@ -838,13 +866,18 @@ impl<'a> DenoCompileBinaryWriter<'a> { InnerCliNpmResolverRef::Byonm(_) => { maybe_warn_different_system(&self.npm_system_info); let mut builder = VfsBuilder::new(root_path.to_path_buf())?; - for pkg_json in cli_options.workspace().package_jsons() { + for pkg_json in self.cli_options.workspace().package_jsons() { builder.add_file_at_path(&pkg_json.path)?; } // traverse and add all the node_modules directories in the workspace let mut pending_dirs = VecDeque::new(); pending_dirs.push_back( - cli_options.workspace().root_dir().to_file_path().unwrap(), + self + .cli_options + .workspace() + .root_dir() + .to_file_path() + .unwrap(), ); while let Some(pending_dir) = pending_dirs.pop_front() { let mut entries = fs::read_dir(&pending_dir) diff --git a/cli/standalone/virtual_fs.rs b/cli/standalone/virtual_fs.rs index 26bb0db75f..d1084f016c 100644 --- a/cli/standalone/virtual_fs.rs +++ b/cli/standalone/virtual_fs.rs @@ -51,7 +51,8 @@ pub struct VfsBuilder { impl VfsBuilder { pub fn new(root_path: PathBuf) -> Result { - let root_path = canonicalize_path(&root_path)?; + let root_path = canonicalize_path(&root_path) + .with_context(|| format!("Canonicalizing {}", root_path.display()))?; log::debug!("Building vfs with root '{}'", root_path.display()); Ok(Self { root_dir: VirtualDirectory { diff --git a/cli/task_runner.rs b/cli/task_runner.rs index 43840e868d..ec043f280e 100644 --- a/cli/task_runner.rs +++ b/cli/task_runner.rs @@ -483,20 +483,32 @@ fn resolve_execution_path_from_npx_shim( static SCRIPT_PATH_RE: Lazy = lazy_regex::lazy_regex!(r#""\$basedir\/([^"]+)" "\$@""#); - if text.starts_with("#!/usr/bin/env node") { - // launch this file itself because it's a JS file - Some(file_path) - } else { - // Search for... - // > "$basedir/../next/dist/bin/next" "$@" - // ...which is what it will look like on Windows - SCRIPT_PATH_RE - .captures(text) - .and_then(|c| c.get(1)) - .map(|relative_path| { - file_path.parent().unwrap().join(relative_path.as_str()) - }) + let maybe_first_line = { + let index = text.find("\n")?; + Some(&text[0..index]) + }; + + if let Some(first_line) = maybe_first_line { + // NOTE(bartlomieju): this is not perfect, but handle two most common scenarios + // where Node is run without any args. If there are args then we use `NodeCommand` + // struct. + if first_line == "#!/usr/bin/env node" + || first_line == "#!/usr/bin/env -S node" + { + // launch this file itself because it's a JS file + return Some(file_path); + } } + + // Search for... + // > "$basedir/../next/dist/bin/next" "$@" + // ...which is what it will look like on Windows + SCRIPT_PATH_RE + .captures(text) + .and_then(|c| c.get(1)) + .map(|relative_path| { + file_path.parent().unwrap().join(relative_path.as_str()) + }) } fn resolve_managed_npm_commands( @@ -564,6 +576,16 @@ mod test { let unix_shim = r#"#!/usr/bin/env node "use strict"; console.log('Hi!'); +"#; + let path = PathBuf::from("/node_modules/.bin/example"); + assert_eq!( + resolve_execution_path_from_npx_shim(path.clone(), unix_shim).unwrap(), + path + ); + // example shim on unix + let unix_shim = r#"#!/usr/bin/env -S node +"use strict"; +console.log('Hi!'); "#; let path = PathBuf::from("/node_modules/.bin/example"); assert_eq!( diff --git a/cli/tools/check.rs b/cli/tools/check.rs index d880278884..ad5c7c3ab1 100644 --- a/cli/tools/check.rs +++ b/cli/tools/check.rs @@ -380,6 +380,11 @@ fn get_check_hash( hasher.write_str(module.specifier.as_str()); hasher.write_str(&module.source); } + Module::Wasm(module) => { + has_file_to_type_check = true; + hasher.write_str(module.specifier.as_str()); + hasher.write_str(&module.source_dts); + } Module::External(module) => { hasher.write_str(module.specifier.as_str()); } @@ -437,6 +442,7 @@ fn get_tsc_roots( | MediaType::SourceMap | MediaType::Unknown => None, }, + Module::Wasm(module) => Some((module.specifier.clone(), MediaType::Dmts)), Module::External(_) | Module::Node(_) | Module::Npm(_) diff --git a/cli/tools/compile.rs b/cli/tools/compile.rs index b3e9993379..4fa9963683 100644 --- a/cli/tools/compile.rs +++ b/cli/tools/compile.rs @@ -7,6 +7,7 @@ use crate::factory::CliFactory; use crate::http_util::HttpClientProvider; use crate::standalone::binary::StandaloneRelativeFileBaseUrl; use crate::standalone::is_standalone_binary; +use deno_ast::MediaType; use deno_ast::ModuleSpecifier; use deno_core::anyhow::bail; use deno_core::anyhow::Context; @@ -31,15 +32,12 @@ pub async fn compile( let module_graph_creator = factory.module_graph_creator().await?; let binary_writer = factory.create_compile_binary_writer().await?; let http_client = factory.http_client_provider(); - let module_specifier = cli_options.resolve_main_module()?; - let module_roots = { - let mut vec = Vec::with_capacity(compile_flags.include.len() + 1); - vec.push(module_specifier.clone()); - for side_module in &compile_flags.include { - vec.push(resolve_url_or_path(side_module, cli_options.initial_cwd())?); - } - vec - }; + let entrypoint = cli_options.resolve_main_module()?; + let (module_roots, include_files) = get_module_roots_and_include_files( + entrypoint, + &compile_flags, + cli_options.initial_cwd(), + )?; // this is not supported, so show a warning about it, but don't error in order // to allow someone to still run `deno compile` when this is in a deno.json @@ -82,18 +80,22 @@ pub async fn compile( check_warn_tsconfig(&ts_config_for_emit); let root_dir_url = resolve_root_dir_from_specifiers( cli_options.workspace().root_dir(), - graph.specifiers().map(|(s, _)| s).chain( - cli_options - .node_modules_dir_path() - .and_then(|p| ModuleSpecifier::from_directory_path(p).ok()) - .iter(), - ), + graph + .specifiers() + .map(|(s, _)| s) + .chain( + cli_options + .node_modules_dir_path() + .and_then(|p| ModuleSpecifier::from_directory_path(p).ok()) + .iter(), + ) + .chain(include_files.iter()), ); log::debug!("Binary root dir: {}", root_dir_url); log::info!( "{} {} to {}", colors::green("Compile"), - module_specifier.to_string(), + entrypoint, output_path.display(), ); validate_output_path(&output_path)?; @@ -118,9 +120,9 @@ pub async fn compile( file, &graph, StandaloneRelativeFileBaseUrl::from(&root_dir_url), - module_specifier, + entrypoint, + &include_files, &compile_flags, - cli_options, ) .await .with_context(|| { @@ -212,6 +214,48 @@ fn validate_output_path(output_path: &Path) -> Result<(), AnyError> { Ok(()) } +fn get_module_roots_and_include_files( + entrypoint: &ModuleSpecifier, + compile_flags: &CompileFlags, + initial_cwd: &Path, +) -> Result<(Vec, Vec), AnyError> { + fn is_module_graph_module(url: &ModuleSpecifier) -> bool { + if url.scheme() != "file" { + return true; + } + let media_type = MediaType::from_specifier(url); + match media_type { + MediaType::JavaScript + | MediaType::Jsx + | MediaType::Mjs + | MediaType::Cjs + | MediaType::TypeScript + | MediaType::Mts + | MediaType::Cts + | MediaType::Dts + | MediaType::Dmts + | MediaType::Dcts + | MediaType::Tsx + | MediaType::Json + | MediaType::Wasm => true, + MediaType::Css | MediaType::SourceMap | MediaType::Unknown => false, + } + } + + let mut module_roots = Vec::with_capacity(compile_flags.include.len() + 1); + let mut include_files = Vec::with_capacity(compile_flags.include.len()); + module_roots.push(entrypoint.clone()); + for side_module in &compile_flags.include { + let url = resolve_url_or_path(side_module, initial_cwd)?; + if is_module_graph_module(&url) { + module_roots.push(url); + } else { + include_files.push(url); + } + } + Ok((module_roots, include_files)) +} + async fn resolve_compile_executable_output_path( http_client_provider: &HttpClientProvider, compile_flags: &CompileFlags, diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs index e33da4efb2..4487d70fd7 100644 --- a/cli/tools/doc.rs +++ b/cli/tools/doc.rs @@ -21,6 +21,8 @@ use deno_core::error::AnyError; use deno_core::serde_json; use deno_doc as doc; use deno_doc::html::UrlResolveKind; +use deno_doc::html::UsageComposer; +use deno_doc::html::UsageComposerEntry; use deno_graph::source::NullFileSystem; use deno_graph::EsParser; use deno_graph::GraphKind; @@ -35,6 +37,9 @@ use std::sync::Arc; const JSON_SCHEMA_VERSION: u8 = 1; +const PRISM_CSS: &str = include_str!("./doc/prism.css"); +const PRISM_JS: &str = include_str!("./doc/prism.js"); + async fn generate_doc_nodes_for_builtin_types( doc_flags: DocFlags, parser: &dyn EsParser, @@ -312,10 +317,6 @@ impl deno_doc::html::HrefResolver for DocResolver { None } - fn resolve_usage(&self, current_resolve: UrlResolveKind) -> Option { - current_resolve.get_file().map(|file| file.path.to_string()) - } - fn resolve_source(&self, location: &deno_doc::Location) -> Option { Some(location.filename.to_string()) } @@ -350,105 +351,30 @@ impl deno_doc::html::HrefResolver for DocResolver { } } -struct DenoDocResolver(bool); +struct DocComposer; -impl deno_doc::html::HrefResolver for DenoDocResolver { - fn resolve_path( +impl UsageComposer for DocComposer { + fn is_single_mode(&self) -> bool { + true + } + + fn compose( &self, - current: UrlResolveKind, - target: UrlResolveKind, - ) -> String { - let path = deno_doc::html::href_path_resolve(current, target); - if self.0 { - if let Some(path) = path - .strip_suffix("index.html") - .or_else(|| path.strip_suffix(".html")) - { - return path.to_owned(); - } - } - - path - } - - fn resolve_global_symbol(&self, _symbol: &[String]) -> Option { - None - } - - fn resolve_import_href( - &self, - _symbol: &[String], - _src: &str, - ) -> Option { - None - } - - fn resolve_usage(&self, _current_resolve: UrlResolveKind) -> Option { - None - } - - fn resolve_source(&self, _location: &deno_doc::Location) -> Option { - None - } - - fn resolve_external_jsdoc_module( - &self, - _module: &str, - _symbol: Option<&str>, - ) -> Option<(String, String)> { - None - } -} - -struct NodeDocResolver(bool); - -impl deno_doc::html::HrefResolver for NodeDocResolver { - fn resolve_path( - &self, - current: UrlResolveKind, - target: UrlResolveKind, - ) -> String { - let path = deno_doc::html::href_path_resolve(current, target); - if self.0 { - if let Some(path) = path - .strip_suffix("index.html") - .or_else(|| path.strip_suffix(".html")) - { - return path.to_owned(); - } - } - - path - } - - fn resolve_global_symbol(&self, _symbol: &[String]) -> Option { - None - } - - fn resolve_import_href( - &self, - _symbol: &[String], - _src: &str, - ) -> Option { - None - } - - fn resolve_usage(&self, current_resolve: UrlResolveKind) -> Option { + current_resolve: UrlResolveKind, + usage_to_md: deno_doc::html::UsageToMd, + ) -> IndexMap { current_resolve .get_file() - .map(|file| format!("node:{}", file.path)) - } - - fn resolve_source(&self, _location: &deno_doc::Location) -> Option { - None - } - - fn resolve_external_jsdoc_module( - &self, - _module: &str, - _symbol: Option<&str>, - ) -> Option<(String, String)> { - None + .map(|current_file| { + IndexMap::from([( + UsageComposerEntry { + name: "".to_string(), + icon: None, + }, + usage_to_md(current_file.path.as_str(), None), + )]) + }) + .unwrap_or_default() } } @@ -461,30 +387,10 @@ fn generate_docs_directory( let cwd = std::env::current_dir().context("Failed to get CWD")?; let output_dir_resolved = cwd.join(&html_options.output); - let internal_env = std::env::var("DENO_INTERNAL_HTML_DOCS").ok(); - - let href_resolver: Rc = if internal_env - .as_ref() - .is_some_and(|internal_html_docs| internal_html_docs == "node") - { - Rc::new(NodeDocResolver(html_options.strip_trailing_html)) - } else if internal_env - .as_ref() - .is_some_and(|internal_html_docs| internal_html_docs == "deno") - || deno_ns.is_empty() - { - Rc::new(DenoDocResolver(html_options.strip_trailing_html)) - } else { - Rc::new(DocResolver { - deno_ns, - strip_trailing_html: html_options.strip_trailing_html, - }) - }; - let category_docs = if let Some(category_docs_path) = &html_options.category_docs_path { let content = std::fs::read(category_docs_path)?; - Some(deno_core::serde_json::from_slice(&content)?) + Some(serde_json::from_slice(&content)?) } else { None }; @@ -493,7 +399,7 @@ fn generate_docs_directory( &html_options.symbol_redirect_map_path { let content = std::fs::read(symbol_redirect_map_path)?; - Some(deno_core::serde_json::from_slice(&content)?) + Some(serde_json::from_slice(&content)?) } else { None }; @@ -502,7 +408,7 @@ fn generate_docs_directory( &html_options.default_symbol_map_path { let content = std::fs::read(default_symbol_map_path)?; - Some(deno_core::serde_json::from_slice(&content)?) + Some(serde_json::from_slice(&content)?) } else { None }; @@ -511,17 +417,59 @@ fn generate_docs_directory( package_name: html_options.name.clone(), main_entrypoint: None, rewrite_map, - href_resolver, - usage_composer: None, + href_resolver: Rc::new(DocResolver { + deno_ns, + strip_trailing_html: html_options.strip_trailing_html, + }), + usage_composer: Rc::new(DocComposer), category_docs, - disable_search: internal_env.is_some(), + disable_search: false, symbol_redirect_map, default_symbol_map, + markdown_renderer: deno_doc::html::comrak::create_renderer( + None, + Some(Box::new(|ammonia| { + ammonia.add_allowed_classes( + "code", + &[ + "language-ts", + "language-tsx", + "language-typescript", + "language-js", + "language-jsx", + "language-javascript", + "language-bash", + "language-shell", + "language-md", + "language-markdown", + "language-rs", + "language-rust", + "language-html", + "language-xml", + "language-css", + "language-json", + "language-regex", + "language-svg", + ], + ); + })), + None, + ), + markdown_stripper: Rc::new(deno_doc::html::comrak::strip), + head_inject: Some(Rc::new(|root| { + format!( + r#""#, + deno_doc::html::comrak::COMRAK_STYLESHEET_FILENAME + ) + })), }; - let files = deno_doc::html::generate(options, doc_nodes_by_url) + let mut files = deno_doc::html::generate(options, doc_nodes_by_url) .context("Failed to generate HTML documentation")?; + files.insert("prism.js".to_string(), PRISM_JS.to_string()); + files.insert("prism.css".to_string(), PRISM_CSS.to_string()); + let path = &output_dir_resolved; let _ = std::fs::remove_dir_all(path); std::fs::create_dir(path) diff --git a/cli/tools/doc/prism.css b/cli/tools/doc/prism.css new file mode 100644 index 0000000000..afc2ef6ca9 --- /dev/null +++ b/cli/tools/doc/prism.css @@ -0,0 +1,3 @@ +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+json+markdown+regex+rust+typescript */ +code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} diff --git a/cli/tools/doc/prism.js b/cli/tools/doc/prism.js new file mode 100644 index 0000000000..23bf919589 --- /dev/null +++ b/cli/tools/doc/prism.js @@ -0,0 +1,15 @@ +// MIT LICENSE +// Copyright (c) 2012 Lea Verou +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+json+markdown+regex+rust+typescript */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; +!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",a={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},n={bash:a,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:a}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:n},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:n.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},a.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=n.variable[1].inside,i=0;i/g,(function(){return"(?:\\\\.|[^\\\\\n\r]|(?:\n|\r\n?)(?![\r\n]))"})),RegExp("((?:^|[^\\\\])(?:\\\\{2})*)(?:"+n+")")}var t="(?:\\\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\\\|\r\n`])+",a="\\|?__(?:\\|__)+\\|?(?:(?:\n|\r\n?)|(?![^]))".replace(/__/g,(function(){return t})),i="\\|?[ \t]*:?-{3,}:?[ \t]*(?:\\|[ \t]*:?-{3,}:?[ \t]*)+\\|?(?:\n|\r\n?)";n.languages.markdown=n.languages.extend("markup",{}),n.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:n.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+i+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+i+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(t),inside:n.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+i+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(t),alias:"important",inside:n.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:e("\\b__(?:(?!_)|_(?:(?!_))+_)+__\\b|\\*\\*(?:(?!\\*)|\\*(?:(?!\\*))+\\*)+\\*\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:e("\\b_(?:(?!_)|__(?:(?!_))+__)+_\\b|\\*(?:(?!\\*)|\\*\\*(?:(?!\\*))+\\*\\*)+\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:e("(~~?)(?:(?!~))+\\2"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:e('!?\\[(?:(?!\\]))+\\](?:\\([^\\s)]+(?:[\t ]+"(?:\\\\.|[^"\\\\])*")?\\)|[ \t]?\\[(?:(?!\\]))+\\])'),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(e){["url","bold","italic","strike","code-snippet"].forEach((function(t){e!==t&&(n.languages.markdown[e].inside.content.inside[t]=n.languages.markdown[t])}))})),n.hooks.add("after-tokenize",(function(n){"markdown"!==n.language&&"md"!==n.language||function n(e){if(e&&"string"!=typeof e)for(var t=0,a=e.length;t",quot:'"'},l=String.fromCodePoint||String.fromCharCode;n.languages.md=n.languages.markdown}(Prism); +!function(a){var e={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},n=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|0[0-7]{0,2}|[123][0-7]{2}|c[a-zA-Z]|.)/,t="(?:[^\\\\-]|"+n.source+")",s=RegExp(t+"-"+t),i={pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"};a.languages.regex={"char-class":{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"char-class-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"char-class-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:s,inside:{escape:n,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":e,"char-set":{pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},escape:n}},"special-escape":e,"char-set":{pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":i}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:n,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|)*\\*/",t=0;t<2;t++)a=a.replace(//g,(function(){return a}));a=a.replace(//g,(function(){return"[^\\s\\S]"})),e.languages.rust={comment:[{pattern:RegExp("(^|[^\\\\])"+a),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism); +!function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var s=e.languages.extend("typescript",{});delete s["class-name"],e.languages.typescript["class-name"].inside=s,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:s}}}}),e.languages.ts=e.languages.typescript}(Prism); diff --git a/cli/tools/fmt.rs b/cli/tools/fmt.rs index d40abd5f50..9c2c709129 100644 --- a/cli/tools/fmt.rs +++ b/cli/tools/fmt.rs @@ -272,6 +272,7 @@ fn format_markdown( | "njk" | "yml" | "yaml" + | "sql" ) { // It's important to tell dprint proper file extension, otherwise // it might parse the file twice. @@ -301,6 +302,13 @@ fn format_markdown( } } "yml" | "yaml" => format_yaml(text, fmt_options), + "sql" => { + if unstable_options.sql { + format_sql(text, fmt_options) + } else { + Ok(None) + } + } _ => { let mut codeblock_config = get_resolved_typescript_config(fmt_options); @@ -503,7 +511,48 @@ pub fn format_html( }) } -/// Formats a single TS, TSX, JS, JSX, JSONC, JSON, MD, or IPYNB file. +pub fn format_sql( + file_text: &str, + fmt_options: &FmtOptionsConfig, +) -> Result, AnyError> { + let ignore_file = file_text + .lines() + .take_while(|line| line.starts_with("--")) + .any(|line| { + line + .strip_prefix("--") + .unwrap() + .trim() + .starts_with("deno-fmt-ignore-file") + }); + + if ignore_file { + return Ok(None); + } + + let mut formatted_str = sqlformat::format( + file_text, + &sqlformat::QueryParams::None, + &sqlformat::FormatOptions { + ignore_case_convert: None, + indent: if fmt_options.use_tabs.unwrap_or_default() { + sqlformat::Indent::Tabs + } else { + sqlformat::Indent::Spaces(fmt_options.indent_width.unwrap_or(2)) + }, + // leave one blank line between queries. + lines_between_queries: 2, + uppercase: Some(true), + }, + ); + + // Add single new line to the end of file. + formatted_str.push('\n'); + + Ok(Some(formatted_str)) +} + +/// Formats a single TS, TSX, JS, JSX, JSONC, JSON, MD, IPYNB or SQL file. pub fn format_file( file_path: &Path, file_text: &str, @@ -538,6 +587,13 @@ pub fn format_file( format_file(file_path, &file_text, fmt_options, unstable_options, None) }, ), + "sql" => { + if unstable_options.sql { + format_sql(file_text, fmt_options) + } else { + Ok(None) + } + } _ => { let config = get_resolved_typescript_config(fmt_options); dprint_plugin_typescript::format_text( @@ -1209,6 +1265,7 @@ fn is_supported_ext_fmt(path: &Path) -> bool { | "yml" | "yaml" | "ipynb" + | "sql" ) }) } @@ -1269,6 +1326,11 @@ mod test { assert!(is_supported_ext_fmt(Path::new("foo.yaml"))); assert!(is_supported_ext_fmt(Path::new("foo.YaML"))); assert!(is_supported_ext_fmt(Path::new("foo.ipynb"))); + assert!(is_supported_ext_fmt(Path::new("foo.sql"))); + assert!(is_supported_ext_fmt(Path::new("foo.Sql"))); + assert!(is_supported_ext_fmt(Path::new("foo.sQl"))); + assert!(is_supported_ext_fmt(Path::new("foo.sqL"))); + assert!(is_supported_ext_fmt(Path::new("foo.SQL"))); } #[test] diff --git a/cli/tools/info.rs b/cli/tools/info.rs index c2f5a8cb8d..c3c37f0268 100644 --- a/cli/tools/info.rs +++ b/cli/tools/info.rs @@ -126,6 +126,7 @@ fn print_cache_info( let registry_cache = dir.registries_folder_path(); let mut origin_dir = dir.origin_data_folder_path(); let deno_dir = dir.root_path_for_display().to_string(); + let web_cache_dir = crate::worker::get_cache_storage_dir(); if let Some(location) = &location { origin_dir = @@ -143,6 +144,7 @@ fn print_cache_info( "typescriptCache": typescript_cache, "registryCache": registry_cache, "originStorage": origin_dir, + "webCacheStorage": web_cache_dir, }); if location.is_some() { @@ -177,6 +179,11 @@ fn print_cache_info( colors::bold("Origin storage:"), origin_dir.display() ); + println!( + "{} {}", + colors::bold("Web cache storage:"), + web_cache_dir.display() + ); if location.is_some() { println!( "{} {}", @@ -446,6 +453,7 @@ impl<'a> GraphDisplayContext<'a> { let maybe_cache_info = match root { Module::Js(module) => module.maybe_cache_info.as_ref(), Module::Json(module) => module.maybe_cache_info.as_ref(), + Module::Wasm(module) => module.maybe_cache_info.as_ref(), Module::Node(_) | Module::Npm(_) | Module::External(_) => None, }; if let Some(cache_info) = maybe_cache_info { @@ -468,6 +476,7 @@ impl<'a> GraphDisplayContext<'a> { let size = match m { Module::Js(module) => module.size(), Module::Json(module) => module.size(), + Module::Wasm(module) => module.size(), Module::Node(_) | Module::Npm(_) | Module::External(_) => 0, }; size as f64 @@ -567,6 +576,7 @@ impl<'a> GraphDisplayContext<'a> { Specifier(_) => match module { Module::Js(module) => Some(module.size() as u64), Module::Json(module) => Some(module.size() as u64), + Module::Wasm(module) => Some(module.size() as u64), Module::Node(_) | Module::Npm(_) | Module::External(_) => None, }, }; @@ -580,8 +590,8 @@ impl<'a> GraphDisplayContext<'a> { Package(package) => { tree_node.children.extend(self.build_npm_deps(package)); } - Specifier(_) => { - if let Some(module) = module.js() { + Specifier(_) => match module { + Module::Js(module) => { if let Some(types_dep) = &module.maybe_types_dependency { if let Some(child) = self.build_resolved_info(&types_dep.dependency, true) @@ -593,7 +603,16 @@ impl<'a> GraphDisplayContext<'a> { tree_node.children.extend(self.build_dep_info(dep)); } } - } + Module::Wasm(module) => { + for dep in module.dependencies.values() { + tree_node.children.extend(self.build_dep_info(dep)); + } + } + Module::Json(_) + | Module::Npm(_) + | Module::Node(_) + | Module::External(_) => {} + }, } } tree_node @@ -658,7 +677,7 @@ impl<'a> GraphDisplayContext<'a> { }; self.build_error_msg(specifier, message.as_ref()) } - ModuleError::ParseErr(_, _) => { + ModuleError::ParseErr(_, _) | ModuleError::WasmParseErr(_, _) => { self.build_error_msg(specifier, "(parsing error)") } ModuleError::UnsupportedImportAttributeType { .. } => { diff --git a/cli/tools/registry/mod.rs b/cli/tools/registry/mod.rs index 12289c581b..89447f04f9 100644 --- a/cli/tools/registry/mod.rs +++ b/cli/tools/registry/mod.rs @@ -12,6 +12,7 @@ use std::sync::Arc; use base64::prelude::BASE64_STANDARD; use base64::Engine; use deno_ast::ModuleSpecifier; +use deno_config::deno_json::ConfigFile; use deno_config::workspace::JsrPackageConfig; use deno_config::workspace::PackageJsonDepResolution; use deno_config::workspace::Workspace; @@ -90,13 +91,14 @@ pub async fn publish( let cli_options = cli_factory.cli_options()?; let directory_path = cli_options.initial_cwd(); - let publish_configs = cli_options.start_dir.jsr_packages_for_publish(); + let mut publish_configs = cli_options.start_dir.jsr_packages_for_publish(); if publish_configs.is_empty() { match cli_options.start_dir.maybe_deno_json() { Some(deno_json) => { debug_assert!(!deno_json.is_package()); + error_missing_exports_field(deno_json)?; bail!( - "Missing 'name', 'version' and 'exports' field in '{}'.", + "Missing 'name' or 'exports' field in '{}'.", deno_json.specifier ); } @@ -108,6 +110,18 @@ pub async fn publish( } } } + + if let Some(version) = &publish_flags.set_version { + if publish_configs.len() > 1 { + bail!("Cannot use --set-version when publishing a workspace. Change your cwd to an individual package instead."); + } + if let Some(publish_config) = publish_configs.get_mut(0) { + let mut config_file = publish_config.config_file.as_ref().clone(); + config_file.json.version = Some(version.clone()); + publish_config.config_file = Arc::new(config_file); + } + } + let specifier_unfurler = Arc::new(SpecifierUnfurler::new( if cli_options.unstable_sloppy_imports() { Some(CliSloppyImportsResolver::new(SloppyImportsCachedFs::new( @@ -404,43 +418,15 @@ impl PublishPreparer { graph: Arc, diagnostics_collector: &PublishDiagnosticsCollector, ) -> Result, AnyError> { - static SUGGESTED_ENTRYPOINTS: [&str; 4] = - ["mod.ts", "mod.js", "index.ts", "index.js"]; - let deno_json = &package.config_file; let config_path = deno_json.specifier.to_file_path().unwrap(); let root_dir = config_path.parent().unwrap().to_path_buf(); - let Some(version) = deno_json.json.version.clone() else { - bail!("{} is missing 'version' field", deno_json.specifier); - }; - if deno_json.json.exports.is_none() { - let mut suggested_entrypoint = None; - - for entrypoint in SUGGESTED_ENTRYPOINTS { - if root_dir.join(entrypoint).exists() { - suggested_entrypoint = Some(entrypoint); - break; - } - } - - let exports_content = format!( - r#"{{ - "name": "{}", - "version": "{}", - "exports": "{}" -}}"#, - package.name, - version, - suggested_entrypoint.unwrap_or("") - ); - - bail!( - "You did not specify an entrypoint to \"{}\" package in {}. Add `exports` mapping in the configuration file, eg:\n{}", - package.name, - deno_json.specifier, - exports_content - ); - } + let version = deno_json.json.version.clone().ok_or_else(|| { + deno_core::anyhow::anyhow!( + "{} is missing 'version' field", + deno_json.specifier + ) + })?; let Some(name_no_at) = package.name.strip_prefix('@') else { bail!("Invalid package name, use '@/ format"); }; @@ -1107,9 +1093,9 @@ fn collect_excluded_module_diagnostics( let graph_specifiers = graph .modules() .filter_map(|m| match m { - deno_graph::Module::Js(_) | deno_graph::Module::Json(_) => { - Some(m.specifier()) - } + deno_graph::Module::Js(_) + | deno_graph::Module::Json(_) + | deno_graph::Module::Wasm(_) => Some(m.specifier()), deno_graph::Module::Npm(_) | deno_graph::Module::Node(_) | deno_graph::Module::External(_) => None, @@ -1272,6 +1258,36 @@ fn has_license_file<'a>( }) } +fn error_missing_exports_field(deno_json: &ConfigFile) -> Result<(), AnyError> { + static SUGGESTED_ENTRYPOINTS: [&str; 4] = + ["mod.ts", "mod.js", "index.ts", "index.js"]; + let mut suggested_entrypoint = None; + + for entrypoint in SUGGESTED_ENTRYPOINTS { + if deno_json.dir_path().join(entrypoint).exists() { + suggested_entrypoint = Some(entrypoint); + break; + } + } + + let exports_content = format!( + r#"{{ + "name": "{}", + "version": "{}", + "exports": "{}" +}}"#, + deno_json.json.name.as_deref().unwrap_or("@scope/name"), + deno_json.json.name.as_deref().unwrap_or("0.0.0"), + suggested_entrypoint.unwrap_or("") + ); + + bail!( + "You did not specify an entrypoint in {}. Add `exports` mapping in the configuration file, eg:\n{}", + deno_json.specifier, + exports_content + ); +} + #[allow(clippy::print_stderr)] fn ring_bell() { // ASCII code for the bell character. diff --git a/cli/tools/task.rs b/cli/tools/task.rs index a13efbaf45..85145c7af7 100644 --- a/cli/tools/task.rs +++ b/cli/tools/task.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use std::collections::HashSet; +use std::num::NonZeroUsize; use std::path::Path; use std::path::PathBuf; use std::rc::Rc; @@ -15,6 +16,10 @@ use deno_core::anyhow::anyhow; use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::AnyError; +use deno_core::futures::future::LocalBoxFuture; +use deno_core::futures::stream::futures_unordered; +use deno_core::futures::FutureExt; +use deno_core::futures::StreamExt; use deno_core::url::Url; use deno_path_util::normalize_path; use deno_runtime::deno_node::NodeResolver; @@ -37,7 +42,7 @@ pub async fn execute_script( let factory = CliFactory::from_flags(flags); let cli_options = factory.cli_options()?; let start_dir = &cli_options.start_dir; - if !start_dir.has_deno_or_pkg_json() { + if !start_dir.has_deno_or_pkg_json() && !task_flags.eval { bail!("deno task couldn't find deno.json(c). See https://docs.deno.com/go/config") } let force_use_pkg_json = @@ -68,6 +73,13 @@ pub async fn execute_script( let node_resolver = factory.node_resolver().await?; let env_vars = task_runner::real_env_vars(); + let no_of_concurrent_tasks = if let Ok(value) = std::env::var("DENO_JOBS") { + value.parse::().ok() + } else { + std::thread::available_parallelism().ok() + } + .unwrap_or_else(|| NonZeroUsize::new(2).unwrap()); + let task_runner = TaskRunner { tasks_config, task_flags: &task_flags, @@ -75,7 +87,22 @@ pub async fn execute_script( node_resolver: node_resolver.as_ref(), env_vars, cli_options, + concurrency: no_of_concurrent_tasks.into(), }; + + if task_flags.eval { + return task_runner + .run_deno_task( + &Url::from_directory_path(cli_options.initial_cwd()).unwrap(), + &"".to_string(), + &TaskDefinition { + command: task_flags.task.as_ref().unwrap().to_string(), + dependencies: vec![], + description: None, + }, + ) + .await; + } task_runner.run_task(task_name).await } @@ -93,29 +120,155 @@ struct TaskRunner<'a> { node_resolver: &'a NodeResolver, env_vars: HashMap, cli_options: &'a CliOptions, + concurrency: usize, } impl<'a> TaskRunner<'a> { - async fn run_task( + pub async fn run_task( + &self, + task_name: &str, + ) -> Result { + match sort_tasks_topo(task_name, &self.tasks_config) { + Ok(sorted) => self.run_tasks_in_parallel(sorted).await, + Err(err) => match err { + TaskError::NotFound(name) => { + if self.task_flags.is_run { + return Err(anyhow!("Task not found: {}", name)); + } + + log::error!("Task not found: {}", name); + if log::log_enabled!(log::Level::Error) { + self.print_available_tasks()?; + } + Ok(1) + } + TaskError::TaskDepCycle { path } => { + log::error!("Task cycle detected: {}", path.join(" -> ")); + Ok(1) + } + }, + } + } + + pub fn print_available_tasks(&self) -> Result<(), std::io::Error> { + print_available_tasks( + &mut std::io::stderr(), + &self.cli_options.start_dir, + &self.tasks_config, + ) + } + + async fn run_tasks_in_parallel( + &self, + task_names: Vec, + ) -> Result { + struct PendingTasksContext { + completed: HashSet, + running: HashSet, + task_names: Vec, + } + + impl PendingTasksContext { + fn has_remaining_tasks(&self) -> bool { + self.completed.len() < self.task_names.len() + } + + fn mark_complete(&mut self, task_name: String) { + self.running.remove(&task_name); + self.completed.insert(task_name); + } + + fn get_next_task<'a>( + &mut self, + runner: &'a TaskRunner<'a>, + ) -> Option>> { + for name in &self.task_names { + if self.completed.contains(name) || self.running.contains(name) { + continue; + } + + let should_run = if let Ok((_, def)) = runner.get_task(name) { + match def { + TaskOrScript::Task(_, def) => def + .dependencies + .iter() + .all(|dep| self.completed.contains(dep)), + TaskOrScript::Script(_, _) => true, + } + } else { + false + }; + + if !should_run { + continue; + } + + self.running.insert(name.clone()); + let name = name.clone(); + return Some( + async move { + runner + .run_task_no_dependencies(&name) + .await + .map(|exit_code| (exit_code, name)) + } + .boxed_local(), + ); + } + None + } + } + + let mut context = PendingTasksContext { + completed: HashSet::with_capacity(task_names.len()), + running: HashSet::with_capacity(self.concurrency), + task_names, + }; + + let mut queue = futures_unordered::FuturesUnordered::new(); + + while context.has_remaining_tasks() { + while queue.len() < self.concurrency { + if let Some(task) = context.get_next_task(self) { + queue.push(task); + } else { + break; + } + } + + // If queue is empty at this point, then there are no more tasks in the queue. + let Some(result) = queue.next().await else { + debug_assert_eq!(context.task_names.len(), 0); + break; + }; + + let (exit_code, name) = result?; + if exit_code > 0 { + return Ok(exit_code); + } + + context.mark_complete(name); + } + + Ok(0) + } + + fn get_task( + &self, + task_name: &str, + ) -> Result<(&Url, TaskOrScript), TaskError> { + let Some(result) = self.tasks_config.task(task_name) else { + return Err(TaskError::NotFound(task_name.to_string())); + }; + + Ok(result) + } + + async fn run_task_no_dependencies( &self, task_name: &String, ) -> Result { - let Some((dir_url, task_or_script)) = self.tasks_config.task(task_name) - else { - if self.task_flags.is_run { - return Err(anyhow!("Task not found: {}", task_name)); - } - - log::error!("Task not found: {}", task_name); - if log::log_enabled!(log::Level::Error) { - print_available_tasks( - &mut std::io::stderr(), - &self.cli_options.start_dir, - &self.tasks_config, - )?; - } - return Ok(1); - }; + let (dir_url, task_or_script) = self.get_task(task_name.as_str()).unwrap(); match task_or_script { TaskOrScript::Task(_tasks, definition) => { @@ -234,6 +387,59 @@ impl<'a> TaskRunner<'a> { } } +#[derive(Debug)] +enum TaskError { + NotFound(String), + TaskDepCycle { path: Vec }, +} + +fn sort_tasks_topo( + name: &str, + task_config: &WorkspaceTasksConfig, +) -> Result, TaskError> { + fn sort_visit<'a>( + name: &'a str, + sorted: &mut Vec, + mut path: Vec<&'a str>, + tasks_config: &'a WorkspaceTasksConfig, + ) -> Result<(), TaskError> { + // Already sorted + if sorted.iter().any(|sorted_name| sorted_name == name) { + return Ok(()); + } + + // Graph has a cycle + if path.contains(&name) { + path.push(name); + return Err(TaskError::TaskDepCycle { + path: path.iter().map(|s| s.to_string()).collect(), + }); + } + + let Some(def) = tasks_config.task(name) else { + return Err(TaskError::NotFound(name.to_string())); + }; + + if let TaskOrScript::Task(_, actual_def) = def.1 { + for dep in &actual_def.dependencies { + let mut path = path.clone(); + path.push(name); + sort_visit(dep, sorted, path, tasks_config)? + } + } + + sorted.push(name.to_string()); + + Ok(()) + } + + let mut sorted: Vec = vec![]; + + sort_visit(name, &mut sorted, Vec::new(), task_config)?; + + Ok(sorted) +} + fn output_task(task_name: &str, script: &str) { log::info!( "{} {} {}", @@ -339,6 +545,14 @@ fn print_available_tasks( )?; } writeln!(writer, " {}", desc.task.command)?; + if !desc.task.dependencies.is_empty() { + writeln!( + writer, + " {} {}", + colors::gray("depends on:"), + colors::cyan(desc.task.dependencies.join(", ")) + )?; + } } Ok(()) diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js index 68d099253a..93b9e92d89 100644 --- a/cli/tsc/99_main_compiler.js +++ b/cli/tsc/99_main_compiler.js @@ -450,6 +450,12 @@ delete Object.prototype.__proto__; // We specify the resolution mode to be CommonJS for some npm files and this // diagnostic gets generated even though we're using custom module resolution. 1452, + // Module '...' cannot be imported using this construct. The specifier only resolves to an + // ES module, which cannot be imported with 'require'. + 1471, + // TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; + // however, the referenced file is an ECMAScript module and cannot be imported with 'require'. + 1479, // TS2306: File '.../index.d.ts' is not a module. // We get this for `x-typescript-types` declaration files which don't export // anything. We prefer to treat these as modules with no exports. diff --git a/cli/tsc/dts/lib.deno.ns.d.ts b/cli/tsc/dts/lib.deno.ns.d.ts index 8179e4223c..d9f66f11a7 100644 --- a/cli/tsc/dts/lib.deno.ns.d.ts +++ b/cli/tsc/dts/lib.deno.ns.d.ts @@ -4535,7 +4535,7 @@ declare namespace Deno { /** The object that is returned from a {@linkcode Deno.upgradeWebSocket} * request. * - * @category Web Sockets */ + * @category WebSockets */ export interface WebSocketUpgrade { /** The response object that represents the HTTP response to the client, * which should be used to the {@linkcode RequestEvent} `.respondWith()` for @@ -4549,7 +4549,7 @@ declare namespace Deno { /** Options which can be set when performing a * {@linkcode Deno.upgradeWebSocket} upgrade of a {@linkcode Request} * - * @category Web Sockets */ + * @category WebSockets */ export interface UpgradeWebSocketOptions { /** Sets the `.protocol` property on the client side web socket to the * value provided here, which should be one of the strings specified in the @@ -4597,7 +4597,7 @@ declare namespace Deno { * This operation does not yet consume the request or open the websocket. This * only happens once the returned response has been passed to `respondWith()`. * - * @category Web Sockets + * @category WebSockets */ export function upgradeWebSocket( request: Request, diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs index 8f8bed20a4..976d407c15 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -650,6 +650,10 @@ fn op_load_inner( media_type = MediaType::Json; Some(Cow::Borrowed(&*module.source)) } + Module::Wasm(module) => { + media_type = MediaType::Dts; + Some(Cow::Borrowed(&*module.source_dts)) + } Module::Npm(_) | Module::Node(_) => None, Module::External(module) => { // means it's Deno code importing an npm module @@ -889,6 +893,9 @@ fn resolve_graph_specifier_types( Some(Module::Json(module)) => { Ok(Some((module.specifier.clone(), module.media_type))) } + Some(Module::Wasm(module)) => { + Ok(Some((module.specifier.clone(), MediaType::Dmts))) + } Some(Module::Npm(module)) => { if let Some(npm) = &state.maybe_npm.as_ref() { let package_folder = npm @@ -1196,7 +1203,7 @@ mod tests { .context("Unable to get CWD") .unwrap(), ); - let mut op_state = OpState::new(None); + let mut op_state = OpState::new(None, None); op_state.put(state); op_state } diff --git a/cli/worker.rs b/cli/worker.rs index 3b09714d59..0b07bb4bf3 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -393,6 +393,13 @@ impl CliMainWorker { } } +// TODO(bartlomieju): this should be moved to some other place, added to avoid string +// duplication between worker setups and `deno info` output. +pub fn get_cache_storage_dir() -> PathBuf { + // Note: we currently use temp_dir() to avoid managing storage size. + std::env::temp_dir().join("deno_cache") +} + #[derive(Clone)] pub struct CliMainWorkerFactory { shared: Arc, @@ -529,10 +536,7 @@ impl CliMainWorkerFactory { }); let cache_storage_dir = maybe_storage_key.map(|key| { // TODO(@satyarohith): storage quota management - // Note: we currently use temp_dir() to avoid managing storage size. - std::env::temp_dir() - .join("deno_cache") - .join(checksum::gen(&[key.as_bytes()])) + get_cache_storage_dir().join(checksum::gen(&[key.as_bytes()])) }); // TODO(bartlomieju): this is cruft, update FeatureChecker to spit out @@ -729,10 +733,7 @@ fn create_web_worker_callback( .resolve_storage_key(&args.main_module); let cache_storage_dir = maybe_storage_key.map(|key| { // TODO(@satyarohith): storage quota management - // Note: we currently use temp_dir() to avoid managing storage size. - std::env::temp_dir() - .join("deno_cache") - .join(checksum::gen(&[key.as_bytes()])) + get_cache_storage_dir().join(checksum::gen(&[key.as_bytes()])) }); // TODO(bartlomieju): this is cruft, update FeatureChecker to spit out diff --git a/ext/ffi/dlfcn.rs b/ext/ffi/dlfcn.rs index 55909468f8..26d1b71e9f 100644 --- a/ext/ffi/dlfcn.rs +++ b/ext/ffi/dlfcn.rs @@ -15,6 +15,7 @@ use dlopen2::raw::Library; use serde::Deserialize; use serde_value::ValueDeserializer; use std::borrow::Cow; +use std::cell::RefCell; use std::collections::HashMap; use std::ffi::c_void; use std::rc::Rc; @@ -126,14 +127,17 @@ pub struct FfiLoadArgs { #[op2] pub fn op_ffi_load<'scope, FP>( scope: &mut v8::HandleScope<'scope>, - state: &mut OpState, + state: Rc>, #[serde] args: FfiLoadArgs, ) -> Result, DlfcnError> where FP: FfiPermissions + 'static, { - let permissions = state.borrow_mut::(); - let path = permissions.check_partial_with_path(&args.path)?; + let path = { + let mut state = state.borrow_mut(); + let permissions = state.borrow_mut::(); + permissions.check_partial_with_path(&args.path)? + }; let lib = Library::open(&path).map_err(|e| { dlopen2::Error::OpeningLibraryError(std::io::Error::new( @@ -215,6 +219,7 @@ where } } + let mut state = state.borrow_mut(); let out = v8::Array::new(scope, 2); let rid = state.resource_table.add(resource); let rid_v8 = v8::Integer::new_from_unsigned(scope, rid); diff --git a/ext/node/Cargo.toml b/ext/node/Cargo.toml index c4ee86a957..36910a8446 100644 --- a/ext/node/Cargo.toml +++ b/ext/node/Cargo.toml @@ -95,6 +95,7 @@ spki.workspace = true stable_deref_trait = "1.2.0" thiserror.workspace = true tokio.workspace = true +tokio-eld = "0.2" url.workspace = true webpki-root-certs.workspace = true winapi.workspace = true diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 80f9f19fee..a05f4776e2 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -427,6 +427,9 @@ deno_core::extension!(deno_node, ops::inspector::op_inspector_emit_protocol_event, ops::inspector::op_inspector_enabled, ], + objects = [ + ops::perf_hooks::EldHistogram + ], esm_entry_point = "ext:deno_node/02_init.js", esm = [ dir "polyfills", diff --git a/ext/node/ops/mod.rs b/ext/node/ops/mod.rs index b53f19dc23..e5ea8b4172 100644 --- a/ext/node/ops/mod.rs +++ b/ext/node/ops/mod.rs @@ -10,6 +10,7 @@ pub mod idna; pub mod inspector; pub mod ipc; pub mod os; +pub mod perf_hooks; pub mod process; pub mod require; pub mod tls; diff --git a/ext/node/ops/perf_hooks.rs b/ext/node/ops/perf_hooks.rs new file mode 100644 index 0000000000..636d0b2adb --- /dev/null +++ b/ext/node/ops/perf_hooks.rs @@ -0,0 +1,135 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use deno_core::op2; +use deno_core::GarbageCollected; + +use std::cell::Cell; + +#[derive(Debug, thiserror::Error)] +pub enum PerfHooksError { + #[error(transparent)] + TokioEld(#[from] tokio_eld::Error), +} + +pub struct EldHistogram { + eld: tokio_eld::EldHistogram, + started: Cell, +} + +impl GarbageCollected for EldHistogram {} + +#[op2] +impl EldHistogram { + // Creates an interval EldHistogram object that samples and reports the event + // loop delay over time. + // + // The delays will be reported in nanoseconds. + #[constructor] + #[cppgc] + pub fn new(#[smi] resolution: u32) -> Result { + Ok(EldHistogram { + eld: tokio_eld::EldHistogram::new(resolution as usize)?, + started: Cell::new(false), + }) + } + + // Disables the update interval timer. + // + // Returns true if the timer was stopped, false if it was already stopped. + #[fast] + fn enable(&self) -> bool { + if self.started.get() { + return false; + } + + self.eld.start(); + self.started.set(true); + + true + } + + // Enables the update interval timer. + // + // Returns true if the timer was started, false if it was already started. + #[fast] + fn disable(&self) -> bool { + if !self.started.get() { + return false; + } + + self.eld.stop(); + self.started.set(false); + + true + } + + // Returns the value at the given percentile. + // + // `percentile` ∈ (0, 100] + #[fast] + #[number] + fn percentile(&self, percentile: f64) -> u64 { + self.eld.value_at_percentile(percentile) + } + + // Returns the value at the given percentile as a bigint. + #[fast] + #[bigint] + fn percentile_big_int(&self, percentile: f64) -> u64 { + self.eld.value_at_percentile(percentile) + } + + // The number of samples recorded by the histogram. + #[getter] + #[number] + fn count(&self) -> u64 { + self.eld.len() + } + + // The number of samples recorded by the histogram as a bigint. + #[getter] + #[bigint] + fn count_big_int(&self) -> u64 { + self.eld.len() + } + + // The maximum recorded event loop delay. + #[getter] + #[number] + fn max(&self) -> u64 { + self.eld.max() + } + + // The maximum recorded event loop delay as a bigint. + #[getter] + #[bigint] + fn max_big_int(&self) -> u64 { + self.eld.max() + } + + // The mean of the recorded event loop delays. + #[getter] + fn mean(&self) -> f64 { + self.eld.mean() + } + + // The minimum recorded event loop delay. + #[getter] + #[number] + fn min(&self) -> u64 { + self.eld.min() + } + + // The minimum recorded event loop delay as a bigint. + #[getter] + #[bigint] + fn min_big_int(&self) -> u64 { + self.eld.min() + } + + // The standard deviation of the recorded event loop delays. + #[getter] + fn stddev(&self) -> f64 { + self.eld.stdev() + } +} diff --git a/ext/node/polyfills/01_require.js b/ext/node/polyfills/01_require.js index 083d4e49be..db032014c2 100644 --- a/ext/node/polyfills/01_require.js +++ b/ext/node/polyfills/01_require.js @@ -1086,12 +1086,10 @@ function loadESMFromCJS(module, filename, code) { module.exports = namespace; } -Module._extensions[".mjs"] = Module._extensions[".mts"] = function ( - module, - filename, -) { - loadESMFromCJS(module, filename); -}; +Module._extensions[".mjs"] = + Module._extensions[".mts"] = + Module._extensions[".wasm"] = + loadESMFromCJS; function stripBOM(content) { if (StringPrototypeCharCodeAt(content, 0) === 0xfeff) { diff --git a/ext/node/polyfills/perf_hooks.ts b/ext/node/polyfills/perf_hooks.ts index d92b925b5f..ec76b3ce2d 100644 --- a/ext/node/polyfills/perf_hooks.ts +++ b/ext/node/polyfills/perf_hooks.ts @@ -8,6 +8,7 @@ import { performance as shimPerformance, PerformanceEntry, } from "ext:deno_web/15_performance.js"; +import { EldHistogram } from "ext:core/ops"; class PerformanceObserver { static supportedEntryTypes: string[] = []; @@ -89,10 +90,11 @@ const performance: ) => shimPerformance.dispatchEvent(...args), }; -const monitorEventLoopDelay = () => - notImplemented( - "monitorEventLoopDelay from performance", - ); +function monitorEventLoopDelay(options = {}) { + const { resolution = 10 } = options; + + return new EldHistogram(resolution); +} export default { performance, diff --git a/resolvers/node/resolution.rs b/resolvers/node/resolution.rs index 673a61abe6..c2ec25aca4 100644 --- a/resolvers/node/resolution.rs +++ b/resolvers/node/resolution.rs @@ -202,7 +202,7 @@ impl NodeResolver { mode: NodeResolutionMode, ) -> Result { if should_be_treated_as_relative_or_absolute_path(specifier) { - Ok(referrer.join(specifier).map_err(|err| { + Ok(node_join_url(referrer, specifier).map_err(|err| { NodeResolveRelativeJoinError { path: specifier.to_string(), base: referrer.clone(), @@ -1763,6 +1763,17 @@ fn get_module_name_from_builtin_node_module_specifier( Some(specifier) } +/// Node is more lenient joining paths than the url crate is, +/// so this function handles that. +fn node_join_url(url: &Url, path: &str) -> Result { + if let Some(suffix) = path.strip_prefix(".//") { + // specifier had two leading slashes + url.join(&format!("./{}", suffix)) + } else { + url.join(path) + } +} + #[cfg(test)] mod tests { use serde_json::json; diff --git a/runtime/worker.rs b/runtime/worker.rs index 909147df9b..97cbb6428f 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -78,7 +78,7 @@ pub fn validate_import_attributes_callback( for (key, value) in attributes { let msg = if key != "type" { Some(format!("\"{key}\" attribute is not supported.")) - } else if value != "json" { + } else if value != "json" && value != "$$deno-core-internal-wasm-module" { Some(format!("\"{value}\" is not a valid module type.")) } else { None diff --git a/tests/integration/fmt_tests.rs b/tests/integration/fmt_tests.rs index b890b3b72a..ccf54a4d0f 100644 --- a/tests/integration/fmt_tests.rs +++ b/tests/integration/fmt_tests.rs @@ -61,6 +61,12 @@ fn fmt_test() { let badly_formatted_yaml = t.path().join("badly_formatted.yaml"); badly_formatted_original_yaml.copy(&badly_formatted_yaml); + let fixed_sql = testdata_fmt_dir.join("badly_formatted_fixed.sql"); + let badly_formatted_original_sql = + testdata_fmt_dir.join("badly_formatted.sql"); + let badly_formatted_sql = t.path().join("badly_formatted.sql"); + badly_formatted_original_sql.copy(&badly_formatted_sql); + // First, check formatting by ignoring the badly formatted file. let output = context .new_command() @@ -71,11 +77,12 @@ fn fmt_test() { "--unstable-html".to_string(), "--unstable-component".to_string(), "--unstable-yaml".to_string(), + "--unstable-sql".to_string(), format!( - "--ignore={badly_formatted_js},{badly_formatted_md},{badly_formatted_json},{badly_formatted_css},{badly_formatted_html},{badly_formatted_component},{badly_formatted_yaml},{badly_formatted_ipynb}", + "--ignore={badly_formatted_js},{badly_formatted_md},{badly_formatted_json},{badly_formatted_css},{badly_formatted_html},{badly_formatted_component},{badly_formatted_yaml},{badly_formatted_ipynb},{badly_formatted_sql}", ), format!( - "--check {badly_formatted_js} {badly_formatted_md} {badly_formatted_json} {badly_formatted_css} {badly_formatted_html} {badly_formatted_component} {badly_formatted_yaml} {badly_formatted_ipynb}", + "--check {badly_formatted_js} {badly_formatted_md} {badly_formatted_json} {badly_formatted_css} {badly_formatted_html} {badly_formatted_component} {badly_formatted_yaml} {badly_formatted_ipynb} {badly_formatted_sql}", ), ]) .run(); @@ -95,6 +102,7 @@ fn fmt_test() { "--unstable-html".to_string(), "--unstable-component".to_string(), "--unstable-yaml".to_string(), + "--unstable-sql".to_string(), badly_formatted_js.to_string(), badly_formatted_md.to_string(), badly_formatted_json.to_string(), @@ -103,6 +111,7 @@ fn fmt_test() { badly_formatted_component.to_string(), badly_formatted_yaml.to_string(), badly_formatted_ipynb.to_string(), + badly_formatted_sql.to_string(), ]) .run(); @@ -119,6 +128,7 @@ fn fmt_test() { "--unstable-html".to_string(), "--unstable-component".to_string(), "--unstable-yaml".to_string(), + "--unstable-sql".to_string(), badly_formatted_js.to_string(), badly_formatted_md.to_string(), badly_formatted_json.to_string(), @@ -127,6 +137,7 @@ fn fmt_test() { badly_formatted_component.to_string(), badly_formatted_yaml.to_string(), badly_formatted_ipynb.to_string(), + badly_formatted_sql.to_string(), ]) .run(); @@ -141,6 +152,7 @@ fn fmt_test() { let expected_component = fixed_component.read_to_string(); let expected_yaml = fixed_yaml.read_to_string(); let expected_ipynb = fixed_ipynb.read_to_string(); + let expected_sql = fixed_sql.read_to_string(); let actual_js = badly_formatted_js.read_to_string(); let actual_md = badly_formatted_md.read_to_string(); let actual_json = badly_formatted_json.read_to_string(); @@ -149,6 +161,7 @@ fn fmt_test() { let actual_component = badly_formatted_component.read_to_string(); let actual_yaml = badly_formatted_yaml.read_to_string(); let actual_ipynb = badly_formatted_ipynb.read_to_string(); + let actual_sql = badly_formatted_sql.read_to_string(); assert_eq!(expected_js, actual_js); assert_eq!(expected_md, actual_md); assert_eq!(expected_json, actual_json); @@ -157,6 +170,7 @@ fn fmt_test() { assert_eq!(expected_component, actual_component); assert_eq!(expected_yaml, actual_yaml); assert_eq!(expected_ipynb, actual_ipynb); + assert_eq!(expected_sql, actual_sql); } #[test] diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs index 8eaccb5487..b716aa921e 100644 --- a/tests/integration/lsp_tests.rs +++ b/tests/integration/lsp_tests.rs @@ -5427,7 +5427,8 @@ fn lsp_code_actions_deno_cache() { let res = client - .write_request( "textDocument/codeAction", + .write_request( + "textDocument/codeAction", json!({ "textDocument": { "uri": "file:///a/file.ts" @@ -5453,8 +5454,7 @@ fn lsp_code_actions_deno_cache() { "only": ["quickfix"] } }), - ) - ; + ); assert_eq!( res, json!([{ @@ -16516,3 +16516,47 @@ fn lsp_jsdoc_named_example() { }), ); } + +#[test] +fn lsp_wasm_module() { + let context = TestContextBuilder::new() + .use_temp_cwd() + .use_http_server() + .build(); + let mut client = context.new_lsp_command().build(); + client.initialize_default(); + client.did_open(json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "import { add } from \"http://localhost:4545/wasm/math.wasm\";\nadd(1, '');\n" + } + })); + + client.write_request( + "workspace/executeCommand", + json!({ + "command": "deno.cache", + "arguments": [[], "file:///a/file.ts"], + }), + ); + + let diagnostics = client.read_diagnostics(); + assert_eq!( + json!(diagnostics.all()), + json!([ + { + "range": { + "start": { "line": 1, "character": 7 }, + "end": { "line": 1, "character": 9 } + }, + "severity": 1, + "code": 2345, + "source": "deno-ts", + "message": "Argument of type 'string' is not assignable to parameter of type 'number'." + } + ]) + ); + client.shutdown(); +} diff --git a/tests/registry/npm/@denotest/specifier-two-slashes/1.0.0/index.js b/tests/registry/npm/@denotest/specifier-two-slashes/1.0.0/index.js new file mode 100644 index 0000000000..aca5ca1b8e --- /dev/null +++ b/tests/registry/npm/@denotest/specifier-two-slashes/1.0.0/index.js @@ -0,0 +1,2 @@ +// node.js will resolve this as ./other.js +export * from ".//other.js"; \ No newline at end of file diff --git a/tests/registry/npm/@denotest/specifier-two-slashes/1.0.0/other.js b/tests/registry/npm/@denotest/specifier-two-slashes/1.0.0/other.js new file mode 100644 index 0000000000..7d658310b0 --- /dev/null +++ b/tests/registry/npm/@denotest/specifier-two-slashes/1.0.0/other.js @@ -0,0 +1,3 @@ +export function add(a, b) { + return a + b; +} diff --git a/tests/registry/npm/@denotest/specifier-two-slashes/1.0.0/package.json b/tests/registry/npm/@denotest/specifier-two-slashes/1.0.0/package.json new file mode 100644 index 0000000000..55e46b2fd1 --- /dev/null +++ b/tests/registry/npm/@denotest/specifier-two-slashes/1.0.0/package.json @@ -0,0 +1,6 @@ +{ + "name": "@denotest/specifier-two-slashes", + "version": "1.0.0", + "type": "module", + "main": "index.js" +} \ No newline at end of file diff --git a/tests/specs/check/wasm/__test__.jsonc b/tests/specs/check/wasm/__test__.jsonc new file mode 100644 index 0000000000..cb11ce33bd --- /dev/null +++ b/tests/specs/check/wasm/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "check --allow-import main.ts", + "output": "check.out", + "exitCode": 1 +} diff --git a/tests/specs/check/wasm/check.out b/tests/specs/check/wasm/check.out new file mode 100644 index 0000000000..b3a23646db --- /dev/null +++ b/tests/specs/check/wasm/check.out @@ -0,0 +1,6 @@ +Download http://localhost:4545/wasm/math.wasm +Check file:///[WILDLINE]/main.ts +error: TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type 'number'. +console.log(add(1, "")); + ~~ + at file:///[WILDLINE]/main.ts:3:20 diff --git a/tests/specs/check/wasm/main.ts b/tests/specs/check/wasm/main.ts new file mode 100644 index 0000000000..64a8f64d8d --- /dev/null +++ b/tests/specs/check/wasm/main.ts @@ -0,0 +1,3 @@ +import { add } from "http://localhost:4545/wasm/math.wasm"; + +console.log(add(1, "")); diff --git a/tests/specs/compile/include_data_files/__test__.jsonc b/tests/specs/compile/include_data_files/__test__.jsonc new file mode 100644 index 0000000000..5d5d967ca2 --- /dev/null +++ b/tests/specs/compile/include_data_files/__test__.jsonc @@ -0,0 +1,41 @@ +{ + "tempDir": true, + "tests": { + "success": { + "steps": [{ + "if": "unix", + "args": "compile --allow-read=data-file.txt --include data-file.txt --output main main.js", + "output": "[WILDCARD]" + }, { + "if": "unix", + "commandName": "./main", + "args": [], + "output": "output.out", + "exitCode": 0 + }, { + "if": "windows", + "args": "compile --allow-read=data-file.txt --include data-file.txt --output main.exe main.js", + "output": "[WILDCARD]" + }, { + "if": "windows", + "commandName": "./main.exe", + "args": [], + "output": "output.out", + "exitCode": 0 + }] + }, + "non_existent": { + "steps": [{ + "if": "unix", + "args": "compile --include does_not_exist.txt --output main main.js", + "output": "non_existent.out", + "exitCode": 1 + }, { + "if": "windows", + "args": "compile --include does_not_exist.txt --output main.exe main.js", + "output": "non_existent.out", + "exitCode": 1 + }] + } + } +} diff --git a/tests/specs/compile/include_data_files/data-file.txt b/tests/specs/compile/include_data_files/data-file.txt new file mode 100644 index 0000000000..b14df6442e --- /dev/null +++ b/tests/specs/compile/include_data_files/data-file.txt @@ -0,0 +1 @@ +Hi diff --git a/tests/specs/compile/include_data_files/main.js b/tests/specs/compile/include_data_files/main.js new file mode 100644 index 0000000000..4c1f1e98d5 --- /dev/null +++ b/tests/specs/compile/include_data_files/main.js @@ -0,0 +1 @@ +console.log(Deno.readTextFileSync("./data-file.txt").trim()); diff --git a/tests/specs/compile/include_data_files/non_existent.out b/tests/specs/compile/include_data_files/non_existent.out new file mode 100644 index 0000000000..a88b441ba8 --- /dev/null +++ b/tests/specs/compile/include_data_files/non_existent.out @@ -0,0 +1,6 @@ +Compile file:///[WILDLINE]/main.js to [WILDLINE] +error: Writing deno compile executable to temporary file 'main[WILDLINE]' + +Caused by: + 0: Including [WILDLINE]does_not_exist.txt + 1: [WILDLINE] diff --git a/tests/specs/compile/include_data_files/output.out b/tests/specs/compile/include_data_files/output.out new file mode 100644 index 0000000000..b14df6442e --- /dev/null +++ b/tests/specs/compile/include_data_files/output.out @@ -0,0 +1 @@ +Hi diff --git a/tests/specs/compile/include_folder/__test__.jsonc b/tests/specs/compile/include_folder/__test__.jsonc new file mode 100644 index 0000000000..eeaea53b65 --- /dev/null +++ b/tests/specs/compile/include_folder/__test__.jsonc @@ -0,0 +1,24 @@ +{ + "tempDir": true, + "steps": [{ + "if": "unix", + "args": "compile --allow-read=data --include data --output main main.js", + "output": "[WILDCARD]" + }, { + "if": "unix", + "commandName": "./main", + "args": [], + "output": "output.out", + "exitCode": 0 + }, { + "if": "windows", + "args": "compile --allow-read=data --include data --output main.exe main.js", + "output": "[WILDCARD]" + }, { + "if": "windows", + "commandName": "./main.exe", + "args": [], + "output": "output.out", + "exitCode": 0 + }] +} diff --git a/tests/specs/compile/include_folder/data/a.txt b/tests/specs/compile/include_folder/data/a.txt new file mode 100644 index 0000000000..7898192261 --- /dev/null +++ b/tests/specs/compile/include_folder/data/a.txt @@ -0,0 +1 @@ +a diff --git a/tests/specs/compile/include_folder/data/b.txt b/tests/specs/compile/include_folder/data/b.txt new file mode 100644 index 0000000000..6178079822 --- /dev/null +++ b/tests/specs/compile/include_folder/data/b.txt @@ -0,0 +1 @@ +b diff --git a/tests/specs/compile/include_folder/main.js b/tests/specs/compile/include_folder/main.js new file mode 100644 index 0000000000..831d26167f --- /dev/null +++ b/tests/specs/compile/include_folder/main.js @@ -0,0 +1,8 @@ +const dataDir = import.meta.dirname + "/data"; +const files = Array.from( + Deno.readDirSync(dataDir).map((entry) => dataDir + "/" + entry.name), +); +files.sort(); +for (const file of files) { + console.log(Deno.readTextFileSync(file).trim()); +} diff --git a/tests/specs/compile/include_folder/output.out b/tests/specs/compile/include_folder/output.out new file mode 100644 index 0000000000..422c2b7ab3 --- /dev/null +++ b/tests/specs/compile/include_folder/output.out @@ -0,0 +1,2 @@ +a +b diff --git a/tests/specs/doc/lint_html_success/lint_success_html.out b/tests/specs/doc/lint_html_success/lint_success_html.out index 783dd5927e..57b179e226 100644 --- a/tests/specs/doc/lint_html_success/lint_success_html.out +++ b/tests/specs/doc/lint_html_success/lint_success_html.out @@ -1 +1 @@ -Written 12 files to "./docs/" +Written 15 files to "./docs/" diff --git a/tests/specs/doc/wasm/__test__.jsonc b/tests/specs/doc/wasm/__test__.jsonc new file mode 100644 index 0000000000..967bd08ea3 --- /dev/null +++ b/tests/specs/doc/wasm/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "doc http://localhost:4545/wasm/math.wasm", + "output": "doc.out" +} diff --git a/tests/specs/doc/wasm/doc.out b/tests/specs/doc/wasm/doc.out new file mode 100644 index 0000000000..9e93f1b938 --- /dev/null +++ b/tests/specs/doc/wasm/doc.out @@ -0,0 +1,21 @@ +Download http://localhost:4545/wasm/math.wasm +Defined in http://localhost:4545/wasm/math.wasm:2:1 + +function add(arg0: number, arg1: number): number + +Defined in http://localhost:4545/wasm/math.wasm:3:1 + +function subtract(arg0: number, arg1: number): number + +Defined in http://localhost:4545/wasm/math.wasm:4:22 + +const __data_end: number + +Defined in http://localhost:4545/wasm/math.wasm:5:22 + +const __heap_base: number + +Defined in http://localhost:4545/wasm/math.wasm:1:22 + +const memory: WebAssembly.Memory + diff --git a/tests/specs/fmt/sql/__test__.jsonc b/tests/specs/fmt/sql/__test__.jsonc new file mode 100644 index 0000000000..a335e79c24 --- /dev/null +++ b/tests/specs/fmt/sql/__test__.jsonc @@ -0,0 +1,25 @@ +{ + "tempDir": true, + "tests": { + "nothing": { + "args": "fmt", + "output": "Checked 7 files\n" + }, + "flag": { + "args": "fmt --unstable-sql", + "output": "[UNORDERED_START]\n[WILDLINE]badly_formatted.sql\n[WILDLINE]well_formatted.sql\n[WILDLINE]wrong_file_ignore.sql\n[UNORDERED_END]\nChecked 7 files\n" + }, + "config_file": { + "steps": [{ + "args": [ + "eval", + "Deno.writeTextFile('deno.json', '{\\n \"unstable\": [\"fmt-sql\"]\\n}\\n')" + ], + "output": "[WILDCARD]" + }, { + "args": "fmt", + "output": "[UNORDERED_START]\n[WILDLINE]badly_formatted.sql\n[WILDLINE]well_formatted.sql\n[WILDLINE]wrong_file_ignore.sql\n[UNORDERED_END]\nChecked 8 files\n" + }] + } + } +} diff --git a/tests/specs/fmt/sql/badly_formatted.sql b/tests/specs/fmt/sql/badly_formatted.sql new file mode 100644 index 0000000000..619fc7afdd --- /dev/null +++ b/tests/specs/fmt/sql/badly_formatted.sql @@ -0,0 +1 @@ +select *; \ No newline at end of file diff --git a/tests/specs/fmt/sql/ignore_file.sql b/tests/specs/fmt/sql/ignore_file.sql new file mode 100644 index 0000000000..62418c611b --- /dev/null +++ b/tests/specs/fmt/sql/ignore_file.sql @@ -0,0 +1,3 @@ +-- deno-fmt-ignore-file + +foo%! diff --git a/tests/specs/fmt/sql/ignore_file2.sql b/tests/specs/fmt/sql/ignore_file2.sql new file mode 100644 index 0000000000..fe9969f1d3 --- /dev/null +++ b/tests/specs/fmt/sql/ignore_file2.sql @@ -0,0 +1,3 @@ +--deno-fmt-ignore-file + +foo%! diff --git a/tests/specs/fmt/sql/ignore_file3.sql b/tests/specs/fmt/sql/ignore_file3.sql new file mode 100644 index 0000000000..c87da3e591 --- /dev/null +++ b/tests/specs/fmt/sql/ignore_file3.sql @@ -0,0 +1,6 @@ +-- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor +-- incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, +-- quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +-- deno-fmt-ignore-file + + foo%! diff --git a/tests/specs/fmt/sql/ignore_file4.sql b/tests/specs/fmt/sql/ignore_file4.sql new file mode 100644 index 0000000000..2de65712a5 --- /dev/null +++ b/tests/specs/fmt/sql/ignore_file4.sql @@ -0,0 +1,3 @@ +-- deno-fmt-ignore-file Foo bar biz + + foo%! diff --git a/tests/specs/fmt/sql/well_formatted.sql b/tests/specs/fmt/sql/well_formatted.sql new file mode 100644 index 0000000000..92ce980185 --- /dev/null +++ b/tests/specs/fmt/sql/well_formatted.sql @@ -0,0 +1,4 @@ +SELECT + * +FROM + foo; diff --git a/tests/specs/fmt/sql/wrong_file_ignore.sql b/tests/specs/fmt/sql/wrong_file_ignore.sql new file mode 100644 index 0000000000..c124855dc2 --- /dev/null +++ b/tests/specs/fmt/sql/wrong_file_ignore.sql @@ -0,0 +1,6 @@ +-- File ignore directive only works if it's in the first cluster +-- of comment, ie. there are no empty lines after the first n-leading lines. + +-- deno-fmt-ignore-file + + foo \ No newline at end of file diff --git a/tests/specs/info/flag/041_info_flag.out b/tests/specs/info/flag/041_info_flag.out index 72a00be303..48a08de4d9 100644 --- a/tests/specs/info/flag/041_info_flag.out +++ b/tests/specs/info/flag/041_info_flag.out @@ -4,3 +4,4 @@ npm modules cache: [WILDCARD]npm Emitted modules cache: [WILDCARD]gen Language server registries cache: [WILDCARD]registries Origin storage: [WILDCARD]location_data +Web cache storage: [WILDCARD]deno_cache diff --git a/tests/specs/info/flag_location/041_info_flag_location.out b/tests/specs/info/flag_location/041_info_flag_location.out index 684db2eec5..d3ba01ad35 100644 --- a/tests/specs/info/flag_location/041_info_flag_location.out +++ b/tests/specs/info/flag_location/041_info_flag_location.out @@ -4,4 +4,5 @@ npm modules cache: [WILDCARD]npm Emitted modules cache: [WILDCARD]gen Language server registries cache: [WILDCARD]registries Origin storage: [WILDCARD]location_data[WILDCARD] +Web cache storage: [WILDCARD]deno_cache Local Storage: [WILDCARD]location_data[WILDCARD]local_storage diff --git a/tests/specs/info/json/info_json.out b/tests/specs/info/json/info_json.out index 551f61026d..cc43c5f10a 100644 --- a/tests/specs/info/json/info_json.out +++ b/tests/specs/info/json/info_json.out @@ -5,5 +5,6 @@ "npmCache": "[WILDCARD]npm", "typescriptCache": "[WILDCARD]gen", "registryCache": "[WILDCARD]registries", - "originStorage": "[WILDCARD]location_data" + "originStorage": "[WILDCARD]location_data", + "webCacheStorage": [WILDCARD]deno_cache" } diff --git a/tests/specs/info/wasm_module/__test__.jsonc b/tests/specs/info/wasm_module/__test__.jsonc new file mode 100644 index 0000000000..37a02b4484 --- /dev/null +++ b/tests/specs/info/wasm_module/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "info --allow-import main.js", + "output": "main.out" +} diff --git a/tests/specs/info/wasm_module/main.js b/tests/specs/info/wasm_module/main.js new file mode 100644 index 0000000000..9ad66df35b --- /dev/null +++ b/tests/specs/info/wasm_module/main.js @@ -0,0 +1,7 @@ +import { + add, + subtract, +} from "http://localhost:4545/wasm/math_with_import.wasm"; + +console.log(add(1, 2)); +console.log(subtract(100, 50)); diff --git a/tests/specs/info/wasm_module/main.out b/tests/specs/info/wasm_module/main.out new file mode 100644 index 0000000000..d8daf39409 --- /dev/null +++ b/tests/specs/info/wasm_module/main.out @@ -0,0 +1,10 @@ +Download http://localhost:4545/wasm/math_with_import.wasm +Download http://localhost:4545/wasm/math.ts +local: [WILDLINE]main.js +type: JavaScript +dependencies: 2 unique +size: [WILDLINE] + +file:///[WILDLINE]/main.js ([WILDLINE]) +└─┬ http://localhost:4545/wasm/math_with_import.wasm ([WILDLINE]) + └── http://localhost:4545/wasm/math.ts ([WILDLINE]) diff --git a/tests/specs/lockfile/jsx_import_source_and_types/__test__.jsonc b/tests/specs/lockfile/jsx_import_source_and_types/__test__.jsonc new file mode 100644 index 0000000000..08ab2acf95 --- /dev/null +++ b/tests/specs/lockfile/jsx_import_source_and_types/__test__.jsonc @@ -0,0 +1,13 @@ +{ + "tempDir": true, + "steps": [{ + "args": "run index.tsx", + "output": "index.out" + }, { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('deno.lock').trim())" + ], + "output": "deno.lock.out" + }] +} diff --git a/tests/specs/lockfile/jsx_import_source_and_types/deno.json b/tests/specs/lockfile/jsx_import_source_and_types/deno.json new file mode 100644 index 0000000000..3755934a58 --- /dev/null +++ b/tests/specs/lockfile/jsx_import_source_and_types/deno.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "jsxImportSource": "npm:react", + "jsxImportSourceTypes": "npm:@types/react", + "types": [ + "npm:@types/node" + ] + } +} diff --git a/tests/specs/lockfile/jsx_import_source_and_types/deno.lock.out b/tests/specs/lockfile/jsx_import_source_and_types/deno.lock.out new file mode 100644 index 0000000000..3a933a1aa2 --- /dev/null +++ b/tests/specs/lockfile/jsx_import_source_and_types/deno.lock.out @@ -0,0 +1,30 @@ +{ + "version": "4", + "specifiers": { + "npm:react@*": "18.2.0" + }, + "npm": { + "js-tokens@4.0.0": { + "integrity": "[WILDLINE]" + }, + "loose-envify@1.4.0": { + "integrity": "[WILDLINE]", + "dependencies": [ + "js-tokens" + ] + }, + "react@18.2.0": { + "integrity": "[WILDLINE]", + "dependencies": [ + "loose-envify" + ] + } + }, + "workspace": { + "dependencies": [ + "npm:@types/node@*", + "npm:@types/react@*", + "npm:react@*" + ] + } +} diff --git a/tests/specs/lockfile/jsx_import_source_and_types/index.out b/tests/specs/lockfile/jsx_import_source_and_types/index.out new file mode 100644 index 0000000000..7fc82c71df --- /dev/null +++ b/tests/specs/lockfile/jsx_import_source_and_types/index.out @@ -0,0 +1,7 @@ +Download http://localhost:4260/react +Download http://localhost:4260/loose-envify +Download http://localhost:4260/js-tokens +Download http://localhost:4260/react/react-18.2.0.tgz +Download http://localhost:4260/loose-envify/loose-envify-1.4.0.tgz +Download http://localhost:4260/js-tokens/js-tokens-4.0.0.tgz +1 diff --git a/tests/specs/lockfile/jsx_import_source_and_types/index.tsx b/tests/specs/lockfile/jsx_import_source_and_types/index.tsx new file mode 100644 index 0000000000..296d5492b0 --- /dev/null +++ b/tests/specs/lockfile/jsx_import_source_and_types/index.tsx @@ -0,0 +1 @@ +console.log(1); diff --git a/tests/specs/npm/specifier_two_slashes/__test__.jsonc b/tests/specs/npm/specifier_two_slashes/__test__.jsonc new file mode 100644 index 0000000000..bddbdbc1c8 --- /dev/null +++ b/tests/specs/npm/specifier_two_slashes/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --quiet main.ts", + "output": "3\n" +} diff --git a/tests/specs/npm/specifier_two_slashes/main.ts b/tests/specs/npm/specifier_two_slashes/main.ts new file mode 100644 index 0000000000..ef1adceb5c --- /dev/null +++ b/tests/specs/npm/specifier_two_slashes/main.ts @@ -0,0 +1,3 @@ +import { add } from "npm:@denotest/specifier-two-slashes"; + +console.log(add(1, 2)); diff --git a/tests/specs/publish/missing_exports/LICENSE b/tests/specs/publish/missing_exports/LICENSE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/publish/missing_exports/__test__.jsonc b/tests/specs/publish/missing_exports/__test__.jsonc new file mode 100644 index 0000000000..241bb87e04 --- /dev/null +++ b/tests/specs/publish/missing_exports/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "publish --token 'sadfasdf'", + "output": "publish.out", + "exitCode": 1 +} diff --git a/tests/specs/publish/missing_exports/deno.json b/tests/specs/publish/missing_exports/deno.json new file mode 100644 index 0000000000..4a66546360 --- /dev/null +++ b/tests/specs/publish/missing_exports/deno.json @@ -0,0 +1,7 @@ +{ + "name": "@foo/bar", + "version": "1.0.0", + "imports": { + "@std/http": "./std_http.ts" + } +} diff --git a/tests/specs/publish/missing_exports/mod.ts b/tests/specs/publish/missing_exports/mod.ts new file mode 100644 index 0000000000..8d9b8a22a1 --- /dev/null +++ b/tests/specs/publish/missing_exports/mod.ts @@ -0,0 +1,3 @@ +export function add(a: number, b: number): number { + return a + b; +} diff --git a/tests/specs/publish/missing_exports/publish.out b/tests/specs/publish/missing_exports/publish.out new file mode 100644 index 0000000000..ded06f638b --- /dev/null +++ b/tests/specs/publish/missing_exports/publish.out @@ -0,0 +1,8 @@ +Warning "exports" field should be specified when specifying a "name". + at file:///[WILDLINE]/deno.json +error: You did not specify an entrypoint in file:///[WILDLINE]/deno.json. Add `exports` mapping in the configuration file, eg: +{ + "name": "@foo/bar", + "version": "@foo/bar", + "exports": "mod.ts" +} diff --git a/tests/specs/publish/set_version/multiple_packages/LICENSE b/tests/specs/publish/set_version/multiple_packages/LICENSE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/publish/set_version/multiple_packages/__test__.jsonc b/tests/specs/publish/set_version/multiple_packages/__test__.jsonc new file mode 100644 index 0000000000..c191386d80 --- /dev/null +++ b/tests/specs/publish/set_version/multiple_packages/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "publish --set-version 1.1.0 --token 'sadfasdf'", + "output": "error_set_version.out", + "exitCode": 1 +} diff --git a/tests/specs/publish/set_version/multiple_packages/deno.json b/tests/specs/publish/set_version/multiple_packages/deno.json new file mode 100644 index 0000000000..4b3ffe44da --- /dev/null +++ b/tests/specs/publish/set_version/multiple_packages/deno.json @@ -0,0 +1,8 @@ +{ + "workspace": { + "members": [ + "packages/package1", + "packages/package2" + ] + } +} diff --git a/tests/specs/publish/set_version/multiple_packages/error_set_version.out b/tests/specs/publish/set_version/multiple_packages/error_set_version.out new file mode 100644 index 0000000000..098692c4c6 --- /dev/null +++ b/tests/specs/publish/set_version/multiple_packages/error_set_version.out @@ -0,0 +1 @@ +error: Cannot use --set-version when publishing a workspace. Change your cwd to an individual package instead. diff --git a/tests/specs/publish/set_version/multiple_packages/packages/package1/deno.json b/tests/specs/publish/set_version/multiple_packages/packages/package1/deno.json new file mode 100644 index 0000000000..737fc9c139 --- /dev/null +++ b/tests/specs/publish/set_version/multiple_packages/packages/package1/deno.json @@ -0,0 +1,7 @@ +{ + "name": "@foo/package1", + "version": "1.0.0", + "exports": { + ".": "./mod.ts" + } +} diff --git a/tests/specs/publish/set_version/multiple_packages/packages/package1/mod.ts b/tests/specs/publish/set_version/multiple_packages/packages/package1/mod.ts new file mode 100644 index 0000000000..a2cd81bed7 --- /dev/null +++ b/tests/specs/publish/set_version/multiple_packages/packages/package1/mod.ts @@ -0,0 +1,3 @@ +export function package1() { + return "package1"; +} diff --git a/tests/specs/publish/set_version/multiple_packages/packages/package2/deno.json b/tests/specs/publish/set_version/multiple_packages/packages/package2/deno.json new file mode 100644 index 0000000000..16987e6194 --- /dev/null +++ b/tests/specs/publish/set_version/multiple_packages/packages/package2/deno.json @@ -0,0 +1,7 @@ +{ + "name": "@foo/package2", + "version": "1.0.0", + "exports": { + ".": "./mod.ts" + } +} diff --git a/tests/specs/publish/set_version/multiple_packages/packages/package2/mod.ts b/tests/specs/publish/set_version/multiple_packages/packages/package2/mod.ts new file mode 100644 index 0000000000..6c1361aa42 --- /dev/null +++ b/tests/specs/publish/set_version/multiple_packages/packages/package2/mod.ts @@ -0,0 +1,3 @@ +export function package2() { + return "package2"; +} diff --git a/tests/specs/publish/set_version/success/LICENSE b/tests/specs/publish/set_version/success/LICENSE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/publish/set_version/success/__test__.jsonc b/tests/specs/publish/set_version/success/__test__.jsonc new file mode 100644 index 0000000000..6f0bf802e7 --- /dev/null +++ b/tests/specs/publish/set_version/success/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "publish --set-version 1.1.0 --token 'sadfasdf'", + "output": "successful_set_version.out" +} diff --git a/tests/specs/publish/set_version/success/deno.json b/tests/specs/publish/set_version/success/deno.json new file mode 100644 index 0000000000..fefab899bd --- /dev/null +++ b/tests/specs/publish/set_version/success/deno.json @@ -0,0 +1,10 @@ +{ + "name": "@foo/bar", + "version": "1.0.0", + "exports": { + ".": "./mod.ts" + }, + "imports": { + "@std/http": "./std_http.ts" + } +} diff --git a/tests/specs/publish/set_version/success/mod.ts b/tests/specs/publish/set_version/success/mod.ts new file mode 100644 index 0000000000..6e8a61bae9 --- /dev/null +++ b/tests/specs/publish/set_version/success/mod.ts @@ -0,0 +1,7 @@ +import http from "@std/http"; + +export function foobar(): { fileServer(): void } { + return { + fileServer: http.fileServer, + }; +} diff --git a/tests/specs/publish/set_version/success/std_http.ts b/tests/specs/publish/set_version/success/std_http.ts new file mode 100644 index 0000000000..9d57b36f34 --- /dev/null +++ b/tests/specs/publish/set_version/success/std_http.ts @@ -0,0 +1,6 @@ +// temp until we get jsr:@std/http in the test server +export default { + fileServer() { + console.log("Hi"); + }, +}; diff --git a/tests/specs/publish/set_version/success/successful_set_version.out b/tests/specs/publish/set_version/success/successful_set_version.out new file mode 100644 index 0000000000..a5cb9aa821 --- /dev/null +++ b/tests/specs/publish/set_version/success/successful_set_version.out @@ -0,0 +1,6 @@ +Check file:///[WILDCARD]/success/mod.ts +Checking for slow types in the public API... +Check file:///[WILDCARD]/success/mod.ts +Publishing @foo/bar@1.1.0 ... +Successfully published @foo/bar@1.1.0 +Visit http://127.0.0.1:4250/@foo/bar@1.1.0 for details diff --git a/tests/specs/run/wasm_module/cjs_importing/__test__.jsonc b/tests/specs/run/wasm_module/cjs_importing/__test__.jsonc new file mode 100644 index 0000000000..9c91b73692 --- /dev/null +++ b/tests/specs/run/wasm_module/cjs_importing/__test__.jsonc @@ -0,0 +1,12 @@ +{ + "steps": [{ + "args": "run -A setup.ts", + "output": "[WILDCARD]" + }, { + "args": "run -A --check main.cts", + "output": "main.out" + }, { + "args": "run -A --check main.cjs", + "output": "main.out" + }] +} diff --git a/tests/specs/run/wasm_module/cjs_importing/main.cjs b/tests/specs/run/wasm_module/cjs_importing/main.cjs new file mode 100644 index 0000000000..51d253203e --- /dev/null +++ b/tests/specs/run/wasm_module/cjs_importing/main.cjs @@ -0,0 +1,5 @@ +// @ts-check +const { add, subtract } = require("./math.wasm"); + +console.log(add(1, 2)); +console.log(subtract(9, 3)); diff --git a/tests/specs/run/wasm_module/cjs_importing/main.cts b/tests/specs/run/wasm_module/cjs_importing/main.cts new file mode 100644 index 0000000000..2b22d48500 --- /dev/null +++ b/tests/specs/run/wasm_module/cjs_importing/main.cts @@ -0,0 +1,4 @@ +import WasmModule = require("./math.wasm"); + +console.log(WasmModule.add(1, 2)); +console.log(WasmModule.subtract(9, 3)); diff --git a/tests/specs/run/wasm_module/cjs_importing/main.out b/tests/specs/run/wasm_module/cjs_importing/main.out new file mode 100644 index 0000000000..69dbf81127 --- /dev/null +++ b/tests/specs/run/wasm_module/cjs_importing/main.out @@ -0,0 +1,3 @@ +Check file:///[WILDLINE] +3 +6 diff --git a/tests/specs/run/wasm_module/cjs_importing/math.wasm b/tests/specs/run/wasm_module/cjs_importing/math.wasm new file mode 100644 index 0000000000..6b3950fcc5 Binary files /dev/null and b/tests/specs/run/wasm_module/cjs_importing/math.wasm differ diff --git a/tests/specs/run/wasm_module/cjs_importing/package.json b/tests/specs/run/wasm_module/cjs_importing/package.json new file mode 100644 index 0000000000..b04e77362d --- /dev/null +++ b/tests/specs/run/wasm_module/cjs_importing/package.json @@ -0,0 +1,4 @@ +{ + "args": "run -A main.cjs", + "output": "main.out" +} diff --git a/tests/specs/run/wasm_module/cjs_importing/setup.ts b/tests/specs/run/wasm_module/cjs_importing/setup.ts new file mode 100644 index 0000000000..6f5c0e7781 --- /dev/null +++ b/tests/specs/run/wasm_module/cjs_importing/setup.ts @@ -0,0 +1,7 @@ +fetch("http://localhost:4545/wasm/math.wasm").then(async (response) => { + if (!response.ok) { + throw new Error(`Failed to fetch WASM module: ${response.statusText}`); + } + using file = Deno.openSync("math.wasm", { write: true, create: true }); + await response.body!.pipeTo(file.writable); +}); diff --git a/tests/specs/run/wasm_module/import_file_not_found/__test__.jsonc b/tests/specs/run/wasm_module/import_file_not_found/__test__.jsonc new file mode 100644 index 0000000000..a27fcfa82b --- /dev/null +++ b/tests/specs/run/wasm_module/import_file_not_found/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "--allow-import main.js", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/specs/run/wasm_module/import_file_not_found/deno.jsonc b/tests/specs/run/wasm_module/import_file_not_found/deno.jsonc new file mode 100644 index 0000000000..d24935d178 --- /dev/null +++ b/tests/specs/run/wasm_module/import_file_not_found/deno.jsonc @@ -0,0 +1,9 @@ +{ + "lock": false, + "scopes": { + "http://localhost:4545/wasm/": { + // file won't exist + "http://localhost:4545/wasm/math.ts": "./local_math.ts" + } + } +} diff --git a/tests/specs/run/wasm_module/import_file_not_found/main.js b/tests/specs/run/wasm_module/import_file_not_found/main.js new file mode 100644 index 0000000000..9ad66df35b --- /dev/null +++ b/tests/specs/run/wasm_module/import_file_not_found/main.js @@ -0,0 +1,7 @@ +import { + add, + subtract, +} from "http://localhost:4545/wasm/math_with_import.wasm"; + +console.log(add(1, 2)); +console.log(subtract(100, 50)); diff --git a/tests/specs/run/wasm_module/import_file_not_found/main.out b/tests/specs/run/wasm_module/import_file_not_found/main.out new file mode 100644 index 0000000000..54343673f1 --- /dev/null +++ b/tests/specs/run/wasm_module/import_file_not_found/main.out @@ -0,0 +1,3 @@ +Download http://localhost:4545/wasm/math_with_import.wasm +error: Module not found "file:///[WILDLINE]/local_math.ts". + at http://localhost:4545/wasm/math_with_import.wasm:1:8 diff --git a/tests/specs/run/wasm_module/import_named_export_not_found/__test__.jsonc b/tests/specs/run/wasm_module/import_named_export_not_found/__test__.jsonc new file mode 100644 index 0000000000..a27fcfa82b --- /dev/null +++ b/tests/specs/run/wasm_module/import_named_export_not_found/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "--allow-import main.js", + "output": "main.out", + "exitCode": 1 +} diff --git a/tests/specs/run/wasm_module/import_named_export_not_found/deno.jsonc b/tests/specs/run/wasm_module/import_named_export_not_found/deno.jsonc new file mode 100644 index 0000000000..a8f541dcec --- /dev/null +++ b/tests/specs/run/wasm_module/import_named_export_not_found/deno.jsonc @@ -0,0 +1,8 @@ +{ + "lock": false, + "scopes": { + "http://localhost:4545/wasm/": { + "http://localhost:4545/wasm/math.ts": "./local_math.ts" + } + } +} diff --git a/tests/specs/run/wasm_module/import_named_export_not_found/local_math.ts b/tests/specs/run/wasm_module/import_named_export_not_found/local_math.ts new file mode 100644 index 0000000000..8a72ea008b --- /dev/null +++ b/tests/specs/run/wasm_module/import_named_export_not_found/local_math.ts @@ -0,0 +1,7 @@ +export function addTest(a: number, b: number) { + return (a + b) * 2; +} + +export function subtractTest(a: number, b: number) { + return (a - b) / 2; +} diff --git a/tests/specs/run/wasm_module/import_named_export_not_found/main.js b/tests/specs/run/wasm_module/import_named_export_not_found/main.js new file mode 100644 index 0000000000..9ad66df35b --- /dev/null +++ b/tests/specs/run/wasm_module/import_named_export_not_found/main.js @@ -0,0 +1,7 @@ +import { + add, + subtract, +} from "http://localhost:4545/wasm/math_with_import.wasm"; + +console.log(add(1, 2)); +console.log(subtract(100, 50)); diff --git a/tests/specs/run/wasm_module/import_named_export_not_found/main.out b/tests/specs/run/wasm_module/import_named_export_not_found/main.out new file mode 100644 index 0000000000..f79dab7a05 --- /dev/null +++ b/tests/specs/run/wasm_module/import_named_export_not_found/main.out @@ -0,0 +1,3 @@ +Download http://localhost:4545/wasm/math_with_import.wasm +error: Uncaught SyntaxError: The requested module './math.ts' does not provide an export named 'add' + at (http://localhost:4545/wasm/math_with_import.wasm:[WILDLINE]) diff --git a/tests/specs/run/wasm_module/imports/__test__.jsonc b/tests/specs/run/wasm_module/imports/__test__.jsonc new file mode 100644 index 0000000000..744ae74d3e --- /dev/null +++ b/tests/specs/run/wasm_module/imports/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "--allow-import main.js", + "output": "main.out" +} diff --git a/tests/specs/run/wasm_module/imports/main.js b/tests/specs/run/wasm_module/imports/main.js new file mode 100644 index 0000000000..9ad66df35b --- /dev/null +++ b/tests/specs/run/wasm_module/imports/main.js @@ -0,0 +1,7 @@ +import { + add, + subtract, +} from "http://localhost:4545/wasm/math_with_import.wasm"; + +console.log(add(1, 2)); +console.log(subtract(100, 50)); diff --git a/tests/specs/run/wasm_module/imports/main.out b/tests/specs/run/wasm_module/imports/main.out new file mode 100644 index 0000000000..1b1210ded4 --- /dev/null +++ b/tests/specs/run/wasm_module/imports/main.out @@ -0,0 +1,4 @@ +Download http://localhost:4545/wasm/math_with_import.wasm +Download http://localhost:4545/wasm/math.ts +3 +50 diff --git a/tests/specs/run/wasm_module/integrity_check_failed/__test__.jsonc b/tests/specs/run/wasm_module/integrity_check_failed/__test__.jsonc new file mode 100644 index 0000000000..711016d259 --- /dev/null +++ b/tests/specs/run/wasm_module/integrity_check_failed/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "--allow-import main.js", + "output": "main.out", + "exitCode": 10 +} diff --git a/tests/specs/run/wasm_module/integrity_check_failed/deno.json b/tests/specs/run/wasm_module/integrity_check_failed/deno.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/run/wasm_module/integrity_check_failed/deno.json @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/specs/run/wasm_module/integrity_check_failed/deno.lock b/tests/specs/run/wasm_module/integrity_check_failed/deno.lock new file mode 100644 index 0000000000..adb4b91ee9 --- /dev/null +++ b/tests/specs/run/wasm_module/integrity_check_failed/deno.lock @@ -0,0 +1,6 @@ +{ + "version": "4", + "remote": { + "http://localhost:4545/wasm/math.wasm": "c4fdd49432f1517835b93274447890007947f9d30674ab7f1474091860113d95" + } +} diff --git a/tests/specs/run/wasm_module/integrity_check_failed/main.js b/tests/specs/run/wasm_module/integrity_check_failed/main.js new file mode 100644 index 0000000000..1e1b2629d1 --- /dev/null +++ b/tests/specs/run/wasm_module/integrity_check_failed/main.js @@ -0,0 +1,4 @@ +import { add, subtract } from "http://localhost:4545/wasm/math.wasm"; + +console.log(add(1, 2)); +console.log(subtract(100, 50)); diff --git a/tests/specs/run/wasm_module/integrity_check_failed/main.out b/tests/specs/run/wasm_module/integrity_check_failed/main.out new file mode 100644 index 0000000000..6434bfcf93 --- /dev/null +++ b/tests/specs/run/wasm_module/integrity_check_failed/main.out @@ -0,0 +1,12 @@ +Download http://localhost:4545/wasm/math.wasm +error: Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file. + + Specifier: http://localhost:4545/wasm/math.wasm + Actual: d1643d9d4ba8f34ee5198717860cbc629013179addba6d4e347b68eb721c73b4 + Expected: c4fdd49432f1517835b93274447890007947f9d30674ab7f1474091860113d95 + +This could be caused by: + * the lock file may be corrupt + * the source itself may be corrupt + +Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server. diff --git a/tests/specs/run/wasm_module/map_imports_via_import_map/__test__.jsonc b/tests/specs/run/wasm_module/map_imports_via_import_map/__test__.jsonc new file mode 100644 index 0000000000..744ae74d3e --- /dev/null +++ b/tests/specs/run/wasm_module/map_imports_via_import_map/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "--allow-import main.js", + "output": "main.out" +} diff --git a/tests/specs/run/wasm_module/map_imports_via_import_map/deno.json b/tests/specs/run/wasm_module/map_imports_via_import_map/deno.json new file mode 100644 index 0000000000..a8f541dcec --- /dev/null +++ b/tests/specs/run/wasm_module/map_imports_via_import_map/deno.json @@ -0,0 +1,8 @@ +{ + "lock": false, + "scopes": { + "http://localhost:4545/wasm/": { + "http://localhost:4545/wasm/math.ts": "./local_math.ts" + } + } +} diff --git a/tests/specs/run/wasm_module/map_imports_via_import_map/local_math.ts b/tests/specs/run/wasm_module/map_imports_via_import_map/local_math.ts new file mode 100644 index 0000000000..e681c2d7da --- /dev/null +++ b/tests/specs/run/wasm_module/map_imports_via_import_map/local_math.ts @@ -0,0 +1,7 @@ +export function add(a: number, b: number) { + return (a + b) * 2; +} + +export function subtract(a: number, b: number) { + return (a - b) / 2; +} diff --git a/tests/specs/run/wasm_module/map_imports_via_import_map/main.js b/tests/specs/run/wasm_module/map_imports_via_import_map/main.js new file mode 100644 index 0000000000..9ad66df35b --- /dev/null +++ b/tests/specs/run/wasm_module/map_imports_via_import_map/main.js @@ -0,0 +1,7 @@ +import { + add, + subtract, +} from "http://localhost:4545/wasm/math_with_import.wasm"; + +console.log(add(1, 2)); +console.log(subtract(100, 50)); diff --git a/tests/specs/run/wasm_module/map_imports_via_import_map/main.out b/tests/specs/run/wasm_module/map_imports_via_import_map/main.out new file mode 100644 index 0000000000..3a90c739aa --- /dev/null +++ b/tests/specs/run/wasm_module/map_imports_via_import_map/main.out @@ -0,0 +1,3 @@ +Download http://localhost:4545/wasm/math_with_import.wasm +6 +25 diff --git a/tests/specs/run/wasm_module/no_imports/__test__.jsonc b/tests/specs/run/wasm_module/no_imports/__test__.jsonc new file mode 100644 index 0000000000..29c4a86f31 --- /dev/null +++ b/tests/specs/run/wasm_module/no_imports/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-import main.ts", + "output": "main.out" +} diff --git a/tests/specs/run/wasm_module/no_imports/main.out b/tests/specs/run/wasm_module/no_imports/main.out new file mode 100644 index 0000000000..ce0d170ffd --- /dev/null +++ b/tests/specs/run/wasm_module/no_imports/main.out @@ -0,0 +1,3 @@ +Download http://localhost:4545/wasm/math.wasm +3 +6 diff --git a/tests/specs/run/wasm_module/no_imports/main.ts b/tests/specs/run/wasm_module/no_imports/main.ts new file mode 100644 index 0000000000..3cd3f675d2 --- /dev/null +++ b/tests/specs/run/wasm_module/no_imports/main.ts @@ -0,0 +1,4 @@ +import { add, subtract } from "http://localhost:4545/wasm/math.wasm"; + +console.log(add(1, 2)); +console.log(subtract(8, 2)); diff --git a/tests/specs/task/dependencies/__test__.jsonc b/tests/specs/task/dependencies/__test__.jsonc new file mode 100644 index 0000000000..38d085d796 --- /dev/null +++ b/tests/specs/task/dependencies/__test__.jsonc @@ -0,0 +1,61 @@ +{ + "tests": { + "basic1": { + "cwd": "basic1", + "tempDir": true, + "args": "task run", + "output": "./basic1.out" + }, + "basic2": { + "cwd": "basic2", + "tempDir": true, + "args": "task run", + "output": "./basic2.out" + }, + "cross_package": { + "cwd": "cross_package/package1", + "tempDir": true, + "args": "task run", + "output": "./cross_package.out", + "exitCode": 1 + }, + "diamond": { + "cwd": "diamond", + "tempDir": true, + "args": "task a", + "output": "./diamond.out" + }, + "diamond_list": { + "cwd": "diamond", + "tempDir": true, + "args": "task", + "output": "./diamond_list.out" + }, + "diamond_big": { + "cwd": "diamond_big", + "tempDir": true, + "args": "task a", + "output": "./diamond_big.out" + }, + "diamond_big_list": { + "cwd": "diamond_big", + "tempDir": true, + "args": "task", + "output": "./diamond_big_list.out" + }, + "cycle": { + "cwd": "cycle", + "tempDir": true, + "output": "./cycle.out", + "args": "task a", + "exitCode": 1 + }, + "cycle_2": { + "cwd": "cycle_2", + "tempDir": true, + "args": "task a", + "output": "./cycle_2.out", + "exitCode": 1 + } + } +} diff --git a/tests/specs/task/dependencies/basic1.out b/tests/specs/task/dependencies/basic1.out new file mode 100644 index 0000000000..8c31d02b4e --- /dev/null +++ b/tests/specs/task/dependencies/basic1.out @@ -0,0 +1,12 @@ +Task build1 deno run ../build1.js +Task build2 deno run ../build2.js +[UNORDERED_START] +Starting build1 +build1 performing more work... +build1 finished +Starting build2 +build2 performing more work... +build2 finished +[UNORDERED_END] +Task run deno run ../run.js +run finished diff --git a/tests/specs/task/dependencies/basic1/deno.json b/tests/specs/task/dependencies/basic1/deno.json new file mode 100644 index 0000000000..16bb9937e4 --- /dev/null +++ b/tests/specs/task/dependencies/basic1/deno.json @@ -0,0 +1,10 @@ +{ + "tasks": { + "build1": "deno run ../build1.js", + "build2": "deno run ../build2.js", + "run": { + "command": "deno run ../run.js", + "dependencies": ["build1", "build2"] + } + } +} diff --git a/tests/specs/task/dependencies/basic2.out b/tests/specs/task/dependencies/basic2.out new file mode 100644 index 0000000000..24ccd0eb03 --- /dev/null +++ b/tests/specs/task/dependencies/basic2.out @@ -0,0 +1,10 @@ +Task build1 deno run ../build1.js +Starting build1 +build1 performing more work... +build1 finished +Task build2 deno run ../build2.js +Starting build2 +build2 performing more work... +build2 finished +Task run deno run ../run.js +run finished diff --git a/tests/specs/task/dependencies/basic2/deno.json b/tests/specs/task/dependencies/basic2/deno.json new file mode 100644 index 0000000000..9a54926dd3 --- /dev/null +++ b/tests/specs/task/dependencies/basic2/deno.json @@ -0,0 +1,13 @@ +{ + "tasks": { + "build1": "deno run ../build1.js", + "build2": { + "command": "deno run ../build2.js", + "dependencies": ["build1"] + }, + "run": { + "command": "deno run ../run.js", + "dependencies": ["build2"] + } + } +} diff --git a/tests/specs/task/dependencies/build1.js b/tests/specs/task/dependencies/build1.js new file mode 100644 index 0000000000..d14fb401a3 --- /dev/null +++ b/tests/specs/task/dependencies/build1.js @@ -0,0 +1,9 @@ +import { randomTimeout } from "./util.js"; + +console.log("Starting build1"); + +await randomTimeout(500, 750); +console.log("build1 performing more work..."); +await randomTimeout(500, 750); + +console.log("build1 finished"); diff --git a/tests/specs/task/dependencies/build2.js b/tests/specs/task/dependencies/build2.js new file mode 100644 index 0000000000..3032a099ae --- /dev/null +++ b/tests/specs/task/dependencies/build2.js @@ -0,0 +1,9 @@ +import { randomTimeout } from "./util.js"; + +console.log("Starting build2"); + +await randomTimeout(250, 750); +console.log("build2 performing more work..."); +await randomTimeout(250, 750); + +console.log("build2 finished"); diff --git a/tests/specs/task/dependencies/cross_package.out b/tests/specs/task/dependencies/cross_package.out new file mode 100644 index 0000000000..a57f4de9ff --- /dev/null +++ b/tests/specs/task/dependencies/cross_package.out @@ -0,0 +1,5 @@ +Task not found: ../package2:run +Available tasks: +- run + deno run.js + depends on: ../package2:run diff --git a/tests/specs/task/dependencies/cross_package/package1/deno.json b/tests/specs/task/dependencies/cross_package/package1/deno.json new file mode 100644 index 0000000000..6684a1e2c4 --- /dev/null +++ b/tests/specs/task/dependencies/cross_package/package1/deno.json @@ -0,0 +1,8 @@ +{ + "tasks": { + "run": { + "command": "deno run.js", + "dependencies": ["../package2:run"] + } + } +} diff --git a/tests/specs/task/dependencies/cross_package/package2/deno.json b/tests/specs/task/dependencies/cross_package/package2/deno.json new file mode 100644 index 0000000000..e45ec398f6 --- /dev/null +++ b/tests/specs/task/dependencies/cross_package/package2/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "run": "deno run.js" + } +} diff --git a/tests/specs/task/dependencies/cycle.out b/tests/specs/task/dependencies/cycle.out new file mode 100644 index 0000000000..33352b0bbc --- /dev/null +++ b/tests/specs/task/dependencies/cycle.out @@ -0,0 +1 @@ +Task cycle detected: a -> a diff --git a/tests/specs/task/dependencies/cycle/a.js b/tests/specs/task/dependencies/cycle/a.js new file mode 100644 index 0000000000..688695558e --- /dev/null +++ b/tests/specs/task/dependencies/cycle/a.js @@ -0,0 +1 @@ +console.log("Running a"); diff --git a/tests/specs/task/dependencies/cycle/deno.jsonc b/tests/specs/task/dependencies/cycle/deno.jsonc new file mode 100644 index 0000000000..31e67488cb --- /dev/null +++ b/tests/specs/task/dependencies/cycle/deno.jsonc @@ -0,0 +1,8 @@ +{ + "tasks": { + "a": { + "command": "deno run a.js", + "dependencies": ["a"] + } + } +} diff --git a/tests/specs/task/dependencies/cycle_2.out b/tests/specs/task/dependencies/cycle_2.out new file mode 100644 index 0000000000..89ef04a00b --- /dev/null +++ b/tests/specs/task/dependencies/cycle_2.out @@ -0,0 +1 @@ +Task cycle detected: a -> b -> a diff --git a/tests/specs/task/dependencies/cycle_2/a.js b/tests/specs/task/dependencies/cycle_2/a.js new file mode 100644 index 0000000000..688695558e --- /dev/null +++ b/tests/specs/task/dependencies/cycle_2/a.js @@ -0,0 +1 @@ +console.log("Running a"); diff --git a/tests/specs/task/dependencies/cycle_2/b.js b/tests/specs/task/dependencies/cycle_2/b.js new file mode 100644 index 0000000000..ed1addf1a7 --- /dev/null +++ b/tests/specs/task/dependencies/cycle_2/b.js @@ -0,0 +1 @@ +console.log("Running b"); diff --git a/tests/specs/task/dependencies/cycle_2/deno.jsonc b/tests/specs/task/dependencies/cycle_2/deno.jsonc new file mode 100644 index 0000000000..5a5d38ec9c --- /dev/null +++ b/tests/specs/task/dependencies/cycle_2/deno.jsonc @@ -0,0 +1,12 @@ +{ + "tasks": { + "a": { + "command": "deno run a.js", + "dependencies": ["b"] + }, + "b": { + "command": "deno run b.js", + "dependencies": ["a"] + } + } +} diff --git a/tests/specs/task/dependencies/diamond.out b/tests/specs/task/dependencies/diamond.out new file mode 100644 index 0000000000..75b06a35b2 --- /dev/null +++ b/tests/specs/task/dependencies/diamond.out @@ -0,0 +1,10 @@ +Task d deno run d.js +Running d +[UNORDERED_START] +Task b deno run b.js +Running b +Task c deno run c.js +Running c +[UNORDERED_END] +Task a deno run a.js +Running a diff --git a/tests/specs/task/dependencies/diamond/a.js b/tests/specs/task/dependencies/diamond/a.js new file mode 100644 index 0000000000..688695558e --- /dev/null +++ b/tests/specs/task/dependencies/diamond/a.js @@ -0,0 +1 @@ +console.log("Running a"); diff --git a/tests/specs/task/dependencies/diamond/b.js b/tests/specs/task/dependencies/diamond/b.js new file mode 100644 index 0000000000..ed1addf1a7 --- /dev/null +++ b/tests/specs/task/dependencies/diamond/b.js @@ -0,0 +1 @@ +console.log("Running b"); diff --git a/tests/specs/task/dependencies/diamond/c.js b/tests/specs/task/dependencies/diamond/c.js new file mode 100644 index 0000000000..194d656be6 --- /dev/null +++ b/tests/specs/task/dependencies/diamond/c.js @@ -0,0 +1 @@ +console.log("Running c"); diff --git a/tests/specs/task/dependencies/diamond/d.js b/tests/specs/task/dependencies/diamond/d.js new file mode 100644 index 0000000000..a9f231f83d --- /dev/null +++ b/tests/specs/task/dependencies/diamond/d.js @@ -0,0 +1 @@ +console.log("Running d"); diff --git a/tests/specs/task/dependencies/diamond/deno.jsonc b/tests/specs/task/dependencies/diamond/deno.jsonc new file mode 100644 index 0000000000..07d0a91775 --- /dev/null +++ b/tests/specs/task/dependencies/diamond/deno.jsonc @@ -0,0 +1,22 @@ +{ + // a + // / \ + // b c + // \ / + // d + "tasks": { + "a": { + "command": "deno run a.js", + "dependencies": ["b", "c"] + }, + "b": { + "command": "deno run b.js", + "dependencies": ["d"] + }, + "c": { + "command": "deno run c.js", + "dependencies": ["d"] + }, + "d": "deno run d.js" + } +} diff --git a/tests/specs/task/dependencies/diamond_big.out b/tests/specs/task/dependencies/diamond_big.out new file mode 100644 index 0000000000..f0b827b0da --- /dev/null +++ b/tests/specs/task/dependencies/diamond_big.out @@ -0,0 +1,13 @@ +Task e deno run e.js +Running e +[UNORDERED_START] +Task b deno run b.js +Running b +Task d deno run d.js +Running d +Task c deno run c.js +Running c +Finished b +[UNORDERED_END] +Task a deno run a.js +Running a diff --git a/tests/specs/task/dependencies/diamond_big/a.js b/tests/specs/task/dependencies/diamond_big/a.js new file mode 100644 index 0000000000..688695558e --- /dev/null +++ b/tests/specs/task/dependencies/diamond_big/a.js @@ -0,0 +1 @@ +console.log("Running a"); diff --git a/tests/specs/task/dependencies/diamond_big/b.js b/tests/specs/task/dependencies/diamond_big/b.js new file mode 100644 index 0000000000..4b00ef5692 --- /dev/null +++ b/tests/specs/task/dependencies/diamond_big/b.js @@ -0,0 +1,4 @@ +console.log("Running b"); +setTimeout(() => { + console.log("Finished b"); +}, 10); diff --git a/tests/specs/task/dependencies/diamond_big/c.js b/tests/specs/task/dependencies/diamond_big/c.js new file mode 100644 index 0000000000..194d656be6 --- /dev/null +++ b/tests/specs/task/dependencies/diamond_big/c.js @@ -0,0 +1 @@ +console.log("Running c"); diff --git a/tests/specs/task/dependencies/diamond_big/d.js b/tests/specs/task/dependencies/diamond_big/d.js new file mode 100644 index 0000000000..a9f231f83d --- /dev/null +++ b/tests/specs/task/dependencies/diamond_big/d.js @@ -0,0 +1 @@ +console.log("Running d"); diff --git a/tests/specs/task/dependencies/diamond_big/deno.jsonc b/tests/specs/task/dependencies/diamond_big/deno.jsonc new file mode 100644 index 0000000000..28ea7f6954 --- /dev/null +++ b/tests/specs/task/dependencies/diamond_big/deno.jsonc @@ -0,0 +1,28 @@ +{ + // a + // / \ + // b c + // | | + // | d + // \ / + // e + "tasks": { + "a": { + "command": "deno run a.js", + "dependencies": ["b", "c"] + }, + "b": { + "command": "deno run b.js", + "dependencies": ["e"] + }, + "c": { + "command": "deno run c.js", + "dependencies": ["d"] + }, + "d": { + "command": "deno run d.js", + "dependencies": ["e"] + }, + "e": "deno run e.js" + } +} diff --git a/tests/specs/task/dependencies/diamond_big/e.js b/tests/specs/task/dependencies/diamond_big/e.js new file mode 100644 index 0000000000..b36066c3d7 --- /dev/null +++ b/tests/specs/task/dependencies/diamond_big/e.js @@ -0,0 +1 @@ +console.log("Running e"); diff --git a/tests/specs/task/dependencies/diamond_big_list.out b/tests/specs/task/dependencies/diamond_big_list.out new file mode 100644 index 0000000000..c95bcd272d --- /dev/null +++ b/tests/specs/task/dependencies/diamond_big_list.out @@ -0,0 +1,15 @@ +Available tasks: +- a + deno run a.js + depends on: b, c +- b + deno run b.js + depends on: e +- c + deno run c.js + depends on: d +- d + deno run d.js + depends on: e +- e + deno run e.js diff --git a/tests/specs/task/dependencies/diamond_list.out b/tests/specs/task/dependencies/diamond_list.out new file mode 100644 index 0000000000..dfd725a405 --- /dev/null +++ b/tests/specs/task/dependencies/diamond_list.out @@ -0,0 +1,12 @@ +Available tasks: +- a + deno run a.js + depends on: b, c +- b + deno run b.js + depends on: d +- c + deno run c.js + depends on: d +- d + deno run d.js diff --git a/tests/specs/task/dependencies/run.js b/tests/specs/task/dependencies/run.js new file mode 100644 index 0000000000..f457de6ab0 --- /dev/null +++ b/tests/specs/task/dependencies/run.js @@ -0,0 +1 @@ +console.log("run finished"); diff --git a/tests/specs/task/dependencies/util.js b/tests/specs/task/dependencies/util.js new file mode 100644 index 0000000000..9579eb9c9f --- /dev/null +++ b/tests/specs/task/dependencies/util.js @@ -0,0 +1,4 @@ +export async function randomTimeout(min, max) { + const timeout = Math.floor(Math.random() * (max - min + 1) + min); + return new Promise((resolve) => setTimeout(resolve, timeout)); +} diff --git a/tests/specs/task/eval/__test__.jsonc b/tests/specs/task/eval/__test__.jsonc new file mode 100644 index 0000000000..394db3052a --- /dev/null +++ b/tests/specs/task/eval/__test__.jsonc @@ -0,0 +1,35 @@ +{ + "tests": { + "no_arg": { + "args": "task --eval", + "output": "no_arg.out", + "exitCode": 1 + }, + "echo_pwd": { + "args": ["task", "--eval", "echo $(pwd)"], + "output": "echo_pwd.out" + }, + "piped": { + "args": [ + "task", + "--eval", + "echo 12345 | (deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)' && deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)')" + ], + "output": "piped.out" + }, + "node_modules_bin": { + "tempDir": true, + "steps": [{ + "args": "install", + "output": "[WILDCARD]Initialize @denotest/bin[WILDCARD]" + }, { + "args": [ + "task", + "--eval", + "cli-esm hi hello" + ], + "output": "bin.out" + }] + } + } +} diff --git a/tests/specs/task/eval/bin.out b/tests/specs/task/eval/bin.out new file mode 100644 index 0000000000..7663216bf7 --- /dev/null +++ b/tests/specs/task/eval/bin.out @@ -0,0 +1,3 @@ +Task cli-esm hi hello +hi +hello diff --git a/tests/specs/task/eval/echo_pwd.out b/tests/specs/task/eval/echo_pwd.out new file mode 100644 index 0000000000..f0c53d8b49 --- /dev/null +++ b/tests/specs/task/eval/echo_pwd.out @@ -0,0 +1,2 @@ +Task echo $(pwd) +[WILDCARD] diff --git a/tests/specs/task/eval/no_arg.out b/tests/specs/task/eval/no_arg.out new file mode 100644 index 0000000000..e462855762 --- /dev/null +++ b/tests/specs/task/eval/no_arg.out @@ -0,0 +1,4 @@ +error: [TASK] must be specified when using --eval + +Usage: deno task [OPTIONS] [TASK] + diff --git a/tests/specs/task/eval/package.json b/tests/specs/task/eval/package.json new file mode 100644 index 0000000000..c0a34548f5 --- /dev/null +++ b/tests/specs/task/eval/package.json @@ -0,0 +1,9 @@ +{ + "name": "bin_package", + "devDependencies": { + "@denotest/bin": "1.0.0" + }, + "scripts": { + "sayhi": "cli-esm hi hello" + } +} diff --git a/tests/specs/task/eval/piped.out b/tests/specs/task/eval/piped.out new file mode 100644 index 0000000000..64ccd7ab72 --- /dev/null +++ b/tests/specs/task/eval/piped.out @@ -0,0 +1,3 @@ +Task echo 12345 | (deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)' && deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)') +Uint8Array(1) [ 49 ] +Uint8Array(1) [ 50 ] diff --git a/tests/testdata/fmt/badly_formatted.md b/tests/testdata/fmt/badly_formatted.md index 642918ceae..be90ff845f 100644 --- a/tests/testdata/fmt/badly_formatted.md +++ b/tests/testdata/fmt/badly_formatted.md @@ -63,3 +63,15 @@ function foo(): number { let a:number ``` + + +```sql + seLect * , biz, buz +from baz; +``` + +```sql +-- deno-fmt-ignore-file + seLect * , biz, buz +from baz; +``` diff --git a/tests/testdata/fmt/badly_formatted.sql b/tests/testdata/fmt/badly_formatted.sql new file mode 100644 index 0000000000..8b4cb978f0 --- /dev/null +++ b/tests/testdata/fmt/badly_formatted.sql @@ -0,0 +1,21 @@ +select * from foo; +update foo set a = 'b'Where id = 'biz'; + + + create table foo(id text not null +bar text, + biz int, + buz number NOT NULL +); + +INSERT + into + user_data + (first_name, +last_name, address, phone, email) +VALUES + ('foo', 'bar', + 'biz', 1, 'bix'); + + + diff --git a/tests/testdata/fmt/badly_formatted_fixed.md b/tests/testdata/fmt/badly_formatted_fixed.md index 21176742bb..7a482e058f 100644 --- a/tests/testdata/fmt/badly_formatted_fixed.md +++ b/tests/testdata/fmt/badly_formatted_fixed.md @@ -56,3 +56,18 @@ function foo(): number { let a: number; ``` + +```sql +SELECT + *, + biz, + buz +FROM + baz; +``` + +```sql +-- deno-fmt-ignore-file + seLect * , biz, buz +from baz; +``` diff --git a/tests/testdata/fmt/badly_formatted_fixed.sql b/tests/testdata/fmt/badly_formatted_fixed.sql new file mode 100644 index 0000000000..d50c619216 --- /dev/null +++ b/tests/testdata/fmt/badly_formatted_fixed.sql @@ -0,0 +1,22 @@ +SELECT + * +FROM + foo; + +UPDATE + foo +SET + a = 'b' +WHERE + id = 'biz'; + +CREATE TABLE foo( + id text NOT NULL bar text, + biz int, + buz number NOT NULL +); + +INSERT INTO + user_data (first_name, last_name, address, phone, email) +VALUES + ('foo', 'bar', 'biz', 1, 'bix'); diff --git a/tests/testdata/wasm/math.ts b/tests/testdata/wasm/math.ts new file mode 100644 index 0000000000..5a1de0865e --- /dev/null +++ b/tests/testdata/wasm/math.ts @@ -0,0 +1,8 @@ +// this file is imported by math_with_import.wasm +export function add(a: number, b: number) { + return a + b; +} + +export function subtract(a: number, b: number) { + return a - b; +} diff --git a/tests/testdata/wasm/math.wasm b/tests/testdata/wasm/math.wasm new file mode 100644 index 0000000000..6b3950fcc5 Binary files /dev/null and b/tests/testdata/wasm/math.wasm differ diff --git a/tests/testdata/wasm/math_with_import.wasm b/tests/testdata/wasm/math_with_import.wasm new file mode 100644 index 0000000000..64e195e42b Binary files /dev/null and b/tests/testdata/wasm/math_with_import.wasm differ diff --git a/tests/unit_node/perf_hooks_test.ts b/tests/unit_node/perf_hooks_test.ts index 8247f9fd3a..83d0062228 100644 --- a/tests/unit_node/perf_hooks_test.ts +++ b/tests/unit_node/perf_hooks_test.ts @@ -5,7 +5,7 @@ import { performance, PerformanceObserver, } from "node:perf_hooks"; -import { assertEquals, assertThrows } from "@std/assert"; +import { assert, assertEquals, assertThrows } from "@std/assert"; Deno.test({ name: "[perf_hooks] performance", @@ -73,11 +73,16 @@ Deno.test("[perf_hooks]: eventLoopUtilization", () => { assertEquals(typeof obj.utilization, "number"); }); -Deno.test("[perf_hooks]: monitorEventLoopDelay", () => { - const e = assertThrows(() => { - monitorEventLoopDelay({ resolution: 1 }); - }); +Deno.test("[perf_hooks]: monitorEventLoopDelay", async () => { + const e = monitorEventLoopDelay(); + assertEquals(e.count, 0); + e.enable(); - // deno-lint-ignore no-explicit-any - assertEquals((e as any).code, "ERR_NOT_IMPLEMENTED"); + await new Promise((resolve) => setTimeout(resolve, 100)); + + assert(e.min > 0); + assert(e.minBigInt > 0n); + assert(e.count > 0); + + e.disable(); }); diff --git a/tests/util/server/src/lib.rs b/tests/util/server/src/lib.rs index 89dc1ffc3b..953896cffd 100644 --- a/tests/util/server/src/lib.rs +++ b/tests/util/server/src/lib.rs @@ -919,6 +919,11 @@ pub fn wildcard_match_detailed( if was_last_wildcard || was_last_wildline || current_text.is_empty() { WildcardMatchResult::Success + } else if current_text == "\n" { + WildcardMatchResult::Fail( + "\n!!!! PROBLEM: Missing final newline at end of expected output !!!!" + .to_string(), + ) } else { output_lines.push("==== HAD TEXT AT END OF FILE ====".to_string()); output_lines.push(colors::red(annotate_whitespace(current_text))); diff --git a/tools/copyright_checker.js b/tools/copyright_checker.js index 24afe1dfd7..d7d196bc44 100755 --- a/tools/copyright_checker.js +++ b/tools/copyright_checker.js @@ -31,6 +31,8 @@ export async function checkCopyright() { ":!:.github/mtime_cache/action.js", ":!:cli/bench/testdata/**", ":!:cli/tools/bench/mitata.rs", + ":!:cli/tools/doc/prism.css", + ":!:cli/tools/doc/prism.js", ":!:cli/tools/init/templates/**", ":!:cli/tsc/*typescript.js", ":!:cli/tsc/compiler.d.ts", diff --git a/tools/lint.js b/tools/lint.js index 604dee9b30..8e0057fa30 100755 --- a/tools/lint.js +++ b/tools/lint.js @@ -51,6 +51,8 @@ async function dlint() { ":!:cli/bench/testdata/express-router.js", ":!:cli/bench/testdata/react-dom.js", ":!:cli/compilers/wasm_wrap.js", + ":!:cli/tools/doc/prism.css", + ":!:cli/tools/doc/prism.js", ":!:cli/tsc/dts/**", ":!:cli/tsc/*typescript.js", ":!:cli/tsc/compiler.d.ts",