diff --git a/cli/node/mod.rs b/cli/node/mod.rs index fc4db33ee2..fa6f0bddaa 100644 --- a/cli/node/mod.rs +++ b/cli/node/mod.rs @@ -636,17 +636,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)?; diff --git a/cli/tests/inspector_tests.rs b/cli/tests/inspector_tests.rs index 94ebbb2058..407e8f071f 100644 --- a/cli/tests/inspector_tests.rs +++ b/cli/tests/inspector_tests.rs @@ -12,6 +12,7 @@ use std::io::BufRead; use std::pin::Pin; use test_util as util; use tokio::net::TcpStream; +use util::http_server; mod inspector { use super::*; @@ -1133,4 +1134,177 @@ mod inspector { child.kill().unwrap(); child.wait().unwrap(); } + + #[tokio::test] + async fn inspector_break_on_first_line_npm_esm() { + let _server = http_server(); + + let mut child = util::deno_cmd() + .arg("run") + .arg("--quiet") + .arg(inspect_flag_with_unique_port("--inspect-brk")) + .arg("npm:@denotest/bin/cli-esm") + .arg("this") + .arg("is") + .arg("a") + .arg("test") + .envs(util::env_vars_for_npm_tests()) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .spawn() + .unwrap(); + + let stderr = child.stderr.as_mut().unwrap(); + let mut stderr_lines = + std::io::BufReader::new(stderr).lines().map(|r| r.unwrap()); + let ws_url = extract_ws_url_from_stderr(&mut stderr_lines); + + let (socket, response) = + tokio_tungstenite::connect_async(ws_url).await.unwrap(); + assert_eq!(response.status(), 101); // Switching protocols. + + let (mut socket_tx, socket_rx) = socket.split(); + let mut socket_rx = socket_rx + .map(|msg| msg.unwrap().to_string()) + .filter(|msg| { + let pass = !msg.starts_with(r#"{"method":"Debugger.scriptParsed","#); + futures::future::ready(pass) + }) + .boxed_local(); + + let stdout = child.stdout.as_mut().unwrap(); + let mut stdout_lines = + std::io::BufReader::new(stdout).lines().map(|r| r.unwrap()); + + assert_stderr_for_inspect_brk(&mut stderr_lines); + + assert_inspector_messages( + &mut socket_tx, + &[ + r#"{"id":1,"method":"Runtime.enable"}"#, + r#"{"id":2,"method":"Debugger.enable"}"#, + ], + &mut socket_rx, + &[ + r#"{"id":1,"result":{}}"#, + r#"{"id":2,"result":{"debuggerId":"#, + ], + &[ + r#"{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"#, + ], + ) + .await; + + assert_inspector_messages( + &mut socket_tx, + &[r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#], + &mut socket_rx, + &[r#"{"id":3,"result":{}}"#], + &[r#"{"method":"Debugger.paused","#], + ) + .await; + + assert_inspector_messages( + &mut socket_tx, + &[r#"{"id":4,"method":"Debugger.resume"}"#], + &mut socket_rx, + &[r#"{"id":4,"result":{}}"#], + &[], + ) + .await; + + assert_eq!(&stdout_lines.next().unwrap(), "this"); + assert_eq!(&stdout_lines.next().unwrap(), "is"); + assert_eq!(&stdout_lines.next().unwrap(), "a"); + assert_eq!(&stdout_lines.next().unwrap(), "test"); + + child.kill().unwrap(); + child.wait().unwrap(); + } + + #[tokio::test] + async fn inspector_break_on_first_line_npm_cjs() { + let _server = http_server(); + let mut child = util::deno_cmd() + .arg("run") + .arg("--quiet") + .arg(inspect_flag_with_unique_port("--inspect-brk")) + .arg("npm:@denotest/bin/cli-cjs") + .arg("this") + .arg("is") + .arg("a") + .arg("test") + .envs(util::env_vars_for_npm_tests()) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .spawn() + .unwrap(); + + let stderr = child.stderr.as_mut().unwrap(); + let mut stderr_lines = + std::io::BufReader::new(stderr).lines().map(|r| r.unwrap()); + let ws_url = extract_ws_url_from_stderr(&mut stderr_lines); + + let (socket, response) = + tokio_tungstenite::connect_async(ws_url).await.unwrap(); + assert_eq!(response.status(), 101); // Switching protocols. + + let (mut socket_tx, socket_rx) = socket.split(); + let mut socket_rx = socket_rx + .map(|msg| msg.unwrap().to_string()) + .filter(|msg| { + let pass = !msg.starts_with(r#"{"method":"Debugger.scriptParsed","#); + futures::future::ready(pass) + }) + .boxed_local(); + + let stdout = child.stdout.as_mut().unwrap(); + let mut stdout_lines = + std::io::BufReader::new(stdout).lines().map(|r| r.unwrap()); + + assert_stderr_for_inspect_brk(&mut stderr_lines); + + assert_inspector_messages( + &mut socket_tx, + &[ + r#"{"id":1,"method":"Runtime.enable"}"#, + r#"{"id":2,"method":"Debugger.enable"}"#, + ], + &mut socket_rx, + &[ + r#"{"id":1,"result":{}}"#, + r#"{"id":2,"result":{"debuggerId":"#, + ], + &[ + r#"{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"#, + ], + ) + .await; + + assert_inspector_messages( + &mut socket_tx, + &[r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#], + &mut socket_rx, + &[r#"{"id":3,"result":{}}"#], + &[r#"{"method":"Debugger.paused","#], + ) + .await; + + assert_inspector_messages( + &mut socket_tx, + &[r#"{"id":4,"method":"Debugger.resume"}"#], + &mut socket_rx, + &[r#"{"id":4,"result":{}}"#], + &[], + ) + .await; + + assert_eq!(&stdout_lines.next().unwrap(), "this"); + assert_eq!(&stdout_lines.next().unwrap(), "is"); + assert_eq!(&stdout_lines.next().unwrap(), "a"); + assert_eq!(&stdout_lines.next().unwrap(), "test"); + + child.kill().unwrap(); + child.wait().unwrap(); + } } diff --git a/cli/tests/npm_tests.rs b/cli/tests/npm_tests.rs index 3939ee7bec..9c53fdeac4 100644 --- a/cli/tests/npm_tests.rs +++ b/cli/tests/npm_tests.rs @@ -8,6 +8,8 @@ mod npm { use std::process::Stdio; use test_util as util; use util::assert_contains; + use util::env_vars_for_npm_tests; + use util::env_vars_for_npm_tests_no_sync_download; use util::http_server; // NOTE: See how to make test npm packages at ./testdata/npm/README.md @@ -15,7 +17,7 @@ mod npm { itest!(esm_module { args: "run --allow-read --allow-env npm/esm/main.js", output: "npm/esm/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -25,56 +27,56 @@ mod npm { "import chalk from 'npm:chalk@5'; console.log(chalk.green('chalk esm loads'));", ], output: "npm/esm/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(esm_module_deno_test { args: "test --allow-read --allow-env --unstable npm/esm/test.js", output: "npm/esm/test.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(esm_import_cjs_default { args: "run --allow-read --allow-env --unstable --quiet --check=all npm/esm_import_cjs_default/main.ts", output: "npm/esm_import_cjs_default/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(cjs_with_deps { args: "run --allow-read --allow-env npm/cjs_with_deps/main.js", output: "npm/cjs_with_deps/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(cjs_sub_path { args: "run --allow-read npm/cjs_sub_path/main.js", output: "npm/cjs_sub_path/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(cjs_local_global_decls { args: "run --allow-read npm/cjs_local_global_decls/main.ts", output: "npm/cjs_local_global_decls/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(cjs_reexport_collision { args: "run -A --quiet npm/cjs_reexport_collision/main.ts", output: "npm/cjs_reexport_collision/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(cjs_this_in_exports { args: "run --allow-read --quiet npm/cjs_this_in_exports/main.js", output: "npm/cjs_this_in_exports/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -82,49 +84,49 @@ mod npm { itest!(translate_cjs_to_esm { args: "run -A --quiet npm/translate_cjs_to_esm/main.js", output: "npm/translate_cjs_to_esm/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(compare_globals { args: "run --allow-read --unstable --check=all npm/compare_globals/main.ts", output: "npm/compare_globals/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(conditional_exports { args: "run --allow-read npm/conditional_exports/main.js", output: "npm/conditional_exports/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(dual_cjs_esm { args: "run -A --quiet npm/dual_cjs_esm/main.ts", output: "npm/dual_cjs_esm/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(child_process_fork_test { args: "run -A --quiet npm/child_process_fork_test/main.ts", output: "npm/child_process_fork_test/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(cjs_module_export_assignment { args: "run -A --unstable --quiet --check=all npm/cjs_module_export_assignment/main.ts", output: "npm/cjs_module_export_assignment/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(cjs_module_export_assignment_number { args: "run -A --unstable --quiet --check=all npm/cjs_module_export_assignment_number/main.ts", output: "npm/cjs_module_export_assignment_number/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -132,7 +134,7 @@ mod npm { args: "run npm/mixed_case_package_name/global.ts", output: "npm/mixed_case_package_name/global.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -141,7 +143,7 @@ mod npm { "run --node-modules-dir -A $TESTDATA/npm/mixed_case_package_name/local.ts", output: "npm/mixed_case_package_name/local.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, temp_cwd: true, }); @@ -151,21 +153,21 @@ mod npm { // itest!(dynamic_import { // args: "run --allow-read --allow-env npm/dynamic_import/main.ts", // output: "npm/dynamic_import/main.out", - // envs: env_vars(), + // envs: env_vars_for_npm_tests(), // http_server: true, // }); itest!(dynamic_import_reload_same_package { args: "run -A --reload npm/dynamic_import_reload_same_package/main.ts", output: "npm/dynamic_import_reload_same_package/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(env_var_re_export_dev { args: "run --allow-read --allow-env --quiet npm/env_var_re_export/main.js", output_str: Some("dev\n"), - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -173,7 +175,7 @@ mod npm { args: "run --allow-read --allow-env --quiet npm/env_var_re_export/main.js", output_str: Some("prod\n"), envs: { - let mut vars = env_vars(); + let mut vars = env_vars_for_npm_tests(); vars.push(("NODE_ENV".to_string(), "production".to_string())); vars }, @@ -183,21 +185,21 @@ mod npm { itest!(cached_only { args: "run --cached-only npm/cached_only/main.ts", output: "npm/cached_only/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), exit_code: 1, }); itest!(import_map { args: "run --allow-read --allow-env --import-map npm/import_map/import_map.json npm/import_map/main.js", output: "npm/import_map/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(lock_file { args: "run --allow-read --allow-env --lock npm/lock_file/lock.json npm/lock_file/main.js", output: "npm/lock_file/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 10, }); @@ -205,14 +207,14 @@ mod npm { itest!(sub_paths { args: "run -A --quiet npm/sub_paths/main.jsx", output: "npm/sub_paths/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(remote_npm_specifier { args: "run --quiet npm/remote_npm_specifier/main.ts", output: "npm/remote_npm_specifier/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -220,14 +222,14 @@ mod npm { itest!(tarball_with_global_header { args: "run -A --quiet npm/tarball_with_global_header/main.js", output: "npm/tarball_with_global_header/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(nonexistent_file { args: "run -A --quiet npm/nonexistent_file/main.js", output: "npm/nonexistent_file/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -235,21 +237,21 @@ mod npm { itest!(invalid_package_name { args: "run -A --quiet npm/invalid_package_name/main.js", output: "npm/invalid_package_name/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), exit_code: 1, }); itest!(require_json { args: "run -A --quiet npm/require_json/main.js", output: "npm/require_json/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(error_version_after_subpath { args: "run -A --quiet npm/error_version_after_subpath/main.js", output: "npm/error_version_after_subpath/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -257,14 +259,14 @@ mod npm { itest!(deno_cache { args: "cache --reload npm:chalk npm:mkdirp", output: "npm/deno_cache.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(check_all { args: "check --remote npm/check_errors/main.ts", output: "npm/check_errors/main_all.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -272,7 +274,7 @@ mod npm { itest!(check_local { args: "check npm/check_errors/main.ts", output: "npm/check_errors/main_local.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -280,7 +282,7 @@ mod npm { itest!(types { args: "check --quiet npm/types/main.ts", output: "npm/types/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -288,7 +290,7 @@ mod npm { itest!(types_ambient_module { args: "check --quiet npm/types_ambient_module/main.ts", output: "npm/types_ambient_module/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -296,7 +298,7 @@ mod npm { itest!(types_ambient_module_import_map { args: "check --quiet --import-map=npm/types_ambient_module/import_map.json npm/types_ambient_module/main_import_map.ts", output: "npm/types_ambient_module/main_import_map.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -305,14 +307,14 @@ mod npm { args: "run --check --unstable npm/no_types_in_conditional_exports/main.ts", output: "npm/no_types_in_conditional_exports/main.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(types_entry_value_not_exists { args: "run --check=all npm/types_entry_value_not_exists/main.ts", output: "npm/types_entry_value_not_exists/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 0, }); @@ -320,7 +322,7 @@ mod npm { itest!(types_no_types_entry { args: "run --check=all npm/types_no_types_entry/main.ts", output: "npm/types_no_types_entry/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 0, }); @@ -328,7 +330,7 @@ mod npm { itest!(typescript_file_in_package { args: "run npm/typescript_file_in_package/main.ts", output: "npm/typescript_file_in_package/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -345,7 +347,7 @@ mod npm { ], None, // don't use the sync env var - Some(env_vars_no_sync_download()), + Some(env_vars_for_npm_tests_no_sync_download()), true, ); assert!(out.contains("chalk cjs loads")); @@ -364,7 +366,7 @@ mod npm { .arg("--allow-env") .arg("npm/cached_only_after_first_run/main1.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -384,7 +386,7 @@ mod npm { .arg("--cached-only") .arg("npm/cached_only_after_first_run/main2.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -407,7 +409,7 @@ mod npm { .arg("--cached-only") .arg("npm/cached_only_after_first_run/main1.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -434,7 +436,7 @@ mod npm { .arg("--allow-env") .arg("npm/reload/main.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -454,7 +456,7 @@ mod npm { .arg("--reload") .arg("npm/reload/main.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -474,7 +476,7 @@ mod npm { .arg("--reload=npm:") .arg("npm/reload/main.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -494,7 +496,7 @@ mod npm { .arg("--reload=npm:chalk") .arg("npm/reload/main.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -514,7 +516,7 @@ mod npm { .arg("--reload=npm:foobar") .arg("npm/reload/main.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -541,7 +543,7 @@ mod npm { .arg("--no-npm") .arg("npm/no_npm_after_first_run/main1.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -563,7 +565,7 @@ mod npm { .arg("--allow-env") .arg("npm/no_npm_after_first_run/main1.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -583,7 +585,7 @@ mod npm { .arg("--no-npm") .arg("npm/no_npm_after_first_run/main1.ts") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -614,7 +616,7 @@ mod npm { .arg("npm:mkdirp@1.0.4") .arg("test_dir") .env("NO_COLOR", "1") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -626,49 +628,49 @@ mod npm { itest!(deno_run_cowsay { args: "run -A --quiet npm:cowsay@1.5.0 Hello", output: "npm/deno_run_cowsay.out", - envs: env_vars_no_sync_download(), + envs: env_vars_for_npm_tests_no_sync_download(), http_server: true, }); itest!(deno_run_cowsay_explicit { args: "run -A --quiet npm:cowsay@1.5.0/cowsay Hello", output: "npm/deno_run_cowsay.out", - envs: env_vars_no_sync_download(), + envs: env_vars_for_npm_tests_no_sync_download(), http_server: true, }); itest!(deno_run_cowthink { args: "run -A --quiet npm:cowsay@1.5.0/cowthink Hello", output: "npm/deno_run_cowthink.out", - envs: env_vars_no_sync_download(), + envs: env_vars_for_npm_tests_no_sync_download(), http_server: true, }); itest!(deno_run_bin_esm { args: "run -A --quiet npm:@denotest/bin/cli-esm this is a test", output: "npm/deno_run_esm.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(deno_run_bin_no_ext { args: "run -A --quiet npm:@denotest/bin/cli-no-ext this is a test", output: "npm/deno_run_no_ext.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(deno_run_bin_cjs { args: "run -A --quiet npm:@denotest/bin/cli-cjs this is a test", output: "npm/deno_run_cjs.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); itest!(deno_run_non_existent { args: "run npm:mkdirp@0.5.125", output: "npm/deno_run_non_existent.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 1, }); @@ -676,7 +678,7 @@ mod npm { itest!(builtin_module_module { args: "run --allow-read --quiet npm/builtin_module_module/main.js", output: "npm/builtin_module_module/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -684,7 +686,7 @@ mod npm { args: "run --node-modules-dir -A --quiet $TESTDATA/npm/require_added_nm_folder/main.js", output: "npm/require_added_nm_folder/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, exit_code: 0, temp_cwd: true, @@ -693,7 +695,7 @@ mod npm { itest!(node_modules_dir_with_deps { args: "run --allow-read --allow-env --node-modules-dir $TESTDATA/npm/cjs_with_deps/main.js", output: "npm/cjs_with_deps/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, temp_cwd: true, }); @@ -701,7 +703,7 @@ mod npm { itest!(node_modules_dir_yargs { args: "run --allow-read --allow-env --node-modules-dir $TESTDATA/npm/cjs_yargs/main.js", output: "npm/cjs_yargs/main.out", - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, temp_cwd: true, }); @@ -718,7 +720,7 @@ mod npm { .arg("--node-modules-dir") .arg("--quiet") .arg(util::testdata_path().join("npm/dual_cjs_esm/main.ts")) - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -754,7 +756,7 @@ mod npm { .arg("--quiet") .arg("-A") .arg(util::testdata_path().join("npm/dual_cjs_esm/main.ts")) - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -792,7 +794,7 @@ mod npm { args: "compile -A --quiet npm/cached_only/main.ts", output_str: Some("error: npm specifiers have not yet been implemented for this sub command (https://github.com/denoland/deno/issues/15960). Found: npm:chalk@5\n"), exit_code: 1, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -800,7 +802,7 @@ mod npm { args: "bundle --quiet npm/esm/main.js", output_str: Some("error: npm specifiers have not yet been implemented for this sub command (https://github.com/denoland/deno/issues/15960). Found: npm:chalk@5\n"), exit_code: 1, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -808,7 +810,7 @@ mod npm { args: "info --quiet npm/cjs_with_deps/main.js", output: "npm/cjs_with_deps/main_info.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -816,7 +818,7 @@ mod npm { args: "info --quiet --node-modules-dir $TESTDATA/npm/cjs_with_deps/main.js", output: "npm/cjs_with_deps/main_info.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, temp_cwd: true, }); @@ -825,7 +827,7 @@ mod npm { args: "info --quiet --json npm/cjs_with_deps/main.js", output: "npm/cjs_with_deps/main_info_json.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -834,7 +836,7 @@ mod npm { "info --quiet --node-modules-dir --json $TESTDATA/npm/cjs_with_deps/main.js", output: "npm/cjs_with_deps/main_info_json.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, temp_cwd: true, }); @@ -843,7 +845,7 @@ mod npm { args: "info --quiet npm:chalk@4", output: "npm/info/chalk.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -851,7 +853,7 @@ mod npm { args: "info --quiet --json npm:chalk@4", output: "npm/info/chalk_json.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -1054,7 +1056,7 @@ mod npm { .arg("deno.lock") .arg("-A") .arg("main.ts") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1270,7 +1272,7 @@ mod npm { .arg("--lock-write") .arg("--quiet") .arg("npm:cowsay@1.5.0") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1322,7 +1324,7 @@ mod npm { .arg("-A") .arg("npm:@denotest/bin/cli-esm") .arg("test") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1358,7 +1360,7 @@ mod npm { .arg("run") .arg("-A") .arg("main.ts") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1389,7 +1391,7 @@ mod npm { .arg("run") .arg("-A") .arg("main.ts") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1404,7 +1406,7 @@ mod npm { .arg("--reload") .arg("-A") .arg("main.ts") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1420,7 +1422,7 @@ mod npm { .arg("--node-modules-dir") .arg("-A") .arg("main.ts") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1444,7 +1446,7 @@ mod npm { .arg("--node-modules-dir") .arg("-A") .arg("main.ts") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1461,7 +1463,7 @@ mod npm { .arg("--reload") .arg("-A") .arg("main.ts") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1479,7 +1481,7 @@ mod npm { .arg("--reload") .arg("-A") .arg("main.ts") - .envs(env_vars()) + .envs(env_vars_for_npm_tests()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -1493,7 +1495,7 @@ mod npm { args: "info --quiet npm/peer_deps_with_copied_folders/main.ts", output: "npm/peer_deps_with_copied_folders/main_info.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -1501,7 +1503,7 @@ mod npm { args: "info --quiet --json npm/peer_deps_with_copied_folders/main.ts", output: "npm/peer_deps_with_copied_folders/main_info_json.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); @@ -1509,25 +1511,7 @@ mod npm { args: "run --reload npm/create_require/main.ts", output: "npm/create_require/main.out", exit_code: 0, - envs: env_vars(), + envs: env_vars_for_npm_tests(), http_server: true, }); - - fn env_vars_no_sync_download() -> Vec<(String, String)> { - vec![ - ("DENO_NODE_COMPAT_URL".to_string(), util::std_file_url()), - ("DENO_NPM_REGISTRY".to_string(), util::npm_registry_url()), - ("NO_COLOR".to_string(), "1".to_string()), - ] - } - - fn env_vars() -> Vec<(String, String)> { - let mut env_vars = env_vars_no_sync_download(); - env_vars.push(( - // make downloads determinstic - "DENO_UNSTABLE_NPM_SYNC_DOWNLOAD".to_string(), - "1".to_string(), - )); - env_vars - } } diff --git a/cli/worker.rs b/cli/worker.rs index fb021b614c..ad7b4e8ed2 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -70,6 +70,7 @@ impl CliMainWorker { &mut self.worker.js_runtime, &self.main_module.to_file_path().unwrap().to_string_lossy(), true, + self.ps.options.inspect_brk().is_some(), )?; } else { self.execute_main_module_possibly_with_npm().await?; diff --git a/ext/node/02_require.js b/ext/node/02_require.js index 372cc84719..db43299117 100644 --- a/ext/node/02_require.js +++ b/ext/node/02_require.js @@ -69,6 +69,8 @@ let statCache = null; let isPreloading = false; let mainModule = null; + let hasBrokenOnInspectBrk = false; + let hasInspectBrk = false; function stat(filename) { // TODO: required only on windows @@ -723,6 +725,12 @@ if (requireDepth === 0) { statCache = new SafeMap(); } + + if (hasInspectBrk && !hasBrokenOnInspectBrk) { + hasBrokenOnInspectBrk = true; + core.ops.op_require_break_on_next_statement(); + } + const result = compiledWrapper.call( thisValue, exports, @@ -896,6 +904,9 @@ window.__bootstrap.internals = { ...window.__bootstrap.internals ?? {}, require: { + setInspectBrk() { + hasInspectBrk = true; + }, Module, wrapSafe, toRealPath, diff --git a/ext/node/lib.rs b/ext/node/lib.rs index d69d3b6fe5..0e84cea7bb 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -7,6 +7,7 @@ use deno_core::normalize_path; use deno_core::op; use deno_core::url::Url; use deno_core::Extension; +use deno_core::JsRuntimeInspector; use deno_core::OpState; use once_cell::sync::Lazy; use std::collections::HashSet; @@ -31,6 +32,7 @@ pub use resolution::path_to_declaration_path; pub use resolution::NodeModuleKind; pub use resolution::DEFAULT_CONDITIONS; pub use resolution::TYPES_CONDITIONS; +use std::cell::RefCell; pub trait NodePermissions { fn check_read(&mut self, path: &Path) -> Result<(), AnyError>; @@ -106,6 +108,7 @@ pub fn init( op_require_read_closest_package_json::decl::

(), op_require_read_package_scope::decl(), op_require_package_imports_resolve::decl::

(), + op_require_break_on_next_statement::decl(), ]) .state(move |state| { if let Some(npm_resolver) = maybe_npm_resolver.clone() { @@ -630,3 +633,11 @@ where Ok(None) } } + +#[op] +fn op_require_break_on_next_statement(state: &mut OpState) { + let inspector = state.borrow::>>(); + inspector + .borrow_mut() + .wait_for_session_and_break_on_next_statement() +} diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 89f0bd6c22..ee47d0d990 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -473,6 +473,12 @@ impl WebWorker { &mut js_runtime, false, ); + + // Put inspector handle into the op state so we can put a breakpoint when + // executing a CJS entrypoint. + let op_state = js_runtime.op_state(); + let inspector = js_runtime.inspector(); + op_state.borrow_mut().put(inspector); } let (internal_handle, external_handle) = { diff --git a/runtime/worker.rs b/runtime/worker.rs index 967d53ea82..01498e1f62 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -250,6 +250,12 @@ impl MainWorker { &mut js_runtime, options.should_break_on_first_statement, ); + + // Put inspector handle into the op state so we can put a breakpoint when + // executing a CJS entrypoint. + let op_state = js_runtime.op_state(); + let inspector = js_runtime.inspector(); + op_state.borrow_mut().put(inspector); } Self { diff --git a/test_util/src/lib.rs b/test_util/src/lib.rs index 3b23af7364..b1b14c0040 100644 --- a/test_util/src/lib.rs +++ b/test_util/src/lib.rs @@ -94,6 +94,24 @@ lazy_static! { static ref GUARD: Mutex = Mutex::new(HttpServerCount::default()); } +pub fn env_vars_for_npm_tests_no_sync_download() -> Vec<(String, String)> { + vec![ + ("DENO_NODE_COMPAT_URL".to_string(), std_file_url()), + ("DENO_NPM_REGISTRY".to_string(), npm_registry_url()), + ("NO_COLOR".to_string(), "1".to_string()), + ] +} + +pub fn env_vars_for_npm_tests() -> Vec<(String, String)> { + let mut env_vars = env_vars_for_npm_tests_no_sync_download(); + env_vars.push(( + // make downloads determinstic + "DENO_UNSTABLE_NPM_SYNC_DOWNLOAD".to_string(), + "1".to_string(), + )); + env_vars +} + pub fn root_path() -> PathBuf { PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"))) .parent()