1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

Merge branch 'main' into repl_restart

This commit is contained in:
Bartek Iwańczuk 2022-12-07 20:58:07 +01:00
commit d4787b57ea
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750
369 changed files with 40061 additions and 32907 deletions

View file

91
Cargo.lock generated
View file

@ -768,7 +768,7 @@ dependencies = [
[[package]]
name = "deno"
version = "1.28.2"
version = "1.28.3"
dependencies = [
"atty",
"base32",
@ -884,7 +884,7 @@ dependencies = [
[[package]]
name = "deno_bench_util"
version = "0.73.0"
version = "0.74.0"
dependencies = [
"bencher",
"deno_core",
@ -894,7 +894,7 @@ dependencies = [
[[package]]
name = "deno_broadcast_channel"
version = "0.73.0"
version = "0.74.0"
dependencies = [
"async-trait",
"deno_core",
@ -904,7 +904,7 @@ dependencies = [
[[package]]
name = "deno_cache"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"async-trait",
"deno_core",
@ -916,14 +916,14 @@ dependencies = [
[[package]]
name = "deno_console"
version = "0.79.0"
version = "0.80.0"
dependencies = [
"deno_core",
]
[[package]]
name = "deno_core"
version = "0.161.0"
version = "0.162.0"
dependencies = [
"anyhow",
"bytes",
@ -948,7 +948,7 @@ dependencies = [
[[package]]
name = "deno_crypto"
version = "0.93.0"
version = "0.94.0"
dependencies = [
"aes",
"aes-gcm",
@ -982,9 +982,9 @@ dependencies = [
[[package]]
name = "deno_doc"
version = "0.49.1"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa3bb0abda350b6523cfc96e0b14c55037fd7b5a901fcc40cb87ef9a1abb6d92"
checksum = "7a5f0f24f690e9c0c1d22fe9c9da68b65d7378a5c10afe4a61398134eb031e21"
dependencies = [
"cfg-if",
"deno_ast",
@ -1000,9 +1000,9 @@ dependencies = [
[[package]]
name = "deno_emit"
version = "0.11.0"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7be76420d8eaac9d82295eb51cb2c0aebd326d305a2ecbeab6582343fb1b743c"
checksum = "c721cb4e2ca7d94702f6987c2050aedfd270d18f87020080e396865a65dd957e"
dependencies = [
"anyhow",
"base64",
@ -1014,7 +1014,7 @@ dependencies = [
[[package]]
name = "deno_fetch"
version = "0.102.0"
version = "0.103.0"
dependencies = [
"bytes",
"data-url",
@ -1031,7 +1031,7 @@ dependencies = [
[[package]]
name = "deno_ffi"
version = "0.66.0"
version = "0.67.0"
dependencies = [
"deno_core",
"dlopen",
@ -1044,7 +1044,7 @@ dependencies = [
[[package]]
name = "deno_flash"
version = "0.15.0"
version = "0.16.0"
dependencies = [
"deno_core",
"deno_tls",
@ -1063,19 +1063,18 @@ dependencies = [
[[package]]
name = "deno_graph"
version = "0.38.0"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65eb6b2223b71a759b12bc21ee35842193d3703157950d1411c0243239f072eb"
checksum = "87b3758993b62cf234fac6e922b2217aac6c3086d6d9a4fa36ddf7779abb0890"
dependencies = [
"anyhow",
"cfg-if",
"data-url",
"deno_ast",
"futures",
"lazy_static",
"once_cell",
"parking_lot 0.12.1",
"regex",
"ring",
"serde",
"serde_json",
"sourcemap",
@ -1084,7 +1083,7 @@ dependencies = [
[[package]]
name = "deno_http"
version = "0.73.0"
version = "0.74.0"
dependencies = [
"async-compression",
"base64",
@ -1125,7 +1124,7 @@ dependencies = [
[[package]]
name = "deno_napi"
version = "0.9.0"
version = "0.10.0"
dependencies = [
"deno_core",
"libloading",
@ -1133,7 +1132,7 @@ dependencies = [
[[package]]
name = "deno_net"
version = "0.71.0"
version = "0.72.0"
dependencies = [
"deno_core",
"deno_tls",
@ -1147,7 +1146,7 @@ dependencies = [
[[package]]
name = "deno_node"
version = "0.16.0"
version = "0.17.0"
dependencies = [
"deno_core",
"once_cell",
@ -1158,7 +1157,7 @@ dependencies = [
[[package]]
name = "deno_ops"
version = "0.39.0"
version = "0.40.0"
dependencies = [
"once_cell",
"pmutil",
@ -1174,7 +1173,7 @@ dependencies = [
[[package]]
name = "deno_runtime"
version = "0.87.0"
version = "0.88.0"
dependencies = [
"atty",
"deno_broadcast_channel",
@ -1225,9 +1224,9 @@ dependencies = [
[[package]]
name = "deno_task_shell"
version = "0.7.3"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a071a6407ade5107091a2481a502e7e6a9a96c5a631c71748058c5a28928fcd3"
checksum = "532b383a071a05144c712614d62f08a2f9fad48dd62d6d457ed3884b049357da"
dependencies = [
"anyhow",
"futures",
@ -1240,7 +1239,7 @@ dependencies = [
[[package]]
name = "deno_tls"
version = "0.66.0"
version = "0.67.0"
dependencies = [
"deno_core",
"once_cell",
@ -1254,7 +1253,7 @@ dependencies = [
[[package]]
name = "deno_url"
version = "0.79.0"
version = "0.80.0"
dependencies = [
"deno_bench_util",
"deno_core",
@ -1266,7 +1265,7 @@ dependencies = [
[[package]]
name = "deno_web"
version = "0.110.0"
version = "0.111.0"
dependencies = [
"async-trait",
"base64-simd",
@ -1283,7 +1282,7 @@ dependencies = [
[[package]]
name = "deno_webgpu"
version = "0.80.0"
version = "0.81.0"
dependencies = [
"deno_core",
"serde",
@ -1294,14 +1293,14 @@ dependencies = [
[[package]]
name = "deno_webidl"
version = "0.79.0"
version = "0.80.0"
dependencies = [
"deno_core",
]
[[package]]
name = "deno_websocket"
version = "0.84.0"
version = "0.85.0"
dependencies = [
"deno_core",
"deno_tls",
@ -1315,7 +1314,7 @@ dependencies = [
[[package]]
name = "deno_webstorage"
version = "0.74.0"
version = "0.75.0"
dependencies = [
"deno_core",
"deno_web",
@ -1445,15 +1444,16 @@ dependencies = [
[[package]]
name = "dprint-plugin-markdown"
version = "0.14.2"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49cf3bc0cb9cc526a894b1d5af07c2ce2af1fa56b765990845ec781ab4cd1c91"
checksum = "999e8891976e3b15b519b920db4ac70c6a85f0c6f0e0ddb6ef3b247373e8984d"
dependencies = [
"anyhow",
"dprint-core",
"pulldown-cmark",
"regex",
"serde",
"unicode-width",
]
[[package]]
@ -1659,9 +1659,9 @@ dependencies = [
[[package]]
name = "eszip"
version = "0.30.0"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fdf9b31295c768c806cbc0d08d98868b4382684b002d216a16eb661bb8e8575"
checksum = "d8119eb19b5b7f9c6b6da550781249bb05562fbdadb10f80f0a3afb96dde4944"
dependencies = [
"anyhow",
"base64",
@ -2844,7 +2844,7 @@ dependencies = [
[[package]]
name = "napi_sym"
version = "0.9.0"
version = "0.10.0"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
@ -3023,9 +3023,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.14.0"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "opaque-debug"
@ -3977,7 +3977,7 @@ dependencies = [
[[package]]
name = "serde_v8"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"bencher",
"bytes",
@ -5155,9 +5155,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "trybuild"
version = "1.0.71"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea496675d71016e9bc76aa42d87f16aefd95447cc5818e671e12b2d7e269075d"
checksum = "db29f438342820400f2d9acfec0d363e987a38b2950bdb50a7069ed17b2148ee"
dependencies = [
"glob",
"once_cell",
@ -5387,14 +5387,13 @@ dependencies = [
[[package]]
name = "v8"
version = "0.55.0"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46cd4f562bce7520fbb511850c5488366264caf346be221cf7e908f51ac33dbc"
checksum = "8e9b88668afedf6ec9f8f6d30b446f622498da2ef0b3991a52e10f0ea8c6cc09"
dependencies = [
"bitflags",
"fslock",
"lazy_static",
"libc",
"which",
]

View file

@ -5,7 +5,7 @@ resolver = "2"
members = [
"bench_util",
"cli",
"cli/napi_sym",
"cli/napi/sym",
"core",
"ops",
"runtime",
@ -40,36 +40,36 @@ license = "MIT"
repository = "https://github.com/denoland/deno"
[workspace.dependencies]
v8 = { version = "0.55.0", default-features = false }
v8 = { version = "0.58.0", default-features = false }
deno_ast = { version = "0.21.0", features = ["transpiling"] }
deno_core = { version = "0.161.0", path = "./core" }
deno_ops = { version = "0.39.0", path = "./ops" }
serde_v8 = { version = "0.72.0", path = "./serde_v8" }
deno_runtime = { version = "0.87.0", path = "./runtime" }
napi_sym = { version = "0.9.0", path = "./cli/napi_sym" }
deno_bench_util = { version = "0.73.0", path = "./bench_util" }
deno_core = { version = "0.162.0", path = "./core" }
deno_ops = { version = "0.40.0", path = "./ops" }
serde_v8 = { version = "0.73.0", path = "./serde_v8" }
deno_runtime = { version = "0.88.0", path = "./runtime" }
napi_sym = { version = "0.10.0", path = "./cli/napi/sym" }
deno_bench_util = { version = "0.74.0", path = "./bench_util" }
test_util = { path = "./test_util" }
# exts
deno_broadcast_channel = { version = "0.73.0", path = "./ext/broadcast_channel" }
deno_cache = { version = "0.11.0", path = "./ext/cache" }
deno_console = { version = "0.79.0", path = "./ext/console" }
deno_crypto = { version = "0.93.0", path = "./ext/crypto" }
deno_fetch = { version = "0.102.0", path = "./ext/fetch" }
deno_ffi = { version = "0.66.0", path = "./ext/ffi" }
deno_flash = { version = "0.15.0", path = "./ext/flash" }
deno_http = { version = "0.73.0", path = "./ext/http" }
deno_net = { version = "0.71.0", path = "./ext/net" }
deno_node = { version = "0.16.0", path = "./ext/node" }
deno_tls = { version = "0.66.0", path = "./ext/tls" }
deno_url = { version = "0.79.0", path = "./ext/url" }
deno_web = { version = "0.110.0", path = "./ext/web" }
deno_webgpu = { version = "0.80.0", path = "./ext/webgpu" }
deno_webidl = { version = "0.79.0", path = "./ext/webidl" }
deno_websocket = { version = "0.84.0", path = "./ext/websocket" }
deno_webstorage = { version = "0.74.0", path = "./ext/webstorage" }
deno_napi = { version = "0.9.0", path = "./ext/napi" }
deno_broadcast_channel = { version = "0.74.0", path = "./ext/broadcast_channel" }
deno_cache = { version = "0.12.0", path = "./ext/cache" }
deno_console = { version = "0.80.0", path = "./ext/console" }
deno_crypto = { version = "0.94.0", path = "./ext/crypto" }
deno_fetch = { version = "0.103.0", path = "./ext/fetch" }
deno_ffi = { version = "0.67.0", path = "./ext/ffi" }
deno_flash = { version = "0.16.0", path = "./ext/flash" }
deno_http = { version = "0.74.0", path = "./ext/http" }
deno_net = { version = "0.72.0", path = "./ext/net" }
deno_node = { version = "0.17.0", path = "./ext/node" }
deno_tls = { version = "0.67.0", path = "./ext/tls" }
deno_url = { version = "0.80.0", path = "./ext/url" }
deno_web = { version = "0.111.0", path = "./ext/web" }
deno_webgpu = { version = "0.81.0", path = "./ext/webgpu" }
deno_webidl = { version = "0.80.0", path = "./ext/webidl" }
deno_websocket = { version = "0.85.0", path = "./ext/websocket" }
deno_webstorage = { version = "0.75.0", path = "./ext/webstorage" }
deno_napi = { version = "0.10.0", path = "./ext/napi" }
anyhow = "1.0.57"
async-trait = "0.1.51"
@ -89,7 +89,7 @@ libc = "=0.2.126"
log = "=0.4.17"
lzzzz = "1.0"
notify = "=5.0.0"
once_cell = "=1.14.0"
once_cell = "=1.16.0"
os_pipe = "=1.0.1"
parking_lot = "0.12.0"
percent-encoding = "=2.2.0"

View file

@ -6,6 +6,40 @@ https://github.com/denoland/deno/releases
We also have one-line install commands at:
https://github.com/denoland/deno_install
### 1.28.3 / 2022.12.01
- Revert "fix(ext/flash): graceful server startup/shutdown with unsettl…
(#16839)
- feat(core): send "executionContextDestroyed" notification on program end
(#16831)
- feat(core): show unresolved promise origin (#16650)
- feat(core): support initializing extensions with and without JS (#16789)
- feat(ops): fast calls for Wasm (#16776)
- feat(ops): support raw pointer arguments (#16826)
- feat(unstable): rework Deno.Command (#16812)
- fix(cli/js): improve resource sanitizer messages (#16798)
- fix(coverage): Error if the emit cache is invalid (#16850)
- fix(ext/ffi): Null buffer pointer value is inconsistent (#16625)
- fix(ext/node): allow absolute path in createRequire (#16853)
- fix(ext/web): fix typings for readable stream readers (#16191)
- fix(fmt/markdown): fix emoji width calculation in tables (#16870)
- fix(inspector): send "isDefault" in aux data (#16836)
- fix(lsp): analyze fs dependencies of dependencies to find npm package
requirements (#16866)
- fix(npm): allow to inspect npm modules with --inspect-brk (#16841)
- fix(npm): better error message when attempting to use typescript in npm
packages (#16813)
- fix(npm): don't resolve JS files when resolving types (#16854)
- fix(npm): ensure npm package downloaded once per run when using `--reload`
(#16842)
- fix(npm): improve package.json exports support for types (#16880)
- fix(ops): circular dependency in deno_ops test (#16809)
- fix(repl): more reliable history handling (#16797)
- fix(repl): respect --quiet flag (#16875)
- fix(runtime): feature-flag snapshot from snapshot (#16843)
- fix(task): output encoding issues on windows (#16794)
- perf(ops): Reenable fast unit result optimization (#16827)
### 1.28.2 / 2022.11.24
- feat(cli): add warning for incorrectly ordered flags (#16734)

View file

@ -2,7 +2,7 @@
[package]
name = "deno_bench_util"
version = "0.73.0"
version = "0.74.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -9,7 +9,7 @@ use crate::profiling::is_profiling;
pub fn create_js_runtime(setup: impl FnOnce() -> Vec<Extension>) -> JsRuntime {
JsRuntime::new(RuntimeOptions {
extensions: setup(),
extensions_with_js: setup(),
..Default::default()
})
}

View file

@ -2,7 +2,7 @@
[package]
name = "deno"
version = "1.28.2"
version = "1.28.3"
authors.workspace = true
default-run = "deno"
edition.workspace = true
@ -26,7 +26,7 @@ harness = false
path = "./bench/lsp_bench_standalone.rs"
[build-dependencies]
deno_runtime.workspace = true
deno_runtime = { workspace = true, features = ["snapshot_from_snapshot"] }
deno_core.workspace = true
regex.workspace = true
serde.workspace = true
@ -43,12 +43,12 @@ winres.workspace = true
[dependencies]
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
deno_core.workspace = true
deno_doc = "0.49.1"
deno_emit = "0.11.0"
deno_graph = "0.38.0"
deno_doc = "0.51.0"
deno_emit = "0.12.0"
deno_graph = "0.39.0"
deno_lint = { version = "0.35.0", features = ["docs"] }
deno_runtime.workspace = true
deno_task_shell = "0.7.3"
deno_task_shell = "0.8.1"
napi_sym.workspace = true
atty.workspace = true
@ -62,11 +62,11 @@ clap_complete_fig = "=3.1.5"
data-url.workspace = true
dissimilar = "=1.0.4"
dprint-plugin-json = "=0.16.0"
dprint-plugin-markdown = "=0.14.2"
dprint-plugin-markdown = "=0.14.3"
dprint-plugin-typescript = "=0.78.0"
encoding_rs.workspace = true
env_logger = "=0.9.0"
eszip = "=0.30.0"
eszip = "=0.31.0"
fancy-regex = "=0.10.0"
flate2.workspace = true
http.workspace = true

View file

@ -3,10 +3,9 @@
use crate::args::ConfigFlag;
use crate::args::Flags;
use crate::args::TaskFlags;
use crate::fs_util;
use crate::fs_util::canonicalize_path;
use crate::fs_util::specifier_parent;
use crate::fs_util::specifier_to_file_path;
use crate::util::fs::canonicalize_path;
use crate::util::path::specifier_parent;
use crate::util::path::specifier_to_file_path;
use deno_core::anyhow::anyhow;
use deno_core::anyhow::bail;
@ -467,7 +466,7 @@ impl ConfigFile {
..
}) = &flags.subcommand
{
let task_cwd = fs_util::canonicalize_path(&PathBuf::from(path))?;
let task_cwd = canonicalize_path(&PathBuf::from(path))?;
if let Some(path) = Self::discover_from(&task_cwd, &mut checked)? {
return Ok(Some(path));
}

View file

@ -163,6 +163,7 @@ pub struct LintFlags {
pub struct ReplFlags {
pub eval_files: Option<Vec<String>>,
pub eval: Option<String>,
pub is_default_command: bool,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
@ -245,6 +246,7 @@ impl Default for DenoSubcommand {
DenoSubcommand::Repl(ReplFlags {
eval_files: None,
eval: None,
is_default_command: true,
})
}
}
@ -624,6 +626,7 @@ pub fn flags_from_vec(args: Vec<String>) -> clap::Result<Flags> {
ReplFlags {
eval_files: None,
eval: None,
is_default_command: true,
},
),
}
@ -632,15 +635,18 @@ pub fn flags_from_vec(args: Vec<String>) -> clap::Result<Flags> {
}
fn handle_repl_flags(flags: &mut Flags, repl_flags: ReplFlags) {
// If user runs just `deno` binary we enter REPL and allow all permissions.
if repl_flags.is_default_command {
flags.allow_net = Some(vec![]);
flags.allow_env = Some(vec![]);
flags.allow_run = Some(vec![]);
flags.allow_read = Some(vec![]);
flags.allow_sys = Some(vec![]);
flags.allow_write = Some(vec![]);
flags.allow_ffi = Some(vec![]);
flags.allow_hrtime = true;
}
flags.subcommand = DenoSubcommand::Repl(repl_flags);
flags.allow_net = Some(vec![]);
flags.allow_env = Some(vec![]);
flags.allow_run = Some(vec![]);
flags.allow_read = Some(vec![]);
flags.allow_sys = Some(vec![]);
flags.allow_write = Some(vec![]);
flags.allow_ffi = Some(vec![]);
flags.allow_hrtime = true;
}
fn clap_root(version: &str) -> Command {
@ -797,12 +803,20 @@ Future runs of this module will trigger no downloads or compilation unless \
fn check_subcommand<'a>() -> Command<'a> {
compile_args_without_check_args(Command::new("check"))
.arg(
Arg::new("remote")
.long("remote")
.help("Type-check all modules, including remote")
.conflicts_with("no-remote")
.arg(
Arg::new("all")
.long("all")
.help("Type-check all code, including remote modules and npm packages")
.conflicts_with("no-remote")
)
.arg(
// past alias for --all
Arg::new("remote")
.long("remote")
.help("Type-check all modules, including remote")
.conflicts_with("no-remote")
.hide(true)
)
.arg(
Arg::new("file")
.takes_value(true)
@ -1456,7 +1470,7 @@ Ignore linting a file by adding an ignore comment at the top of the file:
}
fn repl_subcommand<'a>() -> Command<'a> {
runtime_args(Command::new("repl"), false, true)
runtime_args(Command::new("repl"), true, true)
.about("Read Eval Print Loop")
.arg(
Arg::new("eval-file")
@ -1475,7 +1489,6 @@ fn repl_subcommand<'a>() -> Command<'a> {
.takes_value(true)
.value_name("code"),
)
.arg(unsafely_ignore_certificate_errors_arg())
}
fn run_subcommand<'a>() -> Command<'a> {
@ -2343,7 +2356,7 @@ fn check_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
.unwrap()
.map(String::from)
.collect();
if matches.is_present("remote") {
if matches.is_present("all") || matches.is_present("remote") {
flags.type_check_mode = TypeCheckMode::All;
}
flags.subcommand = DenoSubcommand::Check(CheckFlags { files });
@ -2646,7 +2659,7 @@ fn lint_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
}
fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
runtime_args_parse(flags, matches, false, true);
runtime_args_parse(flags, matches, true, true);
unsafely_ignore_certificate_errors_parse(flags, matches);
let eval_files: Option<Vec<String>> = matches
@ -2658,6 +2671,7 @@ fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
ReplFlags {
eval_files,
eval: matches.value_of("eval").map(ToOwned::to_owned),
is_default_command: false,
},
);
}
@ -4001,26 +4015,28 @@ mod tests {
}
);
let r = flags_from_vec(svec!["deno", "check", "--remote", "script.ts"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Check(CheckFlags {
files: svec!["script.ts"],
}),
type_check_mode: TypeCheckMode::All,
..Flags::default()
}
);
for all_flag in ["--remote", "--all"] {
let r = flags_from_vec(svec!["deno", "check", all_flag, "script.ts"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Check(CheckFlags {
files: svec!["script.ts"],
}),
type_check_mode: TypeCheckMode::All,
..Flags::default()
}
);
let r = flags_from_vec(svec![
"deno",
"check",
"--remote",
"--no-remote",
"script.ts"
]);
assert_eq!(r.unwrap_err().kind(), clap::ErrorKind::ArgumentConflict);
let r = flags_from_vec(svec![
"deno",
"check",
all_flag,
"--no-remote",
"script.ts"
]);
assert_eq!(r.unwrap_err().kind(), clap::ErrorKind::ArgumentConflict);
}
}
#[test]
@ -4266,7 +4282,8 @@ mod tests {
Flags {
subcommand: DenoSubcommand::Repl(ReplFlags {
eval_files: None,
eval: None
eval: None,
is_default_command: true,
}),
allow_net: Some(vec![]),
unsafely_ignore_certificate_errors: None,
@ -4285,13 +4302,14 @@ mod tests {
#[test]
fn repl_with_flags() {
#[rustfmt::skip]
let r = flags_from_vec(svec!["deno", "repl", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--unsafely-ignore-certificate-errors"]);
let r = flags_from_vec(svec!["deno", "repl", "-A", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--unsafely-ignore-certificate-errors"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Repl(ReplFlags {
eval_files: None,
eval: None
eval: None,
is_default_command: false,
}),
import_map_path: Some("import_map.json".to_string()),
no_remote: true,
@ -4306,6 +4324,7 @@ mod tests {
v8_flags: svec!["--help", "--random-seed=1"],
seed: Some(1),
inspect: Some("127.0.0.1:9229".parse().unwrap()),
allow_all: true,
allow_net: Some(vec![]),
allow_env: Some(vec![]),
allow_run: Some(vec![]),
@ -4323,22 +4342,16 @@ mod tests {
#[test]
fn repl_with_eval_flag() {
#[rustfmt::skip]
let r = flags_from_vec(svec!["deno", "repl", "--eval", "console.log('hello');"]);
let r = flags_from_vec(svec!["deno", "repl", "--allow-write", "--eval", "console.log('hello');"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Repl(ReplFlags {
eval_files: None,
eval: Some("console.log('hello');".to_string()),
is_default_command: false,
}),
allow_net: Some(vec![]),
allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_sys: Some(vec![]),
allow_write: Some(vec![]),
allow_ffi: Some(vec![]),
allow_hrtime: true,
type_check_mode: TypeCheckMode::None,
..Flags::default()
}
@ -4359,15 +4372,8 @@ mod tests {
"https://examples.deno.land/hello-world.ts".to_string()
]),
eval: None,
is_default_command: false,
}),
allow_net: Some(vec![]),
allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_sys: Some(vec![]),
allow_write: Some(vec![]),
allow_ffi: Some(vec![]),
allow_hrtime: true,
type_check_mode: TypeCheckMode::None,
..Flags::default()
}
@ -5162,16 +5168,9 @@ mod tests {
subcommand: DenoSubcommand::Repl(ReplFlags {
eval_files: None,
eval: Some("console.log('hello');".to_string()),
is_default_command: false,
}),
unsafely_ignore_certificate_errors: Some(vec![]),
allow_net: Some(vec![]),
allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_sys: Some(vec![]),
allow_write: Some(vec![]),
allow_ffi: Some(vec![]),
allow_hrtime: true,
type_check_mode: TypeCheckMode::None,
..Flags::default()
}
@ -5236,7 +5235,8 @@ mod tests {
Flags {
subcommand: DenoSubcommand::Repl(ReplFlags {
eval_files: None,
eval: None
eval: None,
is_default_command: false,
}),
unsafely_ignore_certificate_errors: Some(svec![
"deno.land",
@ -5246,14 +5246,6 @@ mod tests {
"[::1]",
"1.2.3.4"
]),
allow_net: Some(vec![]),
allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_sys: Some(vec![]),
allow_write: Some(vec![]),
allow_ffi: Some(vec![]),
allow_hrtime: true,
type_check_mode: TypeCheckMode::None,
..Flags::default()
}

View file

@ -2,24 +2,20 @@
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex;
use deno_core::serde::Deserialize;
use deno_core::serde::Serialize;
use deno_core::serde_json;
use deno_core::ModuleSpecifier;
use log::debug;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io::Write;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use crate::args::ConfigFile;
use crate::npm::NpmPackageId;
use crate::npm::NpmPackageReq;
use crate::npm::NpmResolutionPackage;
use crate::tools::fmt::format_json;
use crate::util;
use crate::Flags;
#[derive(Debug)]
@ -95,15 +91,6 @@ pub struct Lockfile {
}
impl Lockfile {
pub fn as_maybe_locker(
lockfile: Option<Arc<Mutex<Lockfile>>>,
) -> Option<Rc<RefCell<dyn deno_graph::source::Locker>>> {
lockfile.as_ref().map(|lf| {
Rc::new(RefCell::new(Locker(Some(lf.clone()))))
as Rc<RefCell<dyn deno_graph::source::Locker>>
})
}
pub fn discover(
flags: &Flags,
maybe_config_file: Option<&ConfigFile>,
@ -260,7 +247,7 @@ impl Lockfile {
/// is not included, insert it.
fn check_or_insert(&mut self, specifier: &str, code: &str) -> bool {
if let Some(lockfile_checksum) = self.content.remote.get(specifier) {
let compiled_checksum = crate::checksum::gen(&[code.as_bytes()]);
let compiled_checksum = util::checksum::gen(&[code.as_bytes()]);
lockfile_checksum == &compiled_checksum
} else {
self.insert(specifier, code);
@ -269,7 +256,7 @@ impl Lockfile {
}
fn insert(&mut self, specifier: &str, code: &str) {
let checksum = crate::checksum::gen(&[code.as_bytes()]);
let checksum = util::checksum::gen(&[code.as_bytes()]);
self.content.remote.insert(specifier.to_string(), checksum);
self.has_content_changed = true;
}
@ -341,33 +328,6 @@ Use \"--lock-write\" flag to regenerate the lockfile at \"{}\".",
}
}
#[derive(Debug)]
pub struct Locker(Option<Arc<Mutex<Lockfile>>>);
impl deno_graph::source::Locker for Locker {
fn check_or_insert(
&mut self,
specifier: &ModuleSpecifier,
source: &str,
) -> bool {
if let Some(lock_file) = &self.0 {
let mut lock_file = lock_file.lock();
lock_file.check_or_insert_remote(specifier.as_str(), source)
} else {
true
}
}
fn get_checksum(&self, content: &str) -> String {
crate::checksum::gen(&[content.as_bytes()])
}
fn get_filename(&self) -> Option<String> {
let lock_file = self.0.as_ref()?.lock();
lock_file.filename.to_str().map(|s| s.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -22,6 +22,10 @@ pub use config_file::TsConfig;
pub use config_file::TsConfigForEmit;
pub use config_file::TsConfigType;
pub use config_file::TsTypeLib;
use deno_runtime::deno_tls::rustls;
use deno_runtime::deno_tls::rustls_native_certs::load_native_certs;
use deno_runtime::deno_tls::rustls_pemfile;
use deno_runtime::deno_tls::webpki_roots;
pub use flags::*;
pub use lockfile::Lockfile;
pub use lockfile::LockfileError;
@ -40,16 +44,130 @@ use deno_runtime::inspector_server::InspectorServer;
use deno_runtime::permissions::PermissionsOptions;
use std::collections::BTreeMap;
use std::env;
use std::io::BufReader;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::Arc;
use crate::cache::DenoDir;
use crate::file_fetcher::get_root_cert_store;
use crate::file_fetcher::CacheSetting;
use crate::fs_util;
use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::version;
/// Indicates how cached source files should be handled.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum CacheSetting {
/// Only the cached files should be used. Any files not in the cache will
/// error. This is the equivalent of `--cached-only` in the CLI.
Only,
/// No cached source files should be used, and all files should be reloaded.
/// This is the equivalent of `--reload` in the CLI.
ReloadAll,
/// Only some cached resources should be used. This is the equivalent of
/// `--reload=https://deno.land/std` or
/// `--reload=https://deno.land/std,https://deno.land/x/example`.
ReloadSome(Vec<String>),
/// The usability of a cached value is determined by analyzing the cached
/// headers and other metadata associated with a cached response, reloading
/// any cached "non-fresh" cached responses.
RespectHeaders,
/// The cached source files should be used for local modules. This is the
/// default behavior of the CLI.
Use,
}
impl CacheSetting {
pub fn should_use_for_npm_package(&self, package_name: &str) -> bool {
match self {
CacheSetting::ReloadAll => false,
CacheSetting::ReloadSome(list) => {
if list.iter().any(|i| i == "npm:") {
return false;
}
let specifier = format!("npm:{}", package_name);
if list.contains(&specifier) {
return false;
}
true
}
_ => true,
}
}
}
/// Create and populate a root cert store based on the passed options and
/// environment.
pub fn get_root_cert_store(
maybe_root_path: Option<PathBuf>,
maybe_ca_stores: Option<Vec<String>>,
maybe_ca_file: Option<String>,
) -> Result<RootCertStore, AnyError> {
let mut root_cert_store = RootCertStore::empty();
let ca_stores: Vec<String> = maybe_ca_stores
.or_else(|| {
let env_ca_store = env::var("DENO_TLS_CA_STORE").ok()?;
Some(
env_ca_store
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect(),
)
})
.unwrap_or_else(|| vec!["mozilla".to_string()]);
for store in ca_stores.iter() {
match store.as_str() {
"mozilla" => {
root_cert_store.add_server_trust_anchors(
webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
}),
);
}
"system" => {
let roots = load_native_certs().expect("could not load platform certs");
for root in roots {
root_cert_store
.add(&rustls::Certificate(root.0))
.expect("Failed to add platform cert to root cert store");
}
}
_ => {
return Err(anyhow!("Unknown certificate store \"{}\" specified (allowed: \"system,mozilla\")", store));
}
}
}
let ca_file = maybe_ca_file.or_else(|| env::var("DENO_CERT").ok());
if let Some(ca_file) = ca_file {
let ca_file = if let Some(root) = &maybe_root_path {
root.join(&ca_file)
} else {
PathBuf::from(ca_file)
};
let certfile = std::fs::File::open(&ca_file)?;
let mut reader = BufReader::new(certfile);
match rustls_pemfile::certs(&mut reader) {
Ok(certs) => {
root_cert_store.add_parsable_certificates(&certs);
}
Err(e) => {
return Err(anyhow!(
"Unable to add pem file to certificate store: {}",
e
));
}
}
}
Ok(root_cert_store)
}
/// Overrides for the options below that when set will
/// use these values over the values derived from the
/// CLI flags or config file.
@ -176,7 +294,7 @@ impl CliOptions {
} else {
std::env::current_dir()?.join("node_modules")
};
Ok(Some(fs_util::canonicalize_path_maybe_not_exists(&path)?))
Ok(Some(canonicalize_path_maybe_not_exists(&path)?))
}
pub fn resolve_root_cert_store(&self) -> Result<RootCertStore, AnyError> {
@ -342,6 +460,13 @@ impl CliOptions {
self.flags.log_level
}
pub fn is_quiet(&self) -> bool {
self
.log_level()
.map(|l| l == log::Level::Error)
.unwrap_or(false)
}
pub fn location_flag(&self) -> Option<&Url> {
self.flags.location.as_ref()
}

View file

@ -1,8 +1,3 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
const count = 100000;
const start = Date.now();
for (let i = 0; i < count; i++) console.log("Hello World");
const elapsed = Date.now() - start;
const rate = Math.floor(count / (elapsed / 1000));
console.log(`time ${elapsed} ms rate ${rate}`);

View file

@ -1,11 +1,10 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
let [total, count] = typeof Deno !== "undefined"
? Deno.args
: [process.argv[2], process.argv[3]];
total = total ? parseInt(total, 0) : 50;
count = count ? parseInt(count, 10) : 1000000;
count = count ? parseInt(count, 10) : 10000000;
function bench(fun) {
const start = Date.now();
@ -13,7 +12,7 @@ function bench(fun) {
const elapsed = Date.now() - start;
const rate = Math.floor(count / (elapsed / 1000));
console.log(`time ${elapsed} ms rate ${rate}`);
if (--total) queueMicrotask(() => bench(fun));
if (--total) bench(fun);
}
const encoder = new TextEncoder();

View file

@ -0,0 +1,9 @@
## `stdio` benchmarks
Compile the C baseline and run the benchmark:
```bash
cc stdio.c -o stdio -O3
time dd if=/dev/zero bs=65536 count=500000 | ./stdio
time dd if=/dev/zero bs=65536 count=500000 | deno run stdio.js
```

29
cli/bench/stdio/stdio.c Normal file
View file

@ -0,0 +1,29 @@
// From https://github.com/just-js/benchmarks/tree/main/01-stdio
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(int argc, char *argv[]) {
unsigned int blocksize = 65536;
if (argc == 2) {
blocksize = atoi(argv[1]);
}
char buf[blocksize];
unsigned long size = 0;
unsigned int reads = 0;
int n = read(STDIN_FILENO, buf, blocksize);
while (n > 0) {
reads++;
size += n;
n = read(STDIN_FILENO, buf, blocksize);
}
if (n < 0) {
fprintf(stderr, "read: %s (%i)\n", strerror(errno), errno);
exit(1);
}
fprintf(stdout, "size %lu reads %u blocksize %u\n", size, reads, blocksize);
}

16
cli/bench/stdio/stdio.js Normal file
View file

@ -0,0 +1,16 @@
// From https://github.com/just-js/benchmarks/tree/main/01-stdio
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
const blocksize = parseInt(Deno.args[0] || 65536);
const buf = new Uint8Array(blocksize);
let size = 0;
let reads = 0;
let n = Deno.stdin.readSync(buf);
while (n > 0) {
reads++;
size += n;
n = Deno.stdin.readSync(buf);
}
if (n < 0) throw new Error("Bad Read");
console.log(`size ${size} reads ${reads} blocksize ${blocksize}`);

21
cli/bench/webstorage.js Normal file
View file

@ -0,0 +1,21 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
// Note: when benchmarking across different Deno version, make sure to clear
// the DENO_DIR cache.
let [total, count] = typeof Deno !== "undefined" ? Deno.args : [];
total = total ? parseInt(total, 0) : 50;
count = count ? parseInt(count, 10) : 1000000;
function bench(fun) {
const start = Date.now();
for (let i = 0; i < count; i++) fun(i);
const elapsed = Date.now() - start;
const rate = Math.floor(count / (elapsed / 1000));
console.log(`time ${elapsed} ms rate ${rate}`);
if (--total) queueMicrotask(() => bench(fun));
}
localStorage.clear();
localStorage.setItem("foo", "bar");
bench(() => localStorage.getItem("foo"));

View file

@ -130,6 +130,10 @@ mod ts {
path_dts.join(format!("lib.{}.d.ts", name)).display()
);
}
println!(
"cargo:rerun-if-changed={}",
cwd.join("js").join("40_testing.js").display()
);
// create a copy of the vector that includes any op crate libs to be passed
// to the JavaScript compiler to build into the snapshot
@ -243,6 +247,7 @@ mod ts {
Ok(())
})
.build()],
extensions_with_js: vec![],
additional_files: files,
compression_cb: Some(Box::new(|vec, snapshot_slice| {
vec.extend_from_slice(
@ -254,17 +259,24 @@ mod ts {
}
pub(crate) fn version() -> String {
std::fs::read_to_string("tsc/00_typescript.js")
.unwrap()
.lines()
.find(|l| l.contains("ts.version = "))
.expect(
"Failed to find the pattern `ts.version = ` in typescript source code",
)
.chars()
.skip_while(|c| !char::is_numeric(*c))
.take_while(|c| *c != '"')
.collect::<String>()
let file_text = std::fs::read_to_string("tsc/00_typescript.js").unwrap();
let mut version = String::new();
for line in file_text.lines() {
let major_minor_text = "ts.versionMajorMinor = \"";
let version_text = "ts.version = \"\".concat(ts.versionMajorMinor, \"";
if version.is_empty() {
if let Some(index) = line.find(major_minor_text) {
let remaining_line = &line[index + major_minor_text.len()..];
version
.push_str(&remaining_line[..remaining_line.find('"').unwrap()]);
}
} else if let Some(index) = line.find(version_text) {
let remaining_line = &line[index + version_text.len()..];
version.push_str(&remaining_line[..remaining_line.find('"').unwrap()]);
return version;
}
}
panic!("Could not find ts version.")
}
}
@ -304,6 +316,7 @@ fn create_cli_snapshot(snapshot_path: PathBuf, files: Vec<PathBuf>) {
snapshot_path,
startup_snapshot: Some(deno_runtime::js::deno_isolate_init()),
extensions,
extensions_with_js: vec![],
additional_files: files,
compression_cb: Some(Box::new(|vec, snapshot_slice| {
lzzzz::lz4_hc::compress_to_vec(

View file

@ -1,7 +1,8 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::fs_util;
use crate::http_cache::url_to_filename;
use super::http_cache::url_to_filename;
use super::CACHE_PERM;
use crate::util::fs::atomic_write_file;
use deno_core::url::Host;
use deno_core::url::Url;
@ -144,7 +145,7 @@ impl DiskCache {
Some(parent) => self.ensure_dir_exists(parent),
None => Ok(()),
}?;
fs_util::atomic_write_file(&path, data, crate::http_cache::CACHE_PERM)
atomic_write_file(&path, data, CACHE_PERM)
.map_err(|e| with_io_context(&e, format!("{:#?}", &path)))
}
}

29
cli/cache/emit.rs vendored
View file

@ -44,7 +44,7 @@ impl EmitCache {
pub fn get_emit_code(
&self,
specifier: &ModuleSpecifier,
expected_source_hash: Option<u64>,
expected_source_hash: u64,
) -> Option<String> {
let meta_filename = self.get_meta_filename(specifier)?;
let emit_filename = self.get_emit_filename(specifier)?;
@ -52,10 +52,8 @@ impl EmitCache {
// load and verify the meta data file is for this source and CLI version
let bytes = self.disk_cache.get(&meta_filename).ok()?;
let meta: EmitMetadata = serde_json::from_slice(&bytes).ok()?;
if let Some(expected_source_hash) = expected_source_hash {
if meta.source_hash != expected_source_hash.to_string() {
return None;
}
if meta.source_hash != expected_source_hash.to_string() {
return None;
}
// load and verify the emit is for the meta data
@ -173,31 +171,26 @@ mod test {
let specifier2 =
ModuleSpecifier::from_file_path(temp_dir.path().join("file2.ts"))
.unwrap();
assert_eq!(cache.get_emit_code(&specifier1, Some(1)), None);
assert_eq!(cache.get_emit_code(&specifier1, 1), None);
let emit_code1 = "text1".to_string();
let emit_code2 = "text2".to_string();
cache.set_emit_code(&specifier1, 10, &emit_code1);
cache.set_emit_code(&specifier2, 2, &emit_code2);
// providing the incorrect source hash
assert_eq!(cache.get_emit_code(&specifier1, Some(5)), None);
assert_eq!(cache.get_emit_code(&specifier1, 5), None);
// providing the correct source hash
assert_eq!(
cache.get_emit_code(&specifier1, Some(10)),
Some(emit_code1.clone()),
);
assert_eq!(cache.get_emit_code(&specifier2, Some(2)), Some(emit_code2));
// providing no hash
assert_eq!(
cache.get_emit_code(&specifier1, None),
cache.get_emit_code(&specifier1, 10),
Some(emit_code1.clone()),
);
assert_eq!(cache.get_emit_code(&specifier2, 2), Some(emit_code2));
// try changing the cli version (should not load previous ones)
let cache = EmitCache {
disk_cache: disk_cache.clone(),
cli_version: "2.0.0".to_string(),
};
assert_eq!(cache.get_emit_code(&specifier1, Some(10)), None);
assert_eq!(cache.get_emit_code(&specifier1, 10), None);
cache.set_emit_code(&specifier1, 5, &emit_code1);
// recreating the cache should still load the data because the CLI version is the same
@ -205,12 +198,12 @@ mod test {
disk_cache,
cli_version: "2.0.0".to_string(),
};
assert_eq!(cache.get_emit_code(&specifier1, Some(5)), Some(emit_code1));
assert_eq!(cache.get_emit_code(&specifier1, 5), Some(emit_code1));
// adding when already exists should not cause issue
let emit_code3 = "asdf".to_string();
cache.set_emit_code(&specifier1, 20, &emit_code3);
assert_eq!(cache.get_emit_code(&specifier1, Some(5)), None);
assert_eq!(cache.get_emit_code(&specifier1, Some(20)), Some(emit_code3));
assert_eq!(cache.get_emit_code(&specifier1, 5), None);
assert_eq!(cache.get_emit_code(&specifier1, 20), Some(emit_code3));
}
}

View file

@ -3,8 +3,8 @@
//! as defined in RFC 7234 (<https://tools.ietf.org/html/rfc7234>).
//! Currently it's a very simplified version to fulfill Deno needs
//! at hand.
use crate::fs_util;
use crate::http_util::HeadersMap;
use crate::util;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::serde::Deserialize;
@ -19,7 +19,7 @@ use std::path::Path;
use std::path::PathBuf;
use std::time::SystemTime;
pub const CACHE_PERM: u32 = 0o644;
use super::CACHE_PERM;
/// Turn base of url (scheme, hostname, port) into a valid filename.
/// This method replaces port part with a special string token (because
@ -68,31 +68,32 @@ pub fn url_to_filename(url: &Url) -> Option<PathBuf> {
// NOTE: fragment is omitted on purpose - it's not taken into
// account when caching - it denotes parts of webpage, which
// in case of static resources doesn't make much sense
let hashed_filename = crate::checksum::gen(&[rest_str.as_bytes()]);
let hashed_filename = util::checksum::gen(&[rest_str.as_bytes()]);
cache_filename.push(hashed_filename);
Some(cache_filename)
}
/// Cached metadata about a url.
#[derive(Serialize, Deserialize)]
pub struct Metadata {
pub struct CachedUrlMetadata {
pub headers: HeadersMap,
pub url: String,
#[serde(default = "SystemTime::now")]
pub now: SystemTime,
}
impl Metadata {
impl CachedUrlMetadata {
pub fn write(&self, cache_filename: &Path) -> Result<(), AnyError> {
let metadata_filename = Self::filename(cache_filename);
let json = serde_json::to_string_pretty(self)?;
fs_util::atomic_write_file(&metadata_filename, json, CACHE_PERM)?;
util::fs::atomic_write_file(&metadata_filename, json, CACHE_PERM)?;
Ok(())
}
pub fn read(cache_filename: &Path) -> Result<Metadata, AnyError> {
let metadata_filename = Metadata::filename(cache_filename);
pub fn read(cache_filename: &Path) -> Result<Self, AnyError> {
let metadata_filename = Self::filename(cache_filename);
let metadata = fs::read_to_string(metadata_filename)?;
let metadata: Metadata = serde_json::from_str(&metadata)?;
let metadata: Self = serde_json::from_str(&metadata)?;
Ok(metadata)
}
@ -149,10 +150,10 @@ impl HttpCache {
url_to_filename(url)
.ok_or_else(|| generic_error("Can't convert url to filename."))?,
);
let metadata_filename = Metadata::filename(&cache_filename);
let metadata_filename = CachedUrlMetadata::filename(&cache_filename);
let file = File::open(cache_filename)?;
let metadata = fs::read_to_string(metadata_filename)?;
let metadata: Metadata = serde_json::from_str(&metadata)?;
let metadata: CachedUrlMetadata = serde_json::from_str(&metadata)?;
Ok((file, metadata.headers, metadata.now))
}
@ -172,9 +173,9 @@ impl HttpCache {
.expect("Cache filename should have a parent dir");
self.ensure_dir_exists(parent_filename)?;
// Cache content
fs_util::atomic_write_file(&cache_filename, content, CACHE_PERM)?;
util::fs::atomic_write_file(&cache_filename, content, CACHE_PERM)?;
let metadata = Metadata {
let metadata = CachedUrlMetadata {
now: SystemTime::now(),
url: url.to_string(),
headers: headers_map,

6
cli/cache/mod.rs vendored
View file

@ -19,6 +19,7 @@ mod common;
mod deno_dir;
mod disk_cache;
mod emit;
mod http_cache;
mod incremental;
mod node;
mod parsed_source;
@ -28,10 +29,15 @@ pub use common::FastInsecureHasher;
pub use deno_dir::DenoDir;
pub use disk_cache::DiskCache;
pub use emit::EmitCache;
pub use http_cache::CachedUrlMetadata;
pub use http_cache::HttpCache;
pub use incremental::IncrementalCache;
pub use node::NodeAnalysisCache;
pub use parsed_source::ParsedSourceCache;
/// Permissions used to save a file in the disk caches.
pub const CACHE_PERM: u32 = 0o644;
/// A "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides
/// a concise interface to the DENO_DIR when building module graphs.
pub struct FetchCacher {

View file

@ -5,7 +5,7 @@ use once_cell::sync::Lazy;
// WARNING: Ensure this is the only deno_std version reference as this
// is automatically updated by the version bump workflow.
static CURRENT_STD_URL_STR: &str = "https://deno.land/std@0.166.0/";
static CURRENT_STD_URL_STR: &str = "https://deno.land/std@0.167.0/";
pub static CURRENT_STD_URL: Lazy<Url> =
Lazy::new(|| Url::parse(CURRENT_STD_URL_STR).unwrap());

View file

@ -12,7 +12,7 @@ use std::sync::Arc;
/// A hashing function that takes the source code and emit options
/// hash then generates a string hash which can be stored to
/// determine if the cached emit is valid or not.
fn get_source_hash(source_text: &str, emit_options_hash: u64) -> u64 {
pub fn get_source_hash(source_text: &str, emit_options_hash: u64) -> u64 {
FastInsecureHasher::new()
.write_str(source_text)
.write_u64(emit_options_hash)
@ -30,9 +30,7 @@ pub fn emit_parsed_source(
) -> Result<String, AnyError> {
let source_hash = get_source_hash(source, emit_config_hash);
if let Some(emit_code) =
emit_cache.get_emit_code(specifier, Some(source_hash))
{
if let Some(emit_code) = emit_cache.get_emit_code(specifier, source_hash) {
Ok(emit_code)
} else {
// this will use a cached version if it exists

View file

@ -26,8 +26,7 @@ fn get_diagnostic_class(_: &Diagnostic) -> &'static str {
fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str {
match err {
ModuleGraphError::LoadingErr(_, err) => get_error_class_name(err.as_ref()),
ModuleGraphError::InvalidSource(_, _)
| ModuleGraphError::InvalidTypeAssertion { .. } => "SyntaxError",
ModuleGraphError::InvalidTypeAssertion { .. } => "SyntaxError",
ModuleGraphError::ParseErr(_, diagnostic) => {
get_diagnostic_class(diagnostic)
}

View file

@ -1,18 +1,18 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::args::CacheSetting;
use crate::auth_tokens::AuthTokens;
use crate::cache::HttpCache;
use crate::colors;
use crate::http_cache::HttpCache;
use crate::http_util::CacheSemantics;
use crate::http_util::FetchOnceArgs;
use crate::http_util::FetchOnceResult;
use crate::http_util::HttpClient;
use crate::progress_bar::ProgressBar;
use crate::text_encoding;
use crate::util::progress_bar::ProgressBar;
use crate::util::text_encoding;
use data_url::DataUrl;
use deno_ast::MediaType;
use deno_core::anyhow::anyhow;
use deno_core::error::custom_error;
use deno_core::error::generic_error;
use deno_core::error::uri_error;
@ -21,11 +21,6 @@ use deno_core::futures;
use deno_core::futures::future::FutureExt;
use deno_core::parking_lot::Mutex;
use deno_core::ModuleSpecifier;
use deno_runtime::deno_tls::rustls;
use deno_runtime::deno_tls::rustls::RootCertStore;
use deno_runtime::deno_tls::rustls_native_certs::load_native_certs;
use deno_runtime::deno_tls::rustls_pemfile;
use deno_runtime::deno_tls::webpki_roots;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::permissions::Permissions;
use log::debug;
@ -34,7 +29,6 @@ use std::collections::HashMap;
use std::env;
use std::fs;
use std::future::Future;
use std::io::BufReader;
use std::io::Read;
use std::path::PathBuf;
use std::pin::Pin;
@ -82,86 +76,6 @@ impl FileCache {
}
}
/// Indicates how cached source files should be handled.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum CacheSetting {
/// Only the cached files should be used. Any files not in the cache will
/// error. This is the equivalent of `--cached-only` in the CLI.
Only,
/// No cached source files should be used, and all files should be reloaded.
/// This is the equivalent of `--reload` in the CLI.
ReloadAll,
/// Only some cached resources should be used. This is the equivalent of
/// `--reload=https://deno.land/std` or
/// `--reload=https://deno.land/std,https://deno.land/x/example`.
ReloadSome(Vec<String>),
/// The usability of a cached value is determined by analyzing the cached
/// headers and other metadata associated with a cached response, reloading
/// any cached "non-fresh" cached responses.
RespectHeaders,
/// The cached source files should be used for local modules. This is the
/// default behavior of the CLI.
Use,
}
impl CacheSetting {
/// Returns if the cache should be used for a given specifier.
pub fn should_use(
&self,
specifier: &ModuleSpecifier,
http_cache: &HttpCache,
) -> bool {
match self {
CacheSetting::ReloadAll => false,
CacheSetting::Use | CacheSetting::Only => true,
CacheSetting::RespectHeaders => {
if let Ok((_, headers, cache_time)) = http_cache.get(specifier) {
let cache_semantics =
CacheSemantics::new(headers, cache_time, SystemTime::now());
cache_semantics.should_use()
} else {
false
}
}
CacheSetting::ReloadSome(list) => {
let mut url = specifier.clone();
url.set_fragment(None);
if list.contains(&url.as_str().to_string()) {
return false;
}
url.set_query(None);
let mut path = PathBuf::from(url.as_str());
loop {
if list.contains(&path.to_str().unwrap().to_string()) {
return false;
}
if !path.pop() {
break;
}
}
true
}
}
}
pub fn should_use_for_npm_package(&self, package_name: &str) -> bool {
match self {
CacheSetting::ReloadAll => false,
CacheSetting::ReloadSome(list) => {
if list.contains(&"npm:".to_string()) {
return false;
}
let specifier = format!("npm:{}", package_name);
if list.contains(&specifier) {
return false;
}
true
}
_ => true,
}
}
}
/// Fetch a source file from the local file system.
fn fetch_local(specifier: &ModuleSpecifier) -> Result<File, AnyError> {
let local = specifier.to_file_path().map_err(|_| {
@ -182,80 +96,6 @@ fn fetch_local(specifier: &ModuleSpecifier) -> Result<File, AnyError> {
})
}
/// Create and populate a root cert store based on the passed options and
/// environment.
pub fn get_root_cert_store(
maybe_root_path: Option<PathBuf>,
maybe_ca_stores: Option<Vec<String>>,
maybe_ca_file: Option<String>,
) -> Result<RootCertStore, AnyError> {
let mut root_cert_store = RootCertStore::empty();
let ca_stores: Vec<String> = maybe_ca_stores
.or_else(|| {
let env_ca_store = env::var("DENO_TLS_CA_STORE").ok()?;
Some(
env_ca_store
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect(),
)
})
.unwrap_or_else(|| vec!["mozilla".to_string()]);
for store in ca_stores.iter() {
match store.as_str() {
"mozilla" => {
root_cert_store.add_server_trust_anchors(
webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
}),
);
}
"system" => {
let roots = load_native_certs().expect("could not load platform certs");
for root in roots {
root_cert_store
.add(&rustls::Certificate(root.0))
.expect("Failed to add platform cert to root cert store");
}
}
_ => {
return Err(anyhow!("Unknown certificate store \"{}\" specified (allowed: \"system,mozilla\")", store));
}
}
}
let ca_file = maybe_ca_file.or_else(|| env::var("DENO_CERT").ok());
if let Some(ca_file) = ca_file {
let ca_file = if let Some(root) = &maybe_root_path {
root.join(&ca_file)
} else {
PathBuf::from(ca_file)
};
let certfile = fs::File::open(&ca_file)?;
let mut reader = BufReader::new(certfile);
match rustls_pemfile::certs(&mut reader) {
Ok(certs) => {
root_cert_store.add_parsable_certificates(&certs);
}
Err(e) => {
return Err(anyhow!(
"Unable to add pem file to certificate store: {}",
e
));
}
}
}
Ok(root_cert_store)
}
/// Returns the decoded body and content-type of a provided
/// data URL.
pub fn get_source_from_data_url(
@ -571,7 +411,7 @@ impl FileFetcher {
return futures::future::err(err).boxed();
}
if self.cache_setting.should_use(specifier, &self.http_cache) {
if self.should_use_cache(specifier) {
match self.fetch_cached(specifier, redirect_limit) {
Ok(Some(file)) => {
return futures::future::ok(file).boxed();
@ -654,6 +494,41 @@ impl FileFetcher {
.boxed()
}
/// Returns if the cache should be used for a given specifier.
fn should_use_cache(&self, specifier: &ModuleSpecifier) -> bool {
match &self.cache_setting {
CacheSetting::ReloadAll => false,
CacheSetting::Use | CacheSetting::Only => true,
CacheSetting::RespectHeaders => {
if let Ok((_, headers, cache_time)) = self.http_cache.get(specifier) {
let cache_semantics =
CacheSemantics::new(headers, cache_time, SystemTime::now());
cache_semantics.should_use()
} else {
false
}
}
CacheSetting::ReloadSome(list) => {
let mut url = specifier.clone();
url.set_fragment(None);
if list.contains(&url.as_str().to_string()) {
return false;
}
url.set_query(None);
let mut path = PathBuf::from(url.as_str());
loop {
if list.contains(&path.to_str().unwrap().to_string()) {
return false;
}
if !path.pop() {
break;
}
}
true
}
}
}
/// Fetch a source file and asynchronously return it.
pub async fn fetch(
&self,
@ -754,6 +629,7 @@ impl FileFetcher {
#[cfg(test)]
mod tests {
use crate::cache::CachedUrlMetadata;
use crate::http_util::HttpClient;
use super::*;
@ -1175,8 +1051,7 @@ mod tests {
.http_cache
.get_cache_filename(&specifier)
.unwrap();
let mut metadata =
crate::http_cache::Metadata::read(&cache_filename).unwrap();
let mut metadata = CachedUrlMetadata::read(&cache_filename).unwrap();
metadata.headers = HashMap::new();
metadata
.headers
@ -1265,8 +1140,7 @@ mod tests {
.await;
assert!(result.is_ok());
let metadata_filename =
crate::http_cache::Metadata::filename(&cache_filename);
let metadata_filename = CachedUrlMetadata::filename(&cache_filename);
let metadata_file = fs::File::open(metadata_filename).unwrap();
let metadata_file_metadata = metadata_file.metadata().unwrap();
let metadata_file_modified_01 = metadata_file_metadata.modified().unwrap();
@ -1285,8 +1159,7 @@ mod tests {
.await;
assert!(result.is_ok());
let metadata_filename =
crate::http_cache::Metadata::filename(&cache_filename);
let metadata_filename = CachedUrlMetadata::filename(&cache_filename);
let metadata_file = fs::File::open(metadata_filename).unwrap();
let metadata_file_metadata = metadata_file.metadata().unwrap();
let metadata_file_modified_02 = metadata_file_metadata.modified().unwrap();
@ -1438,7 +1311,7 @@ mod tests {
assert!(result.is_ok());
let metadata_filename =
crate::http_cache::Metadata::filename(&redirected_cache_filename);
CachedUrlMetadata::filename(&redirected_cache_filename);
let metadata_file = fs::File::open(metadata_filename).unwrap();
let metadata_file_metadata = metadata_file.metadata().unwrap();
let metadata_file_modified_01 = metadata_file_metadata.modified().unwrap();
@ -1458,7 +1331,7 @@ mod tests {
assert!(result.is_ok());
let metadata_filename =
crate::http_cache::Metadata::filename(&redirected_cache_filename);
CachedUrlMetadata::filename(&redirected_cache_filename);
let metadata_file = fs::File::open(metadata_filename).unwrap();
let metadata_file_metadata = metadata_file.metadata().unwrap();
let metadata_file_modified_02 = metadata_file_metadata.modified().unwrap();

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::args::Lockfile;
use crate::args::TsTypeLib;
use crate::colors;
use crate::errors::get_error_class_name;
@ -80,23 +81,23 @@ impl GraphData {
let mut has_npm_specifier_in_graph = false;
for (specifier, result) in graph.specifiers() {
if NpmPackageReference::from_specifier(&specifier).is_ok() {
if NpmPackageReference::from_specifier(specifier).is_ok() {
has_npm_specifier_in_graph = true;
continue;
}
if !reload && self.modules.contains_key(&specifier) {
if !reload && self.modules.contains_key(specifier) {
continue;
}
if let Some(found) = graph.redirects.get(&specifier) {
if let Some(found) = graph.redirects.get(specifier) {
let module_entry = ModuleEntry::Redirect(found.clone());
self.modules.insert(specifier.clone(), module_entry);
continue;
}
match result {
Ok((_, _, media_type)) => {
let module = graph.get(&specifier).unwrap();
let module = graph.get(specifier).unwrap();
let code = match &module.maybe_source {
Some(source) => source.clone(),
None => continue,
@ -134,11 +135,11 @@ impl GraphData {
checked_libs: Default::default(),
maybe_types,
};
self.modules.insert(specifier, module_entry);
self.modules.insert(specifier.clone(), module_entry);
}
Err(error) => {
let module_entry = ModuleEntry::Error(error);
self.modules.insert(specifier, module_entry);
let module_entry = ModuleEntry::Error(error.clone());
self.modules.insert(specifier.clone(), module_entry);
}
}
}
@ -475,10 +476,23 @@ pub fn graph_valid(
.unwrap()
}
/// Calls `graph.lock()` and exits on errors.
pub fn graph_lock_or_exit(graph: &ModuleGraph) {
if let Err(err) = graph.lock() {
log::error!("{} {}", colors::red("error:"), err);
std::process::exit(10);
/// Checks the lockfile against the graph and and exits on errors.
pub fn graph_lock_or_exit(graph: &ModuleGraph, lockfile: &mut Lockfile) {
for module in graph.modules() {
if let Some(source) = &module.maybe_source {
if !lockfile.check_or_insert_remote(module.specifier.as_str(), source) {
let err = format!(
concat!(
"The source code is invalid, as it does not match the expected hash in the lock file.\n",
" Specifier: {}\n",
" Lock file: {}",
),
module.specifier,
lockfile.filename.display(),
);
log::error!("{} {}", colors::red("error:"), err);
std::process::exit(10);
}
}
}
}

View file

@ -708,7 +708,7 @@
);
}
testDesc.origin = getTestOrigin();
const jsError = Deno.core.destructureError(new Error());
const jsError = core.destructureError(new Error());
testDesc.location = {
fileName: jsError.frames[1].fileName,
lineNumber: jsError.frames[1].lineNumber,
@ -1086,6 +1086,9 @@
}
for (const desc of filtered) {
if (ops.op_tests_should_stop()) {
break;
}
ops.op_dispatch_test_event({ wait: desc.id });
const earlier = DateNow();
const result = await runTest(desc);
@ -1290,7 +1293,7 @@
stepDesc.sanitizeResources ??= desc.sanitizeResources;
stepDesc.sanitizeExit ??= desc.sanitizeExit;
stepDesc.origin = getTestOrigin();
const jsError = Deno.core.destructureError(new Error());
const jsError = core.destructureError(new Error());
stepDesc.location = {
fileName: jsError.frames[1].fileName,
lineNumber: jsError.frames[1].lineNumber,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::http_cache;
use crate::cache::CachedUrlMetadata;
use crate::cache::HttpCache;
use deno_core::parking_lot::Mutex;
use deno_core::ModuleSpecifier;
@ -49,14 +50,14 @@ struct Metadata {
#[derive(Debug, Default, Clone)]
pub struct CacheMetadata {
cache: http_cache::HttpCache,
cache: HttpCache,
metadata: Arc<Mutex<HashMap<ModuleSpecifier, Metadata>>>,
}
impl CacheMetadata {
pub fn new(location: &Path) -> Self {
Self {
cache: http_cache::HttpCache::new(location),
cache: HttpCache::new(location),
metadata: Default::default(),
}
}
@ -87,8 +88,7 @@ impl CacheMetadata {
return None;
}
let cache_filename = self.cache.get_cache_filename(specifier)?;
let specifier_metadata =
http_cache::Metadata::read(&cache_filename).ok()?;
let specifier_metadata = CachedUrlMetadata::read(&cache_filename).ok()?;
let values = Arc::new(parse_metadata(&specifier_metadata.headers));
let version = calculate_fs_version(&cache_filename);
let mut metadata_map = self.metadata.lock();
@ -98,7 +98,7 @@ impl CacheMetadata {
}
pub fn set_location(&mut self, location: &Path) {
self.cache = http_cache::HttpCache::new(location);
self.cache = HttpCache::new(location);
self.metadata.lock().clear();
}
}

View file

@ -7,9 +7,9 @@ use super::lsp_custom;
use super::registries::ModuleRegistry;
use super::tsc;
use crate::fs_util::is_supported_ext;
use crate::fs_util::relative_specifier;
use crate::fs_util::specifier_to_file_path;
use crate::util::path::is_supported_ext;
use crate::util::path::relative_specifier;
use crate::util::path::specifier_to_file_path;
use deno_ast::LineAndColumnIndex;
use deno_ast::SourceTextInfo;
@ -505,7 +505,7 @@ fn get_workspace_completions(
#[cfg(test)]
mod tests {
use super::*;
use crate::http_cache::HttpCache;
use crate::cache::HttpCache;
use crate::lsp::documents::Documents;
use crate::lsp::documents::LanguageId;
use deno_core::resolve_url;

View file

@ -2,7 +2,8 @@
use super::client::Client;
use super::logging::lsp_log;
use crate::fs_util;
use crate::util::path::ensure_directory_specifier;
use crate::util::path::specifier_to_file_path;
use deno_core::error::AnyError;
use deno_core::serde::Deserialize;
use deno_core::serde::Serialize;
@ -549,11 +550,11 @@ impl Config {
workspace: &ModuleSpecifier,
enabled_paths: Vec<String>,
) -> bool {
let workspace = fs_util::ensure_directory_specifier(workspace.clone());
let workspace = ensure_directory_specifier(workspace.clone());
let key = workspace.to_string();
let mut touched = false;
if !enabled_paths.is_empty() {
if let Ok(workspace_path) = fs_util::specifier_to_file_path(&workspace) {
if let Ok(workspace_path) = specifier_to_file_path(&workspace) {
let mut paths = Vec::new();
for path in &enabled_paths {
let fs_path = workspace_path.join(path);

View file

@ -6,21 +6,20 @@ use super::tsc;
use super::tsc::AssetDocument;
use crate::args::ConfigFile;
use crate::cache::CachedUrlMetadata;
use crate::cache::HttpCache;
use crate::file_fetcher::get_source_from_bytes;
use crate::file_fetcher::map_content_type;
use crate::file_fetcher::SUPPORTED_SCHEMES;
use crate::fs_util::specifier_to_file_path;
use crate::http_cache;
use crate::http_cache::HttpCache;
use crate::node;
use crate::node::node_resolve_npm_reference;
use crate::node::NodeResolution;
use crate::node::NodeResolutionMode;
use crate::npm::NpmPackageReference;
use crate::npm::NpmPackageReq;
use crate::npm::NpmPackageResolver;
use crate::resolver::CliResolver;
use crate::text_encoding;
use crate::util::path::specifier_to_file_path;
use crate::util::text_encoding;
use deno_ast::MediaType;
use deno_ast::ParsedSource;
@ -33,10 +32,12 @@ use deno_core::url;
use deno_core::ModuleSpecifier;
use deno_graph::GraphImport;
use deno_graph::Resolved;
use deno_runtime::deno_node::NodeResolutionMode;
use once_cell::sync::Lazy;
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::VecDeque;
use std::fs;
use std::ops::Range;
use std::path::Path;
@ -610,7 +611,7 @@ impl SpecifierResolver {
) -> Option<ModuleSpecifier> {
let cache_filename = self.cache.get_cache_filename(specifier)?;
if redirect_limit > 0 && cache_filename.is_file() {
let headers = http_cache::Metadata::read(&cache_filename)
let headers = CachedUrlMetadata::read(&cache_filename)
.ok()
.map(|m| m.headers)?;
if let Some(location) = headers.get("location") {
@ -633,6 +634,23 @@ struct FileSystemDocuments {
}
impl FileSystemDocuments {
pub fn get(
&mut self,
cache: &HttpCache,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
specifier: &ModuleSpecifier,
) -> Option<Document> {
let fs_version = get_document_path(cache, specifier)
.and_then(|path| calculate_fs_version(&path));
let file_system_doc = self.docs.get(specifier);
if file_system_doc.map(|d| d.fs_version().to_string()) != fs_version {
// attempt to update the file on the file system
self.refresh_document(cache, maybe_resolver, specifier)
} else {
file_system_doc.cloned()
}
}
/// Adds or updates a document by reading the document from the file system
/// returning the document.
fn refresh_document(
@ -657,8 +675,7 @@ impl FileSystemDocuments {
)
} else {
let cache_filename = cache.get_cache_filename(specifier)?;
let specifier_metadata =
http_cache::Metadata::read(&cache_filename).ok()?;
let specifier_metadata = CachedUrlMetadata::read(&cache_filename).ok()?;
let maybe_content_type =
specifier_metadata.headers.get("content-type").cloned();
let maybe_headers = Some(&specifier_metadata.headers);
@ -710,7 +727,7 @@ pub struct Documents {
/// settings.
maybe_resolver: Option<CliResolver>,
/// The npm package requirements.
npm_reqs: HashSet<NpmPackageReq>,
npm_reqs: Arc<HashSet<NpmPackageReq>>,
/// Resolves a specifier to its final redirected to specifier.
specifier_resolver: Arc<SpecifierResolver>,
}
@ -725,7 +742,7 @@ impl Documents {
file_system_docs: Default::default(),
imports: Default::default(),
maybe_resolver: None,
npm_reqs: HashSet::new(),
npm_reqs: Default::default(),
specifier_resolver: Arc::new(SpecifierResolver::new(location)),
}
}
@ -863,7 +880,7 @@ impl Documents {
/// Returns a collection of npm package requirements.
pub fn npm_package_reqs(&mut self) -> HashSet<NpmPackageReq> {
self.calculate_dependents_if_dirty();
self.npm_reqs.clone()
(*self.npm_reqs).clone()
}
/// Return a document for the specifier.
@ -873,19 +890,7 @@ impl Documents {
Some(document.clone())
} else {
let mut file_system_docs = self.file_system_docs.lock();
let fs_version = get_document_path(&self.cache, &specifier)
.and_then(|path| calculate_fs_version(&path));
let file_system_doc = file_system_docs.docs.get(&specifier);
if file_system_doc.map(|d| d.fs_version().to_string()) != fs_version {
// attempt to update the file on the file system
file_system_docs.refresh_document(
&self.cache,
self.get_maybe_resolver(),
&specifier,
)
} else {
file_system_doc.cloned()
}
file_system_docs.get(&self.cache, self.get_maybe_resolver(), &specifier)
}
}
@ -938,7 +943,7 @@ impl Documents {
/// tsc when type checking.
pub fn resolve(
&self,
specifiers: Vec<String>,
specifiers: &[String],
referrer: &ModuleSpecifier,
maybe_npm_resolver: Option<&NpmPackageResolver>,
) -> Option<Vec<Option<(ModuleSpecifier, MediaType)>>> {
@ -950,9 +955,9 @@ impl Documents {
// we're in an npm package, so use node resolution
results.push(Some(NodeResolution::into_specifier_and_media_type(
node::node_resolve(
&specifier,
specifier,
referrer,
node::NodeResolutionMode::Types,
NodeResolutionMode::Types,
npm_resolver,
)
.ok()
@ -963,13 +968,13 @@ impl Documents {
}
// handle npm:<package> urls
if specifier.starts_with("asset:") {
if let Ok(specifier) = ModuleSpecifier::parse(&specifier) {
if let Ok(specifier) = ModuleSpecifier::parse(specifier) {
let media_type = MediaType::from(&specifier);
results.push(Some((specifier, media_type)));
} else {
results.push(None);
}
} else if let Some(dep) = dependencies.deps.get(&specifier) {
} else if let Some(dep) = dependencies.deps.get(specifier) {
if let Resolved::Ok { specifier, .. } = &dep.maybe_type {
results.push(self.resolve_dependency(specifier, maybe_npm_resolver));
} else if let Resolved::Ok { specifier, .. } = &dep.maybe_code {
@ -978,12 +983,12 @@ impl Documents {
results.push(None);
}
} else if let Some(Resolved::Ok { specifier, .. }) =
self.resolve_imports_dependency(&specifier)
self.resolve_imports_dependency(specifier)
{
// clone here to avoid double borrow of self
let specifier = specifier.clone();
results.push(self.resolve_dependency(&specifier, maybe_npm_resolver));
} else if let Ok(npm_ref) = NpmPackageReference::from_str(&specifier) {
} else if let Ok(npm_ref) = NpmPackageReference::from_str(specifier) {
results.push(maybe_npm_resolver.map(|npm_resolver| {
NodeResolution::into_specifier_and_media_type(
node_resolve_npm_reference(
@ -1076,46 +1081,74 @@ impl Documents {
/// document and the value is a set of specifiers that depend on that
/// document.
fn calculate_dependents_if_dirty(&mut self) {
#[derive(Default)]
struct DocAnalyzer {
dependents_map: HashMap<ModuleSpecifier, HashSet<ModuleSpecifier>>,
analyzed_specifiers: HashSet<ModuleSpecifier>,
pending_specifiers: VecDeque<ModuleSpecifier>,
npm_reqs: HashSet<NpmPackageReq>,
}
impl DocAnalyzer {
fn add(&mut self, dep: &ModuleSpecifier, specifier: &ModuleSpecifier) {
if !self.analyzed_specifiers.contains(dep) {
self.analyzed_specifiers.insert(dep.clone());
// perf: ensure this is not added to unless this specifier has never
// been analyzed in order to not cause an extra file system lookup
self.pending_specifiers.push_back(dep.clone());
if let Ok(reference) = NpmPackageReference::from_specifier(dep) {
self.npm_reqs.insert(reference.req);
}
}
self
.dependents_map
.entry(dep.clone())
.or_default()
.insert(specifier.clone());
}
fn analyze_doc(&mut self, specifier: &ModuleSpecifier, doc: &Document) {
self.analyzed_specifiers.insert(specifier.clone());
for dependency in doc.dependencies().values() {
if let Some(dep) = dependency.get_code() {
self.add(dep, specifier);
}
if let Some(dep) = dependency.get_type() {
self.add(dep, specifier);
}
}
if let Resolved::Ok { specifier: dep, .. } =
doc.maybe_types_dependency()
{
self.add(&dep, specifier);
}
}
}
let mut file_system_docs = self.file_system_docs.lock();
if !file_system_docs.dirty && !self.dirty {
return;
}
let mut dependents_map: HashMap<ModuleSpecifier, HashSet<ModuleSpecifier>> =
HashMap::new();
// favour documents that are open in case a document exists in both collections
let mut doc_analyzer = DocAnalyzer::default();
// favor documents that are open in case a document exists in both collections
let documents = file_system_docs.docs.iter().chain(self.open_docs.iter());
for (specifier, doc) in documents {
for dependency in doc.dependencies().values() {
if let Some(dep) = dependency.get_code() {
dependents_map
.entry(dep.clone())
.or_default()
.insert(specifier.clone());
}
if let Some(dep) = dependency.get_type() {
dependents_map
.entry(dep.clone())
.or_default()
.insert(specifier.clone());
}
}
if let Resolved::Ok { specifier: dep, .. } = doc.maybe_types_dependency()
doc_analyzer.analyze_doc(specifier, doc);
}
let maybe_resolver = self.get_maybe_resolver();
while let Some(specifier) = doc_analyzer.pending_specifiers.pop_front() {
if let Some(doc) =
file_system_docs.get(&self.cache, maybe_resolver, &specifier)
{
dependents_map
.entry(dep.clone())
.or_default()
.insert(specifier.clone());
doc_analyzer.analyze_doc(&specifier, &doc);
}
}
let mut npm_reqs = HashSet::new();
for specifier in dependents_map.keys() {
if let Ok(reference) = NpmPackageReference::from_specifier(specifier) {
npm_reqs.insert(reference.req);
}
}
self.dependents_map = Arc::new(dependents_map);
self.npm_reqs = npm_reqs;
self.dependents_map = Arc::new(doc_analyzer.dependents_map);
self.npm_reqs = Arc::new(doc_analyzer.npm_reqs);
self.dirty = false;
file_system_docs.dirty = false;
}

View file

@ -57,6 +57,8 @@ use super::tsc::Assets;
use super::tsc::AssetsSnapshot;
use super::tsc::TsServer;
use super::urls;
use crate::args::get_root_cert_store;
use crate::args::CacheSetting;
use crate::args::CliOptions;
use crate::args::ConfigFile;
use crate::args::Flags;
@ -64,10 +66,7 @@ use crate::args::FmtConfig;
use crate::args::LintConfig;
use crate::args::TsConfig;
use crate::cache::DenoDir;
use crate::file_fetcher::get_root_cert_store;
use crate::file_fetcher::get_source_from_data_url;
use crate::file_fetcher::CacheSetting;
use crate::fs_util;
use crate::graph_util::graph_valid;
use crate::http_util::HttpClient;
use crate::npm::NpmCache;
@ -75,9 +74,12 @@ use crate::npm::NpmPackageResolver;
use crate::npm::RealNpmRegistryApi;
use crate::proc_state::import_map_from_text;
use crate::proc_state::ProcState;
use crate::progress_bar::ProgressBar;
use crate::tools::fmt::format_file;
use crate::tools::fmt::format_parsed_source;
use crate::util::fs::remove_dir_all_if_exists;
use crate::util::path::ensure_directory_specifier;
use crate::util::path::specifier_to_file_path;
use crate::util::progress_bar::ProgressBar;
#[derive(Debug, Clone)]
pub struct LanguageServer(Arc<tokio::sync::Mutex<Inner>>);
@ -238,22 +240,20 @@ fn create_lsp_npm_resolver(
http_client: HttpClient,
) -> NpmPackageResolver {
let registry_url = RealNpmRegistryApi::default_url();
// Use an "only" cache setting in order to make the
// user do an explicit "cache" command and prevent
// the cache from being filled with lots of packages while
// the user is typing.
let cache_setting = CacheSetting::Only;
let progress_bar = ProgressBar::default();
let npm_cache = NpmCache::from_deno_dir(
dir,
cache_setting.clone(),
// Use an "only" cache setting in order to make the
// user do an explicit "cache" command and prevent
// the cache from being filled with lots of packages while
// the user is typing.
CacheSetting::Only,
http_client.clone(),
progress_bar.clone(),
);
let api = RealNpmRegistryApi::new(
registry_url,
npm_cache.clone(),
cache_setting,
http_client,
progress_bar,
);
@ -409,7 +409,7 @@ impl Inner {
// file open and not a workspace. In those situations we can't
// automatically discover the configuration
if let Some(root_uri) = &self.config.root_uri {
let root_path = fs_util::specifier_to_file_path(root_uri)?;
let root_path = specifier_to_file_path(root_uri)?;
let mut checked = std::collections::HashSet::new();
let maybe_config = ConfigFile::discover_from(&root_path, &mut checked)?;
Ok(maybe_config.map(|c| {
@ -483,7 +483,7 @@ impl Inner {
let cache_url = if let Ok(url) = Url::from_file_path(cache_str) {
Ok(url)
} else if let Some(root_uri) = &self.config.root_uri {
let root_path = fs_util::specifier_to_file_path(root_uri)?;
let root_path = specifier_to_file_path(root_uri)?;
let cache_path = root_path.join(cache_str);
Url::from_file_path(cache_path).map_err(|_| {
anyhow!("Bad file path for import path: {:?}", cache_str)
@ -494,7 +494,7 @@ impl Inner {
cache_str
))
}?;
let cache_path = fs_util::specifier_to_file_path(&cache_url)?;
let cache_path = specifier_to_file_path(&cache_url)?;
lsp_log!(
" Resolved cache path: \"{}\"",
cache_path.to_string_lossy()
@ -523,7 +523,7 @@ impl Inner {
.config
.root_uri
.as_ref()
.and_then(|uri| fs_util::specifier_to_file_path(uri).ok());
.and_then(|uri| specifier_to_file_path(uri).ok());
let root_cert_store = Some(get_root_cert_store(
maybe_root_path,
workspace_settings.certificate_stores.clone(),
@ -571,7 +571,7 @@ impl Inner {
anyhow!("Bad data url for import map: {}", import_map_str)
})?)
} else if let Some(root_uri) = &self.config.root_uri {
let root_path = fs_util::specifier_to_file_path(root_uri)?;
let root_path = specifier_to_file_path(root_uri)?;
let import_map_path = root_path.join(&import_map_str);
Some(Url::from_file_path(import_map_path).map_err(|_| {
anyhow!("Bad file path for import map: {}", import_map_str)
@ -614,7 +614,7 @@ impl Inner {
let import_map_json = if import_map_url.scheme() == "data" {
get_source_from_data_url(&import_map_url)?.0
} else {
let import_map_path = fs_util::specifier_to_file_path(&import_map_url)?;
let import_map_path = specifier_to_file_path(&import_map_url)?;
lsp_log!(
" Resolved import map: \"{}\"",
import_map_path.to_string_lossy()
@ -770,7 +770,7 @@ impl Inner {
self.config.root_uri = params
.root_uri
.map(|s| self.url_map.normalize_url(&s))
.map(fs_util::ensure_directory_specifier);
.map(ensure_directory_specifier);
if let Some(value) = params.initialization_options {
self.config.set_workspace_settings(value).map_err(|err| {
@ -1139,11 +1139,10 @@ impl Inner {
_ => return Ok(None),
};
let mark = self.performance.mark("formatting", Some(&params));
let file_path =
fs_util::specifier_to_file_path(&specifier).map_err(|err| {
error!("{}", err);
LspError::invalid_request()
})?;
let file_path = specifier_to_file_path(&specifier).map_err(|err| {
error!("{}", err);
LspError::invalid_request()
})?;
let fmt_options = if let Some(fmt_config) = self.maybe_fmt_config.as_ref() {
// skip formatting any files ignored by the config file
@ -2065,7 +2064,7 @@ impl Inner {
.config
.root_uri
.as_ref()
.and_then(|uri| fs_util::specifier_to_file_path(uri).ok());
.and_then(|uri| specifier_to_file_path(uri).ok());
let mut resolved_items = Vec::<CallHierarchyIncomingCall>::new();
for item in incoming_calls.iter() {
if let Some(resolved) = item.try_resolve_call_hierarchy_incoming_call(
@ -2111,7 +2110,7 @@ impl Inner {
.config
.root_uri
.as_ref()
.and_then(|uri| fs_util::specifier_to_file_path(uri).ok());
.and_then(|uri| specifier_to_file_path(uri).ok());
let mut resolved_items = Vec::<CallHierarchyOutgoingCall>::new();
for item in outgoing_calls.iter() {
if let Some(resolved) = item.try_resolve_call_hierarchy_outgoing_call(
@ -2164,7 +2163,7 @@ impl Inner {
.config
.root_uri
.as_ref()
.and_then(|uri| fs_util::specifier_to_file_path(uri).ok());
.and_then(|uri| specifier_to_file_path(uri).ok());
let mut resolved_items = Vec::<CallHierarchyItem>::new();
match one_or_many {
tsc::OneOrMany::One(item) => {
@ -3012,7 +3011,7 @@ impl Inner {
}
async fn reload_import_registries(&mut self) -> LspResult<Option<Value>> {
fs_util::remove_dir_all_if_exists(&self.module_registries_location)
remove_dir_all_if_exists(&self.module_registries_location)
.await
.map_err(|err| {
error!("Unable to remove registries cache: {}", err);

View file

@ -12,10 +12,10 @@ use super::path_to_regex::StringOrNumber;
use super::path_to_regex::StringOrVec;
use super::path_to_regex::Token;
use crate::args::CacheSetting;
use crate::cache::DenoDir;
use crate::file_fetcher::CacheSetting;
use crate::cache::HttpCache;
use crate::file_fetcher::FileFetcher;
use crate::http_cache::HttpCache;
use crate::http_util::HttpClient;
use deno_core::anyhow::anyhow;

View file

@ -2,9 +2,9 @@
use super::lsp_custom;
use crate::checksum;
use crate::lsp::analysis::source_range_to_lsp_range;
use crate::lsp::client::TestingNotification;
use crate::util::checksum;
use deno_ast::SourceRange;
use deno_ast::SourceTextInfo;

View file

@ -6,7 +6,6 @@ use super::lsp_custom;
use crate::args::flags_from_vec;
use crate::args::DenoSubcommand;
use crate::checksum;
use crate::lsp::client::Client;
use crate::lsp::client::TestingNotification;
use crate::lsp::config;
@ -14,7 +13,9 @@ use crate::lsp::logging::lsp_log;
use crate::ops;
use crate::proc_state;
use crate::tools::test;
use crate::tools::test::FailFastTracker;
use crate::tools::test::TestEventSender;
use crate::util::checksum;
use crate::worker::create_main_worker_for_test_or_bench;
use deno_core::anyhow::anyhow;
@ -144,25 +145,29 @@ impl LspTestFilter {
}
}
#[allow(clippy::too_many_arguments)]
async fn test_specifier(
ps: proc_state::ProcState,
permissions: Permissions,
specifier: ModuleSpecifier,
mode: test::TestMode,
sender: &TestEventSender,
sender: TestEventSender,
fail_fast_tracker: FailFastTracker,
token: CancellationToken,
filter: test::TestFilter,
) -> Result<(), AnyError> {
if !token.is_cancelled() {
let stdout = StdioPipe::File(sender.stdout());
let stderr = StdioPipe::File(sender.stderr());
let mut worker = create_main_worker_for_test_or_bench(
&ps,
specifier.clone(),
permissions,
vec![ops::testing::init(sender.clone(), filter)],
vec![ops::testing::init(sender, fail_fast_tracker, filter)],
Stdio {
stdin: StdioPipe::Inherit,
stdout: StdioPipe::File(sender.stdout()),
stderr: StdioPipe::File(sender.stderr()),
stdout,
stderr,
},
)
.await?;
@ -262,19 +267,17 @@ impl TestRun {
)
.await?;
let (sender, mut receiver) = mpsc::unbounded_channel::<test::TestEvent>();
let sender = TestEventSender::new(sender);
let (concurrent_jobs, fail_fast) =
if let DenoSubcommand::Test(test_flags) = ps.options.sub_command() {
(
test_flags.concurrent_jobs.into(),
test_flags.fail_fast.map(|count| count.into()),
)
(test_flags.concurrent_jobs.into(), test_flags.fail_fast)
} else {
unreachable!("Should always be Test subcommand.");
};
let (sender, mut receiver) = mpsc::unbounded_channel::<test::TestEvent>();
let sender = TestEventSender::new(sender);
let fail_fast_tracker = FailFastTracker::new(fail_fast);
let mut queue = self.queue.iter().collect::<Vec<&ModuleSpecifier>>();
queue.sort();
@ -288,6 +291,7 @@ impl TestRun {
let ps = ps.clone();
let permissions = permissions.clone();
let mut sender = sender.clone();
let fail_fast_tracker = fail_fast_tracker.clone();
let lsp_filter = self.filters.get(&specifier);
let filter = test::TestFilter {
substring: None,
@ -305,13 +309,17 @@ impl TestRun {
let tests = tests_.clone();
tokio::task::spawn_blocking(move || {
if fail_fast_tracker.should_stop() {
return Ok(());
}
let origin = specifier.to_string();
let file_result = run_local(test_specifier(
ps,
permissions,
specifier,
test::TestMode::Executable,
&sender,
sender.clone(),
fail_fast_tracker,
token,
filter,
));
@ -427,12 +435,6 @@ impl TestRun {
);
}
}
if let Some(count) = fail_fast {
if summary.failed >= count {
break;
}
}
}
let elapsed = Instant::now().duration_since(earlier);

View file

@ -18,10 +18,10 @@ use super::urls::LspUrlMap;
use super::urls::INVALID_SPECIFIER;
use crate::args::TsConfig;
use crate::fs_util::relative_specifier;
use crate::fs_util::specifier_to_file_path;
use crate::tsc;
use crate::tsc::ResolveArgs;
use crate::util::path::relative_specifier;
use crate::util::path::specifier_to_file_path;
use deno_core::anyhow::anyhow;
use deno_core::error::custom_error;
@ -2726,7 +2726,7 @@ fn op_resolve(
let referrer = state.normalize_specifier(&args.base)?;
let result = if let Some(resolved) = state.state_snapshot.documents.resolve(
args.specifiers,
&args.specifiers,
&referrer,
state.state_snapshot.maybe_npm_resolver.as_ref(),
) {
@ -3445,7 +3445,7 @@ pub fn request(
#[cfg(test)]
mod tests {
use super::*;
use crate::http_cache::HttpCache;
use crate::cache::HttpCache;
use crate::http_util::HeadersMap;
use crate::lsp::config::WorkspaceSettings;
use crate::lsp::documents::Documents;
@ -3913,7 +3913,7 @@ mod tests {
// You might have found this assertion starts failing after upgrading TypeScript.
// Just update the new number of assets (declaration files) for this number.
assert_eq!(assets.len(), 71);
assert_eq!(assets.len(), 72);
// get some notification when the size of the assets grows
let mut total_size = 0;

View file

@ -56,7 +56,7 @@ fn hash_data_specifier(specifier: &ModuleSpecifier) -> String {
file_name_str.push('?');
file_name_str.push_str(query);
}
crate::checksum::gen(&[file_name_str.as_bytes()])
crate::util::checksum::gen(&[file_name_str.as_bytes()])
}
#[derive(Debug, Default)]

View file

@ -3,20 +3,13 @@
mod args;
mod auth_tokens;
mod cache;
mod checksum;
mod deno_std;
mod diff;
mod display;
mod emit;
mod errors;
mod file_fetcher;
mod file_watcher;
mod fs_util;
mod graph_util;
mod http_cache;
mod http_util;
mod js;
mod logger;
mod lsp;
mod module_loader;
mod napi;
@ -24,15 +17,12 @@ mod node;
mod npm;
mod ops;
mod proc_state;
mod progress_bar;
mod resolver;
mod standalone;
mod text_encoding;
mod tools;
mod tsc;
mod unix_util;
mod util;
mod version;
mod windows_util;
mod worker;
use crate::args::flags_from_vec;
@ -63,14 +53,14 @@ use crate::args::UpgradeFlags;
use crate::args::VendorFlags;
use crate::cache::TypeCheckCache;
use crate::file_fetcher::File;
use crate::file_watcher::ResolutionResult;
use crate::graph_util::graph_lock_or_exit;
use crate::proc_state::ProcState;
use crate::resolver::CliResolver;
use crate::tools::check;
use crate::util::display;
use crate::util::file_watcher::ResolutionResult;
use args::CliOptions;
use args::Lockfile;
use deno_ast::MediaType;
use deno_core::anyhow::bail;
use deno_core::error::generic_error;
@ -324,7 +314,6 @@ async fn create_graph_and_maybe_check(
Permissions::allow_all(),
Permissions::allow_all(),
);
let maybe_locker = Lockfile::as_maybe_locker(ps.lockfile.clone());
let maybe_imports = ps.options.to_maybe_imports()?;
let maybe_cli_resolver = CliResolver::maybe_new(
ps.options.to_maybe_jsx_import_source_config(),
@ -341,7 +330,6 @@ async fn create_graph_and_maybe_check(
is_dynamic: false,
imports: maybe_imports,
resolver: maybe_graph_resolver,
locker: maybe_locker,
module_analyzer: Some(&*analyzer),
reporter: None,
},
@ -362,7 +350,9 @@ async fn create_graph_and_maybe_check(
ps.npm_resolver
.add_package_reqs(graph_data.npm_package_reqs().clone())
.await?;
graph_lock_or_exit(&graph);
if let Some(lockfile) = &ps.lockfile {
graph_lock_or_exit(&graph, &mut lockfile.lock());
}
if ps.options.type_check_mode() != TypeCheckMode::None {
let ts_config_result =
@ -442,7 +432,6 @@ async fn bundle_command(
let mut paths_to_watch: Vec<PathBuf> = graph
.specifiers()
.iter()
.filter_map(|(_, r)| {
r.as_ref().ok().and_then(|(s, _, _)| s.to_file_path().ok())
})
@ -482,7 +471,7 @@ async fn bundle_command(
if let Some(out_file) = out_file.as_ref() {
let output_bytes = bundle_output.code.as_bytes();
let output_len = output_bytes.len();
fs_util::write_file(out_file, output_bytes, 0o644)?;
util::fs::write_file(out_file, output_bytes, 0o644)?;
info!(
"{} {:?} ({})",
colors::green("Emit"),
@ -498,7 +487,7 @@ async fn bundle_command(
"map".to_string()
};
let map_out_file = out_file.with_extension(ext);
fs_util::write_file(&map_out_file, map_bytes, 0o644)?;
util::fs::write_file(&map_out_file, map_bytes, 0o644)?;
info!(
"{} {:?} ({})",
colors::green("Emit"),
@ -515,10 +504,10 @@ async fn bundle_command(
};
if cli_options.watch_paths().is_some() {
file_watcher::watch_func(
util::file_watcher::watch_func(
resolver,
operation,
file_watcher::PrintConfig {
util::file_watcher::PrintConfig {
job_name: "Bundle".to_string(),
clear_screen: !cli_options.no_clear_screen(),
},
@ -542,9 +531,8 @@ fn error_for_any_npm_specifier(
) -> Result<(), AnyError> {
let first_npm_specifier = graph
.specifiers()
.values()
.filter_map(|r| match r {
Ok((specifier, kind, _)) if *kind == deno_graph::ModuleKind::External => {
.filter_map(|(_, r)| match r {
Ok((specifier, kind, _)) if kind == deno_graph::ModuleKind::External => {
Some(specifier.clone())
}
_ => None,
@ -590,8 +578,7 @@ async fn repl_command(
) -> Result<i32, AnyError> {
let main_module = resolve_url_or_path("./$deno$repl.ts").unwrap();
let ps = ProcState::build(flags).await?;
tools::repl::run(&ps, main_module, repl_flags.eval_files, repl_flags.eval)
.await
tools::repl::run(&ps, main_module, repl_flags).await
}
async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
@ -648,11 +635,11 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<i32, AnyError> {
})
};
file_watcher::watch_func2(
util::file_watcher::watch_func2(
receiver,
operation,
(sender, main_module),
file_watcher::PrintConfig {
util::file_watcher::PrintConfig {
job_name: "Process".to_string(),
clear_screen: !flags.no_clear_screen,
},
@ -940,8 +927,8 @@ fn unwrap_or_exit<T>(result: Result<T, AnyError>) -> T {
pub fn main() {
setup_panic_hook();
unix_util::raise_fd_limit();
windows_util::ensure_stdio_open();
util::unix::raise_fd_limit();
util::windows::ensure_stdio_open();
#[cfg(windows)]
colors::enable_ansi(); // For Windows 10
@ -972,7 +959,7 @@ pub fn main() {
init_v8_flags(&flags.v8_flags);
}
logger::init(flags.log_level);
util::logger::init(flags.log_level);
get_subcommand(flags).await
};

View file

@ -5,8 +5,8 @@ use crate::emit::emit_parsed_source;
use crate::graph_util::ModuleEntry;
use crate::node;
use crate::proc_state::ProcState;
use crate::text_encoding::code_without_source_map;
use crate::text_encoding::source_map_from_code;
use crate::util::text_encoding::code_without_source_map;
use crate::util::text_encoding::source_map_from_code;
use deno_ast::MediaType;
use deno_core::anyhow::anyhow;

View file

@ -59,7 +59,7 @@ fn napi_add_env_cleanup_hook(
_hook: extern "C" fn(*const c_void),
_data: *const c_void,
) -> Result {
eprintln!("napi_add_env_cleanup_hook is currently not supported");
log::info!("napi_add_env_cleanup_hook is currently not supported");
Ok(())
}
@ -69,7 +69,7 @@ fn napi_remove_env_cleanup_hook(
_hook: extern "C" fn(*const c_void),
_data: *const c_void,
) -> Result {
eprintln!("napi_remove_env_cleanup_hook is currently not supported");
log::info!("napi_remove_env_cleanup_hook is currently not supported");
Ok(())
}

View file

@ -737,7 +737,7 @@ fn napi_make_callback(
}
if !async_context.is_null() {
eprintln!("napi_make_callback: async_context is not supported");
log::info!("napi_make_callback: async_context is not supported");
}
let recv = transmute::<napi_value, v8::Local<v8::Value>>(recv);
@ -1006,7 +1006,7 @@ fn napi_add_finalizer(
_finalize_hint: *const c_void,
_result: *mut napi_ref,
) -> Result {
eprintln!("napi_add_finalizer is not yet supported.");
log::info!("napi_add_finalizer is not yet supported.");
Ok(())
}
@ -1260,11 +1260,10 @@ fn napi_delete_reference(env: *mut Env, _nref: napi_ref) -> Result {
}
#[napi_sym::napi_sym]
fn napi_detach_arraybuffer(env: *mut Env, value: napi_value) -> Result {
let env: &mut Env = env.as_mut().ok_or(Error::InvalidArg)?;
fn napi_detach_arraybuffer(_env: *mut Env, value: napi_value) -> Result {
let value = transmute::<napi_value, v8::Local<v8::Value>>(value);
let ab = v8::Local::<v8::ArrayBuffer>::try_from(value).unwrap();
ab.detach(v8::undefined(&mut env.scope()).into());
ab.detach(None);
Ok(())
}

View file

@ -2,7 +2,7 @@
[package]
name = "napi_sym"
version = "0.9.0"
version = "0.10.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -20,7 +20,7 @@ pub fn napi_sym(_attr: TokenStream, item: TokenStream) -> TokenStream {
let name = &func.sig.ident;
assert!(
exports.symbols.contains(&name.to_string()),
"tools/napi/symbol_exports.json is out of sync!"
"tools/napi/sym/symbol_exports.json is out of sync!"
);
let block = &func.block;

View file

@ -27,12 +27,12 @@ use deno_runtime::deno_node::package_imports_resolve;
use deno_runtime::deno_node::package_resolve;
use deno_runtime::deno_node::path_to_declaration_path;
use deno_runtime::deno_node::NodeModuleKind;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::PackageJson;
use deno_runtime::deno_node::PathClean;
use deno_runtime::deno_node::RequireNpmResolver;
use deno_runtime::deno_node::DEFAULT_CONDITIONS;
use deno_runtime::deno_node::NODE_GLOBAL_THIS_NAME;
use deno_runtime::deno_node::TYPES_CONDITIONS;
use once_cell::sync::Lazy;
use regex::Regex;
@ -95,25 +95,15 @@ impl NodeResolution {
},
)
}
maybe_response => {
let specifier = match maybe_response {
Some(response) => response.into_url(),
None => {
ModuleSpecifier::parse("deno:///missing_dependency.d.ts").unwrap()
}
};
(specifier, MediaType::Dts)
}
Some(resolution) => (resolution.into_url(), MediaType::Dts),
None => (
ModuleSpecifier::parse("deno:///missing_dependency.d.ts").unwrap(),
MediaType::Dts,
),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeResolutionMode {
Execution,
Types,
}
struct NodeModulePolyfill {
/// Name of the module like "assert" or "timers/promises"
name: &'static str,
@ -480,8 +470,13 @@ pub fn node_resolve(
}
}
let conditions = mode_conditions(mode);
let url = module_resolve(specifier, referrer, conditions, npm_resolver)?;
let url = module_resolve(
specifier,
referrer,
DEFAULT_CONDITIONS,
mode,
npm_resolver,
)?;
let url = match url {
Some(url) => url,
None => return Ok(None),
@ -492,7 +487,10 @@ pub fn node_resolve(
let path = url.to_file_path().unwrap();
// todo(16370): the module kind is not correct here. I think we need
// typescript to tell us if the referrer is esm or cjs
let path = path_to_declaration_path(path, NodeModuleKind::Esm);
let path = match path_to_declaration_path(path, NodeModuleKind::Esm) {
Some(path) => path,
None => return Ok(None),
};
ModuleSpecifier::from_file_path(path).unwrap()
}
};
@ -519,7 +517,8 @@ pub fn node_resolve_npm_reference(
.unwrap_or_else(|| ".".to_string()),
&package_folder,
node_module_kind,
mode_conditions(mode),
DEFAULT_CONDITIONS,
mode,
npm_resolver,
)
.with_context(|| {
@ -532,7 +531,10 @@ pub fn node_resolve_npm_reference(
let resolved_path = match mode {
NodeResolutionMode::Execution => resolved_path,
NodeResolutionMode::Types => {
path_to_declaration_path(resolved_path, node_module_kind)
match path_to_declaration_path(resolved_path, node_module_kind) {
Some(path) => path,
None => return Ok(None),
}
}
};
let url = ModuleSpecifier::from_file_path(resolved_path).unwrap();
@ -542,13 +544,6 @@ pub fn node_resolve_npm_reference(
Ok(Some(resolve_response))
}
fn mode_conditions(mode: NodeResolutionMode) -> &'static [&'static str] {
match mode {
NodeResolutionMode::Execution => DEFAULT_CONDITIONS,
NodeResolutionMode::Types => TYPES_CONDITIONS,
}
}
pub fn node_resolve_binary_export(
pkg_req: &NpmPackageReq,
bin_name: Option<&str>,
@ -636,17 +631,22 @@ pub fn load_cjs_module_from_ext_node(
js_runtime: &mut JsRuntime,
module: &str,
main: bool,
inspect_brk: bool,
) -> Result<(), AnyError> {
fn escape_for_single_quote_string(text: &str) -> String {
text.replace('\\', r"\\").replace('\'', r"\'")
}
let source_code = &format!(
r#"(function loadCjsModule(module) {{
r#"(function loadCjsModule(module, inspectBrk) {{
if (inspectBrk) {{
Deno[Deno.internal].require.setInspectBrk();
}}
Deno[Deno.internal].require.Module._load(module, null, {main});
}})('{module}');"#,
}})('{module}', {inspect_brk});"#,
main = main,
module = escape_for_single_quote_string(module),
inspect_brk = inspect_brk,
);
js_runtime.execute_script(&located_script_name!(), source_code)?;
@ -658,6 +658,7 @@ fn package_config_resolve(
package_dir: &Path,
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
npm_resolver: &dyn RequireNpmResolver,
) -> Result<Option<PathBuf>, AnyError> {
let package_json_path = package_dir.join("package.json");
@ -672,15 +673,15 @@ fn package_config_resolve(
&referrer,
referrer_kind,
conditions,
mode,
npm_resolver,
);
match result {
Ok(found) => return Ok(Some(found)),
Err(exports_err) => {
let is_types = conditions == TYPES_CONDITIONS;
if is_types && package_subpath == "." {
if mode.is_types() && package_subpath == "." {
if let Ok(Some(path)) =
legacy_main_resolve(&package_config, referrer_kind, conditions)
legacy_main_resolve(&package_config, referrer_kind, mode)
{
return Ok(Some(path));
} else {
@ -692,7 +693,7 @@ fn package_config_resolve(
}
}
if package_subpath == "." {
return legacy_main_resolve(&package_config, referrer_kind, conditions);
return legacy_main_resolve(&package_config, referrer_kind, mode);
}
Ok(Some(package_dir.join(package_subpath)))
@ -778,18 +779,21 @@ fn module_resolve(
specifier: &str,
referrer: &ModuleSpecifier,
conditions: &[&str],
mode: NodeResolutionMode,
npm_resolver: &dyn RequireNpmResolver,
) -> Result<Option<ModuleSpecifier>, AnyError> {
// note: if we're here, the referrer is an esm module
let url = if should_be_treated_as_relative_or_absolute_path(specifier) {
let resolved_specifier = referrer.join(specifier)?;
if conditions == TYPES_CONDITIONS {
if mode.is_types() {
let file_path = to_file_path(&resolved_specifier);
// todo(dsherret): the node module kind is not correct and we
// should use the value provided by typescript instead
let declaration_path =
path_to_declaration_path(file_path, NodeModuleKind::Esm);
Some(ModuleSpecifier::from_file_path(declaration_path).unwrap())
declaration_path.map(|declaration_path| {
ModuleSpecifier::from_file_path(declaration_path).unwrap()
})
} else {
Some(resolved_specifier)
}
@ -800,6 +804,7 @@ fn module_resolve(
referrer,
NodeModuleKind::Esm,
conditions,
mode,
npm_resolver,
)
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())?,
@ -812,6 +817,7 @@ fn module_resolve(
referrer,
NodeModuleKind::Esm,
conditions,
mode,
npm_resolver,
)?
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())
@ -943,6 +949,7 @@ pub fn translate_cjs_to_esm(
// FIXME(bartlomieju): check if these conditions are okay, probably
// should be `deno-require`, because `deno` is already used in `esm_resolver.rs`
&["deno", "require", "default"],
NodeResolutionMode::Execution,
npm_resolver,
)?;
let reexport_specifier =
@ -1013,6 +1020,7 @@ fn resolve(
specifier: &str,
referrer: &ModuleSpecifier,
conditions: &[&str],
mode: NodeResolutionMode,
npm_resolver: &dyn RequireNpmResolver,
) -> Result<PathBuf, AnyError> {
if specifier.starts_with('/') {
@ -1037,7 +1045,7 @@ fn resolve(
let module_dir = npm_resolver.resolve_package_folder_from_package(
package_specifier.as_str(),
&referrer_path,
conditions,
mode,
)?;
let package_json_path = module_dir.join("package.json");
@ -1053,6 +1061,7 @@ fn resolve(
referrer,
NodeModuleKind::Esm,
conditions,
mode,
npm_resolver,
);
}

View file

@ -1,21 +1,26 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::collections::HashSet;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex;
use deno_core::url::Url;
use crate::args::CacheSetting;
use crate::cache::DenoDir;
use crate::file_fetcher::CacheSetting;
use crate::fs_util;
use crate::http_util::HttpClient;
use crate::progress_bar::ProgressBar;
use crate::util::fs::canonicalize_path;
use crate::util::fs::hard_link_dir_recursive;
use crate::util::path::root_url_to_safe_local_dirname;
use crate::util::progress_bar::ProgressBar;
use super::registry::NpmPackageVersionDistInfo;
use super::semver::NpmVersion;
@ -159,7 +164,7 @@ impl ReadonlyNpmCache {
std::fs::create_dir_all(root_dir)
.with_context(|| format!("Error creating {}", root_dir.display()))?;
}
Ok(crate::fs_util::canonicalize_path(root_dir)?)
Ok(canonicalize_path(root_dir)?)
}
// this may fail on readonly file systems, so just ignore if so
@ -224,7 +229,7 @@ impl ReadonlyNpmCache {
pub fn registry_folder(&self, registry_url: &Url) -> PathBuf {
self
.root_dir
.join(fs_util::root_url_to_safe_local_dirname(registry_url))
.join(root_url_to_safe_local_dirname(registry_url))
}
pub fn resolve_package_folder_id_from_specifier(
@ -249,7 +254,7 @@ impl ReadonlyNpmCache {
.root_dir_url
.join(&format!(
"{}/",
fs_util::root_url_to_safe_local_dirname(registry_url)
root_url_to_safe_local_dirname(registry_url)
.to_string_lossy()
.replace('\\', "/")
))
@ -317,6 +322,8 @@ pub struct NpmCache {
cache_setting: CacheSetting,
http_client: HttpClient,
progress_bar: ProgressBar,
/// ensures a package is only downloaded once per run
previously_reloaded_packages: Arc<Mutex<HashSet<String>>>,
}
impl NpmCache {
@ -331,6 +338,7 @@ impl NpmCache {
cache_setting,
http_client,
progress_bar,
previously_reloaded_packages: Default::default(),
}
}
@ -338,6 +346,26 @@ impl NpmCache {
self.readonly.clone()
}
pub fn cache_setting(&self) -> &CacheSetting {
&self.cache_setting
}
/// Checks if the cache should be used for the provided name and version.
/// NOTE: Subsequent calls for the same package will always return `true`
/// to ensure a package is only downloaded once per run of the CLI. This
/// prevents downloads from re-occurring when someone has `--reload` and
/// and imports a dynamic import that imports the same package again for example.
fn should_use_global_cache_for_package(
&self,
package: (&str, &NpmVersion),
) -> bool {
self.cache_setting.should_use_for_npm_package(package.0)
|| !self
.previously_reloaded_packages
.lock()
.insert(format!("{}@{}", package.0, package.1))
}
pub async fn ensure_package(
&self,
package: (&str, &NpmVersion),
@ -352,10 +380,6 @@ impl NpmCache {
})
}
pub fn should_use_cache_for_npm_package(&self, package_name: &str) -> bool {
self.cache_setting.should_use_for_npm_package(package_name)
}
async fn ensure_package_inner(
&self,
package: (&str, &NpmVersion),
@ -367,11 +391,11 @@ impl NpmCache {
package.1,
registry_url,
);
if package_folder.exists()
if self.should_use_global_cache_for_package(package)
&& package_folder.exists()
// if this file exists, then the package didn't successfully extract
// the first time, or another process is currently extracting the zip file
&& !package_folder.join(NPM_PACKAGE_SYNC_LOCK_FILENAME).exists()
&& self.should_use_cache_for_npm_package(package.0)
{
return Ok(());
} else if self.cache_setting == CacheSetting::Only {
@ -435,12 +459,7 @@ impl NpmCache {
with_folder_sync_lock(
(id.name.as_str(), &id.version),
&package_folder,
|| {
fs_util::hard_link_dir_recursive(
&original_package_folder,
&package_folder,
)
},
|| hard_link_dir_recursive(&original_package_folder, &package_folder),
)?;
Ok(())
}

View file

@ -2,6 +2,7 @@
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::HashSet;
use std::fs;
use std::io::ErrorKind;
use std::path::PathBuf;
@ -20,11 +21,11 @@ use deno_core::url::Url;
use deno_runtime::colors;
use serde::Serialize;
use crate::file_fetcher::CacheSetting;
use crate::fs_util;
use crate::http_cache::CACHE_PERM;
use crate::args::CacheSetting;
use crate::cache::CACHE_PERM;
use crate::http_util::HttpClient;
use crate::progress_bar::ProgressBar;
use crate::util::fs::atomic_write_file;
use crate::util::progress_bar::ProgressBar;
use super::cache::NpmCache;
use super::resolution::NpmVersionMatcher;
@ -248,7 +249,6 @@ impl RealNpmRegistryApi {
pub fn new(
base_url: Url,
cache: NpmCache,
cache_setting: CacheSetting,
http_client: HttpClient,
progress_bar: ProgressBar,
) -> Self {
@ -256,7 +256,7 @@ impl RealNpmRegistryApi {
base_url,
cache,
mem_cache: Default::default(),
cache_setting,
previously_reloaded_packages: Default::default(),
http_client,
progress_bar,
}))
@ -286,7 +286,7 @@ struct RealNpmRegistryApiInner {
base_url: Url,
cache: NpmCache,
mem_cache: Mutex<HashMap<String, Option<Arc<NpmPackageInfo>>>>,
cache_setting: CacheSetting,
previously_reloaded_packages: Mutex<HashSet<String>>,
http_client: HttpClient,
progress_bar: ProgressBar,
}
@ -296,12 +296,16 @@ impl RealNpmRegistryApiInner {
&self,
name: &str,
) -> Result<Option<Arc<NpmPackageInfo>>, AnyError> {
let maybe_info = self.mem_cache.lock().get(name).cloned();
if let Some(info) = maybe_info {
Ok(info)
let maybe_maybe_info = self.mem_cache.lock().get(name).cloned();
if let Some(maybe_info) = maybe_maybe_info {
Ok(maybe_info)
} else {
let mut maybe_package_info = None;
if self.cache_setting.should_use_for_npm_package(name) {
if self.cache.cache_setting().should_use_for_npm_package(name)
// if this has been previously reloaded, then try loading from the
// file system cache
|| !self.previously_reloaded_packages.lock().insert(name.to_string())
{
// attempt to load from the file cache
maybe_package_info = self.load_file_cached_package_info(name);
}
@ -401,7 +405,7 @@ impl RealNpmRegistryApiInner {
let file_cache_path = self.get_package_file_cache_path(name);
let file_text = serde_json::to_string(&package_info)?;
std::fs::create_dir_all(file_cache_path.parent().unwrap())?;
fs_util::atomic_write_file(&file_cache_path, file_text, CACHE_PERM)?;
atomic_write_file(&file_cache_path, file_text, CACHE_PERM)?;
Ok(())
}
@ -409,15 +413,14 @@ impl RealNpmRegistryApiInner {
&self,
name: &str,
) -> Result<Option<NpmPackageInfo>, AnyError> {
if self.cache_setting == CacheSetting::Only {
if *self.cache.cache_setting() == CacheSetting::Only {
return Err(custom_error(
"NotCached",
format!(
"An npm specifier not found in cache: \"{}\", --cached-only is specified.",
name
)
)
);
));
}
let package_url = self.get_package_url(name);

View file

@ -947,7 +947,6 @@ mod tests {
is_dynamic: false,
imports: None,
resolver: None,
locker: None,
module_analyzer: Some(&analyzer),
reporter: None,
},

View file

@ -10,6 +10,7 @@ use deno_core::error::AnyError;
use deno_core::futures;
use deno_core::futures::future::BoxFuture;
use deno_core::url::Url;
use deno_runtime::deno_node::NodeResolutionMode;
use crate::args::Lockfile;
use crate::npm::cache::should_sync_download;
@ -29,7 +30,7 @@ pub trait InnerNpmPackageResolver: Send + Sync {
&self,
name: &str,
referrer: &ModuleSpecifier,
conditions: &[&str],
mode: NodeResolutionMode,
) -> Result<PathBuf, AnyError>;
fn resolve_package_folder_from_specifier(

View file

@ -12,17 +12,17 @@ use deno_core::error::AnyError;
use deno_core::futures::future::BoxFuture;
use deno_core::futures::FutureExt;
use deno_core::url::Url;
use deno_runtime::deno_node::PackageJson;
use deno_runtime::deno_node::TYPES_CONDITIONS;
use deno_runtime::deno_node::NodeResolutionMode;
use crate::args::Lockfile;
use crate::fs_util;
use crate::npm::cache::NpmPackageCacheFolderId;
use crate::npm::resolution::NpmResolution;
use crate::npm::resolution::NpmResolutionSnapshot;
use crate::npm::resolvers::common::cache_packages;
use crate::npm::NpmCache;
use crate::npm::NpmPackageId;
use crate::npm::NpmPackageReq;
use crate::npm::NpmResolutionPackage;
use crate::npm::RealNpmRegistryApi;
use super::common::ensure_registry_read_permission;
@ -62,6 +62,17 @@ impl GlobalNpmPackageResolver {
.cache
.package_folder_for_id(&folder_id, &self.registry_url)
}
fn resolve_types_package(
&self,
package_name: &str,
referrer_pkg_id: &NpmPackageCacheFolderId,
) -> Result<NpmResolutionPackage, AnyError> {
let types_name = types_package_name(package_name);
self
.resolution
.resolve_package_from_package(&types_name, referrer_pkg_id)
}
}
impl InnerNpmPackageResolver for GlobalNpmPackageResolver {
@ -77,35 +88,25 @@ impl InnerNpmPackageResolver for GlobalNpmPackageResolver {
&self,
name: &str,
referrer: &ModuleSpecifier,
conditions: &[&str],
mode: NodeResolutionMode,
) -> Result<PathBuf, AnyError> {
let referrer_pkg_id = self
.cache
.resolve_package_folder_id_from_specifier(referrer, &self.registry_url)?;
let pkg_result = self
.resolution
.resolve_package_from_package(name, &referrer_pkg_id);
if conditions == TYPES_CONDITIONS && !name.starts_with("@types/") {
// When doing types resolution, the package must contain a "types"
// entry, or else it will then search for a @types package
if let Ok(pkg) = pkg_result {
let package_folder = self.package_folder(&pkg.id);
let package_json = PackageJson::load_skip_read_permission(
package_folder.join("package.json"),
)?;
if package_json.types.is_some() {
return Ok(package_folder);
}
let pkg = if mode.is_types() && !name.starts_with("@types/") {
// attempt to resolve the types package first, then fallback to the regular package
match self.resolve_types_package(name, &referrer_pkg_id) {
Ok(pkg) => pkg,
Err(_) => self
.resolution
.resolve_package_from_package(name, &referrer_pkg_id)?,
}
let name = types_package_name(name);
let pkg = self
.resolution
.resolve_package_from_package(&name, &referrer_pkg_id)?;
Ok(self.package_folder(&pkg.id))
} else {
Ok(self.package_folder(&pkg_result?.id))
}
self
.resolution
.resolve_package_from_package(name, &referrer_pkg_id)?
};
Ok(self.package_folder(&pkg.id))
}
fn resolve_package_folder_from_specifier(
@ -125,7 +126,7 @@ impl InnerNpmPackageResolver for GlobalNpmPackageResolver {
fn package_size(&self, package_id: &NpmPackageId) -> Result<u64, AnyError> {
let package_folder = self.package_folder(package_id);
Ok(fs_util::dir_size(&package_folder)?)
Ok(crate::util::fs::dir_size(&package_folder)?)
}
fn has_packages(&self) -> bool {

View file

@ -10,6 +10,7 @@ use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use crate::util::fs::symlink_dir;
use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
@ -18,12 +19,11 @@ use deno_core::futures::future::BoxFuture;
use deno_core::futures::FutureExt;
use deno_core::url::Url;
use deno_runtime::deno_core::futures;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::PackageJson;
use deno_runtime::deno_node::TYPES_CONDITIONS;
use tokio::task::JoinHandle;
use crate::args::Lockfile;
use crate::fs_util;
use crate::npm::cache::mixed_case_package_name_encode;
use crate::npm::cache::should_sync_download;
use crate::npm::cache::NpmPackageCacheFolderId;
@ -34,6 +34,8 @@ use crate::npm::NpmPackageId;
use crate::npm::NpmPackageReq;
use crate::npm::NpmResolutionPackage;
use crate::npm::RealNpmRegistryApi;
use crate::util::fs::copy_dir_recursive;
use crate::util::fs::hard_link_dir_recursive;
use super::common::ensure_registry_read_permission;
use super::common::types_package_name;
@ -150,7 +152,7 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver {
&self,
name: &str,
referrer: &ModuleSpecifier,
conditions: &[&str],
mode: NodeResolutionMode,
) -> Result<PathBuf, AnyError> {
let local_path = self.resolve_folder_for_specifier(referrer)?;
let package_root_path = self.resolve_package_root(&local_path);
@ -160,7 +162,7 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver {
let sub_dir = join_package_name(current_folder, name);
if sub_dir.is_dir() {
// if doing types resolution, only resolve the package if it specifies a types property
if conditions == TYPES_CONDITIONS && !name.starts_with("@types/") {
if mode.is_types() && !name.starts_with("@types/") {
let package_json = PackageJson::load_skip_read_permission(
sub_dir.join("package.json"),
)?;
@ -173,7 +175,7 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver {
}
// if doing type resolution, check for the existance of a @types package
if conditions == TYPES_CONDITIONS && !name.starts_with("@types/") {
if mode.is_types() && !name.starts_with("@types/") {
let sub_dir =
join_package_name(current_folder, &types_package_name(name));
if sub_dir.is_dir() {
@ -203,7 +205,7 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver {
fn package_size(&self, package_id: &NpmPackageId) -> Result<u64, AnyError> {
let package_folder_path = self.get_package_id_folder(package_id)?;
Ok(fs_util::dir_size(&package_folder_path)?)
Ok(crate::util::fs::dir_size(&package_folder_path)?)
}
fn has_packages(&self) -> bool {
@ -291,7 +293,9 @@ async fn sync_resolution_with_fs(
get_package_folder_id_folder_name(&package.get_package_cache_folder_id());
let folder_path = deno_local_registry_dir.join(&folder_name);
let initialized_file = folder_path.join(".initialized");
if !cache.should_use_cache_for_npm_package(&package.id.name)
if !cache
.cache_setting()
.should_use_for_npm_package(&package.id.name)
|| !initialized_file.exists()
{
let cache = cache.clone();
@ -316,7 +320,7 @@ async fn sync_resolution_with_fs(
&registry_url,
);
// for now copy, but in the future consider hard linking
fs_util::copy_dir_recursive(&cache_folder, &package_path)?;
copy_dir_recursive(&cache_folder, &package_path)?;
// write out a file that indicates this folder has been initialized
fs::write(initialized_file, "")?;
Ok(())
@ -354,7 +358,7 @@ async fn sync_resolution_with_fs(
.join("node_modules"),
&package.id.name,
);
fs_util::hard_link_dir_recursive(&source_path, &package_path)?;
hard_link_dir_recursive(&source_path, &package_path)?;
// write out a file that indicates this folder has been initialized
fs::write(initialized_file, "")?;
}
@ -465,7 +469,7 @@ fn symlink_package_dir(
#[cfg(windows)]
return junction_or_symlink_dir(old_path, new_path);
#[cfg(not(windows))]
fs_util::symlink_dir(old_path, new_path)
symlink_dir(old_path, new_path)
}
#[cfg(windows)]
@ -475,6 +479,7 @@ fn junction_or_symlink_dir(
) -> Result<(), AnyError> {
// Use junctions because they're supported on ntfs file systems without
// needing to elevate privileges on Windows
match junction::create(old_path, new_path) {
Ok(()) => Ok(()),
Err(junction_err) => {
@ -484,7 +489,7 @@ fn junction_or_symlink_dir(
log::warn!("Error creating junction. {:#}", junction_err);
}
match fs_util::symlink_dir(old_path, new_path) {
match symlink_dir(old_path, new_path) {
Ok(()) => Ok(()),
Err(symlink_err) => bail!(
concat!(

View file

@ -11,6 +11,7 @@ use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex;
use deno_core::serde_json;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::PathClean;
use deno_runtime::deno_node::RequireNpmResolver;
use global::GlobalNpmPackageResolver;
@ -23,7 +24,7 @@ use std::path::PathBuf;
use std::sync::Arc;
use crate::args::Lockfile;
use crate::fs_util;
use crate::util::fs::canonicalize_path_maybe_not_exists;
use self::common::InnerNpmPackageResolver;
use self::local::LocalNpmPackageResolver;
@ -187,8 +188,12 @@ impl NpmPackageResolver {
let path = self
.inner
.resolve_package_folder_from_deno_module(pkg_req)?;
let path = fs_util::canonicalize_path_maybe_not_exists(&path)?;
log::debug!("Resolved {} to {}", pkg_req, path.display());
let path = canonicalize_path_maybe_not_exists(&path)?;
log::debug!(
"Resolved package folder of {} to {}",
pkg_req,
path.display()
);
Ok(path)
}
@ -197,11 +202,11 @@ impl NpmPackageResolver {
&self,
name: &str,
referrer: &ModuleSpecifier,
conditions: &[&str],
mode: NodeResolutionMode,
) -> Result<PathBuf, AnyError> {
let path = self
.inner
.resolve_package_folder_from_package(name, referrer, conditions)?;
.resolve_package_folder_from_package(name, referrer, mode)?;
log::debug!("Resolved {} from {} to {}", name, referrer, path.display());
Ok(path)
}
@ -216,7 +221,11 @@ impl NpmPackageResolver {
let path = self
.inner
.resolve_package_folder_from_specifier(specifier)?;
log::debug!("Resolved {} to {}", specifier, path.display());
log::debug!(
"Resolved package folder of {} to {}",
specifier,
path.display()
);
Ok(path)
}
@ -330,10 +339,10 @@ impl RequireNpmResolver for NpmPackageResolver {
&self,
specifier: &str,
referrer: &std::path::Path,
conditions: &[&str],
mode: NodeResolutionMode,
) -> Result<PathBuf, AnyError> {
let referrer = path_to_specifier(referrer)?;
self.resolve_package_folder_from_package(specifier, &referrer, conditions)
self.resolve_package_folder_from_package(specifier, &referrer, mode)
}
fn resolve_package_folder_from_path(

View file

@ -1,10 +1,12 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::tools::test::FailFastTracker;
use crate::tools::test::TestDescription;
use crate::tools::test::TestEvent;
use crate::tools::test::TestEventSender;
use crate::tools::test::TestFilter;
use crate::tools::test::TestLocation;
use crate::tools::test::TestResult;
use crate::tools::test::TestStepDescription;
use deno_core::error::generic_error;
@ -23,7 +25,11 @@ use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use uuid::Uuid;
pub fn init(sender: TestEventSender, filter: TestFilter) -> Extension {
pub fn init(
sender: TestEventSender,
fail_fast_tracker: FailFastTracker,
filter: TestFilter,
) -> Extension {
Extension::builder()
.ops(vec![
op_pledge_test_permissions::decl(),
@ -32,9 +38,11 @@ pub fn init(sender: TestEventSender, filter: TestFilter) -> Extension {
op_register_test::decl(),
op_register_test_step::decl(),
op_dispatch_test_event::decl(),
op_tests_should_stop::decl(),
])
.state(move |state| {
state.put(sender.clone());
state.put(fail_fast_tracker.clone());
state.put(filter.clone());
Ok(())
})
@ -178,7 +186,18 @@ fn op_dispatch_test_event(
state: &mut OpState,
event: TestEvent,
) -> Result<(), AnyError> {
if matches!(
event,
TestEvent::Result(_, TestResult::Cancelled | TestResult::Failed(_), _)
) {
state.borrow::<FailFastTracker>().add_failure();
}
let mut sender = state.borrow::<TestEventSender>().clone();
sender.send(event).ok();
Ok(())
}
#[op]
fn op_tests_should_stop(state: &mut OpState) -> bool {
state.borrow::<FailFastTracker>().should_stop()
}

View file

@ -11,6 +11,7 @@ use crate::cache;
use crate::cache::DenoDir;
use crate::cache::EmitCache;
use crate::cache::FastInsecureHasher;
use crate::cache::HttpCache;
use crate::cache::NodeAnalysisCache;
use crate::cache::ParsedSourceCache;
use crate::cache::TypeCheckCache;
@ -19,7 +20,6 @@ use crate::file_fetcher::FileFetcher;
use crate::graph_util::graph_lock_or_exit;
use crate::graph_util::GraphData;
use crate::graph_util::ModuleEntry;
use crate::http_cache;
use crate::http_util::HttpClient;
use crate::node;
use crate::node::NodeResolution;
@ -28,9 +28,9 @@ use crate::npm::NpmCache;
use crate::npm::NpmPackageReference;
use crate::npm::NpmPackageResolver;
use crate::npm::RealNpmRegistryApi;
use crate::progress_bar::ProgressBar;
use crate::resolver::CliResolver;
use crate::tools::check;
use crate::util::progress_bar::ProgressBar;
use deno_ast::MediaType;
use deno_core::anyhow::anyhow;
@ -53,6 +53,7 @@ use deno_graph::source::Resolver;
use deno_graph::ModuleKind;
use deno_graph::Resolved;
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_tls::rustls::RootCertStore;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::inspector_server::InspectorServer;
@ -153,7 +154,7 @@ impl ProcState {
let compiled_wasm_module_store = CompiledWasmModuleStore::default();
let dir = cli_options.resolve_deno_dir()?;
let deps_cache_location = dir.deps_folder_path();
let http_cache = http_cache::HttpCache::new(&deps_cache_location);
let http_cache = HttpCache::new(&deps_cache_location);
let root_cert_store = cli_options.resolve_root_cert_store()?;
let cache_usage = cli_options.cache_setting();
let progress_bar = ProgressBar::default();
@ -225,7 +226,6 @@ impl ProcState {
let api = RealNpmRegistryApi::new(
registry_url,
npm_cache.clone(),
cli_options.cache_setting(),
http_client,
progress_bar.clone(),
);
@ -329,7 +329,6 @@ impl ProcState {
root_permissions.clone(),
dynamic_permissions.clone(),
);
let maybe_locker = Lockfile::as_maybe_locker(self.lockfile.clone());
let maybe_imports = self.options.to_maybe_imports()?;
let maybe_resolver =
self.maybe_resolver.as_ref().map(|r| r.as_graph_resolver());
@ -383,16 +382,16 @@ impl ProcState {
is_dynamic,
imports: maybe_imports,
resolver: maybe_resolver,
locker: maybe_locker,
module_analyzer: Some(&*analyzer),
reporter: maybe_file_watcher_reporter,
},
)
.await;
// If there was a locker, validate the integrity of all the modules in the
// locker.
graph_lock_or_exit(&graph);
// If there is a lockfile, validate the integrity of all the modules.
if let Some(lockfile) = &self.lockfile {
graph_lock_or_exit(&graph, &mut lockfile.lock());
}
// Determine any modules that have already been emitted this session and
// should be skipped.
@ -515,7 +514,7 @@ impl ProcState {
.handle_node_resolve_result(node::node_resolve(
specifier,
&referrer,
node::NodeResolutionMode::Execution,
NodeResolutionMode::Execution,
&self.npm_resolver,
))
.with_context(|| {
@ -548,7 +547,7 @@ impl ProcState {
return self
.handle_node_resolve_result(node::node_resolve_npm_reference(
&reference,
node::NodeResolutionMode::Execution,
NodeResolutionMode::Execution,
&self.npm_resolver,
))
.with_context(|| format!("Could not resolve '{}'.", reference));
@ -639,7 +638,6 @@ impl ProcState {
roots: Vec<(ModuleSpecifier, ModuleKind)>,
loader: &mut dyn Loader,
) -> Result<deno_graph::ModuleGraph, AnyError> {
let maybe_locker = Lockfile::as_maybe_locker(self.lockfile.clone());
let maybe_imports = self.options.to_maybe_imports()?;
let maybe_cli_resolver = CliResolver::maybe_new(
@ -657,7 +655,6 @@ impl ProcState {
is_dynamic: false,
imports: maybe_imports,
resolver: maybe_graph_resolver,
locker: maybe_locker,
module_analyzer: Some(&*analyzer),
reporter: None,
},

200
cli/tests/bench_tests.rs Normal file
View file

@ -0,0 +1,200 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
use deno_core::url::Url;
use test_util as util;
mod bench {
use super::*;
itest!(overloads {
args: "bench bench/overloads.ts",
exit_code: 0,
output: "bench/overloads.out",
});
itest!(meta {
args: "bench bench/meta.ts",
exit_code: 0,
output: "bench/meta.out",
});
itest!(pass {
args: "bench bench/pass.ts",
exit_code: 0,
output: "bench/pass.out",
});
itest!(ignore {
args: "bench bench/ignore.ts",
exit_code: 0,
output: "bench/ignore.out",
});
itest!(ignore_permissions {
args: "bench bench/ignore_permissions.ts",
exit_code: 0,
output: "bench/ignore_permissions.out",
});
itest!(fail {
args: "bench bench/fail.ts",
exit_code: 1,
output: "bench/fail.out",
});
itest!(collect {
args: "bench --ignore=bench/collect/ignore bench/collect",
exit_code: 0,
output: "bench/collect.out",
});
itest!(load_unload {
args: "bench bench/load_unload.ts",
exit_code: 0,
output: "bench/load_unload.out",
});
itest!(interval {
args: "bench bench/interval.ts",
exit_code: 0,
output: "bench/interval.out",
});
itest!(quiet {
args: "bench --quiet bench/quiet.ts",
exit_code: 0,
output: "bench/quiet.out",
});
itest!(only {
args: "bench bench/only.ts",
exit_code: 1,
output: "bench/only.out",
});
itest!(multifile_summary {
args: "bench bench/group_baseline.ts bench/pass.ts bench/group_baseline.ts",
exit_code: 0,
output: "bench/multifile_summary.out",
});
itest!(no_check {
args: "bench --no-check bench/no_check.ts",
exit_code: 1,
output: "bench/no_check.out",
});
itest!(allow_all {
args: "bench --allow-all bench/allow_all.ts",
exit_code: 0,
output: "bench/allow_all.out",
});
itest!(allow_none {
args: "bench bench/allow_none.ts",
exit_code: 1,
output: "bench/allow_none.out",
});
itest!(exit_sanitizer {
args: "bench bench/exit_sanitizer.ts",
output: "bench/exit_sanitizer.out",
exit_code: 1,
});
itest!(clear_timeout {
args: "bench bench/clear_timeout.ts",
exit_code: 0,
output: "bench/clear_timeout.out",
});
itest!(finally_timeout {
args: "bench bench/finally_timeout.ts",
exit_code: 1,
output: "bench/finally_timeout.out",
});
itest!(group_baseline {
args: "bench bench/group_baseline.ts",
exit_code: 0,
output: "bench/group_baseline.out",
});
itest!(unresolved_promise {
args: "bench bench/unresolved_promise.ts",
exit_code: 1,
output: "bench/unresolved_promise.out",
});
itest!(unhandled_rejection {
args: "bench bench/unhandled_rejection.ts",
exit_code: 1,
output: "bench/unhandled_rejection.out",
});
itest!(filter {
args: "bench --filter=foo bench/filter",
exit_code: 0,
output: "bench/filter.out",
});
itest!(no_prompt_by_default {
args: "bench --quiet bench/no_prompt_by_default.ts",
exit_code: 1,
output: "bench/no_prompt_by_default.out",
});
itest!(no_prompt_with_denied_perms {
args: "bench --quiet --allow-read bench/no_prompt_with_denied_perms.ts",
exit_code: 1,
output: "bench/no_prompt_with_denied_perms.out",
});
itest!(check_local_by_default {
args: "bench --quiet bench/check_local_by_default.ts",
output: "bench/check_local_by_default.out",
http_server: true,
});
itest!(check_local_by_default2 {
args: "bench --quiet bench/check_local_by_default2.ts",
output: "bench/check_local_by_default2.out",
http_server: true,
exit_code: 1,
});
#[test]
fn recursive_permissions_pledge() {
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bench")
.arg("bench/recursive_permissions_pledge.js")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert!(String::from_utf8(output.stderr).unwrap().contains(
"pledge test permissions called before restoring previous pledge"
));
}
#[test]
fn file_protocol() {
let file_url =
Url::from_file_path(util::testdata_path().join("bench/file_protocol.ts"))
.unwrap()
.to_string();
(util::CheckOutputIntegrationTest {
args_vec: vec!["bench", &file_url],
exit_code: 0,
output: "bench/file_protocol.out",
..Default::default()
})
.run();
}
}

473
cli/tests/bundle_tests.rs Normal file
View file

@ -0,0 +1,473 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
use test_util as util;
use test_util::assert_contains;
use test_util::assert_ends_with;
use test_util::TempDir;
mod bundle {
use super::*;
#[test]
fn bundle_exports() {
// First we have to generate a bundle of some module that has exports.
let mod1 = util::testdata_path().join("subdir/mod1.ts");
assert!(mod1.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod1.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod1)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./mod1.bundle.js\";
printHello3(); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_exports_no_check() {
// First we have to generate a bundle of some module that has exports.
let mod1 = util::testdata_path().join("subdir/mod1.ts");
assert!(mod1.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod1.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod1)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./mod1.bundle.js\";
printHello3(); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_circular() {
// First we have to generate a bundle of some module that has exports.
let circular1_path = util::testdata_path().join("subdir/circular1.ts");
assert!(circular1_path.is_file());
let t = TempDir::new();
let bundle_path = t.path().join("circular1.bundle.js");
// run this twice to ensure it works even when cached
for _ in 0..2 {
let mut deno = util::deno_cmd_with_deno_dir(&t)
.current_dir(util::testdata_path())
.arg("bundle")
.arg(&circular1_path)
.arg(&bundle_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle_path.is_file());
}
let output = util::deno_cmd_with_deno_dir(&t)
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle_path)
.output()
.unwrap();
// check the output of the the bundle program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"f2\nf1",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_single_module() {
// First we have to generate a bundle of some module that has exports.
let single_module = util::testdata_path().join("subdir/single_module.ts");
assert!(single_module.is_file());
let t = TempDir::new();
let bundle = t.path().join("single_module.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(single_module)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle)
.output()
.unwrap();
// check the output of the the bundle program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello world!",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_tla() {
// First we have to generate a bundle of some module that has exports.
let tla_import = util::testdata_path().join("subdir/tla.ts");
assert!(tla_import.is_file());
let t = TempDir::new();
let bundle = t.path().join("tla.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(tla_import)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { foo } from \"./tla.bundle.js\";
console.log(foo); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_js() {
// First we have to generate a bundle of some module that has exports.
let mod6 = util::testdata_path().join("subdir/mod6.js");
assert!(mod6.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod6.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod6)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle)
.output()
.unwrap();
// check that nothing went to stderr
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_dynamic_import() {
let _g = util::http_server();
let dynamic_import = util::testdata_path().join("bundle/dynamic_import.ts");
assert!(dynamic_import.is_file());
let t = TempDir::new();
let output_path = t.path().join("bundle_dynamic_import.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(dynamic_import)
.arg(&output_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(output_path.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--allow-net")
.arg("--quiet")
.arg(&output_path)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_import_map() {
let import = util::testdata_path().join("bundle/import_map/main.ts");
let import_map_path =
util::testdata_path().join("bundle/import_map/import_map.json");
assert!(import.is_file());
let t = TempDir::new();
let output_path = t.path().join("import_map.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg("--import-map")
.arg(import_map_path)
.arg(import)
.arg(&output_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(output_path.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./import_map.bundle.js\";
printHello3(); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--check")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_import_map_no_check() {
let import = util::testdata_path().join("bundle/import_map/main.ts");
let import_map_path =
util::testdata_path().join("bundle/import_map/import_map.json");
assert!(import.is_file());
let t = TempDir::new();
let output_path = t.path().join("import_map.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg("--import-map")
.arg(import_map_path)
.arg(import)
.arg(&output_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(output_path.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./import_map.bundle.js\";
printHello3(); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_json_module() {
// First we have to generate a bundle of some module that has exports.
let mod7 = util::testdata_path().join("subdir/mod7.js");
assert!(mod7.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod7.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod7)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle)
.output()
.unwrap();
// check that nothing went to stderr
assert_eq!(output.stderr, b"");
// ensure the output looks right
assert_contains!(String::from_utf8(output.stdout).unwrap(), "with space",);
}
#[test]
fn bundle_json_module_escape_sub() {
// First we have to generate a bundle of some module that has exports.
let mod8 = util::testdata_path().join("subdir/mod8.js");
assert!(mod8.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod8.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod8)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle)
.output()
.unwrap();
// check that nothing went to stderr
assert_eq!(output.stderr, b"");
// make sure the output looks right and the escapes were effective
assert_contains!(
String::from_utf8(output.stdout).unwrap(),
"${globalThis}`and string literal`",
);
}
itest!(lockfile_check_error {
args: "bundle --lock=bundle/lockfile/check_error.json http://127.0.0.1:4545/subdir/mod1.ts",
output: "bundle/lockfile/check_error.out",
exit_code: 10,
http_server: true,
});
itest!(bundle {
args: "bundle subdir/mod1.ts",
output: "bundle/bundle.test.out",
});
itest!(bundle_jsx {
args: "bundle run/jsx_import_from_ts.ts",
output: "bundle/jsx.out",
});
itest!(error_bundle_with_bare_import {
args: "bundle bundle/bare_imports/error_with_bare_import.ts",
output: "bundle/bare_imports/error_with_bare_import.ts.out",
exit_code: 1,
});
itest!(ts_decorators_bundle {
args: "bundle bundle/decorators/ts_decorators.ts",
output: "bundle/decorators/ts_decorators.out",
});
itest!(bundle_export_specifier_with_alias {
args: "bundle bundle/file_tests-fixture16.ts",
output: "bundle/fixture16.out",
});
itest!(bundle_ignore_directives {
args: "bundle subdir/mod1.ts",
output: "bundle/ignore_directives.test.out",
});
itest!(check_local_by_default_no_errors {
args: "bundle --quiet bundle/check_local_by_default/no_errors.ts",
output: "bundle/check_local_by_default/no_errors.out",
http_server: true,
});
itest!(check_local_by_default_type_error {
args: "bundle --quiet bundle/check_local_by_default/type_error.ts",
output: "bundle/check_local_by_default/type_error.out",
http_server: true,
exit_code: 1,
});
}

102
cli/tests/cache_tests.rs Normal file
View file

@ -0,0 +1,102 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
mod cache {
use super::*;
itest!(_036_import_map_fetch {
args:
"cache --quiet --reload --import-map=import_maps/import_map.json import_maps/test.ts",
output: "cache/036_import_map_fetch.out",
});
itest!(_037_fetch_multiple {
args: "cache --reload --check=all run/fetch/test.ts run/fetch/other.ts",
http_server: true,
output: "cache/037_fetch_multiple.out",
});
itest!(_095_cache_with_bare_import {
args: "cache cache/095_cache_with_bare_import.ts",
output: "cache/095_cache_with_bare_import.ts.out",
exit_code: 1,
});
itest!(cache_extensionless {
args: "cache --reload --check=all http://localhost:4545/subdir/no_js_ext",
output: "cache/cache_extensionless.out",
http_server: true,
});
itest!(cache_random_extension {
args:
"cache --reload --check=all http://localhost:4545/subdir/no_js_ext@1.0.0",
output: "cache/cache_random_extension.out",
http_server: true,
});
itest!(performance_stats {
args: "cache --reload --check=all --log-level debug run/002_hello.ts",
output: "cache/performance_stats.out",
});
itest!(redirect_cache {
http_server: true,
args:
"cache --reload --check=all http://localhost:4548/subdir/redirects/a.ts",
output: "cache/redirect_cache.out",
});
itest!(ignore_require {
args: "cache --reload --no-check cache/ignore_require.js",
output_str: Some(""),
exit_code: 0,
});
// This test only runs on linux, because it hardcodes the XDG_CACHE_HOME env var
// which is only used on linux.
#[cfg(target_os = "linux")]
#[test]
fn relative_home_dir() {
use test_util as util;
use test_util::TempDir;
let deno_dir = TempDir::new_in(&util::testdata_path());
let path = deno_dir.path().strip_prefix(util::testdata_path()).unwrap();
let mut deno_cmd = util::deno_cmd();
let output = deno_cmd
.current_dir(util::testdata_path())
.env("XDG_CACHE_HOME", path)
.env_remove("HOME")
.env_remove("DENO_DIR")
.arg("cache")
.arg("--reload")
.arg("--no-check")
.arg("run/002_hello.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"");
}
itest!(check_local_by_default {
args: "cache --quiet cache/check_local_by_default.ts",
output: "cache/check_local_by_default.out",
http_server: true,
});
itest!(check_local_by_default2 {
args: "cache --quiet cache/check_local_by_default2.ts",
output: "cache/check_local_by_default2.out",
http_server: true,
});
itest!(json_import {
// should not error
args: "cache --quiet cache/json_import/main.ts",
});
}

321
cli/tests/cert_tests.rs Normal file
View file

@ -0,0 +1,321 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
use deno_runtime::deno_net::ops_tls::TlsStream;
use deno_runtime::deno_tls::rustls;
use deno_runtime::deno_tls::rustls_pemfile;
use std::io::BufReader;
use std::io::Cursor;
use std::io::Read;
use std::process::Command;
use std::sync::Arc;
use test_util as util;
use test_util::TempDir;
use tokio::task::LocalSet;
mod cert {
use super::*;
itest_flaky!(cafile_url_imports {
args:
"run --quiet --reload --cert tls/RootCA.pem cert/cafile_url_imports.ts",
output: "cert/cafile_url_imports.ts.out",
http_server: true,
});
itest_flaky!(cafile_ts_fetch {
args:
"run --quiet --reload --allow-net --cert tls/RootCA.pem cert/cafile_ts_fetch.ts",
output: "cert/cafile_ts_fetch.ts.out",
http_server: true,
});
itest_flaky!(cafile_eval {
args: "eval --cert tls/RootCA.pem fetch('https://localhost:5545/cert/cafile_ts_fetch.ts.out').then(r=>r.text()).then(t=>console.log(t.trimEnd()))",
output: "cert/cafile_ts_fetch.ts.out",
http_server: true,
});
itest_flaky!(cafile_info {
args:
"info --quiet --cert tls/RootCA.pem https://localhost:5545/cert/cafile_info.ts",
output: "cert/cafile_info.ts.out",
http_server: true,
});
itest_flaky!(cafile_url_imports_unsafe_ssl {
args: "run --quiet --reload --unsafely-ignore-certificate-errors=localhost cert/cafile_url_imports.ts",
output: "cert/cafile_url_imports_unsafe_ssl.ts.out",
http_server: true,
});
itest_flaky!(cafile_ts_fetch_unsafe_ssl {
args:
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors cert/cafile_ts_fetch.ts",
output: "cert/cafile_ts_fetch_unsafe_ssl.ts.out",
http_server: true,
});
itest!(deno_land_unsafe_ssl {
args:
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=deno.land cert/deno_land_unsafe_ssl.ts",
output: "cert/deno_land_unsafe_ssl.ts.out",
});
itest!(ip_address_unsafe_ssl {
args:
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=1.1.1.1 cert/ip_address_unsafe_ssl.ts",
output: "cert/ip_address_unsafe_ssl.ts.out",
});
itest!(localhost_unsafe_ssl {
args:
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=deno.land cert/cafile_url_imports.ts",
output: "cert/localhost_unsafe_ssl.ts.out",
http_server: true,
exit_code: 1,
});
#[flaky_test::flaky_test]
fn cafile_env_fetch() {
use deno_core::url::Url;
let _g = util::http_server();
let deno_dir = TempDir::new();
let module_url =
Url::parse("https://localhost:5545/cert/cafile_url_imports.ts").unwrap();
let cafile = util::testdata_path().join("tls/RootCA.pem");
let output = Command::new(util::deno_exe_path())
.env("DENO_DIR", deno_dir.path())
.env("DENO_CERT", cafile)
.current_dir(util::testdata_path())
.arg("cache")
.arg(module_url.to_string())
.output()
.expect("Failed to spawn script");
assert!(output.status.success());
}
#[flaky_test::flaky_test]
fn cafile_fetch() {
use deno_core::url::Url;
let _g = util::http_server();
let deno_dir = TempDir::new();
let module_url =
Url::parse("http://localhost:4545/cert/cafile_url_imports.ts").unwrap();
let cafile = util::testdata_path().join("tls/RootCA.pem");
let output = Command::new(util::deno_exe_path())
.env("DENO_DIR", deno_dir.path())
.current_dir(util::testdata_path())
.arg("cache")
.arg("--cert")
.arg(cafile)
.arg(module_url.to_string())
.output()
.expect("Failed to spawn script");
assert!(output.status.success());
let out = std::str::from_utf8(&output.stdout).unwrap();
assert_eq!(out, "");
}
#[flaky_test::flaky_test]
fn cafile_install_remote_module() {
let _g = util::http_server();
let temp_dir = TempDir::new();
let bin_dir = temp_dir.path().join("bin");
std::fs::create_dir(&bin_dir).unwrap();
let deno_dir = TempDir::new();
let cafile = util::testdata_path().join("tls/RootCA.pem");
let install_output = Command::new(util::deno_exe_path())
.env("DENO_DIR", deno_dir.path())
.current_dir(util::testdata_path())
.arg("install")
.arg("--cert")
.arg(cafile)
.arg("--root")
.arg(temp_dir.path())
.arg("-n")
.arg("echo_test")
.arg("https://localhost:5545/echo.ts")
.output()
.expect("Failed to spawn script");
println!("{}", std::str::from_utf8(&install_output.stdout).unwrap());
eprintln!("{}", std::str::from_utf8(&install_output.stderr).unwrap());
assert!(install_output.status.success());
let mut echo_test_path = bin_dir.join("echo_test");
if cfg!(windows) {
echo_test_path = echo_test_path.with_extension("cmd");
}
assert!(echo_test_path.exists());
let output = Command::new(echo_test_path)
.current_dir(temp_dir.path())
.arg("foo")
.env("PATH", util::target_dir())
.output()
.expect("failed to spawn script");
let stdout = std::str::from_utf8(&output.stdout).unwrap().trim();
assert!(stdout.ends_with("foo"));
}
#[flaky_test::flaky_test]
fn cafile_bundle_remote_exports() {
let _g = util::http_server();
// First we have to generate a bundle of some remote module that has exports.
let mod1 = "https://localhost:5545/subdir/mod1.ts";
let cafile = util::testdata_path().join("tls/RootCA.pem");
let t = TempDir::new();
let bundle = t.path().join("mod1.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg("--cert")
.arg(cafile)
.arg(mod1)
.arg(&bundle)
.spawn()
.expect("failed to spawn script");
let status = deno.wait().expect("failed to wait for the child process");
assert!(status.success());
assert!(bundle.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./mod1.bundle.js\";
printHello3(); ",
)
.expect("error writing file");
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--check")
.arg(&test)
.output()
.expect("failed to spawn script");
// check the output of the test.ts program.
assert!(std::str::from_utf8(&output.stdout)
.unwrap()
.trim()
.ends_with("Hello"));
assert_eq!(output.stderr, b"");
}
#[tokio::test]
async fn listen_tls_alpn() {
// TLS streams require the presence of an ambient local task set to gracefully
// close dropped connections in the background.
LocalSet::new()
.run_until(async {
let mut child = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--unstable")
.arg("--quiet")
.arg("--allow-net")
.arg("--allow-read")
.arg("./cert/listen_tls_alpn.ts")
.arg("4504")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();
let stdout = child.stdout.as_mut().unwrap();
let mut msg = [0; 5];
let read = stdout.read(&mut msg).unwrap();
assert_eq!(read, 5);
assert_eq!(&msg, b"READY");
let mut reader = &mut BufReader::new(Cursor::new(include_bytes!(
"./testdata/tls/RootCA.crt"
)));
let certs = rustls_pemfile::certs(&mut reader).unwrap();
let mut root_store = rustls::RootCertStore::empty();
root_store.add_parsable_certificates(&certs);
let mut cfg = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth();
cfg.alpn_protocols.push(b"foobar".to_vec());
let cfg = Arc::new(cfg);
let hostname = rustls::ServerName::try_from("localhost").unwrap();
let tcp_stream = tokio::net::TcpStream::connect("localhost:4504")
.await
.unwrap();
let mut tls_stream =
TlsStream::new_client_side(tcp_stream, cfg, hostname);
tls_stream.handshake().await.unwrap();
let (_, rustls_connection) = tls_stream.get_ref();
let alpn = rustls_connection.alpn_protocol().unwrap();
assert_eq!(alpn, b"foobar");
let status = child.wait().unwrap();
assert!(status.success());
})
.await;
}
#[tokio::test]
async fn listen_tls_alpn_fail() {
// TLS streams require the presence of an ambient local task set to gracefully
// close dropped connections in the background.
LocalSet::new()
.run_until(async {
let mut child = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--unstable")
.arg("--quiet")
.arg("--allow-net")
.arg("--allow-read")
.arg("./cert/listen_tls_alpn_fail.ts")
.arg("4505")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();
let stdout = child.stdout.as_mut().unwrap();
let mut msg = [0; 5];
let read = stdout.read(&mut msg).unwrap();
assert_eq!(read, 5);
assert_eq!(&msg, b"READY");
let mut reader = &mut BufReader::new(Cursor::new(include_bytes!(
"./testdata/tls/RootCA.crt"
)));
let certs = rustls_pemfile::certs(&mut reader).unwrap();
let mut root_store = rustls::RootCertStore::empty();
root_store.add_parsable_certificates(&certs);
let mut cfg = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth();
cfg.alpn_protocols.push(b"boofar".to_vec());
let cfg = Arc::new(cfg);
let hostname = rustls::ServerName::try_from("localhost").unwrap();
let tcp_stream = tokio::net::TcpStream::connect("localhost:4505")
.await
.unwrap();
let mut tls_stream =
TlsStream::new_client_side(tcp_stream, cfg, hostname);
tls_stream.handshake().await.unwrap_err();
let (_, rustls_connection) = tls_stream.get_ref();
assert!(rustls_connection.alpn_protocol().is_none());
let status = child.wait().unwrap();
assert!(status.success());
})
.await;
}
}

212
cli/tests/check_tests.rs Normal file
View file

@ -0,0 +1,212 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
use std::process::Command;
use std::process::Stdio;
use test_util as util;
use util::TempDir;
mod check {
use super::*;
itest!(_095_check_with_bare_import {
args: "check cache/095_cache_with_bare_import.ts",
output: "cache/095_cache_with_bare_import.ts.out",
exit_code: 1,
});
itest!(check_extensionless {
args: "check --reload http://localhost:4545/subdir/no_js_ext",
output: "cache/cache_extensionless.out",
http_server: true,
});
itest!(check_random_extension {
args: "check --reload http://localhost:4545/subdir/no_js_ext@1.0.0",
output: "cache/cache_random_extension.out",
http_server: true,
});
itest!(check_all {
args: "check --quiet --all check/check_all.ts",
output: "check/check_all.out",
http_server: true,
exit_code: 1,
});
itest!(check_all_local {
args: "check --quiet check/check_all.ts",
output_str: Some(""),
http_server: true,
});
itest!(module_detection_force {
args: "check --quiet check/module_detection_force/main.ts",
output_str: Some(""),
});
// Regression test for https://github.com/denoland/deno/issues/14937.
itest!(declaration_header_file_with_no_exports {
args: "check --quiet check/declaration_header_file_with_no_exports.ts",
output_str: Some(""),
});
itest!(check_npm_install_diagnostics {
args: "check --quiet check/npm_install_diagnostics/main.ts",
output: "check/npm_install_diagnostics/main.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
exit_code: 1,
});
itest!(check_export_equals_declaration_file {
args: "check --quiet check/export_equals_declaration_file/main.ts",
exit_code: 0,
});
#[test]
fn cache_switching_config_then_no_config() {
let deno_dir = util::new_deno_dir();
assert!(does_type_checking(&deno_dir, true));
assert!(does_type_checking(&deno_dir, false));
// should now not do type checking even when it changes
// configs because it previously did
assert!(!does_type_checking(&deno_dir, true));
assert!(!does_type_checking(&deno_dir, false));
fn does_type_checking(deno_dir: &util::TempDir, with_config: bool) -> bool {
let mut cmd = util::deno_cmd_with_deno_dir(deno_dir);
cmd
.current_dir(util::testdata_path())
.stderr(Stdio::piped())
.arg("check")
.arg("check/cache_config_on_off/main.ts");
if with_config {
cmd
.arg("--config")
.arg("check/cache_config_on_off/deno.json");
}
let output = cmd.spawn().unwrap().wait_with_output().unwrap();
assert!(output.status.success());
let stderr = std::str::from_utf8(&output.stderr).unwrap();
stderr.contains("Check")
}
}
#[test]
fn reload_flag() {
// should do type checking whenever someone specifies --reload
let deno_dir = util::new_deno_dir();
assert!(does_type_checking(&deno_dir, false));
assert!(!does_type_checking(&deno_dir, false));
assert!(does_type_checking(&deno_dir, true));
assert!(does_type_checking(&deno_dir, true));
assert!(!does_type_checking(&deno_dir, false));
fn does_type_checking(deno_dir: &util::TempDir, reload: bool) -> bool {
let mut cmd = util::deno_cmd_with_deno_dir(deno_dir);
cmd
.current_dir(util::testdata_path())
.stderr(Stdio::piped())
.arg("check")
.arg("check/cache_config_on_off/main.ts");
if reload {
cmd.arg("--reload");
}
let output = cmd.spawn().unwrap().wait_with_output().unwrap();
assert!(output.status.success());
let stderr = std::str::from_utf8(&output.stderr).unwrap();
stderr.contains("Check")
}
}
#[test]
fn typecheck_declarations_ns() {
let output = util::deno_cmd()
.arg("test")
.arg("--doc")
.arg(util::root_path().join("cli/tsc/dts/lib.deno.ns.d.ts"))
.output()
.unwrap();
println!("stdout: {}", String::from_utf8(output.stdout).unwrap());
println!("stderr: {}", String::from_utf8(output.stderr).unwrap());
assert!(output.status.success());
}
#[test]
fn typecheck_declarations_unstable() {
let output = util::deno_cmd()
.arg("test")
.arg("--doc")
.arg("--unstable")
.arg(util::root_path().join("cli/tsc/dts/lib.deno.unstable.d.ts"))
.output()
.unwrap();
println!("stdout: {}", String::from_utf8(output.stdout).unwrap());
println!("stderr: {}", String::from_utf8(output.stderr).unwrap());
assert!(output.status.success());
}
#[test]
fn typecheck_core() {
let deno_dir = TempDir::new();
let test_file = deno_dir.path().join("test_deno_core_types.ts");
std::fs::write(
&test_file,
format!(
"import \"{}\";",
deno_core::resolve_path(
util::root_path()
.join("core/lib.deno_core.d.ts")
.to_str()
.unwrap()
)
.unwrap()
),
)
.unwrap();
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.arg("run")
.arg(test_file.to_str().unwrap())
.output()
.unwrap();
println!("stdout: {}", String::from_utf8(output.stdout).unwrap());
println!("stderr: {}", String::from_utf8(output.stderr).unwrap());
assert!(output.status.success());
}
#[test]
fn ts_no_recheck_on_redirect() {
let deno_dir = util::new_deno_dir();
let e = util::deno_exe_path();
let redirect_ts = util::testdata_path().join("run/017_import_redirect.ts");
assert!(redirect_ts.is_file());
let mut cmd = Command::new(e.clone());
cmd.env("DENO_DIR", deno_dir.path());
let mut initial = cmd
.current_dir(util::testdata_path())
.arg("run")
.arg("--check")
.arg(redirect_ts.clone())
.spawn()
.expect("failed to span script");
let status_initial =
initial.wait().expect("failed to wait for child process");
assert!(status_initial.success());
let mut cmd = Command::new(e);
cmd.env("DENO_DIR", deno_dir.path());
let output = cmd
.current_dir(util::testdata_path())
.arg("run")
.arg("--check")
.arg(redirect_ts)
.output()
.expect("failed to spawn script");
assert!(std::str::from_utf8(&output.stderr).unwrap().is_empty());
}
}

536
cli/tests/compile_tests.rs Normal file
View file

@ -0,0 +1,536 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::fs::File;
use std::process::Command;
use test_util as util;
use test_util::TempDir;
mod compile {
use super::*;
#[test]
fn compile() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("welcome.exe")
} else {
dir.path().join("welcome")
};
// try this twice to ensure it works with the cache
for _ in 0..2 {
let output = util::deno_cmd_with_deno_dir(&dir)
.current_dir(util::root_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./test_util/std/examples/welcome.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(&exe)
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, "Welcome to Deno!\n".as_bytes());
}
}
#[test]
fn standalone_args() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("args.exe")
} else {
dir.path().join("args")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.arg("a")
.arg("b")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.arg("foo")
.arg("--bar")
.arg("--unstable")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"a\nb\nfoo\n--bar\n--unstable\n");
}
#[test]
fn standalone_error() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("error.exe")
} else {
dir.path().join("error")
};
let testdata_path = util::testdata_path();
let output = util::deno_cmd()
.current_dir(&testdata_path)
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_error.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.env("NO_COLOR", "1")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert_eq!(output.stdout, b"");
let stderr = String::from_utf8(output.stderr).unwrap();
let stderr = util::strip_ansi_codes(&stderr).to_string();
// On Windows, we cannot assert the file path (because '\').
// Instead we just check for relevant output.
assert!(stderr.contains("error: Uncaught Error: boom!"));
assert!(stderr.contains("throw new Error(\"boom!\");"));
assert!(stderr.contains("\n at boom (file://"));
assert!(stderr.contains("standalone_error.ts:2:11"));
assert!(stderr.contains("at foo (file://"));
assert!(stderr.contains("standalone_error.ts:5:5"));
assert!(stderr.contains("standalone_error.ts:7:1"));
}
#[test]
fn standalone_error_module_with_imports() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("error.exe")
} else {
dir.path().join("error")
};
let testdata_path = util::testdata_path();
let output = util::deno_cmd()
.current_dir(&testdata_path)
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_error_module_with_imports_1.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.env("NO_COLOR", "1")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
println!("{:#?}", &output);
assert_eq!(output.stdout, b"hello\n");
let stderr = String::from_utf8(output.stderr).unwrap();
let stderr = util::strip_ansi_codes(&stderr).to_string();
// On Windows, we cannot assert the file path (because '\').
// Instead we just check for relevant output.
assert!(stderr.contains("error: Uncaught Error: boom!"));
assert!(stderr.contains("throw new Error(\"boom!\");"));
assert!(stderr.contains("\n at file://"));
assert!(stderr.contains("standalone_error_module_with_imports_2.ts:2:7"));
}
#[test]
fn standalone_load_datauri() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("load_datauri.exe")
} else {
dir.path().join("load_datauri")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_import_datauri.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Hello Deno!\n");
}
// https://github.com/denoland/deno/issues/13704
#[test]
fn standalone_follow_redirects() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("follow_redirects.exe")
} else {
dir.path().join("follow_redirects")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_follow_redirects.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Hello\n");
}
#[test]
fn compile_with_file_exists_error() {
let dir = TempDir::new();
let output_path = if cfg!(windows) {
dir.path().join(r"args\")
} else {
dir.path().join("args/")
};
let file_path = dir.path().join("args");
File::create(&file_path).unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&output_path)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
let expected_stderr = format!(
concat!(
"Could not compile to file '{}' because its parent directory ",
"is an existing file. You can use the `--output <file-path>` flag to ",
"provide an alternative name.\n",
),
file_path.display(),
);
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains(&expected_stderr));
}
#[test]
fn compile_with_directory_exists_error() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("args.exe")
} else {
dir.path().join("args")
};
std::fs::create_dir(&exe).unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
let expected_stderr = format!(
concat!(
"Could not compile to file '{}' because a directory exists with ",
"the same name. You can use the `--output <file-path>` flag to ",
"provide an alternative name."
),
exe.display()
);
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains(&expected_stderr));
}
#[test]
fn compile_with_conflict_file_exists_error() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("args.exe")
} else {
dir.path().join("args")
};
std::fs::write(&exe, b"SHOULD NOT BE OVERWRITTEN").unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
let expected_stderr = format!(
concat!(
"Could not compile to file '{}' because the file already exists ",
"and cannot be overwritten. Please delete the existing file or ",
"use the `--output <file-path` flag to provide an alternative name."
),
exe.display()
);
let stderr = String::from_utf8(output.stderr).unwrap();
dbg!(&stderr);
assert!(stderr.contains(&expected_stderr));
assert!(std::fs::read(&exe)
.unwrap()
.eq(b"SHOULD NOT BE OVERWRITTEN"));
}
#[test]
fn compile_and_overwrite_file() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("args.exe")
} else {
dir.path().join("args")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert!(&exe.exists());
let recompile_output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(recompile_output.status.success());
}
#[test]
fn standalone_runtime_flags() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("flags.exe")
} else {
dir.path().join("flags")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--allow-read")
.arg("--seed")
.arg("1")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_runtime_flags.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
let stdout_str = String::from_utf8(output.stdout).unwrap();
assert_eq!(util::strip_ansi_codes(&stdout_str), "0.147205063401058\n");
let stderr_str = String::from_utf8(output.stderr).unwrap();
assert!(util::strip_ansi_codes(&stderr_str)
.contains("PermissionDenied: Requires write access"));
}
#[test]
fn standalone_import_map() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("import_map.exe")
} else {
dir.path().join("import_map")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--allow-read")
.arg("--import-map")
.arg("compile/standalone_import_map.json")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_import_map.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
}
#[test]
// https://github.com/denoland/deno/issues/12670
fn skip_rebundle() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("hello_world.exe")
} else {
dir.path().join("hello_world")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./run/001_hello.js")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
//no "Bundle testdata_path/run/001_hello.js" in output
assert!(!String::from_utf8(output.stderr).unwrap().contains("Bundle"));
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, "Hello World\n".as_bytes());
}
#[test]
fn check_local_by_default() {
let _guard = util::http_server();
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("welcome.exe")
} else {
dir.path().join("welcome")
};
let status = util::deno_cmd()
.current_dir(util::root_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg(util::testdata_path().join("./compile/check_local_by_default.ts"))
.status()
.unwrap();
assert!(status.success());
}
#[test]
fn check_local_by_default2() {
let _guard = util::http_server();
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("welcome.exe")
} else {
dir.path().join("welcome")
};
let output = util::deno_cmd()
.current_dir(util::root_path())
.env("NO_COLOR", "1")
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg(util::testdata_path().join("./compile/check_local_by_default2.ts"))
.output()
.unwrap();
assert!(!output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stdout.is_empty());
assert!(stderr.contains(
r#"error: TS2322 [ERROR]: Type '12' is not assignable to type '"b"'."#
));
}
}

382
cli/tests/coverage_tests.rs Normal file
View file

@ -0,0 +1,382 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::fs;
use test_util as util;
use test_util::TempDir;
mod coverage {
use super::*;
#[test]
fn branch() {
run_coverage_text("branch", "ts");
}
#[test]
fn complex() {
run_coverage_text("complex", "ts");
}
#[test]
fn final_blankline() {
run_coverage_text("final_blankline", "js");
}
#[test]
fn no_snaps() {
no_snaps_included("no_snaps_included", "ts");
}
#[test]
fn error_if_invalid_cache() {
let deno_dir = TempDir::new();
let deno_dir_path = deno_dir.path();
let tempdir = TempDir::new();
let tempdir = tempdir.path().join("cov");
let invalid_cache_path =
util::testdata_path().join("coverage/invalid_cache");
let mod_before_path = util::testdata_path()
.join(&invalid_cache_path)
.join("mod_before.ts");
let mod_after_path = util::testdata_path()
.join(&invalid_cache_path)
.join("mod_after.ts");
let mod_test_path = util::testdata_path()
.join(&invalid_cache_path)
.join("mod.test.ts");
let mod_temp_path = deno_dir_path.join("mod.ts");
let mod_test_temp_path = deno_dir_path.join("mod.test.ts");
// Write the inital mod.ts file
std::fs::copy(mod_before_path, &mod_temp_path).unwrap();
// And the test file
std::fs::copy(mod_test_path, &mod_test_temp_path).unwrap();
// Generate coverage
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(deno_dir_path)
.arg("test")
.arg("--quiet")
.arg(format!("--coverage={}", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.status()
.unwrap();
assert!(status.success());
// Modify the file between deno test and deno coverage, thus invalidating the cache
std::fs::copy(mod_after_path, mod_temp_path).unwrap();
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(deno_dir_path)
.arg("coverage")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.unwrap();
assert!(output.stdout.is_empty());
// Expect error
let error =
util::strip_ansi_codes(std::str::from_utf8(&output.stderr).unwrap())
.to_string();
assert!(error.contains("error: Missing transpiled source code"));
assert!(error.contains("Before generating coverage report, run `deno test --coverage` to ensure consistent state."));
}
fn run_coverage_text(test_name: &str, extension: &str) {
let deno_dir = TempDir::new();
let tempdir = TempDir::new();
let tempdir = tempdir.path().join("cov");
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("test")
.arg("-A")
.arg("--quiet")
.arg("--unstable")
.arg(format!("--coverage={}", tempdir.to_str().unwrap()))
.arg(format!("coverage/{}_test.{}", test_name, extension))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.status()
.unwrap();
assert!(status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--unstable")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.unwrap();
// Verify there's no "Check" being printed
assert!(output.stderr.is_empty());
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path()
.join(format!("coverage/{}_expected.out", test_name)),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--quiet")
.arg("--unstable")
.arg("--lcov")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.output()
.unwrap();
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path()
.join(format!("coverage/{}_expected.lcov", test_name)),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
}
#[test]
fn multifile_coverage() {
let deno_dir = TempDir::new();
let tempdir = TempDir::new();
let tempdir = tempdir.path().join("cov");
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("test")
.arg("--quiet")
.arg("--unstable")
.arg(format!("--coverage={}", tempdir.to_str().unwrap()))
.arg("coverage/multifile/")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.status()
.unwrap();
assert!(status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--unstable")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.unwrap();
// Verify there's no "Check" being printed
assert!(output.stderr.is_empty());
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/multifile/expected.out"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--quiet")
.arg("--unstable")
.arg("--lcov")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.output()
.unwrap();
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/multifile/expected.lcov"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
}
fn no_snaps_included(test_name: &str, extension: &str) {
let deno_dir = TempDir::new();
let tempdir = TempDir::new();
let tempdir = tempdir.path().join("cov");
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("test")
.arg("--quiet")
.arg("--unstable")
.arg("--allow-read")
.arg(format!("--coverage={}", tempdir.to_str().unwrap()))
.arg(format!(
"coverage/no_snaps_included/{}_test.{}",
test_name, extension
))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.status()
.unwrap();
assert!(status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--unstable")
.arg("--include=no_snaps_included.ts")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.unwrap();
// Verify there's no "Check" being printed
assert!(output.stderr.is_empty());
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/no_snaps_included/expected.out"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
}
#[test]
fn no_transpiled_lines() {
let deno_dir = TempDir::new();
let tempdir = TempDir::new();
let tempdir = tempdir.path().join("cov");
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("test")
.arg("--quiet")
.arg(format!("--coverage={}", tempdir.to_str().unwrap()))
.arg("coverage/no_transpiled_lines/")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.status()
.unwrap();
assert!(status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--include=no_transpiled_lines/index.ts")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.unwrap();
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/no_transpiled_lines/expected.out"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--lcov")
.arg("--include=no_transpiled_lines/index.ts")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.output()
.unwrap();
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/no_transpiled_lines/expected.lcov"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
}
}

79
cli/tests/doc_tests.rs Normal file
View file

@ -0,0 +1,79 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
use test_util as util;
use test_util::TempDir;
use util::assert_contains;
mod doc {
use super::*;
itest!(deno_doc_builtin {
args: "doc",
output: "doc/deno_doc_builtin.out",
});
#[test]
fn deno_doc() {
let dir = TempDir::new();
// try this twice to ensure it works with the cache
for _ in 0..2 {
let output = util::deno_cmd_with_deno_dir(&dir)
.current_dir(util::testdata_path())
.arg("doc")
.arg("doc/deno_doc.ts")
.env("NO_COLOR", "1")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_contains!(
std::str::from_utf8(&output.stdout).unwrap(),
"function foo"
);
}
}
itest!(deno_doc_import_map {
args:
"doc --unstable --import-map=doc/import_map.json doc/use_import_map.js",
output: "doc/use_import_map.out",
});
itest!(deno_doc_types_hint {
args: "doc doc/types_hint.ts",
output: "doc/types_hint.out",
});
itest!(deno_doc_types_ref {
args: "doc doc/types_ref.js",
output: "doc/types_ref.out",
});
itest!(deno_doc_types_header {
args: "doc --reload doc/types_header.ts",
output: "doc/types_header.out",
http_server: true,
});
itest!(_060_deno_doc_displays_all_overloads_in_details_view {
args:
"doc doc/060_deno_doc_displays_all_overloads_in_details_view.ts NS.test",
output: "doc/060_deno_doc_displays_all_overloads_in_details_view.ts.out",
});
itest!(deno_doc_types_header_direct {
args: "doc --reload http://127.0.0.1:4545/xTypeScriptTypes.js",
output: "doc/types_header.out",
http_server: true,
});
itest!(deno_doc_invalid_url {
args: "doc https://raw.githubusercontent.com%2Fdyedgreen%2Fdeno-sqlite%2Frework_api%2Fmod.ts",
output: "doc/invalid_url.out",
exit_code: 1,
});
}

86
cli/tests/eval_tests.rs Normal file
View file

@ -0,0 +1,86 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
use test_util as util;
mod eval {
use super::*;
#[test]
fn eval_p() {
let output = util::deno_cmd()
.arg("eval")
.arg("-p")
.arg("1+2")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout_str = util::strip_ansi_codes(
std::str::from_utf8(&output.stdout).unwrap().trim(),
);
assert_eq!("3", stdout_str);
}
// Make sure that snapshot flags don't affect runtime.
#[test]
fn eval_randomness() {
let mut numbers = Vec::with_capacity(10);
for _ in 0..10 {
let output = util::deno_cmd()
.arg("eval")
.arg("-p")
.arg("Math.random()")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout_str = util::strip_ansi_codes(
std::str::from_utf8(&output.stdout).unwrap().trim(),
);
numbers.push(stdout_str.to_string());
}
numbers.dedup();
assert!(numbers.len() > 1);
}
itest!(eval_basic {
args: "eval console.log(\"hello\")",
output_str: Some("hello\n"),
});
// Ugly parentheses due to whitespace delimiting problem.
itest!(eval_ts {
args: "eval --quiet --ext=ts console.log((123)as(number))", // 'as' is a TS keyword only
output_str: Some("123\n"),
});
itest!(dyn_import_eval {
args: "eval import('./subdir/mod4.js').then(console.log)",
output: "eval/dyn_import_eval.out",
});
// Cannot write the expression to evaluate as "console.log(typeof gc)"
// because itest! splits args on whitespace.
itest!(v8_flags_eval {
args: "eval --v8-flags=--expose-gc console.log(typeof(gc))",
output: "run/v8_flags.js.out",
});
itest!(check_local_by_default {
args: "eval --quiet import('http://localhost:4545/subdir/type_error.ts').then(console.log);",
output: "eval/check_local_by_default.out",
http_server: true,
});
itest!(check_local_by_default2 {
args: "eval --quiet import('./eval/check_local_by_default2.ts').then(console.log);",
output: "eval/check_local_by_default2.out",
http_server: true,
});
}

50
cli/tests/flags_tests.rs Normal file
View file

@ -0,0 +1,50 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
use test_util as util;
mod flags {
use super::*;
#[test]
fn help_flag() {
let status = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("--help")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
#[test]
fn version_short_flag() {
let status = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("-V")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
#[test]
fn version_long_flag() {
let status = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("--version")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
itest!(types {
args: "types",
output: "types/types.out",
});
}

257
cli/tests/fmt_tests.rs Normal file
View file

@ -0,0 +1,257 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
use test_util as util;
use test_util::TempDir;
mod fmt {
use super::*;
#[test]
fn fmt_test() {
let t = TempDir::new();
let testdata_fmt_dir = util::testdata_path().join("fmt");
let fixed_js = testdata_fmt_dir.join("badly_formatted_fixed.js");
let badly_formatted_original_js =
testdata_fmt_dir.join("badly_formatted.mjs");
let badly_formatted_js = t.path().join("badly_formatted.js");
let badly_formatted_js_str = badly_formatted_js.to_str().unwrap();
std::fs::copy(&badly_formatted_original_js, &badly_formatted_js).unwrap();
let fixed_md = testdata_fmt_dir.join("badly_formatted_fixed.md");
let badly_formatted_original_md =
testdata_fmt_dir.join("badly_formatted.md");
let badly_formatted_md = t.path().join("badly_formatted.md");
let badly_formatted_md_str = badly_formatted_md.to_str().unwrap();
std::fs::copy(&badly_formatted_original_md, &badly_formatted_md).unwrap();
let fixed_json = testdata_fmt_dir.join("badly_formatted_fixed.json");
let badly_formatted_original_json =
testdata_fmt_dir.join("badly_formatted.json");
let badly_formatted_json = t.path().join("badly_formatted.json");
let badly_formatted_json_str = badly_formatted_json.to_str().unwrap();
std::fs::copy(&badly_formatted_original_json, &badly_formatted_json)
.unwrap();
// First, check formatting by ignoring the badly formatted file.
let status = util::deno_cmd()
.current_dir(&testdata_fmt_dir)
.arg("fmt")
.arg(format!(
"--ignore={},{},{}",
badly_formatted_js_str,
badly_formatted_md_str,
badly_formatted_json_str
))
.arg("--check")
.arg(badly_formatted_js_str)
.arg(badly_formatted_md_str)
.arg(badly_formatted_json_str)
.spawn()
.unwrap()
.wait()
.unwrap();
// No target files found
assert!(!status.success());
// Check without ignore.
let status = util::deno_cmd()
.current_dir(&testdata_fmt_dir)
.arg("fmt")
.arg("--check")
.arg(badly_formatted_js_str)
.arg(badly_formatted_md_str)
.arg(badly_formatted_json_str)
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(!status.success());
// Format the source file.
let status = util::deno_cmd()
.current_dir(&testdata_fmt_dir)
.arg("fmt")
.arg(badly_formatted_js_str)
.arg(badly_formatted_md_str)
.arg(badly_formatted_json_str)
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let expected_js = std::fs::read_to_string(fixed_js).unwrap();
let expected_md = std::fs::read_to_string(fixed_md).unwrap();
let expected_json = std::fs::read_to_string(fixed_json).unwrap();
let actual_js = std::fs::read_to_string(badly_formatted_js).unwrap();
let actual_md = std::fs::read_to_string(badly_formatted_md).unwrap();
let actual_json = std::fs::read_to_string(badly_formatted_json).unwrap();
assert_eq!(expected_js, actual_js);
assert_eq!(expected_md, actual_md);
assert_eq!(expected_json, actual_json);
}
#[test]
fn fmt_stdin_error() {
use std::io::Write;
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("fmt")
.arg("-")
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap();
let stdin = deno.stdin.as_mut().unwrap();
let invalid_js = b"import { example }";
stdin.write_all(invalid_js).unwrap();
let output = deno.wait_with_output().unwrap();
// Error message might change. Just check stdout empty, stderr not.
assert!(output.stdout.is_empty());
assert!(!output.stderr.is_empty());
assert!(!output.status.success());
}
#[test]
fn fmt_ignore_unexplicit_files() {
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.env("NO_COLOR", "1")
.arg("fmt")
.arg("--check")
.arg("--ignore=./")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert_eq!(
String::from_utf8_lossy(&output.stderr),
"error: No target files found.\n"
);
}
#[test]
fn fmt_auto_ignore_git_and_node_modules() {
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::PathBuf;
fn create_bad_json(t: PathBuf) {
let bad_json_path = t.join("bad.json");
let mut bad_json_file = File::create(bad_json_path).unwrap();
writeln!(bad_json_file, "bad json").unwrap();
}
let temp_dir = TempDir::new();
let t = temp_dir.path().join("target");
let nest_git = t.join("nest").join(".git");
let git_dir = t.join(".git");
let nest_node_modules = t.join("nest").join("node_modules");
let node_modules_dir = t.join("node_modules");
create_dir_all(&nest_git).unwrap();
create_dir_all(&git_dir).unwrap();
create_dir_all(&nest_node_modules).unwrap();
create_dir_all(&node_modules_dir).unwrap();
create_bad_json(nest_git);
create_bad_json(git_dir);
create_bad_json(nest_node_modules);
create_bad_json(node_modules_dir);
let output = util::deno_cmd()
.current_dir(t)
.env("NO_COLOR", "1")
.arg("fmt")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert_eq!(
String::from_utf8_lossy(&output.stderr),
"error: No target files found.\n"
);
}
itest!(fmt_quiet_check_fmt_dir {
args: "fmt --check --quiet fmt/regular/",
output_str: Some(""),
exit_code: 0,
});
itest!(fmt_check_formatted_files {
args: "fmt --check fmt/regular/formatted1.js fmt/regular/formatted2.ts fmt/regular/formatted3.markdown fmt/regular/formatted4.jsonc",
output: "fmt/expected_fmt_check_formatted_files.out",
exit_code: 0,
});
itest!(fmt_check_ignore {
args: "fmt --check --ignore=fmt/regular/formatted1.js fmt/regular/",
output: "fmt/expected_fmt_check_ignore.out",
exit_code: 0,
});
itest!(fmt_check_parse_error {
args: "fmt --check fmt/parse_error/parse_error.ts",
output: "fmt/fmt_check_parse_error.out",
exit_code: 1,
});
itest!(fmt_stdin {
args: "fmt -",
input: Some("const a = 1\n"),
output_str: Some("const a = 1;\n"),
});
itest!(fmt_stdin_markdown {
args: "fmt --ext=md -",
input: Some("# Hello Markdown\n```ts\nconsole.log( \"text\")\n```\n\n```cts\nconsole.log( 5 )\n```"),
output_str: Some("# Hello Markdown\n\n```ts\nconsole.log(\"text\");\n```\n\n```cts\nconsole.log(5);\n```\n"),
});
itest!(fmt_stdin_json {
args: "fmt --ext=json -",
input: Some("{ \"key\": \"value\"}"),
output_str: Some("{ \"key\": \"value\" }\n"),
});
itest!(fmt_stdin_check_formatted {
args: "fmt --check -",
input: Some("const a = 1;\n"),
output_str: Some(""),
});
itest!(fmt_stdin_check_not_formatted {
args: "fmt --check -",
input: Some("const a = 1\n"),
output_str: Some("Not formatted stdin\n"),
});
itest!(fmt_with_config {
args: "fmt --config fmt/with_config/deno.jsonc fmt/with_config/subdir",
output: "fmt/fmt_with_config.out",
});
itest!(fmt_with_config_default {
args: "fmt fmt/with_config/subdir",
output: "fmt/fmt_with_config.out",
});
// Check if CLI flags take precedence
itest!(fmt_with_config_and_flags {
args: "fmt --config fmt/with_config/deno.jsonc --ignore=fmt/with_config/subdir/a.ts,fmt/with_config/subdir/b.ts",
output: "fmt/fmt_with_config_and_flags.out",
});
itest!(fmt_with_malformed_config {
args: "fmt --config fmt/deno.malformed.jsonc",
output: "fmt/fmt_with_malformed_config.out",
exit_code: 1,
});
itest!(fmt_with_malformed_config2 {
args: "fmt --config fmt/deno.malformed2.jsonc",
output: "fmt/fmt_with_malformed_config2.out",
exit_code: 1,
});
}

136
cli/tests/info_tests.rs Normal file
View file

@ -0,0 +1,136 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
mod integration;
use test_util as util;
use test_util::TempDir;
mod init {
use super::*;
#[test]
fn info_with_compiled_source() {
let _g = util::http_server();
let module_path = "http://127.0.0.1:4545/run/048_media_types_jsx.ts";
let t = TempDir::new();
let mut deno = util::deno_cmd()
.env("DENO_DIR", t.path())
.current_dir(util::testdata_path())
.arg("cache")
.arg(module_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
let output = util::deno_cmd()
.env("DENO_DIR", t.path())
.env("NO_COLOR", "1")
.current_dir(util::testdata_path())
.arg("info")
.arg(module_path)
.output()
.unwrap();
let str_output = std::str::from_utf8(&output.stdout).unwrap().trim();
eprintln!("{}", str_output);
// check the output of the test.ts program.
assert!(str_output.contains("emit: "));
assert_eq!(output.stderr, b"");
}
itest!(multiple_imports {
args: "info http://127.0.0.1:4545/run/019_media_types.ts",
output: "info/multiple_imports.out",
http_server: true,
});
itest!(info_ts_error {
args: "info info/031_info_ts_error.ts",
output: "info/031_info_ts_error.out",
});
itest!(info_flag {
args: "info",
output: "info/041_info_flag.out",
});
itest!(info_flag_location {
args: "info --location https://deno.land",
output: "info/041_info_flag_location.out",
});
itest!(info_json {
args: "info --json --unstable",
output: "info/info_json.out",
});
itest!(info_json_location {
args: "info --json --unstable --location https://deno.land",
output: "info/info_json_location.out",
});
itest!(info_flag_script_jsx {
args: "info http://127.0.0.1:4545/run/048_media_types_jsx.ts",
output: "info/049_info_flag_script_jsx.out",
http_server: true,
});
itest!(json_file {
args: "info --quiet --json --unstable info/json_output/main.ts",
output: "info/json_output/main.out",
exit_code: 0,
});
itest!(import_map_info {
args:
"info --quiet --import-map=import_maps/import_map.json import_maps/test.ts",
output: "info/065_import_map_info.out",
});
itest!(info_json_deps_order {
args: "info --unstable --json info/076_info_json_deps_order.ts",
output: "info/076_info_json_deps_order.out",
});
itest!(info_missing_module {
args: "info info/error_009_missing_js_module.js",
output: "info/info_missing_module.out",
});
itest!(info_recursive_modules {
args: "info --quiet info/info_recursive_imports_test.ts",
output: "info/info_recursive_imports_test.out",
exit_code: 0,
});
itest!(info_type_import {
args: "info info/info_type_import.ts",
output: "info/info_type_import.out",
});
itest!(_054_info_local_imports {
args: "info --quiet run/005_more_imports.ts",
output: "info/054_info_local_imports.out",
exit_code: 0,
});
// Tests for AssertionError where "data" is unexpectedly null when
// a file contains only triple slash references (#11196)
itest!(data_null_error {
args: "info info/data_null_error/mod.ts",
output: "info/data_null_error/data_null_error.out",
});
itest!(types_header_direct {
args: "info --reload run/type_directives_01.ts",
output: "info/types_header.out",
http_server: true,
});
itest!(with_config_override {
args: "info info/with_config/test.ts --config info/with_config/deno-override.json --import-map info/with_config/import_map.json",
output: "info/with_config/with_config.out",
});
}

163
cli/tests/init_tests.rs Normal file
View file

@ -0,0 +1,163 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::process::Stdio;
use test_util as util;
use test_util::TempDir;
use util::assert_contains;
mod init {
use super::*;
#[test]
fn init_subcommand_without_dir() {
let temp_dir = TempDir::new();
let cwd = temp_dir.path();
let deno_dir = util::new_deno_dir();
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.arg("init")
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert_contains!(stderr, "Project initialized");
assert!(!stderr.contains("cd"));
assert_contains!(stderr, "deno run main.ts");
assert_contains!(stderr, "deno test");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("run")
.arg("main.ts")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Add 2 + 3 = 5\n");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("test")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert_contains!(stdout, "1 passed");
}
#[test]
fn init_subcommand_with_dir_arg() {
let temp_dir = TempDir::new();
let cwd = temp_dir.path();
let deno_dir = util::new_deno_dir();
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.arg("init")
.arg("my_dir")
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert_contains!(stderr, "Project initialized");
assert_contains!(stderr, "cd my_dir");
assert_contains!(stderr, "deno run main.ts");
assert_contains!(stderr, "deno test");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("run")
.arg("my_dir/main.ts")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Add 2 + 3 = 5\n");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("test")
.arg("my_dir/main_test.ts")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert_contains!(stdout, "1 passed");
}
#[test]
fn init_subcommand_with_quiet_arg() {
let temp_dir = TempDir::new();
let cwd = temp_dir.path();
let deno_dir = util::new_deno_dir();
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.arg("init")
.arg("--quiet")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert_eq!(stdout, "");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("run")
.arg("main.ts")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Add 2 + 3 = 5\n");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("test")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert_contains!(stdout, "1 passed");
}
}

1323
cli/tests/inspector_tests.rs Normal file

File diff suppressed because it is too large Load diff

220
cli/tests/install_tests.rs Normal file
View file

@ -0,0 +1,220 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::fs;
use std::process::Command;
use test_util as util;
use test_util::assert_contains;
use test_util::assert_ends_with;
use test_util::TempDir;
mod install {
use super::*;
#[test]
fn install_basic() {
let _guard = util::http_server();
let temp_dir = TempDir::new();
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
let status = util::deno_cmd()
.current_dir(temp_dir.path())
.arg("install")
.arg("--check")
.arg("--name")
.arg("echo_test")
.arg("http://localhost:4545/echo.ts")
.envs([
("HOME", temp_dir_str.as_str()),
("USERPROFILE", temp_dir_str.as_str()),
("DENO_INSTALL_ROOT", ""),
])
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let mut file_path = temp_dir.path().join(".deno/bin/echo_test");
assert!(file_path.exists());
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
let content = fs::read_to_string(file_path).unwrap();
// ensure there's a trailing newline so the shell script can be
// more versatile.
assert_eq!(content.chars().last().unwrap(), '\n');
if cfg!(windows) {
assert_contains!(
content,
r#""run" "--check" "http://localhost:4545/echo.ts""#
);
} else {
assert_contains!(
content,
r#"run --check 'http://localhost:4545/echo.ts'"#
);
}
}
#[test]
fn install_custom_dir_env_var() {
let _guard = util::http_server();
let temp_dir = TempDir::new();
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
let status = util::deno_cmd()
.current_dir(util::root_path()) // different cwd
.arg("install")
.arg("--check")
.arg("--name")
.arg("echo_test")
.arg("http://localhost:4545/echo.ts")
.envs([
("HOME", temp_dir_str.as_str()),
("USERPROFILE", temp_dir_str.as_str()),
("DENO_INSTALL_ROOT", temp_dir_str.as_str()),
])
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let mut file_path = temp_dir.path().join("bin/echo_test");
assert!(file_path.exists());
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
let content = fs::read_to_string(file_path).unwrap();
if cfg!(windows) {
assert_contains!(
content,
r#""run" "--check" "http://localhost:4545/echo.ts""#
);
} else {
assert_contains!(
content,
r#"run --check 'http://localhost:4545/echo.ts'"#
);
}
}
#[test]
fn installer_test_local_module_run() {
let temp_dir = TempDir::new();
let bin_dir = temp_dir.path().join("bin");
std::fs::create_dir(&bin_dir).unwrap();
let status = util::deno_cmd()
.current_dir(util::root_path())
.arg("install")
.arg("--name")
.arg("echo_test")
.arg("--root")
.arg(temp_dir.path())
.arg(util::testdata_path().join("echo.ts"))
.arg("hello")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
assert!(file_path.exists());
// NOTE: using file_path here instead of exec_name, because tests
// shouldn't mess with user's PATH env variable
let output = Command::new(file_path)
.current_dir(temp_dir.path())
.arg("foo")
.env("PATH", util::target_dir())
.output()
.unwrap();
let stdout_str = std::str::from_utf8(&output.stdout).unwrap().trim();
assert_ends_with!(stdout_str, "hello, foo");
}
#[test]
fn installer_test_remote_module_run() {
let _g = util::http_server();
let temp_dir = TempDir::new();
let bin_dir = temp_dir.path().join("bin");
std::fs::create_dir(&bin_dir).unwrap();
let status = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("install")
.arg("--name")
.arg("echo_test")
.arg("--root")
.arg(temp_dir.path())
.arg("http://localhost:4545/echo.ts")
.arg("hello")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
assert!(file_path.exists());
let output = Command::new(file_path)
.current_dir(temp_dir.path())
.arg("foo")
.env("PATH", util::target_dir())
.output()
.unwrap();
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"hello, foo",
);
}
#[test]
fn check_local_by_default() {
let _guard = util::http_server();
let temp_dir = TempDir::new();
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
let status = util::deno_cmd()
.current_dir(temp_dir.path())
.arg("install")
.arg(util::testdata_path().join("./install/check_local_by_default.ts"))
.envs([
("HOME", temp_dir_str.as_str()),
("USERPROFILE", temp_dir_str.as_str()),
("DENO_INSTALL_ROOT", ""),
])
.status()
.unwrap();
assert!(status.success());
}
#[test]
fn check_local_by_default2() {
let _guard = util::http_server();
let temp_dir = TempDir::new();
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
let status = util::deno_cmd()
.current_dir(temp_dir.path())
.arg("install")
.arg(util::testdata_path().join("./install/check_local_by_default2.ts"))
.envs([
("HOME", temp_dir_str.as_str()),
("NO_COLOR", "1"),
("USERPROFILE", temp_dir_str.as_str()),
("DENO_INSTALL_ROOT", ""),
])
.status()
.unwrap();
assert!(status.success());
}
}

View file

@ -1,195 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
use deno_core::url::Url;
use test_util as util;
itest!(overloads {
args: "bench bench/overloads.ts",
exit_code: 0,
output: "bench/overloads.out",
});
itest!(meta {
args: "bench bench/meta.ts",
exit_code: 0,
output: "bench/meta.out",
});
itest!(pass {
args: "bench bench/pass.ts",
exit_code: 0,
output: "bench/pass.out",
});
itest!(ignore {
args: "bench bench/ignore.ts",
exit_code: 0,
output: "bench/ignore.out",
});
itest!(ignore_permissions {
args: "bench bench/ignore_permissions.ts",
exit_code: 0,
output: "bench/ignore_permissions.out",
});
itest!(fail {
args: "bench bench/fail.ts",
exit_code: 1,
output: "bench/fail.out",
});
itest!(collect {
args: "bench --ignore=bench/collect/ignore bench/collect",
exit_code: 0,
output: "bench/collect.out",
});
itest!(load_unload {
args: "bench bench/load_unload.ts",
exit_code: 0,
output: "bench/load_unload.out",
});
itest!(interval {
args: "bench bench/interval.ts",
exit_code: 0,
output: "bench/interval.out",
});
itest!(quiet {
args: "bench --quiet bench/quiet.ts",
exit_code: 0,
output: "bench/quiet.out",
});
itest!(only {
args: "bench bench/only.ts",
exit_code: 1,
output: "bench/only.out",
});
itest!(multifile_summary {
args: "bench bench/group_baseline.ts bench/pass.ts bench/group_baseline.ts",
exit_code: 0,
output: "bench/multifile_summary.out",
});
itest!(no_check {
args: "bench --no-check bench/no_check.ts",
exit_code: 1,
output: "bench/no_check.out",
});
itest!(allow_all {
args: "bench --allow-all bench/allow_all.ts",
exit_code: 0,
output: "bench/allow_all.out",
});
itest!(allow_none {
args: "bench bench/allow_none.ts",
exit_code: 1,
output: "bench/allow_none.out",
});
itest!(exit_sanitizer {
args: "bench bench/exit_sanitizer.ts",
output: "bench/exit_sanitizer.out",
exit_code: 1,
});
itest!(clear_timeout {
args: "bench bench/clear_timeout.ts",
exit_code: 0,
output: "bench/clear_timeout.out",
});
itest!(finally_timeout {
args: "bench bench/finally_timeout.ts",
exit_code: 1,
output: "bench/finally_timeout.out",
});
itest!(group_baseline {
args: "bench bench/group_baseline.ts",
exit_code: 0,
output: "bench/group_baseline.out",
});
itest!(unresolved_promise {
args: "bench bench/unresolved_promise.ts",
exit_code: 1,
output: "bench/unresolved_promise.out",
});
itest!(unhandled_rejection {
args: "bench bench/unhandled_rejection.ts",
exit_code: 1,
output: "bench/unhandled_rejection.out",
});
itest!(filter {
args: "bench --filter=foo bench/filter",
exit_code: 0,
output: "bench/filter.out",
});
itest!(no_prompt_by_default {
args: "bench --quiet bench/no_prompt_by_default.ts",
exit_code: 1,
output: "bench/no_prompt_by_default.out",
});
itest!(no_prompt_with_denied_perms {
args: "bench --quiet --allow-read bench/no_prompt_with_denied_perms.ts",
exit_code: 1,
output: "bench/no_prompt_with_denied_perms.out",
});
itest!(check_local_by_default {
args: "bench --quiet bench/check_local_by_default.ts",
output: "bench/check_local_by_default.out",
http_server: true,
});
itest!(check_local_by_default2 {
args: "bench --quiet bench/check_local_by_default2.ts",
output: "bench/check_local_by_default2.out",
http_server: true,
exit_code: 1,
});
#[test]
fn recursive_permissions_pledge() {
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bench")
.arg("bench/recursive_permissions_pledge.js")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert!(String::from_utf8(output.stderr).unwrap().contains(
"pledge test permissions called before restoring previous pledge"
));
}
#[test]
fn file_protocol() {
let file_url =
Url::from_file_path(util::testdata_path().join("bench/file_protocol.ts"))
.unwrap()
.to_string();
(util::CheckOutputIntegrationTest {
args_vec: vec!["bench", &file_url],
exit_code: 0,
output: "bench/file_protocol.out",
..Default::default()
})
.run();
}

View file

@ -1,468 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
use test_util as util;
use test_util::assert_contains;
use test_util::assert_ends_with;
use test_util::TempDir;
#[test]
fn bundle_exports() {
// First we have to generate a bundle of some module that has exports.
let mod1 = util::testdata_path().join("subdir/mod1.ts");
assert!(mod1.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod1.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod1)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./mod1.bundle.js\";
printHello3(); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_exports_no_check() {
// First we have to generate a bundle of some module that has exports.
let mod1 = util::testdata_path().join("subdir/mod1.ts");
assert!(mod1.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod1.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod1)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./mod1.bundle.js\";
printHello3(); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_circular() {
// First we have to generate a bundle of some module that has exports.
let circular1_path = util::testdata_path().join("subdir/circular1.ts");
assert!(circular1_path.is_file());
let t = TempDir::new();
let bundle_path = t.path().join("circular1.bundle.js");
// run this twice to ensure it works even when cached
for _ in 0..2 {
let mut deno = util::deno_cmd_with_deno_dir(&t)
.current_dir(util::testdata_path())
.arg("bundle")
.arg(&circular1_path)
.arg(&bundle_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle_path.is_file());
}
let output = util::deno_cmd_with_deno_dir(&t)
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle_path)
.output()
.unwrap();
// check the output of the the bundle program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"f2\nf1",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_single_module() {
// First we have to generate a bundle of some module that has exports.
let single_module = util::testdata_path().join("subdir/single_module.ts");
assert!(single_module.is_file());
let t = TempDir::new();
let bundle = t.path().join("single_module.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(single_module)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle)
.output()
.unwrap();
// check the output of the the bundle program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello world!",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_tla() {
// First we have to generate a bundle of some module that has exports.
let tla_import = util::testdata_path().join("subdir/tla.ts");
assert!(tla_import.is_file());
let t = TempDir::new();
let bundle = t.path().join("tla.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(tla_import)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { foo } from \"./tla.bundle.js\";
console.log(foo); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_js() {
// First we have to generate a bundle of some module that has exports.
let mod6 = util::testdata_path().join("subdir/mod6.js");
assert!(mod6.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod6.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod6)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle)
.output()
.unwrap();
// check that nothing went to stderr
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_dynamic_import() {
let _g = util::http_server();
let dynamic_import = util::testdata_path().join("bundle/dynamic_import.ts");
assert!(dynamic_import.is_file());
let t = TempDir::new();
let output_path = t.path().join("bundle_dynamic_import.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(dynamic_import)
.arg(&output_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(output_path.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--allow-net")
.arg("--quiet")
.arg(&output_path)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_import_map() {
let import = util::testdata_path().join("bundle/import_map/main.ts");
let import_map_path =
util::testdata_path().join("bundle/import_map/import_map.json");
assert!(import.is_file());
let t = TempDir::new();
let output_path = t.path().join("import_map.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg("--import-map")
.arg(import_map_path)
.arg(import)
.arg(&output_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(output_path.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./import_map.bundle.js\";
printHello3(); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--check")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_import_map_no_check() {
let import = util::testdata_path().join("bundle/import_map/main.ts");
let import_map_path =
util::testdata_path().join("bundle/import_map/import_map.json");
assert!(import.is_file());
let t = TempDir::new();
let output_path = t.path().join("import_map.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg("--import-map")
.arg(import_map_path)
.arg(import)
.arg(&output_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(output_path.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./import_map.bundle.js\";
printHello3(); ",
)
.unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&test)
.output()
.unwrap();
// check the output of the test.ts program.
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"Hello",
);
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_json_module() {
// First we have to generate a bundle of some module that has exports.
let mod7 = util::testdata_path().join("subdir/mod7.js");
assert!(mod7.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod7.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod7)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle)
.output()
.unwrap();
// check that nothing went to stderr
assert_eq!(output.stderr, b"");
// ensure the output looks right
assert_contains!(String::from_utf8(output.stdout).unwrap(), "with space",);
}
#[test]
fn bundle_json_module_escape_sub() {
// First we have to generate a bundle of some module that has exports.
let mod8 = util::testdata_path().join("subdir/mod8.js");
assert!(mod8.is_file());
let t = TempDir::new();
let bundle = t.path().join("mod8.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg(mod8)
.arg(&bundle)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
assert!(bundle.is_file());
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg(&bundle)
.output()
.unwrap();
// check that nothing went to stderr
assert_eq!(output.stderr, b"");
// make sure the output looks right and the escapes were effective
assert_contains!(
String::from_utf8(output.stdout).unwrap(),
"${globalThis}`and string literal`",
);
}
itest!(lockfile_check_error {
args: "bundle --lock=bundle/lockfile/check_error.json http://127.0.0.1:4545/subdir/mod1.ts",
output: "bundle/lockfile/check_error.out",
exit_code: 10,
http_server: true,
});
itest!(bundle {
args: "bundle subdir/mod1.ts",
output: "bundle/bundle.test.out",
});
itest!(bundle_jsx {
args: "bundle run/jsx_import_from_ts.ts",
output: "bundle/jsx.out",
});
itest!(error_bundle_with_bare_import {
args: "bundle bundle/bare_imports/error_with_bare_import.ts",
output: "bundle/bare_imports/error_with_bare_import.ts.out",
exit_code: 1,
});
itest!(ts_decorators_bundle {
args: "bundle bundle/decorators/ts_decorators.ts",
output: "bundle/decorators/ts_decorators.out",
});
itest!(bundle_export_specifier_with_alias {
args: "bundle bundle/file_tests-fixture16.ts",
output: "bundle/fixture16.out",
});
itest!(bundle_ignore_directives {
args: "bundle subdir/mod1.ts",
output: "bundle/ignore_directives.test.out",
});
itest!(check_local_by_default_no_errors {
args: "bundle --quiet bundle/check_local_by_default/no_errors.ts",
output: "bundle/check_local_by_default/no_errors.out",
http_server: true,
});
itest!(check_local_by_default_type_error {
args: "bundle --quiet bundle/check_local_by_default/type_error.ts",
output: "bundle/check_local_by_default/type_error.out",
http_server: true,
exit_code: 1,
});

View file

@ -1,99 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
itest!(_036_import_map_fetch {
args:
"cache --quiet --reload --import-map=import_maps/import_map.json import_maps/test.ts",
output: "cache/036_import_map_fetch.out",
});
itest!(_037_fetch_multiple {
args: "cache --reload --check=all run/fetch/test.ts run/fetch/other.ts",
http_server: true,
output: "cache/037_fetch_multiple.out",
});
itest!(_095_cache_with_bare_import {
args: "cache cache/095_cache_with_bare_import.ts",
output: "cache/095_cache_with_bare_import.ts.out",
exit_code: 1,
});
itest!(cache_extensionless {
args: "cache --reload --check=all http://localhost:4545/subdir/no_js_ext",
output: "cache/cache_extensionless.out",
http_server: true,
});
itest!(cache_random_extension {
args:
"cache --reload --check=all http://localhost:4545/subdir/no_js_ext@1.0.0",
output: "cache/cache_random_extension.out",
http_server: true,
});
itest!(performance_stats {
args: "cache --reload --check=all --log-level debug run/002_hello.ts",
output: "cache/performance_stats.out",
});
itest!(redirect_cache {
http_server: true,
args:
"cache --reload --check=all http://localhost:4548/subdir/redirects/a.ts",
output: "cache/redirect_cache.out",
});
itest!(ignore_require {
args: "cache --reload --no-check cache/ignore_require.js",
output_str: Some(""),
exit_code: 0,
});
// This test only runs on linux, because it hardcodes the XDG_CACHE_HOME env var
// which is only used on linux.
#[cfg(target_os = "linux")]
#[test]
fn relative_home_dir() {
use test_util as util;
use test_util::TempDir;
let deno_dir = TempDir::new_in(&util::testdata_path());
let path = deno_dir.path().strip_prefix(util::testdata_path()).unwrap();
let mut deno_cmd = util::deno_cmd();
let output = deno_cmd
.current_dir(util::testdata_path())
.env("XDG_CACHE_HOME", path)
.env_remove("HOME")
.env_remove("DENO_DIR")
.arg("cache")
.arg("--reload")
.arg("--no-check")
.arg("run/002_hello.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"");
}
itest!(check_local_by_default {
args: "cache --quiet cache/check_local_by_default.ts",
output: "cache/check_local_by_default.out",
http_server: true,
});
itest!(check_local_by_default2 {
args: "cache --quiet cache/check_local_by_default2.ts",
output: "cache/check_local_by_default2.out",
http_server: true,
});
itest!(json_import {
// should not error
args: "cache --quiet cache/json_import/main.ts",
});

View file

@ -1,316 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
use deno_runtime::deno_net::ops_tls::TlsStream;
use deno_runtime::deno_tls::rustls;
use deno_runtime::deno_tls::rustls_pemfile;
use std::io::BufReader;
use std::io::Cursor;
use std::io::Read;
use std::process::Command;
use std::sync::Arc;
use test_util as util;
use test_util::TempDir;
use tokio::task::LocalSet;
itest_flaky!(cafile_url_imports {
args: "run --quiet --reload --cert tls/RootCA.pem cert/cafile_url_imports.ts",
output: "cert/cafile_url_imports.ts.out",
http_server: true,
});
itest_flaky!(cafile_ts_fetch {
args:
"run --quiet --reload --allow-net --cert tls/RootCA.pem cert/cafile_ts_fetch.ts",
output: "cert/cafile_ts_fetch.ts.out",
http_server: true,
});
itest_flaky!(cafile_eval {
args: "eval --cert tls/RootCA.pem fetch('https://localhost:5545/cert/cafile_ts_fetch.ts.out').then(r=>r.text()).then(t=>console.log(t.trimEnd()))",
output: "cert/cafile_ts_fetch.ts.out",
http_server: true,
});
itest_flaky!(cafile_info {
args:
"info --quiet --cert tls/RootCA.pem https://localhost:5545/cert/cafile_info.ts",
output: "cert/cafile_info.ts.out",
http_server: true,
});
itest_flaky!(cafile_url_imports_unsafe_ssl {
args: "run --quiet --reload --unsafely-ignore-certificate-errors=localhost cert/cafile_url_imports.ts",
output: "cert/cafile_url_imports_unsafe_ssl.ts.out",
http_server: true,
});
itest_flaky!(cafile_ts_fetch_unsafe_ssl {
args:
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors cert/cafile_ts_fetch.ts",
output: "cert/cafile_ts_fetch_unsafe_ssl.ts.out",
http_server: true,
});
itest!(deno_land_unsafe_ssl {
args:
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=deno.land cert/deno_land_unsafe_ssl.ts",
output: "cert/deno_land_unsafe_ssl.ts.out",
});
itest!(ip_address_unsafe_ssl {
args:
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=1.1.1.1 cert/ip_address_unsafe_ssl.ts",
output: "cert/ip_address_unsafe_ssl.ts.out",
});
itest!(localhost_unsafe_ssl {
args:
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=deno.land cert/cafile_url_imports.ts",
output: "cert/localhost_unsafe_ssl.ts.out",
http_server: true,
exit_code: 1,
});
#[flaky_test::flaky_test]
fn cafile_env_fetch() {
use deno_core::url::Url;
let _g = util::http_server();
let deno_dir = TempDir::new();
let module_url =
Url::parse("https://localhost:5545/cert/cafile_url_imports.ts").unwrap();
let cafile = util::testdata_path().join("tls/RootCA.pem");
let output = Command::new(util::deno_exe_path())
.env("DENO_DIR", deno_dir.path())
.env("DENO_CERT", cafile)
.current_dir(util::testdata_path())
.arg("cache")
.arg(module_url.to_string())
.output()
.expect("Failed to spawn script");
assert!(output.status.success());
}
#[flaky_test::flaky_test]
fn cafile_fetch() {
use deno_core::url::Url;
let _g = util::http_server();
let deno_dir = TempDir::new();
let module_url =
Url::parse("http://localhost:4545/cert/cafile_url_imports.ts").unwrap();
let cafile = util::testdata_path().join("tls/RootCA.pem");
let output = Command::new(util::deno_exe_path())
.env("DENO_DIR", deno_dir.path())
.current_dir(util::testdata_path())
.arg("cache")
.arg("--cert")
.arg(cafile)
.arg(module_url.to_string())
.output()
.expect("Failed to spawn script");
assert!(output.status.success());
let out = std::str::from_utf8(&output.stdout).unwrap();
assert_eq!(out, "");
}
#[flaky_test::flaky_test]
fn cafile_install_remote_module() {
let _g = util::http_server();
let temp_dir = TempDir::new();
let bin_dir = temp_dir.path().join("bin");
std::fs::create_dir(&bin_dir).unwrap();
let deno_dir = TempDir::new();
let cafile = util::testdata_path().join("tls/RootCA.pem");
let install_output = Command::new(util::deno_exe_path())
.env("DENO_DIR", deno_dir.path())
.current_dir(util::testdata_path())
.arg("install")
.arg("--cert")
.arg(cafile)
.arg("--root")
.arg(temp_dir.path())
.arg("-n")
.arg("echo_test")
.arg("https://localhost:5545/echo.ts")
.output()
.expect("Failed to spawn script");
println!("{}", std::str::from_utf8(&install_output.stdout).unwrap());
eprintln!("{}", std::str::from_utf8(&install_output.stderr).unwrap());
assert!(install_output.status.success());
let mut echo_test_path = bin_dir.join("echo_test");
if cfg!(windows) {
echo_test_path = echo_test_path.with_extension("cmd");
}
assert!(echo_test_path.exists());
let output = Command::new(echo_test_path)
.current_dir(temp_dir.path())
.arg("foo")
.env("PATH", util::target_dir())
.output()
.expect("failed to spawn script");
let stdout = std::str::from_utf8(&output.stdout).unwrap().trim();
assert!(stdout.ends_with("foo"));
}
#[flaky_test::flaky_test]
fn cafile_bundle_remote_exports() {
let _g = util::http_server();
// First we have to generate a bundle of some remote module that has exports.
let mod1 = "https://localhost:5545/subdir/mod1.ts";
let cafile = util::testdata_path().join("tls/RootCA.pem");
let t = TempDir::new();
let bundle = t.path().join("mod1.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("bundle")
.arg("--cert")
.arg(cafile)
.arg(mod1)
.arg(&bundle)
.spawn()
.expect("failed to spawn script");
let status = deno.wait().expect("failed to wait for the child process");
assert!(status.success());
assert!(bundle.is_file());
// Now we try to use that bundle from another module.
let test = t.path().join("test.js");
std::fs::write(
&test,
"
import { printHello3 } from \"./mod1.bundle.js\";
printHello3(); ",
)
.expect("error writing file");
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--check")
.arg(&test)
.output()
.expect("failed to spawn script");
// check the output of the test.ts program.
assert!(std::str::from_utf8(&output.stdout)
.unwrap()
.trim()
.ends_with("Hello"));
assert_eq!(output.stderr, b"");
}
#[tokio::test]
async fn listen_tls_alpn() {
// TLS streams require the presence of an ambient local task set to gracefully
// close dropped connections in the background.
LocalSet::new()
.run_until(async {
let mut child = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--unstable")
.arg("--quiet")
.arg("--allow-net")
.arg("--allow-read")
.arg("./cert/listen_tls_alpn.ts")
.arg("4504")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();
let stdout = child.stdout.as_mut().unwrap();
let mut msg = [0; 5];
let read = stdout.read(&mut msg).unwrap();
assert_eq!(read, 5);
assert_eq!(&msg, b"READY");
let mut reader = &mut BufReader::new(Cursor::new(include_bytes!(
"../testdata/tls/RootCA.crt"
)));
let certs = rustls_pemfile::certs(&mut reader).unwrap();
let mut root_store = rustls::RootCertStore::empty();
root_store.add_parsable_certificates(&certs);
let mut cfg = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth();
cfg.alpn_protocols.push(b"foobar".to_vec());
let cfg = Arc::new(cfg);
let hostname = rustls::ServerName::try_from("localhost").unwrap();
let tcp_stream = tokio::net::TcpStream::connect("localhost:4504")
.await
.unwrap();
let mut tls_stream =
TlsStream::new_client_side(tcp_stream, cfg, hostname);
tls_stream.handshake().await.unwrap();
let (_, rustls_connection) = tls_stream.get_ref();
let alpn = rustls_connection.alpn_protocol().unwrap();
assert_eq!(alpn, b"foobar");
let status = child.wait().unwrap();
assert!(status.success());
})
.await;
}
#[tokio::test]
async fn listen_tls_alpn_fail() {
// TLS streams require the presence of an ambient local task set to gracefully
// close dropped connections in the background.
LocalSet::new()
.run_until(async {
let mut child = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("run")
.arg("--unstable")
.arg("--quiet")
.arg("--allow-net")
.arg("--allow-read")
.arg("./cert/listen_tls_alpn_fail.ts")
.arg("4505")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();
let stdout = child.stdout.as_mut().unwrap();
let mut msg = [0; 5];
let read = stdout.read(&mut msg).unwrap();
assert_eq!(read, 5);
assert_eq!(&msg, b"READY");
let mut reader = &mut BufReader::new(Cursor::new(include_bytes!(
"../testdata/tls/RootCA.crt"
)));
let certs = rustls_pemfile::certs(&mut reader).unwrap();
let mut root_store = rustls::RootCertStore::empty();
root_store.add_parsable_certificates(&certs);
let mut cfg = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth();
cfg.alpn_protocols.push(b"boofar".to_vec());
let cfg = Arc::new(cfg);
let hostname = rustls::ServerName::try_from("localhost").unwrap();
let tcp_stream = tokio::net::TcpStream::connect("localhost:4505")
.await
.unwrap();
let mut tls_stream =
TlsStream::new_client_side(tcp_stream, cfg, hostname);
tls_stream.handshake().await.unwrap_err();
let (_, rustls_connection) = tls_stream.get_ref();
assert!(rustls_connection.alpn_protocol().is_none());
let status = child.wait().unwrap();
assert!(status.success());
})
.await;
}

View file

@ -1,210 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::process::Command;
use std::process::Stdio;
use crate::itest;
use test_util as util;
use util::TempDir;
itest!(_095_check_with_bare_import {
args: "check cache/095_cache_with_bare_import.ts",
output: "cache/095_cache_with_bare_import.ts.out",
exit_code: 1,
});
itest!(check_extensionless {
args: "check --reload http://localhost:4545/subdir/no_js_ext",
output: "cache/cache_extensionless.out",
http_server: true,
});
itest!(check_random_extension {
args: "check --reload http://localhost:4545/subdir/no_js_ext@1.0.0",
output: "cache/cache_random_extension.out",
http_server: true,
});
itest!(check_all {
args: "check --quiet --remote check/check_all.ts",
output: "check/check_all.out",
http_server: true,
exit_code: 1,
});
itest!(check_all_local {
args: "check --quiet check/check_all.ts",
output_str: Some(""),
http_server: true,
});
itest!(module_detection_force {
args: "check --quiet check/module_detection_force/main.ts",
output_str: Some(""),
});
// Regression test for https://github.com/denoland/deno/issues/14937.
itest!(declaration_header_file_with_no_exports {
args: "check --quiet check/declaration_header_file_with_no_exports.ts",
output_str: Some(""),
});
itest!(check_npm_install_diagnostics {
args: "check --quiet check/npm_install_diagnostics/main.ts",
output: "check/npm_install_diagnostics/main.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
exit_code: 1,
});
itest!(check_export_equals_declaration_file {
args: "check --quiet check/export_equals_declaration_file/main.ts",
exit_code: 0,
});
#[test]
fn cache_switching_config_then_no_config() {
let deno_dir = util::new_deno_dir();
assert!(does_type_checking(&deno_dir, true));
assert!(does_type_checking(&deno_dir, false));
// should now not do type checking even when it changes
// configs because it previously did
assert!(!does_type_checking(&deno_dir, true));
assert!(!does_type_checking(&deno_dir, false));
fn does_type_checking(deno_dir: &util::TempDir, with_config: bool) -> bool {
let mut cmd = util::deno_cmd_with_deno_dir(deno_dir);
cmd
.current_dir(util::testdata_path())
.stderr(Stdio::piped())
.arg("check")
.arg("check/cache_config_on_off/main.ts");
if with_config {
cmd
.arg("--config")
.arg("check/cache_config_on_off/deno.json");
}
let output = cmd.spawn().unwrap().wait_with_output().unwrap();
assert!(output.status.success());
let stderr = std::str::from_utf8(&output.stderr).unwrap();
stderr.contains("Check")
}
}
#[test]
fn reload_flag() {
// should do type checking whenever someone specifies --reload
let deno_dir = util::new_deno_dir();
assert!(does_type_checking(&deno_dir, false));
assert!(!does_type_checking(&deno_dir, false));
assert!(does_type_checking(&deno_dir, true));
assert!(does_type_checking(&deno_dir, true));
assert!(!does_type_checking(&deno_dir, false));
fn does_type_checking(deno_dir: &util::TempDir, reload: bool) -> bool {
let mut cmd = util::deno_cmd_with_deno_dir(deno_dir);
cmd
.current_dir(util::testdata_path())
.stderr(Stdio::piped())
.arg("check")
.arg("check/cache_config_on_off/main.ts");
if reload {
cmd.arg("--reload");
}
let output = cmd.spawn().unwrap().wait_with_output().unwrap();
assert!(output.status.success());
let stderr = std::str::from_utf8(&output.stderr).unwrap();
stderr.contains("Check")
}
}
#[test]
fn typecheck_declarations_ns() {
let output = util::deno_cmd()
.arg("test")
.arg("--doc")
.arg(util::root_path().join("cli/tsc/dts/lib.deno.ns.d.ts"))
.output()
.unwrap();
println!("stdout: {}", String::from_utf8(output.stdout).unwrap());
println!("stderr: {}", String::from_utf8(output.stderr).unwrap());
assert!(output.status.success());
}
#[test]
fn typecheck_declarations_unstable() {
let output = util::deno_cmd()
.arg("test")
.arg("--doc")
.arg("--unstable")
.arg(util::root_path().join("cli/tsc/dts/lib.deno.unstable.d.ts"))
.output()
.unwrap();
println!("stdout: {}", String::from_utf8(output.stdout).unwrap());
println!("stderr: {}", String::from_utf8(output.stderr).unwrap());
assert!(output.status.success());
}
#[test]
fn typecheck_core() {
let deno_dir = TempDir::new();
let test_file = deno_dir.path().join("test_deno_core_types.ts");
std::fs::write(
&test_file,
format!(
"import \"{}\";",
deno_core::resolve_path(
util::root_path()
.join("core/lib.deno_core.d.ts")
.to_str()
.unwrap()
)
.unwrap()
),
)
.unwrap();
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.arg("run")
.arg(test_file.to_str().unwrap())
.output()
.unwrap();
println!("stdout: {}", String::from_utf8(output.stdout).unwrap());
println!("stderr: {}", String::from_utf8(output.stderr).unwrap());
assert!(output.status.success());
}
#[test]
fn ts_no_recheck_on_redirect() {
let deno_dir = util::new_deno_dir();
let e = util::deno_exe_path();
let redirect_ts = util::testdata_path().join("run/017_import_redirect.ts");
assert!(redirect_ts.is_file());
let mut cmd = Command::new(e.clone());
cmd.env("DENO_DIR", deno_dir.path());
let mut initial = cmd
.current_dir(util::testdata_path())
.arg("run")
.arg("--check")
.arg(redirect_ts.clone())
.spawn()
.expect("failed to span script");
let status_initial =
initial.wait().expect("failed to wait for child process");
assert!(status_initial.success());
let mut cmd = Command::new(e);
cmd.env("DENO_DIR", deno_dir.path());
let output = cmd
.current_dir(util::testdata_path())
.arg("run")
.arg("--check")
.arg(redirect_ts)
.output()
.expect("failed to spawn script");
assert!(std::str::from_utf8(&output.stderr).unwrap().is_empty());
}

View file

@ -1,533 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::fs::File;
use std::process::Command;
use test_util as util;
use test_util::TempDir;
#[test]
fn compile() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("welcome.exe")
} else {
dir.path().join("welcome")
};
// try this twice to ensure it works with the cache
for _ in 0..2 {
let output = util::deno_cmd_with_deno_dir(&dir)
.current_dir(util::root_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./test_util/std/examples/welcome.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(&exe)
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, "Welcome to Deno!\n".as_bytes());
}
}
#[test]
fn standalone_args() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("args.exe")
} else {
dir.path().join("args")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.arg("a")
.arg("b")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.arg("foo")
.arg("--bar")
.arg("--unstable")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"a\nb\nfoo\n--bar\n--unstable\n");
}
#[test]
fn standalone_error() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("error.exe")
} else {
dir.path().join("error")
};
let testdata_path = util::testdata_path();
let output = util::deno_cmd()
.current_dir(&testdata_path)
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_error.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.env("NO_COLOR", "1")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert_eq!(output.stdout, b"");
let stderr = String::from_utf8(output.stderr).unwrap();
let stderr = util::strip_ansi_codes(&stderr).to_string();
// On Windows, we cannot assert the file path (because '\').
// Instead we just check for relevant output.
assert!(stderr.contains("error: Uncaught Error: boom!"));
assert!(stderr.contains("throw new Error(\"boom!\");"));
assert!(stderr.contains("\n at boom (file://"));
assert!(stderr.contains("standalone_error.ts:2:11"));
assert!(stderr.contains("at foo (file://"));
assert!(stderr.contains("standalone_error.ts:5:5"));
assert!(stderr.contains("standalone_error.ts:7:1"));
}
#[test]
fn standalone_error_module_with_imports() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("error.exe")
} else {
dir.path().join("error")
};
let testdata_path = util::testdata_path();
let output = util::deno_cmd()
.current_dir(&testdata_path)
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_error_module_with_imports_1.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.env("NO_COLOR", "1")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
println!("{:#?}", &output);
assert_eq!(output.stdout, b"hello\n");
let stderr = String::from_utf8(output.stderr).unwrap();
let stderr = util::strip_ansi_codes(&stderr).to_string();
// On Windows, we cannot assert the file path (because '\').
// Instead we just check for relevant output.
assert!(stderr.contains("error: Uncaught Error: boom!"));
assert!(stderr.contains("throw new Error(\"boom!\");"));
assert!(stderr.contains("\n at file://"));
assert!(stderr.contains("standalone_error_module_with_imports_2.ts:2:7"));
}
#[test]
fn standalone_load_datauri() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("load_datauri.exe")
} else {
dir.path().join("load_datauri")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_import_datauri.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Hello Deno!\n");
}
// https://github.com/denoland/deno/issues/13704
#[test]
fn standalone_follow_redirects() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("follow_redirects.exe")
} else {
dir.path().join("follow_redirects")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_follow_redirects.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Hello\n");
}
#[test]
fn compile_with_file_exists_error() {
let dir = TempDir::new();
let output_path = if cfg!(windows) {
dir.path().join(r"args\")
} else {
dir.path().join("args/")
};
let file_path = dir.path().join("args");
File::create(&file_path).unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&output_path)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
let expected_stderr = format!(
concat!(
"Could not compile to file '{}' because its parent directory ",
"is an existing file. You can use the `--output <file-path>` flag to ",
"provide an alternative name.\n",
),
file_path.display(),
);
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains(&expected_stderr));
}
#[test]
fn compile_with_directory_exists_error() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("args.exe")
} else {
dir.path().join("args")
};
std::fs::create_dir(&exe).unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
let expected_stderr = format!(
concat!(
"Could not compile to file '{}' because a directory exists with ",
"the same name. You can use the `--output <file-path>` flag to ",
"provide an alternative name."
),
exe.display()
);
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains(&expected_stderr));
}
#[test]
fn compile_with_conflict_file_exists_error() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("args.exe")
} else {
dir.path().join("args")
};
std::fs::write(&exe, b"SHOULD NOT BE OVERWRITTEN").unwrap();
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
let expected_stderr = format!(
concat!(
"Could not compile to file '{}' because the file already exists ",
"and cannot be overwritten. Please delete the existing file or ",
"use the `--output <file-path` flag to provide an alternative name."
),
exe.display()
);
let stderr = String::from_utf8(output.stderr).unwrap();
dbg!(&stderr);
assert!(stderr.contains(&expected_stderr));
assert!(std::fs::read(&exe)
.unwrap()
.eq(b"SHOULD NOT BE OVERWRITTEN"));
}
#[test]
fn compile_and_overwrite_file() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("args.exe")
} else {
dir.path().join("args")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert!(&exe.exists());
let recompile_output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./compile/args.ts")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(recompile_output.status.success());
}
#[test]
fn standalone_runtime_flags() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("flags.exe")
} else {
dir.path().join("flags")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--allow-read")
.arg("--seed")
.arg("1")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_runtime_flags.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
let stdout_str = String::from_utf8(output.stdout).unwrap();
assert_eq!(util::strip_ansi_codes(&stdout_str), "0.147205063401058\n");
let stderr_str = String::from_utf8(output.stderr).unwrap();
assert!(util::strip_ansi_codes(&stderr_str)
.contains("PermissionDenied: Requires write access"));
}
#[test]
fn standalone_import_map() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("import_map.exe")
} else {
dir.path().join("import_map")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--allow-read")
.arg("--import-map")
.arg("compile/standalone_import_map.json")
.arg("--output")
.arg(&exe)
.arg("./compile/standalone_import_map.ts")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
}
#[test]
// https://github.com/denoland/deno/issues/12670
fn skip_rebundle() {
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("hello_world.exe")
} else {
dir.path().join("hello_world")
};
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg("./run/001_hello.js")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
//no "Bundle testdata_path/run/001_hello.js" in output
assert!(!String::from_utf8(output.stderr).unwrap().contains("Bundle"));
let output = Command::new(exe)
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, "Hello World\n".as_bytes());
}
#[test]
fn check_local_by_default() {
let _guard = util::http_server();
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("welcome.exe")
} else {
dir.path().join("welcome")
};
let status = util::deno_cmd()
.current_dir(util::root_path())
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg(util::testdata_path().join("./compile/check_local_by_default.ts"))
.status()
.unwrap();
assert!(status.success());
}
#[test]
fn check_local_by_default2() {
let _guard = util::http_server();
let dir = TempDir::new();
let exe = if cfg!(windows) {
dir.path().join("welcome.exe")
} else {
dir.path().join("welcome")
};
let output = util::deno_cmd()
.current_dir(util::root_path())
.env("NO_COLOR", "1")
.arg("compile")
.arg("--unstable")
.arg("--output")
.arg(&exe)
.arg(util::testdata_path().join("./compile/check_local_by_default2.ts"))
.output()
.unwrap();
assert!(!output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stdout.is_empty());
assert!(stderr.contains(
r#"error: TS2322 [ERROR]: Type '12' is not assignable to type '"b"'."#
));
}

View file

@ -1,315 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::fs;
use test_util as util;
use test_util::TempDir;
#[test]
fn branch() {
run_coverage_text("branch", "ts");
}
#[test]
fn complex() {
run_coverage_text("complex", "ts");
}
#[test]
fn final_blankline() {
run_coverage_text("final_blankline", "js");
}
#[test]
fn no_snaps() {
no_snaps_included("no_snaps_included", "ts");
}
fn run_coverage_text(test_name: &str, extension: &str) {
let deno_dir = TempDir::new();
let tempdir = TempDir::new();
let tempdir = tempdir.path().join("cov");
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("test")
.arg("-A")
.arg("--quiet")
.arg("--unstable")
.arg(format!("--coverage={}", tempdir.to_str().unwrap()))
.arg(format!("coverage/{}_test.{}", test_name, extension))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.status()
.unwrap();
assert!(status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--unstable")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.unwrap();
// Verify there's no "Check" being printed
assert!(output.stderr.is_empty());
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join(format!("coverage/{}_expected.out", test_name)),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--quiet")
.arg("--unstable")
.arg("--lcov")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.output()
.unwrap();
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join(format!("coverage/{}_expected.lcov", test_name)),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
}
#[test]
fn multifile_coverage() {
let deno_dir = TempDir::new();
let tempdir = TempDir::new();
let tempdir = tempdir.path().join("cov");
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("test")
.arg("--quiet")
.arg("--unstable")
.arg(format!("--coverage={}", tempdir.to_str().unwrap()))
.arg("coverage/multifile/")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.status()
.unwrap();
assert!(status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--unstable")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.unwrap();
// Verify there's no "Check" being printed
assert!(output.stderr.is_empty());
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/multifile/expected.out"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--quiet")
.arg("--unstable")
.arg("--lcov")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.output()
.unwrap();
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/multifile/expected.lcov"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
}
fn no_snaps_included(test_name: &str, extension: &str) {
let deno_dir = TempDir::new();
let tempdir = TempDir::new();
let tempdir = tempdir.path().join("cov");
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("test")
.arg("--quiet")
.arg("--unstable")
.arg("--allow-read")
.arg(format!("--coverage={}", tempdir.to_str().unwrap()))
.arg(format!(
"coverage/no_snaps_included/{}_test.{}",
test_name, extension
))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.status()
.unwrap();
assert!(status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--unstable")
.arg("--include=no_snaps_included.ts")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.unwrap();
// Verify there's no "Check" being printed
assert!(output.stderr.is_empty());
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/no_snaps_included/expected.out"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
}
#[test]
fn no_transpiled_lines() {
let deno_dir = TempDir::new();
let tempdir = TempDir::new();
let tempdir = tempdir.path().join("cov");
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("test")
.arg("--quiet")
.arg(format!("--coverage={}", tempdir.to_str().unwrap()))
.arg("coverage/no_transpiled_lines/")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.status()
.unwrap();
assert!(status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--include=no_transpiled_lines/index.ts")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.unwrap();
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/no_transpiled_lines/expected.out"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("coverage")
.arg("--lcov")
.arg("--include=no_transpiled_lines/index.ts")
.arg(format!("{}/", tempdir.to_str().unwrap()))
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.output()
.unwrap();
let actual =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap())
.to_string();
let expected = fs::read_to_string(
util::testdata_path().join("coverage/no_transpiled_lines/expected.lcov"),
)
.unwrap();
if !util::wildcard_match(&expected, &actual) {
println!("OUTPUT\n{}\nOUTPUT", actual);
println!("EXPECTED\n{}\nEXPECTED", expected);
panic!("pattern match failed");
}
assert!(output.status.success());
}

View file

@ -1,74 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use test_util as util;
use test_util::TempDir;
use util::assert_contains;
use crate::itest;
itest!(deno_doc_builtin {
args: "doc",
output: "doc/deno_doc_builtin.out",
});
#[test]
fn deno_doc() {
let dir = TempDir::new();
// try this twice to ensure it works with the cache
for _ in 0..2 {
let output = util::deno_cmd_with_deno_dir(&dir)
.current_dir(util::testdata_path())
.arg("doc")
.arg("doc/deno_doc.ts")
.env("NO_COLOR", "1")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_contains!(
std::str::from_utf8(&output.stdout).unwrap(),
"function foo"
);
}
}
itest!(deno_doc_import_map {
args: "doc --unstable --import-map=doc/import_map.json doc/use_import_map.js",
output: "doc/use_import_map.out",
});
itest!(deno_doc_types_hint {
args: "doc doc/types_hint.ts",
output: "doc/types_hint.out",
});
itest!(deno_doc_types_ref {
args: "doc doc/types_ref.js",
output: "doc/types_ref.out",
});
itest!(deno_doc_types_header {
args: "doc --reload doc/types_header.ts",
output: "doc/types_header.out",
http_server: true,
});
itest!(_060_deno_doc_displays_all_overloads_in_details_view {
args:
"doc doc/060_deno_doc_displays_all_overloads_in_details_view.ts NS.test",
output: "doc/060_deno_doc_displays_all_overloads_in_details_view.ts.out",
});
itest!(deno_doc_types_header_direct {
args: "doc --reload http://127.0.0.1:4545/xTypeScriptTypes.js",
output: "doc/types_header.out",
http_server: true,
});
itest!(deno_doc_invalid_url {
args: "doc https://raw.githubusercontent.com%2Fdyedgreen%2Fdeno-sqlite%2Frework_api%2Fmod.ts",
output: "doc/invalid_url.out",
exit_code: 1,
});

View file

@ -1,80 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
use test_util as util;
#[test]
fn eval_p() {
let output = util::deno_cmd()
.arg("eval")
.arg("-p")
.arg("1+2")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout_str =
util::strip_ansi_codes(std::str::from_utf8(&output.stdout).unwrap().trim());
assert_eq!("3", stdout_str);
}
// Make sure that snapshot flags don't affect runtime.
#[test]
fn eval_randomness() {
let mut numbers = Vec::with_capacity(10);
for _ in 0..10 {
let output = util::deno_cmd()
.arg("eval")
.arg("-p")
.arg("Math.random()")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout_str = util::strip_ansi_codes(
std::str::from_utf8(&output.stdout).unwrap().trim(),
);
numbers.push(stdout_str.to_string());
}
numbers.dedup();
assert!(numbers.len() > 1);
}
itest!(eval_basic {
args: "eval console.log(\"hello\")",
output_str: Some("hello\n"),
});
// Ugly parentheses due to whitespace delimiting problem.
itest!(eval_ts {
args: "eval --quiet --ext=ts console.log((123)as(number))", // 'as' is a TS keyword only
output_str: Some("123\n"),
});
itest!(dyn_import_eval {
args: "eval import('./subdir/mod4.js').then(console.log)",
output: "eval/dyn_import_eval.out",
});
// Cannot write the expression to evaluate as "console.log(typeof gc)"
// because itest! splits args on whitespace.
itest!(v8_flags_eval {
args: "eval --v8-flags=--expose-gc console.log(typeof(gc))",
output: "run/v8_flags.js.out",
});
itest!(check_local_by_default {
args: "eval --quiet import('http://localhost:4545/subdir/type_error.ts').then(console.log);",
output: "eval/check_local_by_default.out",
http_server: true,
});
itest!(check_local_by_default2 {
args: "eval --quiet import('./eval/check_local_by_default2.ts').then(console.log);",
output: "eval/check_local_by_default2.out",
http_server: true,
});

View file

@ -1,45 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
use test_util as util;
#[test]
fn help_flag() {
let status = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("--help")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
#[test]
fn version_short_flag() {
let status = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("-V")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
#[test]
fn version_long_flag() {
let status = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("--version")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
itest!(types {
args: "types",
output: "types/types.out",
});

View file

@ -1,248 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
use test_util as util;
use test_util::TempDir;
#[test]
fn fmt_test() {
let t = TempDir::new();
let testdata_fmt_dir = util::testdata_path().join("fmt");
let fixed_js = testdata_fmt_dir.join("badly_formatted_fixed.js");
let badly_formatted_original_js =
testdata_fmt_dir.join("badly_formatted.mjs");
let badly_formatted_js = t.path().join("badly_formatted.js");
let badly_formatted_js_str = badly_formatted_js.to_str().unwrap();
std::fs::copy(&badly_formatted_original_js, &badly_formatted_js).unwrap();
let fixed_md = testdata_fmt_dir.join("badly_formatted_fixed.md");
let badly_formatted_original_md = testdata_fmt_dir.join("badly_formatted.md");
let badly_formatted_md = t.path().join("badly_formatted.md");
let badly_formatted_md_str = badly_formatted_md.to_str().unwrap();
std::fs::copy(&badly_formatted_original_md, &badly_formatted_md).unwrap();
let fixed_json = testdata_fmt_dir.join("badly_formatted_fixed.json");
let badly_formatted_original_json =
testdata_fmt_dir.join("badly_formatted.json");
let badly_formatted_json = t.path().join("badly_formatted.json");
let badly_formatted_json_str = badly_formatted_json.to_str().unwrap();
std::fs::copy(&badly_formatted_original_json, &badly_formatted_json).unwrap();
// First, check formatting by ignoring the badly formatted file.
let status = util::deno_cmd()
.current_dir(&testdata_fmt_dir)
.arg("fmt")
.arg(format!(
"--ignore={},{},{}",
badly_formatted_js_str, badly_formatted_md_str, badly_formatted_json_str
))
.arg("--check")
.arg(badly_formatted_js_str)
.arg(badly_formatted_md_str)
.arg(badly_formatted_json_str)
.spawn()
.unwrap()
.wait()
.unwrap();
// No target files found
assert!(!status.success());
// Check without ignore.
let status = util::deno_cmd()
.current_dir(&testdata_fmt_dir)
.arg("fmt")
.arg("--check")
.arg(badly_formatted_js_str)
.arg(badly_formatted_md_str)
.arg(badly_formatted_json_str)
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(!status.success());
// Format the source file.
let status = util::deno_cmd()
.current_dir(&testdata_fmt_dir)
.arg("fmt")
.arg(badly_formatted_js_str)
.arg(badly_formatted_md_str)
.arg(badly_formatted_json_str)
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let expected_js = std::fs::read_to_string(fixed_js).unwrap();
let expected_md = std::fs::read_to_string(fixed_md).unwrap();
let expected_json = std::fs::read_to_string(fixed_json).unwrap();
let actual_js = std::fs::read_to_string(badly_formatted_js).unwrap();
let actual_md = std::fs::read_to_string(badly_formatted_md).unwrap();
let actual_json = std::fs::read_to_string(badly_formatted_json).unwrap();
assert_eq!(expected_js, actual_js);
assert_eq!(expected_md, actual_md);
assert_eq!(expected_json, actual_json);
}
#[test]
fn fmt_stdin_error() {
use std::io::Write;
let mut deno = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("fmt")
.arg("-")
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap();
let stdin = deno.stdin.as_mut().unwrap();
let invalid_js = b"import { example }";
stdin.write_all(invalid_js).unwrap();
let output = deno.wait_with_output().unwrap();
// Error message might change. Just check stdout empty, stderr not.
assert!(output.stdout.is_empty());
assert!(!output.stderr.is_empty());
assert!(!output.status.success());
}
#[test]
fn fmt_ignore_unexplicit_files() {
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.env("NO_COLOR", "1")
.arg("fmt")
.arg("--check")
.arg("--ignore=./")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert_eq!(
String::from_utf8_lossy(&output.stderr),
"error: No target files found.\n"
);
}
#[test]
fn fmt_auto_ignore_git_and_node_modules() {
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::PathBuf;
fn create_bad_json(t: PathBuf) {
let bad_json_path = t.join("bad.json");
let mut bad_json_file = File::create(bad_json_path).unwrap();
writeln!(bad_json_file, "bad json").unwrap();
}
let temp_dir = TempDir::new();
let t = temp_dir.path().join("target");
let nest_git = t.join("nest").join(".git");
let git_dir = t.join(".git");
let nest_node_modules = t.join("nest").join("node_modules");
let node_modules_dir = t.join("node_modules");
create_dir_all(&nest_git).unwrap();
create_dir_all(&git_dir).unwrap();
create_dir_all(&nest_node_modules).unwrap();
create_dir_all(&node_modules_dir).unwrap();
create_bad_json(nest_git);
create_bad_json(git_dir);
create_bad_json(nest_node_modules);
create_bad_json(node_modules_dir);
let output = util::deno_cmd()
.current_dir(t)
.env("NO_COLOR", "1")
.arg("fmt")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert_eq!(
String::from_utf8_lossy(&output.stderr),
"error: No target files found.\n"
);
}
itest!(fmt_quiet_check_fmt_dir {
args: "fmt --check --quiet fmt/regular/",
output_str: Some(""),
exit_code: 0,
});
itest!(fmt_check_formatted_files {
args: "fmt --check fmt/regular/formatted1.js fmt/regular/formatted2.ts fmt/regular/formatted3.markdown fmt/regular/formatted4.jsonc",
output: "fmt/expected_fmt_check_formatted_files.out",
exit_code: 0,
});
itest!(fmt_check_ignore {
args: "fmt --check --ignore=fmt/regular/formatted1.js fmt/regular/",
output: "fmt/expected_fmt_check_ignore.out",
exit_code: 0,
});
itest!(fmt_check_parse_error {
args: "fmt --check fmt/parse_error/parse_error.ts",
output: "fmt/fmt_check_parse_error.out",
exit_code: 1,
});
itest!(fmt_stdin {
args: "fmt -",
input: Some("const a = 1\n"),
output_str: Some("const a = 1;\n"),
});
itest!(fmt_stdin_markdown {
args: "fmt --ext=md -",
input: Some("# Hello Markdown\n```ts\nconsole.log( \"text\")\n```\n\n```cts\nconsole.log( 5 )\n```"),
output_str: Some("# Hello Markdown\n\n```ts\nconsole.log(\"text\");\n```\n\n```cts\nconsole.log(5);\n```\n"),
});
itest!(fmt_stdin_json {
args: "fmt --ext=json -",
input: Some("{ \"key\": \"value\"}"),
output_str: Some("{ \"key\": \"value\" }\n"),
});
itest!(fmt_stdin_check_formatted {
args: "fmt --check -",
input: Some("const a = 1;\n"),
output_str: Some(""),
});
itest!(fmt_stdin_check_not_formatted {
args: "fmt --check -",
input: Some("const a = 1\n"),
output_str: Some("Not formatted stdin\n"),
});
itest!(fmt_with_config {
args: "fmt --config fmt/with_config/deno.jsonc fmt/with_config/subdir",
output: "fmt/fmt_with_config.out",
});
itest!(fmt_with_config_default {
args: "fmt fmt/with_config/subdir",
output: "fmt/fmt_with_config.out",
});
// Check if CLI flags take precedence
itest!(fmt_with_config_and_flags {
args: "fmt --config fmt/with_config/deno.jsonc --ignore=fmt/with_config/subdir/a.ts,fmt/with_config/subdir/b.ts",
output: "fmt/fmt_with_config_and_flags.out",
});
itest!(fmt_with_malformed_config {
args: "fmt --config fmt/deno.malformed.jsonc",
output: "fmt/fmt_with_malformed_config.out",
exit_code: 1,
});
itest!(fmt_with_malformed_config2 {
args: "fmt --config fmt/deno.malformed2.jsonc",
output: "fmt/fmt_with_malformed_config2.out",
exit_code: 1,
});

View file

@ -1,132 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
use test_util as util;
use test_util::TempDir;
#[test]
fn info_with_compiled_source() {
let _g = util::http_server();
let module_path = "http://127.0.0.1:4545/run/048_media_types_jsx.ts";
let t = TempDir::new();
let mut deno = util::deno_cmd()
.env("DENO_DIR", t.path())
.current_dir(util::testdata_path())
.arg("cache")
.arg(module_path)
.spawn()
.unwrap();
let status = deno.wait().unwrap();
assert!(status.success());
let output = util::deno_cmd()
.env("DENO_DIR", t.path())
.env("NO_COLOR", "1")
.current_dir(util::testdata_path())
.arg("info")
.arg(module_path)
.output()
.unwrap();
let str_output = std::str::from_utf8(&output.stdout).unwrap().trim();
eprintln!("{}", str_output);
// check the output of the test.ts program.
assert!(str_output.contains("emit: "));
assert_eq!(output.stderr, b"");
}
itest!(multiple_imports {
args: "info http://127.0.0.1:4545/run/019_media_types.ts",
output: "info/multiple_imports.out",
http_server: true,
});
itest!(info_ts_error {
args: "info info/031_info_ts_error.ts",
output: "info/031_info_ts_error.out",
});
itest!(info_flag {
args: "info",
output: "info/041_info_flag.out",
});
itest!(info_flag_location {
args: "info --location https://deno.land",
output: "info/041_info_flag_location.out",
});
itest!(info_json {
args: "info --json --unstable",
output: "info/info_json.out",
});
itest!(info_json_location {
args: "info --json --unstable --location https://deno.land",
output: "info/info_json_location.out",
});
itest!(info_flag_script_jsx {
args: "info http://127.0.0.1:4545/run/048_media_types_jsx.ts",
output: "info/049_info_flag_script_jsx.out",
http_server: true,
});
itest!(json_file {
args: "info --quiet --json --unstable info/json_output/main.ts",
output: "info/json_output/main.out",
exit_code: 0,
});
itest!(import_map_info {
args:
"info --quiet --import-map=import_maps/import_map.json import_maps/test.ts",
output: "info/065_import_map_info.out",
});
itest!(info_json_deps_order {
args: "info --unstable --json info/076_info_json_deps_order.ts",
output: "info/076_info_json_deps_order.out",
});
itest!(info_missing_module {
args: "info info/error_009_missing_js_module.js",
output: "info/info_missing_module.out",
});
itest!(info_recursive_modules {
args: "info --quiet info/info_recursive_imports_test.ts",
output: "info/info_recursive_imports_test.out",
exit_code: 0,
});
itest!(info_type_import {
args: "info info/info_type_import.ts",
output: "info/info_type_import.out",
});
itest!(_054_info_local_imports {
args: "info --quiet run/005_more_imports.ts",
output: "info/054_info_local_imports.out",
exit_code: 0,
});
// Tests for AssertionError where "data" is unexpectedly null when
// a file contains only triple slash references (#11196)
itest!(data_null_error {
args: "info info/data_null_error/mod.ts",
output: "info/data_null_error/data_null_error.out",
});
itest!(types_header_direct {
args: "info --reload run/type_directives_01.ts",
output: "info/types_header.out",
http_server: true,
});
itest!(with_config_override {
args: "info info/with_config/test.ts --config info/with_config/deno-override.json --import-map info/with_config/import_map.json",
output: "info/with_config/with_config.out",
});

View file

@ -1,159 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::process::Stdio;
use test_util as util;
use test_util::TempDir;
use util::assert_contains;
#[test]
fn init_subcommand_without_dir() {
let temp_dir = TempDir::new();
let cwd = temp_dir.path();
let deno_dir = util::new_deno_dir();
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.arg("init")
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert_contains!(stderr, "Project initialized");
assert!(!stderr.contains("cd"));
assert_contains!(stderr, "deno run main.ts");
assert_contains!(stderr, "deno test");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("run")
.arg("main.ts")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Add 2 + 3 = 5\n");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("test")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert_contains!(stdout, "1 passed");
}
#[test]
fn init_subcommand_with_dir_arg() {
let temp_dir = TempDir::new();
let cwd = temp_dir.path();
let deno_dir = util::new_deno_dir();
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.arg("init")
.arg("my_dir")
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert_contains!(stderr, "Project initialized");
assert_contains!(stderr, "cd my_dir");
assert_contains!(stderr, "deno run main.ts");
assert_contains!(stderr, "deno test");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("run")
.arg("my_dir/main.ts")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Add 2 + 3 = 5\n");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("test")
.arg("my_dir/main_test.ts")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert_contains!(stdout, "1 passed");
}
#[test]
fn init_subcommand_with_quiet_arg() {
let temp_dir = TempDir::new();
let cwd = temp_dir.path();
let deno_dir = util::new_deno_dir();
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.arg("init")
.arg("--quiet")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert_eq!(stdout, "");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("run")
.arg("main.ts")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(output.stdout, b"Add 2 + 3 = 5\n");
let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir);
let output = deno_cmd
.current_dir(cwd)
.env("NO_COLOR", "1")
.arg("test")
.stdout(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert_contains!(stdout, "1 passed");
}

File diff suppressed because it is too large Load diff

View file

@ -1,210 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::fs;
use std::process::Command;
use test_util as util;
use test_util::assert_contains;
use test_util::assert_ends_with;
use test_util::TempDir;
#[test]
fn install_basic() {
let _guard = util::http_server();
let temp_dir = TempDir::new();
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
let status = util::deno_cmd()
.current_dir(temp_dir.path())
.arg("install")
.arg("--check")
.arg("--name")
.arg("echo_test")
.arg("http://localhost:4545/echo.ts")
.envs([
("HOME", temp_dir_str.as_str()),
("USERPROFILE", temp_dir_str.as_str()),
("DENO_INSTALL_ROOT", ""),
])
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let mut file_path = temp_dir.path().join(".deno/bin/echo_test");
assert!(file_path.exists());
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
let content = fs::read_to_string(file_path).unwrap();
// ensure there's a trailing newline so the shell script can be
// more versatile.
assert_eq!(content.chars().last().unwrap(), '\n');
if cfg!(windows) {
assert_contains!(
content,
r#""run" "--check" "http://localhost:4545/echo.ts""#
);
} else {
assert_contains!(content, r#"run --check 'http://localhost:4545/echo.ts'"#);
}
}
#[test]
fn install_custom_dir_env_var() {
let _guard = util::http_server();
let temp_dir = TempDir::new();
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
let status = util::deno_cmd()
.current_dir(util::root_path()) // different cwd
.arg("install")
.arg("--check")
.arg("--name")
.arg("echo_test")
.arg("http://localhost:4545/echo.ts")
.envs([
("HOME", temp_dir_str.as_str()),
("USERPROFILE", temp_dir_str.as_str()),
("DENO_INSTALL_ROOT", temp_dir_str.as_str()),
])
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let mut file_path = temp_dir.path().join("bin/echo_test");
assert!(file_path.exists());
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
let content = fs::read_to_string(file_path).unwrap();
if cfg!(windows) {
assert_contains!(
content,
r#""run" "--check" "http://localhost:4545/echo.ts""#
);
} else {
assert_contains!(content, r#"run --check 'http://localhost:4545/echo.ts'"#);
}
}
#[test]
fn installer_test_local_module_run() {
let temp_dir = TempDir::new();
let bin_dir = temp_dir.path().join("bin");
std::fs::create_dir(&bin_dir).unwrap();
let status = util::deno_cmd()
.current_dir(util::root_path())
.arg("install")
.arg("--name")
.arg("echo_test")
.arg("--root")
.arg(temp_dir.path())
.arg(util::testdata_path().join("echo.ts"))
.arg("hello")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
assert!(file_path.exists());
// NOTE: using file_path here instead of exec_name, because tests
// shouldn't mess with user's PATH env variable
let output = Command::new(file_path)
.current_dir(temp_dir.path())
.arg("foo")
.env("PATH", util::target_dir())
.output()
.unwrap();
let stdout_str = std::str::from_utf8(&output.stdout).unwrap().trim();
assert_ends_with!(stdout_str, "hello, foo");
}
#[test]
fn installer_test_remote_module_run() {
let _g = util::http_server();
let temp_dir = TempDir::new();
let bin_dir = temp_dir.path().join("bin");
std::fs::create_dir(&bin_dir).unwrap();
let status = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("install")
.arg("--name")
.arg("echo_test")
.arg("--root")
.arg(temp_dir.path())
.arg("http://localhost:4545/echo.ts")
.arg("hello")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
assert!(file_path.exists());
let output = Command::new(file_path)
.current_dir(temp_dir.path())
.arg("foo")
.env("PATH", util::target_dir())
.output()
.unwrap();
assert_ends_with!(
std::str::from_utf8(&output.stdout).unwrap().trim(),
"hello, foo",
);
}
#[test]
fn check_local_by_default() {
let _guard = util::http_server();
let temp_dir = TempDir::new();
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
let status = util::deno_cmd()
.current_dir(temp_dir.path())
.arg("install")
.arg(util::testdata_path().join("./install/check_local_by_default.ts"))
.envs([
("HOME", temp_dir_str.as_str()),
("USERPROFILE", temp_dir_str.as_str()),
("DENO_INSTALL_ROOT", ""),
])
.status()
.unwrap();
assert!(status.success());
}
#[test]
fn check_local_by_default2() {
let _guard = util::http_server();
let temp_dir = TempDir::new();
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
let status = util::deno_cmd()
.current_dir(temp_dir.path())
.arg("install")
.arg(util::testdata_path().join("./install/check_local_by_default2.ts"))
.envs([
("HOME", temp_dir_str.as_str()),
("NO_COLOR", "1"),
("USERPROFILE", temp_dir_str.as_str()),
("DENO_INSTALL_ROOT", ""),
])
.status()
.unwrap();
assert!(status.success());
}

View file

@ -1,133 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
use test_util as util;
#[test]
fn ignore_unexplicit_files() {
let output = util::deno_cmd()
.current_dir(util::root_path())
.env("NO_COLOR", "1")
.arg("lint")
.arg("--unstable")
.arg("--ignore=./")
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert_eq!(
String::from_utf8_lossy(&output.stderr),
"error: No target files found.\n"
);
}
itest!(all {
args: "lint lint/without_config/file1.js lint/without_config/file2.ts lint/without_config/ignored_file.ts",
output: "lint/expected.out",
exit_code: 1,
});
itest!(quiet {
args: "lint --quiet lint/without_config/file1.js",
output: "lint/expected_quiet.out",
exit_code: 1,
});
itest!(json {
args:
"lint --json lint/without_config/file1.js lint/without_config/file2.ts lint/without_config/ignored_file.ts lint/without_config/malformed.js",
output: "lint/expected_json.out",
exit_code: 1,
});
itest!(compact {
args:
"lint --compact lint/without_config/file1.js lint/without_config/ignored_file.tss",
output: "lint/expected_compact.out",
exit_code: 1,
});
itest!(ignore {
args:
"lint --ignore=lint/without_config/file1.js,lint/without_config/malformed.js,lint/without_config/lint_with_config/ lint/without_config/",
output: "lint/expected_ignore.out",
exit_code: 1,
});
itest!(glob {
args: "lint --ignore=lint/without_config/malformed.js,lint/with_config/ lint/without_config/",
output: "lint/expected_glob.out",
exit_code: 1,
});
itest!(stdin {
args: "lint -",
input: Some("let _a: any;"),
output: "lint/expected_from_stdin.out",
exit_code: 1,
});
itest!(stdin_json {
args: "lint --json -",
input: Some("let _a: any;"),
output: "lint/expected_from_stdin_json.out",
exit_code: 1,
});
itest!(rules {
args: "lint --rules",
output: "lint/expected_rules.out",
exit_code: 0,
});
// Make sure that the rules are printed if quiet option is enabled.
itest!(rules_quiet {
args: "lint --rules -q",
output: "lint/expected_rules.out",
exit_code: 0,
});
itest!(lint_with_config {
args: "lint --config lint/Deno.jsonc lint/with_config/",
output: "lint/with_config.out",
exit_code: 1,
});
itest!(lint_with_report_config {
args: "lint --config lint/Deno.compact.format.jsonc lint/with_config/",
output: "lint/with_report_config_compact.out",
exit_code: 1,
});
// Check if CLI flags take precedence
itest!(lint_with_report_config_override {
args: "lint --config lint/Deno.compact.format.jsonc lint/with_config/ --json",
output: "lint/with_report_config_override.out",
exit_code: 1,
});
itest!(lint_with_config_and_flags {
args: "lint --config lint/Deno.jsonc --ignore=lint/with_config/a.ts",
output: "lint/with_config_and_flags.out",
exit_code: 1,
});
itest!(lint_with_config_without_tags {
args: "lint --config lint/Deno.no_tags.jsonc lint/with_config/",
output: "lint/with_config_without_tags.out",
exit_code: 1,
});
itest!(lint_with_malformed_config {
args: "lint --config lint/Deno.malformed.jsonc",
output: "lint/with_malformed_config.out",
exit_code: 1,
});
itest!(lint_with_malformed_config2 {
args: "lint --config lint/Deno.malformed2.jsonc",
output: "lint/with_malformed_config2.out",
exit_code: 1,
});

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,5 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use test_util as util;
#[macro_export]
macro_rules! itest(
($name:ident {$( $key:ident: $value:expr,)*}) => {
@ -31,96 +29,3 @@ macro_rules! itest_flaky(
}
}
);
// These files have `_tests.rs` suffix to make it easier to tell which file is
// the test (ex. `lint_tests.rs`) and which is the implementation (ex. `lint.rs`)
// when both are open, especially for two tabs in VS Code
#[path = "bench_tests.rs"]
mod bench;
#[path = "bundle_tests.rs"]
mod bundle;
#[path = "cache_tests.rs"]
mod cache;
#[path = "cert_tests.rs"]
mod cert;
#[path = "check_tests.rs"]
mod check;
#[path = "compile_tests.rs"]
mod compile;
#[path = "coverage_tests.rs"]
mod coverage;
#[path = "doc_tests.rs"]
mod doc;
#[path = "eval_tests.rs"]
mod eval;
#[path = "flags_tests.rs"]
mod flags;
#[path = "fmt_tests.rs"]
mod fmt;
#[path = "info_tests.rs"]
mod info;
#[path = "init_tests.rs"]
mod init;
#[path = "inspector_tests.rs"]
mod inspector;
#[path = "install_tests.rs"]
mod install;
#[path = "lint_tests.rs"]
mod lint;
#[path = "lsp_tests.rs"]
mod lsp;
#[path = "npm_tests.rs"]
mod npm;
#[path = "repl_tests.rs"]
mod repl;
#[path = "run_tests.rs"]
mod run;
#[path = "task_tests.rs"]
mod task;
#[path = "test_tests.rs"]
mod test;
#[path = "upgrade_tests.rs"]
mod upgrade;
#[path = "vendor_tests.rs"]
mod vendor;
#[path = "watcher_tests.rs"]
mod watcher;
#[path = "worker_tests.rs"]
mod worker;
#[test]
fn js_unit_tests_lint() {
let status = util::deno_cmd()
.arg("lint")
.arg("--unstable")
.arg(util::tests_path().join("unit"))
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
#[test]
fn js_unit_tests() {
let _g = util::http_server();
// Note that the unit tests are not safe for concurrency and must be run with a concurrency limit
// of one because there are some chdir tests in there.
// TODO(caspervonb) split these tests into two groups: parallel and serial.
let mut deno = util::deno_cmd()
.current_dir(util::root_path())
.arg("test")
.arg("--unstable")
.arg("--location=http://js-unit-tests/foo/bar")
.arg("--no-prompt")
.arg("-A")
.arg(util::tests_path().join("unit"))
.spawn()
.expect("failed to spawn script");
let status = deno.wait().expect("failed to wait for the child process");
assert_eq!(Some(0), status.code());
assert!(status.success());
}

File diff suppressed because it is too large Load diff

View file

@ -1,877 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use test_util as util;
use test_util::assert_contains;
use test_util::assert_ends_with;
use test_util::assert_not_contains;
#[test]
fn pty_multiline() {
util::with_pty(&["repl"], |mut console| {
console.write_line("(\n1 + 2\n)");
console.write_line("{\nfoo: \"foo\"\n}");
console.write_line("`\nfoo\n`");
console.write_line("`\n\\`\n`");
console.write_line("'{'");
console.write_line("'('");
console.write_line("'['");
console.write_line("/{/");
console.write_line("/\\(/");
console.write_line("/\\[/");
console.write_line("console.log(\"{test1} abc {test2} def {{test3}}\".match(/{([^{].+?)}/));");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, '3');
assert_contains!(output, "{ foo: \"foo\" }");
assert_contains!(output, "\"\\nfoo\\n\"");
assert_contains!(output, "\"\\n`\\n\"");
assert_contains!(output, "\"{\"");
assert_contains!(output, "\"(\"");
assert_contains!(output, "\"[\"");
assert_contains!(output, "/{/");
assert_contains!(output, "/\\(/");
assert_contains!(output, "/\\[/");
assert_contains!(output, "[ \"{test1}\", \"test1\" ]");
});
}
#[test]
fn pty_null() {
util::with_pty(&["repl"], |mut console| {
console.write_line("null");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "null");
});
}
#[test]
fn pty_unpaired_braces() {
util::with_pty(&["repl"], |mut console| {
console.write_line(")");
console.write_line("]");
console.write_line("}");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "Unexpected token `)`");
assert_contains!(output, "Unexpected token `]`");
assert_contains!(output, "Unexpected token `}`");
});
}
#[test]
fn pty_bad_input() {
util::with_pty(&["repl"], |mut console| {
console.write_line("'\\u{1f3b5}'[0]");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "Unterminated string literal");
});
}
#[test]
fn pty_syntax_error_input() {
util::with_pty(&["repl"], |mut console| {
console.write_line("('\\u')");
console.write_line("'");
console.write_line("[{'a'}];");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(
output,
"Bad character escape sequence, expected 4 hex characters"
);
assert_contains!(output, "Unterminated string constant");
assert_contains!(output, "Expected a semicolon");
});
}
#[test]
fn pty_complete_symbol() {
util::with_pty(&["repl"], |mut console| {
console.write_line("Symbol.it\t");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "Symbol(Symbol.iterator)");
});
}
#[test]
fn pty_complete_declarations() {
util::with_pty(&["repl"], |mut console| {
console.write_line("class MyClass {}");
console.write_line("My\t");
console.write_line("let myVar;");
console.write_line("myV\t");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "> MyClass");
assert_contains!(output, "> myVar");
});
}
#[test]
fn pty_complete_primitives() {
util::with_pty(&["repl"], |mut console| {
console.write_line("let func = function test(){}");
console.write_line("func.appl\t");
console.write_line("let str = ''");
console.write_line("str.leng\t");
console.write_line("false.valueO\t");
console.write_line("5n.valueO\t");
console.write_line("let num = 5");
console.write_line("num.toStrin\t");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "> func.apply");
assert_contains!(output, "> str.length");
assert_contains!(output, "> 5n.valueOf");
assert_contains!(output, "> false.valueOf");
assert_contains!(output, "> num.toString");
});
}
#[test]
fn pty_complete_expression() {
util::with_pty(&["repl"], |mut console| {
console.write_text("Deno.\t\t");
console.write_text("y");
console.write_line("");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "Display all");
assert_contains!(output, "core");
assert_contains!(output, "args");
assert_contains!(output, "exit");
assert_contains!(output, "symlink");
assert_contains!(output, "permissions");
});
}
#[test]
fn pty_complete_imports() {
util::with_pty(&["repl"], |mut console| {
// single quotes
console.write_line("import './run/001_hel\t'");
// double quotes
console.write_line("import { output } from \"./run/045_out\t\"");
console.write_line("output('testing output');");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "Hello World");
assert_contains!(
output,
// on windows, could contain either (it's flaky)
"\ntesting output",
"testing output\u{1b}",
);
});
// ensure when the directory changes that the suggestions come from the cwd
util::with_pty(&["repl"], |mut console| {
console.write_line("Deno.chdir('./subdir');");
console.write_line("import '../run/001_hel\t'");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "Hello World");
});
}
#[test]
fn pty_complete_imports_no_panic_empty_specifier() {
// does not panic when tabbing when empty
util::with_pty(&["repl"], |mut console| {
console.write_line("import '\t';");
console.write_line("close();");
});
}
#[test]
fn pty_ignore_symbols() {
util::with_pty(&["repl"], |mut console| {
console.write_line("Array.Symbol\t");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "undefined");
assert_not_contains!(
output,
"Uncaught TypeError: Array.Symbol is not a function"
);
});
}
#[test]
fn pty_assign_global_this() {
util::with_pty(&["repl"], |mut console| {
console.write_line("globalThis = 42;");
console.write_line("close();");
let output = console.read_all_output();
assert_not_contains!(output, "panicked");
});
}
#[test]
fn pty_emoji() {
// windows was having issues displaying this
util::with_pty(&["repl"], |mut console| {
console.write_line(r#"console.log('\u{1F995}');"#);
console.write_line("close();");
let output = console.read_all_output();
// only one for the output (since input is escaped)
let emoji_count = output.chars().filter(|c| *c == '🦕').count();
assert_eq!(emoji_count, 1);
});
}
#[test]
fn console_log() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["console.log('hello')", "'world'"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "hello\nundefined\n\"world\"\n");
assert!(err.is_empty());
}
#[test]
fn object_literal() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["{}", "{ foo: 'bar' }"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "{}\n{ foo: \"bar\" }\n");
assert!(err.is_empty());
}
#[test]
fn block_expression() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["{};", "{\"\"}"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "undefined\n\"\"\n");
assert!(err.is_empty());
}
#[test]
fn await_resolve() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["await Promise.resolve('done')"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "\"done\"\n");
assert!(err.is_empty());
}
#[test]
fn await_timeout() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["await new Promise((r) => setTimeout(r, 0, 'done'))"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "\"done\"\n");
assert!(err.is_empty());
}
#[test]
fn let_redeclaration() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["let foo = 0;", "foo", "let foo = 1;", "foo"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "undefined\n0\nundefined\n1\n");
assert!(err.is_empty());
}
#[test]
fn repl_cwd() {
let (_out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["Deno.cwd()"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert!(err.is_empty());
}
#[test]
fn typescript() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec![
"function add(a: number, b: number) { return a + b }",
"const result: number = add(1, 2) as number;",
"result",
]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "undefined\nundefined\n3\n");
assert!(err.is_empty());
}
#[test]
fn typescript_declarations() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec![
"namespace Test { export enum Values { A, B, C } }",
"Test.Values.A",
"Test.Values.C",
"interface MyInterface { prop: string; }",
"type MyTypeAlias = string;",
]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
let expected_end_text = "undefined\n0\n2\nundefined\nundefined\n";
assert_ends_with!(out, expected_end_text);
assert!(err.is_empty());
}
#[test]
fn typescript_decorators() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec![
"function dec(target) { target.prototype.test = () => 2; }",
"@dec class Test {}",
"new Test().test()",
]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "undefined\n[Function: Test]\n2\n");
assert!(err.is_empty());
}
#[test]
fn eof() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["1 + 2"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "3\n");
assert!(err.is_empty());
}
#[test]
fn strict() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec![
"let a = {};",
"Object.preventExtensions(a);",
"a.c = 1;",
]),
None,
false,
);
assert_contains!(
out,
"Uncaught TypeError: Cannot add property c, object is not extensible"
);
assert!(err.is_empty());
}
#[test]
fn close_command() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["close()", "'ignored'"]),
None,
false,
);
assert_not_contains!(out, "ignored");
assert!(err.is_empty());
}
#[test]
fn function() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["Deno.writeFileSync"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "[Function: writeFileSync]\n");
assert!(err.is_empty());
}
#[test]
#[ignore]
fn multiline() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["(\n1 + 2\n)"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "3\n");
assert!(err.is_empty());
}
#[test]
fn import() {
let (out, _) = util::run_and_collect_output(
true,
"repl",
Some(vec!["import('./subdir/auto_print_hello.ts')"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_contains!(out, "hello!\n");
}
#[test]
fn import_declarations() {
let (out, _) = util::run_and_collect_output(
true,
"repl",
Some(vec!["import './subdir/auto_print_hello.ts';"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_contains!(out, "hello!\n");
}
#[test]
fn exports_stripped() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["export default 5;", "export class Test {}"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_contains!(out, "5\n");
assert!(err.is_empty());
}
#[test]
fn call_eval_unterminated() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["eval('{')"]),
None,
false,
);
assert_contains!(out, "Unexpected end of input");
assert!(err.is_empty());
}
#[test]
fn unpaired_braces() {
for right_brace in &[")", "]", "}"] {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec![right_brace]),
None,
false,
);
assert_contains!(out, "Unexpected token");
assert!(err.is_empty());
}
}
#[test]
fn reference_error() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["not_a_variable"]),
None,
false,
);
assert_contains!(out, "not_a_variable is not defined");
assert!(err.is_empty());
}
#[test]
fn syntax_error() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec![
"syntax error",
"2", // ensure it keeps accepting input after
]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "parse error: Expected ';', '}' or <eof> at 1:8\n2\n");
assert!(err.is_empty());
}
#[test]
fn syntax_error_jsx() {
// JSX is not supported in the REPL
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["const element = <div />;"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_contains!(out, "Unexpected token `>`");
assert!(err.is_empty());
}
#[test]
fn type_error() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["console()"]),
None,
false,
);
assert_contains!(out, "console is not a function");
assert!(err.is_empty());
}
#[test]
fn variable() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["var a = 123;", "a"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "undefined\n123\n");
assert!(err.is_empty());
}
#[test]
fn lexical_scoped_variable() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["let a = 123;", "a"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "undefined\n123\n");
assert!(err.is_empty());
}
#[test]
fn missing_deno_dir() {
use std::fs::{read_dir, remove_dir_all};
const DENO_DIR: &str = "nonexistent";
let test_deno_dir = test_util::testdata_path().join(DENO_DIR);
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["1"]),
Some(vec![
("DENO_DIR".to_owned(), DENO_DIR.to_owned()),
("NO_COLOR".to_owned(), "1".to_owned()),
]),
false,
);
assert!(read_dir(&test_deno_dir).is_ok());
remove_dir_all(&test_deno_dir).unwrap();
assert_ends_with!(out, "1\n");
assert!(err.is_empty());
}
#[test]
fn save_last_eval() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["1", "_"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "1\n1\n");
assert!(err.is_empty());
}
#[test]
fn save_last_thrown() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["throw 1", "_error"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(out, "Uncaught 1\n1\n");
assert!(err.is_empty());
}
#[test]
fn assign_underscore() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["_ = 1", "2", "_"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_ends_with!(
out,
"Last evaluation result is no longer saved to _.\n1\n2\n1\n"
);
assert!(err.is_empty());
}
#[test]
fn assign_underscore_error() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["_error = 1", "throw 2", "_error"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
println!("{}", out);
assert_ends_with!(
out,
"Last thrown error is no longer saved to _error.\n1\nUncaught 2\n1\n"
);
assert!(err.is_empty());
}
#[test]
fn custom_inspect() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec![
r#"const o = {
[Symbol.for("Deno.customInspect")]() {
throw new Error('Oops custom inspect error');
},
};"#,
"o",
]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_contains!(out, "Oops custom inspect error");
assert!(err.is_empty());
}
#[test]
fn eval_flag_valid_input() {
let (out, err) = util::run_and_collect_output_with_args(
true,
vec!["repl", "--eval", "const t = 10;"],
Some(vec!["t * 500;"]),
None,
false,
);
assert_contains!(out, "5000");
assert!(err.is_empty());
}
#[test]
fn eval_flag_parse_error() {
let (out, err) = util::run_and_collect_output_with_args(
true,
vec!["repl", "--eval", "const %"],
Some(vec!["250 * 10"]),
None,
false,
);
assert_contains!(
test_util::strip_ansi_codes(&out),
"error in --eval flag. parse error: Unexpected token `%`."
);
assert_contains!(out, "2500"); // should not prevent input
assert!(err.is_empty());
}
#[test]
fn eval_flag_runtime_error() {
let (out, err) = util::run_and_collect_output_with_args(
true,
vec!["repl", "--eval", "throw new Error('Testing')"],
Some(vec!["250 * 10"]),
None,
false,
);
assert_contains!(out, "error in --eval flag. Uncaught Error: Testing");
assert_contains!(out, "2500"); // should not prevent input
assert!(err.is_empty());
}
#[test]
fn eval_file_flag_valid_input() {
let (out, err) = util::run_and_collect_output_with_args(
true,
vec!["repl", "--eval-file=./run/001_hello.js"],
None,
None,
false,
);
assert_contains!(out, "Hello World");
assert!(err.is_empty());
}
#[test]
fn eval_file_flag_call_defined_function() {
let (out, err) = util::run_and_collect_output_with_args(
true,
vec!["repl", "--eval-file=./tsc/d.ts"],
Some(vec!["v4()"]),
None,
false,
);
assert_contains!(out, "hello");
assert!(err.is_empty());
}
#[test]
fn eval_file_flag_http_input() {
let (out, err) = util::run_and_collect_output_with_args(
true,
vec!["repl", "--eval-file=http://127.0.0.1:4545/tsc/d.ts"],
Some(vec!["v4()"]),
None,
true,
);
assert_contains!(out, "hello");
assert!(err.contains("Download"));
}
#[test]
fn eval_file_flag_multiple_files() {
let (out, err) = util::run_and_collect_output_with_args(
true,
vec!["repl", "--eval-file=http://127.0.0.1:4545/repl/import_type.ts,./tsc/d.ts,http://127.0.0.1:4545/type_definitions/foo.js"],
Some(vec!["b.method1=v4", "b.method1()+foo.toUpperCase()"]),
None,
true,
);
assert_contains!(out, "helloFOO");
assert_contains!(err, "Download");
}
#[test]
fn pty_clear_function() {
util::with_pty(&["repl"], |mut console| {
console.write_line("console.log('hello');");
console.write_line("clear();");
console.write_line("const clear = 1234 + 2000;");
console.write_line("clear;");
console.write_line("close();");
let output = console.read_all_output();
if cfg!(windows) {
// Windows will overwrite what's in the console buffer before
// we read from it. It contains this string repeated many times
// to clear the screen.
assert_contains!(output, "\r\n\u{1b}[K\r\n\u{1b}[K\r\n\u{1b}[K");
} else {
assert_contains!(output, "hello");
assert_contains!(output, "[1;1H");
}
assert_contains!(output, "undefined");
assert_contains!(output, "const clear = 1234 + 2000;");
assert_contains!(output, "3234");
});
}
#[test]
fn pty_tab_handler() {
// If the last character is **not** whitespace, we show the completions
util::with_pty(&["repl"], |mut console| {
console.write_line("a\t\t");
console.write_line("close();");
let output = console.read_all_output();
assert_contains!(output, "addEventListener");
assert_contains!(output, "alert");
assert_contains!(output, "atob");
});
// If the last character is whitespace, we just insert a tab
util::with_pty(&["repl"], |mut console| {
console.write_line("a; \t\t"); // last character is whitespace
console.write_line("close();");
let output = console.read_all_output();
assert_not_contains!(output, "addEventListener");
assert_not_contains!(output, "alert");
assert_not_contains!(output, "atob");
});
}
#[test]
fn repl_report_error() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec![
r#"console.log(1); reportError(new Error("foo")); console.log(2);"#,
]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
// TODO(nayeemrmn): The REPL should report event errors and rejections.
assert_contains!(out, "1\n2\nundefined\n");
assert!(err.is_empty());
}
#[test]
fn pty_aggregate_error() {
let (out, err) = util::run_and_collect_output(
true,
"repl",
Some(vec!["await Promise.any([])"]),
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
false,
);
assert_contains!(out, "AggregateError");
assert!(err.is_empty());
}

File diff suppressed because it is too large Load diff

View file

@ -1,132 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
// Most of the tests for this are in deno_task_shell.
// These tests are intended to only test integration.
itest!(task_no_args {
args: "task -q --config task/deno.json",
output: "task/task_no_args.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
exit_code: 1,
});
itest!(task_cwd {
args: "task -q --config task/deno.json --cwd .. echo_cwd",
output: "task/task_cwd.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
exit_code: 0,
});
itest!(task_init_cwd {
args: "task -q --config task/deno.json --cwd .. echo_init_cwd",
output: "task/task_init_cwd.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
exit_code: 0,
});
itest!(task_init_cwd_already_set {
args: "task -q --config task/deno.json echo_init_cwd",
output: "task/task_init_cwd_already_set.out",
envs: vec![
("NO_COLOR".to_string(), "1".to_string()),
("INIT_CWD".to_string(), "HELLO".to_string())
],
exit_code: 0,
});
itest!(task_cwd_resolves_config_from_specified_dir {
args: "task -q --cwd task",
output: "task/task_no_args.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
exit_code: 1,
});
itest!(task_non_existent {
args: "task --config task/deno.json non_existent",
output: "task/task_non_existent.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
exit_code: 1,
});
#[test]
fn task_emoji() {
// this bug only appears when using a pty/tty
let args = "task --config task/deno.json echo_emoji";
use test_util::PtyData::*;
test_util::test_pty2(args, vec![Output("Task echo_emoji echo 🔥\r\n🔥")]);
}
itest!(task_boolean_logic {
args: "task -q --config task/deno.json boolean_logic",
output: "task/task_boolean_logic.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
});
itest!(task_exit_code_5 {
args: "task --config task/deno.json exit_code_5",
output: "task/task_exit_code_5.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
exit_code: 5,
});
itest!(task_additional_args {
args: "task -q --config task/deno.json echo 2",
output: "task/task_additional_args.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
});
itest!(task_additional_args_no_shell_expansion {
args_vec: vec![
"task",
"-q",
"--config",
"task/deno.json",
"echo",
"$(echo 5)"
],
output: "task/task_additional_args_no_shell_expansion.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
});
itest!(task_additional_args_nested_strings {
args_vec: vec![
"task",
"-q",
"--config",
"task/deno.json",
"echo",
"string \"quoted string\""
],
output: "task/task_additional_args_nested_strings.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
});
itest!(task_additional_args_no_logic {
args_vec: vec![
"task",
"-q",
"--config",
"task/deno.json",
"echo",
"||",
"echo",
"5"
],
output: "task/task_additional_args_no_logic.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
});
itest!(task_deno_exe_no_env {
args_vec: vec!["task", "-q", "--config", "task/deno.json", "deno_echo"],
output: "task/task_deno_exe_no_env.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
env_clear: true,
});
itest!(task_piped_stdin {
args_vec: vec!["task", "-q", "--config", "task/deno.json", "piped"],
output: "task/task_piped_stdin.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
});

View file

@ -1,449 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
use deno_core::url::Url;
use test_util as util;
#[test]
fn no_color() {
let (out, _) = util::run_and_collect_output(
false,
"test test/no_color.ts",
None,
Some(vec![("NO_COLOR".to_owned(), "true".to_owned())]),
false,
);
// ANSI escape codes should be stripped.
assert!(out.contains("success ... ok"));
assert!(out.contains("fail ... FAILED"));
assert!(out.contains("ignored ... ignored"));
assert!(out.contains("FAILED | 1 passed | 1 failed | 1 ignored"));
}
itest!(overloads {
args: "test test/overloads.ts",
exit_code: 0,
output: "test/overloads.out",
});
itest!(meta {
args: "test test/meta.ts",
exit_code: 0,
output: "test/meta.out",
});
itest!(pass {
args: "test test/pass.ts",
exit_code: 0,
output: "test/pass.out",
});
itest!(ignore {
args: "test test/ignore.ts",
exit_code: 0,
output: "test/ignore.out",
});
itest!(ignore_permissions {
args: "test --unstable test/ignore_permissions.ts",
exit_code: 0,
output: "test/ignore_permissions.out",
});
itest!(fail {
args: "test test/fail.ts",
exit_code: 1,
output: "test/fail.out",
});
itest!(collect {
args: "test --ignore=test/collect/ignore test/collect",
exit_code: 0,
output: "test/collect.out",
});
itest!(test_with_config {
args: "test --config test/collect/deno.jsonc test/collect",
exit_code: 0,
output: "test/collect.out",
});
itest!(test_with_config2 {
args: "test --config test/collect/deno2.jsonc test/collect",
exit_code: 0,
output: "test/collect2.out",
});
itest!(test_with_malformed_config {
args: "test --config test/collect/deno.malformed.jsonc",
exit_code: 1,
output: "test/collect_with_malformed_config.out",
});
itest!(parallel_flag {
args: "test test/short-pass.ts --parallel",
exit_code: 0,
output: "test/short-pass.out",
});
itest!(parallel_flag_with_env_variable {
args: "test test/short-pass.ts --parallel",
envs: vec![("DENO_JOBS".to_owned(), "2".to_owned())],
exit_code: 0,
output: "test/short-pass.out",
});
itest!(jobs_flag {
args: "test test/short-pass.ts --jobs",
exit_code: 0,
output: "test/short-pass-jobs-flag-warning.out",
});
itest!(jobs_flag_with_numeric_value {
args: "test test/short-pass.ts --jobs=2",
exit_code: 0,
output: "test/short-pass-jobs-flag-warning.out",
});
itest!(load_unload {
args: "test test/load_unload.ts",
exit_code: 0,
output: "test/load_unload.out",
});
itest!(interval {
args: "test test/interval.ts",
exit_code: 0,
output: "test/interval.out",
});
itest!(doc {
args: "test --doc --allow-all test/doc.ts",
exit_code: 1,
output: "test/doc.out",
});
itest!(doc_only {
args: "test --doc --allow-all test/doc_only",
exit_code: 0,
output: "test/doc_only.out",
});
itest!(markdown {
args: "test --doc --allow-all test/markdown.md",
exit_code: 1,
output: "test/markdown.out",
});
itest!(markdown_windows {
args: "test --doc --allow-all test/markdown_windows.md",
exit_code: 1,
output: "test/markdown_windows.out",
});
itest!(markdown_full_block_names {
args: "test --doc --allow-all test/markdown_full_block_names.md",
exit_code: 1,
output: "test/markdown_full_block_names.out",
});
itest!(markdown_ignore_html_comment {
args: "test --doc --allow-all test/markdown_with_comment.md",
exit_code: 1,
output: "test/markdown_with_comment.out",
});
itest!(text {
args: "test --doc --allow-all test/text.md",
exit_code: 0,
output: "test/text.out",
});
itest!(quiet {
args: "test --quiet test/quiet.ts",
exit_code: 0,
output: "test/quiet.out",
});
itest!(fail_fast {
args: "test --fail-fast test/fail_fast.ts",
exit_code: 1,
output: "test/fail_fast.out",
});
itest!(only {
args: "test test/only.ts",
exit_code: 1,
output: "test/only.out",
});
itest!(no_check {
args: "test --no-check test/no_check.ts",
exit_code: 1,
output: "test/no_check.out",
});
itest!(no_run {
args: "test --unstable --no-run test/no_run.ts",
output: "test/no_run.out",
exit_code: 1,
});
itest!(allow_all {
args: "test --unstable --allow-all test/allow_all.ts",
exit_code: 0,
output: "test/allow_all.out",
});
itest!(allow_none {
args: "test --unstable test/allow_none.ts",
exit_code: 1,
output: "test/allow_none.out",
});
itest!(ops_sanitizer_unstable {
args: "test --unstable --trace-ops test/ops_sanitizer_unstable.ts",
exit_code: 1,
output: "test/ops_sanitizer_unstable.out",
});
itest!(ops_sanitizer_timeout_failure {
args: "test test/ops_sanitizer_timeout_failure.ts",
output: "test/ops_sanitizer_timeout_failure.out",
});
itest!(ops_sanitizer_multiple_timeout_tests {
args: "test --trace-ops test/ops_sanitizer_multiple_timeout_tests.ts",
exit_code: 1,
output: "test/ops_sanitizer_multiple_timeout_tests.out",
});
itest!(ops_sanitizer_multiple_timeout_tests_no_trace {
args: "test test/ops_sanitizer_multiple_timeout_tests.ts",
exit_code: 1,
output: "test/ops_sanitizer_multiple_timeout_tests_no_trace.out",
});
// TODO(@littledivy): re-enable this test, recent optimizations made output non deterministic.
// https://github.com/denoland/deno/issues/14268
//
// itest!(ops_sanitizer_missing_details {
// args: "test --allow-write --allow-read test/ops_sanitizer_missing_details.ts",
// exit_code: 1,
// output: "test/ops_sanitizer_missing_details.out",
// });
itest!(ops_sanitizer_nexttick {
args: "test test/ops_sanitizer_nexttick.ts",
output: "test/ops_sanitizer_nexttick.out",
});
itest!(resource_sanitizer {
args: "test --allow-read test/resource_sanitizer.ts",
exit_code: 1,
output: "test/resource_sanitizer.out",
});
itest!(exit_sanitizer {
args: "test test/exit_sanitizer.ts",
output: "test/exit_sanitizer.out",
exit_code: 1,
});
itest!(clear_timeout {
args: "test test/clear_timeout.ts",
exit_code: 0,
output: "test/clear_timeout.out",
});
itest!(finally_timeout {
args: "test test/finally_timeout.ts",
exit_code: 1,
output: "test/finally_timeout.out",
});
itest!(unresolved_promise {
args: "test test/unresolved_promise.ts",
exit_code: 1,
output: "test/unresolved_promise.out",
});
itest!(unhandled_rejection {
args: "test test/unhandled_rejection.ts",
exit_code: 1,
output: "test/unhandled_rejection.out",
});
itest!(filter {
args: "test --filter=foo test/filter",
exit_code: 0,
output: "test/filter.out",
});
itest!(shuffle {
args: "test --shuffle test/shuffle",
exit_code: 0,
output_str: Some("[WILDCARD]"),
});
itest!(shuffle_with_seed {
args: "test --shuffle=42 test/shuffle",
exit_code: 0,
output: "test/shuffle.out",
});
itest!(aggregate_error {
args: "test --quiet test/aggregate_error.ts",
exit_code: 1,
output: "test/aggregate_error.out",
});
itest!(steps_passing_steps {
args: "test test/steps/passing_steps.ts",
exit_code: 0,
output: "test/steps/passing_steps.out",
});
itest!(steps_failing_steps {
args: "test test/steps/failing_steps.ts",
exit_code: 1,
output: "test/steps/failing_steps.out",
});
itest!(steps_ignored_steps {
args: "test test/steps/ignored_steps.ts",
exit_code: 0,
output: "test/steps/ignored_steps.out",
});
itest!(steps_invalid_usage {
args: "test test/steps/invalid_usage.ts",
exit_code: 1,
output: "test/steps/invalid_usage.out",
});
itest!(steps_output_within {
args: "test test/steps/output_within.ts",
exit_code: 0,
output: "test/steps/output_within.out",
});
itest!(no_prompt_by_default {
args: "test --quiet test/no_prompt_by_default.ts",
exit_code: 1,
output: "test/no_prompt_by_default.out",
});
itest!(no_prompt_with_denied_perms {
args: "test --quiet --allow-read test/no_prompt_with_denied_perms.ts",
exit_code: 1,
output: "test/no_prompt_with_denied_perms.out",
});
itest!(test_with_custom_jsx {
args: "test --quiet --allow-read test/hello_world.ts --config=test/deno_custom_jsx.json",
exit_code: 0,
output: "test/hello_world.out",
});
#[test]
fn captured_output() {
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("test")
.arg("--allow-run")
.arg("--allow-read")
.arg("--unstable")
.arg("test/captured_output.ts")
.env("NO_COLOR", "1")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
let output_start = "------- output -------";
let output_end = "----- output end -----";
assert!(output.status.success());
let output_text = String::from_utf8(output.stdout).unwrap();
let start = output_text.find(output_start).unwrap() + output_start.len();
let end = output_text.find(output_end).unwrap();
// replace zero width space that may appear in test output due
// to test runner output flusher
let output_text = output_text[start..end]
.replace('\u{200B}', "")
.trim()
.to_string();
let mut lines = output_text.lines().collect::<Vec<_>>();
// the output is racy on either stdout or stderr being flushed
// from the runtime into the rust code, so sort it... the main
// thing here to ensure is that we're capturing the output in
// this block on stdout
lines.sort_unstable();
assert_eq!(lines.join(" "), "0 1 2 3 4 5 6 7 8 9");
}
#[test]
fn recursive_permissions_pledge() {
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("test")
.arg("test/recursive_permissions_pledge.js")
.stderr(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert!(String::from_utf8(output.stderr).unwrap().contains(
"pledge test permissions called before restoring previous pledge"
));
}
#[test]
fn file_protocol() {
let file_url =
Url::from_file_path(util::testdata_path().join("test/file_protocol.ts"))
.unwrap()
.to_string();
(util::CheckOutputIntegrationTest {
args_vec: vec!["test", &file_url],
exit_code: 0,
output: "test/file_protocol.out",
..Default::default()
})
.run();
}
itest!(uncaught_errors {
args: "test --quiet test/uncaught_errors_1.ts test/uncaught_errors_2.ts test/uncaught_errors_3.ts",
output: "test/uncaught_errors.out",
exit_code: 1,
});
itest!(check_local_by_default {
args: "test --quiet test/check_local_by_default.ts",
output: "test/check_local_by_default.out",
http_server: true,
});
itest!(check_local_by_default2 {
args: "test --quiet test/check_local_by_default2.ts",
output: "test/check_local_by_default2.out",
http_server: true,
exit_code: 1,
});
itest!(non_error_thrown {
args: "test --quiet test/non_error_thrown.ts",
output: "test/non_error_thrown.out",
exit_code: 1,
});
itest!(parallel_output {
args: "test --parallel --reload test/parallel_output.ts",
output: "test/parallel_output.out",
exit_code: 1,
});

View file

@ -1,193 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::process::{Command, Stdio};
use test_util as util;
use test_util::TempDir;
// Warning: this test requires internet access.
// TODO(#7412): reenable. test is flaky
#[test]
#[ignore]
fn upgrade_in_tmpdir() {
let temp_dir = TempDir::new();
let exe_path = temp_dir.path().join("deno");
let _ = std::fs::copy(util::deno_exe_path(), &exe_path).unwrap();
assert!(exe_path.exists());
let _mtime1 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
let status = Command::new(&exe_path)
.arg("upgrade")
.arg("--force")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let _mtime2 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
// TODO(ry) assert!(mtime1 < mtime2);
}
// Warning: this test requires internet access.
// TODO(#7412): reenable. test is flaky
#[test]
#[ignore]
fn upgrade_with_space_in_path() {
let temp_dir = TempDir::new_with_prefix("directory with spaces");
let exe_path = temp_dir.path().join("deno");
let _ = std::fs::copy(util::deno_exe_path(), &exe_path).unwrap();
assert!(exe_path.exists());
let status = Command::new(&exe_path)
.arg("upgrade")
.arg("--force")
.env("TMP", temp_dir.path())
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
// Warning: this test requires internet access.
// TODO(#7412): reenable. test is flaky
#[test]
#[ignore]
fn upgrade_with_version_in_tmpdir() {
let temp_dir = TempDir::new();
let exe_path = temp_dir.path().join("deno");
let _ = std::fs::copy(util::deno_exe_path(), &exe_path).unwrap();
assert!(exe_path.exists());
let _mtime1 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
let status = Command::new(&exe_path)
.arg("upgrade")
.arg("--force")
.arg("--version")
.arg("1.11.5")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let upgraded_deno_version = String::from_utf8(
Command::new(&exe_path).arg("-V").output().unwrap().stdout,
)
.unwrap();
assert!(upgraded_deno_version.contains("1.11.5"));
let _mtime2 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
// TODO(ry) assert!(mtime1 < mtime2);
}
// Warning: this test requires internet access.
// TODO(#7412): reenable. test is flaky
#[test]
#[ignore]
fn upgrade_with_canary_in_tmpdir() {
let temp_dir = TempDir::new();
let exe_path = temp_dir.path().join("deno");
let _ = std::fs::copy(util::deno_exe_path(), &exe_path).unwrap();
assert!(exe_path.exists());
let _mtime1 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
let status = Command::new(&exe_path)
.arg("upgrade")
.arg("--canary")
.arg("--version")
.arg("e6685f0f01b8a11a5eaff020f5babcfde76b3038")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let upgraded_deno_version = String::from_utf8(
Command::new(&exe_path).arg("-V").output().unwrap().stdout,
)
.unwrap();
assert!(upgraded_deno_version.contains("e6685f0"));
let _mtime2 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
// TODO(ry) assert!(mtime1 < mtime2);
}
// Warning: this test requires internet access.
// TODO(#7412): reenable. test is flaky
#[test]
#[ignore]
fn upgrade_with_out_in_tmpdir() {
let temp_dir = TempDir::new();
let exe_path = temp_dir.path().join("deno");
let new_exe_path = temp_dir.path().join("foo");
let _ = std::fs::copy(util::deno_exe_path(), &exe_path).unwrap();
assert!(exe_path.exists());
let mtime1 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
let status = Command::new(&exe_path)
.arg("upgrade")
.arg("--version")
.arg("1.11.5")
.arg("--output")
.arg(new_exe_path.to_str().unwrap())
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
assert!(new_exe_path.exists());
let mtime2 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
assert_eq!(mtime1, mtime2); // Original exe_path was not changed.
let v = String::from_utf8(
Command::new(&new_exe_path)
.arg("-V")
.output()
.unwrap()
.stdout,
)
.unwrap();
assert!(v.contains("1.11.5"));
}
// Warning: this test requires internet access.
// TODO(#7412): reenable. test is flaky
#[test]
#[ignore]
fn upgrade_invalid_stable_version() {
let temp_dir = TempDir::new();
let exe_path = temp_dir.path().join("deno");
let _ = std::fs::copy(util::deno_exe_path(), &exe_path).unwrap();
assert!(exe_path.exists());
let output = Command::new(&exe_path)
.arg("upgrade")
.arg("--version")
.arg("foobar")
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert_eq!(
"error: Invalid semver passed\n",
util::strip_ansi_codes(&String::from_utf8(output.stderr).unwrap())
);
}
// Warning: this test requires internet access.
// TODO(#7412): reenable. test is flaky
#[test]
#[ignore]
fn upgrade_invalid_canary_version() {
let temp_dir = TempDir::new();
let exe_path = temp_dir.path().join("deno");
let _ = std::fs::copy(util::deno_exe_path(), &exe_path).unwrap();
assert!(exe_path.exists());
let output = Command::new(&exe_path)
.arg("upgrade")
.arg("--canary")
.arg("--version")
.arg("foobar")
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
assert_eq!(
"error: Invalid commit hash passed\n",
util::strip_ansi_codes(&String::from_utf8(output.stderr).unwrap())
);
}

View file

@ -1,574 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::serde_json;
use deno_core::serde_json::json;
use pretty_assertions::assert_eq;
use std::fmt::Write as _;
use std::path::PathBuf;
use std::process::Stdio;
use test_util as util;
use test_util::TempDir;
use util::http_server;
use util::new_deno_dir;
#[test]
fn output_dir_exists() {
let t = TempDir::new();
t.write("mod.ts", "");
t.create_dir_all("vendor");
t.write("vendor/mod.ts", "");
let deno = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("vendor")
.arg("mod.ts")
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(
String::from_utf8_lossy(&output.stderr).trim(),
concat!(
"error: Output directory was not empty. Please specify an empty ",
"directory or use --force to ignore this error and potentially ",
"overwrite its contents.",
),
);
assert!(!output.status.success());
// ensure it errors when using the `--output` arg too
let deno = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("vendor")
.arg("--output")
.arg("vendor")
.arg("mod.ts")
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(
String::from_utf8_lossy(&output.stderr).trim(),
concat!(
"error: Output directory was not empty. Please specify an empty ",
"directory or use --force to ignore this error and potentially ",
"overwrite its contents.",
),
);
assert!(!output.status.success());
// now use `--force`
let status = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("vendor")
.arg("mod.ts")
.arg("--force")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
#[test]
fn standard_test() {
let _server = http_server();
let t = TempDir::new();
let vendor_dir = t.path().join("vendor2");
t.write(
"my_app.ts",
"import {Logger} from 'http://localhost:4545/vendor/query_reexport.ts?testing'; new Logger().log('outputted');",
);
let deno = util::deno_cmd()
.current_dir(t.path())
.arg("vendor")
.arg("my_app.ts")
.arg("--output")
.arg("vendor2")
.env("NO_COLOR", "1")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(
String::from_utf8_lossy(&output.stderr).trim(),
format!(
concat!(
"Download http://localhost:4545/vendor/query_reexport.ts?testing\n",
"Download http://localhost:4545/vendor/logger.ts?test\n",
"{}",
),
success_text("2 modules", "vendor2", true),
)
);
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "");
assert!(output.status.success());
assert!(vendor_dir.exists());
assert!(!t.path().join("vendor").exists());
let import_map: serde_json::Value =
serde_json::from_str(&t.read_to_string("vendor2/import_map.json")).unwrap();
assert_eq!(
import_map,
json!({
"imports": {
"http://localhost:4545/vendor/query_reexport.ts?testing": "./localhost_4545/vendor/query_reexport.ts",
"http://localhost:4545/": "./localhost_4545/",
},
"scopes": {
"./localhost_4545/": {
"./localhost_4545/vendor/logger.ts?test": "./localhost_4545/vendor/logger.ts"
}
}
}),
);
// try running the output with `--no-remote`
let deno = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("run")
.arg("--no-remote")
.arg("--check")
.arg("--quiet")
.arg("--import-map")
.arg("vendor2/import_map.json")
.arg("my_app.ts")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(String::from_utf8_lossy(&output.stderr).trim(), "");
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "outputted");
assert!(output.status.success());
}
#[test]
fn import_map_output_dir() {
let _server = http_server();
let t = TempDir::new();
t.write("mod.ts", "");
t.create_dir_all("vendor");
t.write(
"vendor/import_map.json",
// will be ignored
"{ \"imports\": { \"https://localhost:4545/\": \"./localhost/\" }}",
);
t.write(
"deno.json",
"{ \"import_map\": \"./vendor/import_map.json\" }",
);
t.write(
"my_app.ts",
"import {Logger} from 'http://localhost:4545/vendor/logger.ts'; new Logger().log('outputted');",
);
let deno = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("vendor")
.arg("--force")
.arg("--import-map")
.arg("vendor/import_map.json")
.arg("my_app.ts")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(
String::from_utf8_lossy(&output.stderr).trim(),
format!(
concat!(
"Ignoring import map. Specifying an import map file ({}) in the deno ",
"vendor output directory is not supported. If you wish to use an ",
"import map while vendoring, please specify one located outside this ",
"directory.\n",
"Download http://localhost:4545/vendor/logger.ts\n",
"{}",
),
PathBuf::from("vendor").join("import_map.json").display(),
success_text_updated_deno_json("1 module", "vendor/"),
)
);
assert!(output.status.success());
}
#[test]
fn remote_module_test() {
let _server = http_server();
let t = TempDir::new();
let vendor_dir = t.path().join("vendor");
let deno = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("vendor")
.arg("http://localhost:4545/vendor/query_reexport.ts")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(
String::from_utf8_lossy(&output.stderr).trim(),
format!(
concat!(
"Download http://localhost:4545/vendor/query_reexport.ts\n",
"Download http://localhost:4545/vendor/logger.ts?test\n",
"{}",
),
success_text("2 modules", "vendor/", true),
)
);
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "");
assert!(output.status.success());
assert!(vendor_dir.exists());
assert!(vendor_dir
.join("localhost_4545/vendor/query_reexport.ts")
.exists());
assert!(vendor_dir.join("localhost_4545/vendor/logger.ts").exists());
let import_map: serde_json::Value =
serde_json::from_str(&t.read_to_string("vendor/import_map.json")).unwrap();
assert_eq!(
import_map,
json!({
"imports": {
"http://localhost:4545/": "./localhost_4545/",
},
"scopes": {
"./localhost_4545/": {
"./localhost_4545/vendor/logger.ts?test": "./localhost_4545/vendor/logger.ts",
}
}
}),
);
}
#[test]
fn existing_import_map_no_remote() {
let _server = http_server();
let t = TempDir::new();
t.write(
"mod.ts",
"import {Logger} from 'http://localhost:4545/vendor/logger.ts';",
);
let import_map_filename = "imports2.json";
let import_map_text =
r#"{ "imports": { "http://localhost:4545/vendor/": "./logger/" } }"#;
t.write(import_map_filename, import_map_text);
t.create_dir_all("logger");
t.write("logger/logger.ts", "export class Logger {}");
let deno = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("vendor")
.arg("mod.ts")
.arg("--import-map")
.arg(import_map_filename)
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(
String::from_utf8_lossy(&output.stderr).trim(),
success_text("0 modules", "vendor/", false)
);
assert!(output.status.success());
// it should not have found any remote dependencies because
// the provided import map mapped it to a local directory
assert_eq!(t.read_to_string(import_map_filename), import_map_text);
}
#[test]
fn existing_import_map_mixed_with_remote() {
let _server = http_server();
let deno_dir = new_deno_dir();
let t = TempDir::new();
t.write(
"mod.ts",
"import {Logger} from 'http://localhost:4545/vendor/logger.ts';",
);
let status = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(t.path())
.arg("vendor")
.arg("mod.ts")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
assert_eq!(
t.read_to_string("vendor/import_map.json"),
r#"{
"imports": {
"http://localhost:4545/": "./localhost_4545/"
}
}
"#,
);
// make the import map specific to support vendoring mod.ts in the next step
t.write(
"vendor/import_map.json",
r#"{
"imports": {
"http://localhost:4545/vendor/logger.ts": "./localhost_4545/vendor/logger.ts"
}
}
"#,
);
t.write(
"mod.ts",
concat!(
"import {Logger} from 'http://localhost:4545/vendor/logger.ts';\n",
"import {Logger as OtherLogger} from 'http://localhost:4545/vendor/mod.ts';\n",
),
);
// now vendor with the existing import map in a separate vendor directory
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
.env("NO_COLOR", "1")
.current_dir(t.path())
.arg("vendor")
.arg("mod.ts")
.arg("--import-map")
.arg("vendor/import_map.json")
.arg("--output")
.arg("vendor2")
.stderr(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(
String::from_utf8_lossy(&output.stderr).trim(),
format!(
concat!("Download http://localhost:4545/vendor/mod.ts\n", "{}",),
success_text("1 module", "vendor2", true),
)
);
assert!(output.status.success());
// tricky scenario here where the output directory now contains a mapping
// back to the previous vendor location
assert_eq!(
t.read_to_string("vendor2/import_map.json"),
r#"{
"imports": {
"http://localhost:4545/vendor/logger.ts": "../vendor/localhost_4545/vendor/logger.ts",
"http://localhost:4545/": "./localhost_4545/"
},
"scopes": {
"./localhost_4545/": {
"./localhost_4545/vendor/logger.ts": "../vendor/localhost_4545/vendor/logger.ts"
}
}
}
"#,
);
// ensure it runs
let status = util::deno_cmd()
.current_dir(t.path())
.arg("run")
.arg("--check")
.arg("--no-remote")
.arg("--import-map")
.arg("vendor2/import_map.json")
.arg("mod.ts")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
#[test]
fn dynamic_import() {
let _server = http_server();
let t = TempDir::new();
t.write(
"mod.ts",
"import {Logger} from 'http://localhost:4545/vendor/dynamic.ts'; new Logger().log('outputted');",
);
let status = util::deno_cmd()
.current_dir(t.path())
.arg("vendor")
.arg("mod.ts")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let import_map: serde_json::Value =
serde_json::from_str(&t.read_to_string("vendor/import_map.json")).unwrap();
assert_eq!(
import_map,
json!({
"imports": {
"http://localhost:4545/": "./localhost_4545/",
}
}),
);
// try running the output with `--no-remote`
let deno = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("run")
.arg("--allow-read=.")
.arg("--no-remote")
.arg("--check")
.arg("--quiet")
.arg("--import-map")
.arg("vendor/import_map.json")
.arg("mod.ts")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(String::from_utf8_lossy(&output.stderr).trim(), "");
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "outputted");
assert!(output.status.success());
}
#[test]
fn dynamic_non_analyzable_import() {
let _server = http_server();
let t = TempDir::new();
t.write(
"mod.ts",
"import {Logger} from 'http://localhost:4545/vendor/dynamic_non_analyzable.ts'; new Logger().log('outputted');",
);
let deno = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("vendor")
.arg("--reload")
.arg("mod.ts")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
// todo(https://github.com/denoland/deno_graph/issues/138): it should warn about
// how it couldn't analyze the dynamic import
assert_eq!(
String::from_utf8_lossy(&output.stderr).trim(),
format!(
"Download http://localhost:4545/vendor/dynamic_non_analyzable.ts\n{}",
success_text("1 module", "vendor/", true),
)
);
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "");
assert!(output.status.success());
}
#[test]
fn update_existing_config_test() {
let _server = http_server();
let t = TempDir::new();
t.write(
"my_app.ts",
"import {Logger} from 'http://localhost:4545/vendor/logger.ts'; new Logger().log('outputted');",
);
t.write("deno.json", "{\n}");
let deno = util::deno_cmd()
.current_dir(t.path())
.arg("vendor")
.arg("my_app.ts")
.arg("--output")
.arg("vendor2")
.env("NO_COLOR", "1")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(
String::from_utf8_lossy(&output.stderr).trim(),
format!(
"Download http://localhost:4545/vendor/logger.ts\n{}",
success_text_updated_deno_json("1 module", "vendor2",)
)
);
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "");
assert!(output.status.success());
// try running the output with `--no-remote` and not specifying a `--vendor`
let deno = util::deno_cmd()
.current_dir(t.path())
.env("NO_COLOR", "1")
.arg("run")
.arg("--no-remote")
.arg("--check")
.arg("--quiet")
.arg("my_app.ts")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert_eq!(String::from_utf8_lossy(&output.stderr).trim(), "");
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "outputted");
assert!(output.status.success());
}
fn success_text(module_count: &str, dir: &str, has_import_map: bool) -> String {
let mut text = format!("Vendored {} into {} directory.", module_count, dir);
if has_import_map {
let f = format!(
concat!(
"\n\nTo use vendored modules, specify the `--import-map {}import_map.json` flag when ",
r#"invoking Deno subcommands or add an `"importMap": "<path_to_vendored_import_map>"` "#,
"entry to a deno.json file.",
),
if dir != "vendor/" {
format!("{}{}", dir.trim_end_matches('/'), if cfg!(windows) { '\\' } else {'/'})
} else {
dir.to_string()
}
);
write!(text, "{}", f).unwrap();
}
text
}
fn success_text_updated_deno_json(module_count: &str, dir: &str) -> String {
format!(
concat!(
"Vendored {} into {} directory.\n\n",
"Updated your local Deno configuration file with a reference to the ",
"new vendored import map at {}import_map.json. Invoking Deno subcommands will ",
"now automatically resolve using the vendored modules. You may override ",
"this by providing the `--import-map <other-import-map>` flag or by ",
"manually editing your Deno configuration file.",
),
module_count,
dir,
if dir != "vendor/" {
format!(
"{}{}",
dir.trim_end_matches('/'),
if cfg!(windows) { '\\' } else { '/' }
)
} else {
dir.to_string()
}
)
}

File diff suppressed because it is too large Load diff

View file

@ -1,112 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::itest;
itest!(workers {
args: "test --reload --location http://127.0.0.1:4545/ -A --unstable workers/test.ts",
output: "workers/test.ts.out",
http_server: true,
});
itest!(worker_error {
args: "run -A workers/worker_error.ts",
output: "workers/worker_error.ts.out",
exit_code: 1,
});
itest!(worker_nested_error {
args: "run -A workers/worker_nested_error.ts",
output: "workers/worker_nested_error.ts.out",
exit_code: 1,
});
itest!(worker_async_error {
args: "run -A --quiet --reload workers/worker_async_error.ts",
output: "workers/worker_async_error.ts.out",
http_server: true,
exit_code: 1,
});
itest!(worker_message_handler_error {
args: "run -A --quiet --reload workers/worker_message_handler_error.ts",
output: "workers/worker_message_handler_error.ts.out",
http_server: true,
exit_code: 1,
});
itest!(nonexistent_worker {
args: "run --allow-read workers/nonexistent_worker.ts",
output: "workers/nonexistent_worker.out",
exit_code: 1,
});
itest!(_084_worker_custom_inspect {
args: "run --allow-read workers/custom_inspect/main.ts",
output: "workers/custom_inspect/main.out",
});
itest!(error_worker_permissions_local {
args: "run --reload workers/error_worker_permissions_local.ts",
output: "workers/error_worker_permissions_local.ts.out",
exit_code: 1,
});
itest!(error_worker_permissions_remote {
args: "run --reload workers/error_worker_permissions_remote.ts",
http_server: true,
output: "workers/error_worker_permissions_remote.ts.out",
exit_code: 1,
});
itest!(worker_permissions_remote_remote {
args: "run --quiet --reload --allow-net=localhost:4545 workers/permissions_remote_remote.ts",
output: "workers/permissions_remote_remote.ts.out",
http_server: true,
exit_code: 1,
});
itest!(worker_permissions_dynamic_remote {
args: "run --quiet --reload --allow-net --unstable workers/permissions_dynamic_remote.ts",
output: "workers/permissions_dynamic_remote.ts.out",
http_server: true,
exit_code: 1,
});
itest!(worker_permissions_data_remote {
args: "run --quiet --reload --allow-net=localhost:4545 workers/permissions_data_remote.ts",
output: "workers/permissions_data_remote.ts.out",
http_server: true,
exit_code: 1,
});
itest!(worker_permissions_blob_remote {
args: "run --quiet --reload --allow-net=localhost:4545 workers/permissions_blob_remote.ts",
output: "workers/permissions_blob_remote.ts.out",
http_server: true,
exit_code: 1,
});
itest!(worker_permissions_data_local {
args: "run --quiet --reload --allow-net=localhost:4545 workers/permissions_data_local.ts",
output: "workers/permissions_data_local.ts.out",
http_server: true,
exit_code: 1,
});
itest!(worker_permissions_blob_local {
args: "run --quiet --reload --allow-net=localhost:4545 workers/permissions_blob_local.ts",
output: "workers/permissions_blob_local.ts.out",
http_server: true,
exit_code: 1,
});
itest!(worker_terminate_tla_crash {
args: "run --quiet --reload workers/terminate_tla_crash.js",
output: "workers/terminate_tla_crash.js.out",
});
itest!(worker_error_event {
args: "run --quiet -A workers/error_event.ts",
output: "workers/error_event.ts.out",
exit_code: 1,
});

Some files were not shown because too many files have changed in this diff Show more