2024-01-01 19:58:21 +00:00
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2019-09-04 02:12:21 +00:00
2022-06-27 20:54:09 +00:00
mod args ;
2021-02-16 02:50:27 +00:00
mod auth_tokens ;
2021-10-10 21:26:22 +00:00
mod cache ;
2023-11-05 22:58:59 +00:00
mod cdp ;
2022-08-29 18:19:54 +00:00
mod deno_std ;
2024-01-23 15:37:43 +00:00
mod diagnostics ;
2021-10-10 21:26:22 +00:00
mod emit ;
2020-10-12 11:25:25 +00:00
mod errors ;
2023-05-01 18:35:23 +00:00
mod factory ;
2020-05-11 21:33:36 +00:00
mod file_fetcher ;
2021-12-16 10:45:41 +00:00
mod graph_util ;
2020-05-11 21:33:36 +00:00
mod http_util ;
2022-11-21 13:36:26 +00:00
mod js ;
2020-12-07 10:46:39 +00:00
mod lsp ;
2020-10-13 11:35:35 +00:00
mod module_loader ;
2022-10-05 14:06:44 +00:00
mod napi ;
2022-08-20 15:31:33 +00:00
mod node ;
2022-08-10 19:23:58 +00:00
mod npm ;
2020-10-12 11:25:25 +00:00
mod ops ;
2021-10-10 21:26:22 +00:00
mod resolver ;
2020-11-30 19:35:12 +00:00
mod standalone ;
2020-11-19 18:19:34 +00:00
mod tools ;
2020-11-02 19:41:20 +00:00
mod tsc ;
2022-11-28 22:28:54 +00:00
mod util ;
2020-10-12 11:25:25 +00:00
mod version ;
2022-08-11 20:59:12 +00:00
mod worker ;
2020-05-11 21:33:36 +00:00
2022-06-27 20:54:09 +00:00
use crate ::args ::flags_from_vec ;
use crate ::args ::DenoSubcommand ;
use crate ::args ::Flags ;
2022-11-28 22:28:54 +00:00
use crate ::util ::display ;
2023-01-25 04:03:03 +00:00
use crate ::util ::v8 ::get_v8_flags_from_env ;
use crate ::util ::v8 ::init_v8_flags ;
2022-06-27 20:54:09 +00:00
2024-01-23 14:33:07 +00:00
pub use deno_runtime ::UNSTABLE_GRANULAR_FLAGS ;
2022-12-09 14:40:48 +00:00
use deno_core ::anyhow ::Context ;
2020-09-14 16:48:57 +00:00
use deno_core ::error ::AnyError ;
2022-04-26 23:06:10 +00:00
use deno_core ::error ::JsError ;
2023-05-17 21:49:57 +00:00
use deno_core ::futures ::FutureExt ;
2023-08-23 23:03:05 +00:00
use deno_core ::unsync ::JoinHandle ;
2024-01-22 21:31:12 +00:00
use deno_npm ::resolution ::SnapshotFromLockfileError ;
2022-09-02 20:53:23 +00:00
use deno_runtime ::fmt_errors ::format_js_error ;
2023-06-09 11:52:51 +00:00
use deno_runtime ::tokio_util ::create_and_run_current_thread_with_maybe_metrics ;
2024-02-07 16:25:14 +00:00
use deno_terminal ::colors ;
2023-05-01 18:35:23 +00:00
use factory ::CliFactory ;
2020-05-11 21:33:36 +00:00
use std ::env ;
2023-04-19 21:50:56 +00:00
use std ::env ::current_exe ;
2023-05-17 21:49:57 +00:00
use std ::future ::Future ;
2020-05-11 21:33:36 +00:00
use std ::path ::PathBuf ;
2022-02-16 18:14:19 +00:00
2023-05-17 21:49:57 +00:00
/// Ensures that all subcommands return an i32 exit code and an [`AnyError`] error type.
trait SubcommandOutput {
fn output ( self ) -> Result < i32 , AnyError > ;
}
impl SubcommandOutput for Result < i32 , AnyError > {
fn output ( self ) -> Result < i32 , AnyError > {
self
}
}
impl SubcommandOutput for Result < ( ) , AnyError > {
fn output ( self ) -> Result < i32 , AnyError > {
self . map ( | _ | 0 )
}
}
impl SubcommandOutput for Result < ( ) , std ::io ::Error > {
fn output ( self ) -> Result < i32 , AnyError > {
self . map ( | _ | 0 ) . map_err ( | e | e . into ( ) )
}
}
/// Ensure that the subcommand runs in a task, rather than being directly executed. Since some of these
/// futures are very large, this prevents the stack from getting blown out from passing them by value up
/// the callchain (especially in debug mode when Rust doesn't have a chance to elide copies!).
#[ inline(always) ]
fn spawn_subcommand < F : Future < Output = T > + 'static , T : SubcommandOutput > (
f : F ,
) -> JoinHandle < Result < i32 , AnyError > > {
2023-09-30 16:06:38 +00:00
// the boxed_local() is important in order to get windows to not blow the stack in debug
deno_core ::unsync ::spawn (
async move { f . map ( | r | r . output ( ) ) . await } . boxed_local ( ) ,
)
2023-05-17 21:49:57 +00:00
}
2022-12-09 14:40:48 +00:00
async fn run_subcommand ( flags : Flags ) -> Result < i32 , AnyError > {
2023-05-17 21:49:57 +00:00
let handle = match flags . subcommand . clone ( ) {
DenoSubcommand ::Bench ( bench_flags ) = > spawn_subcommand ( async {
2023-06-15 17:09:37 +00:00
if bench_flags . watch . is_some ( ) {
2023-06-14 22:29:19 +00:00
tools ::bench ::run_benchmarks_with_watch ( flags , bench_flags ) . await
2022-12-09 14:40:48 +00:00
} else {
2023-06-14 22:29:19 +00:00
tools ::bench ::run_benchmarks ( flags , bench_flags ) . await
2022-12-09 14:40:48 +00:00
}
2023-05-17 21:49:57 +00:00
} ) ,
DenoSubcommand ::Bundle ( bundle_flags ) = > spawn_subcommand ( async {
tools ::bundle ::bundle ( flags , bundle_flags ) . await
} ) ,
2021-09-03 23:33:35 +00:00
DenoSubcommand ::Doc ( doc_flags ) = > {
2023-11-01 15:25:05 +00:00
spawn_subcommand ( async { tools ::doc ::doc ( flags , doc_flags ) . await } )
2021-09-03 23:33:35 +00:00
}
2023-05-17 21:49:57 +00:00
DenoSubcommand ::Eval ( eval_flags ) = > spawn_subcommand ( async {
2022-12-09 14:40:48 +00:00
tools ::run ::eval_command ( flags , eval_flags ) . await
2023-05-17 21:49:57 +00:00
} ) ,
DenoSubcommand ::Cache ( cache_flags ) = > spawn_subcommand ( async move {
2023-05-01 18:35:23 +00:00
let factory = CliFactory ::from_flags ( flags ) . await ? ;
let module_load_preparer = factory . module_load_preparer ( ) . await ? ;
let emitter = factory . emitter ( ) ? ;
let graph_container = factory . graph_container ( ) ;
module_load_preparer
2023-04-14 20:22:33 +00:00
. load_and_type_check_files ( & cache_flags . files )
. await ? ;
2023-05-17 21:49:57 +00:00
emitter . cache_module_emits ( & graph_container . graph ( ) )
} ) ,
DenoSubcommand ::Check ( check_flags ) = > spawn_subcommand ( async move {
2023-05-01 18:35:23 +00:00
let factory = CliFactory ::from_flags ( flags ) . await ? ;
let module_load_preparer = factory . module_load_preparer ( ) . await ? ;
module_load_preparer
2023-04-14 20:22:33 +00:00
. load_and_type_check_files ( & check_flags . files )
2023-05-17 21:49:57 +00:00
. await
} ) ,
DenoSubcommand ::Compile ( compile_flags ) = > spawn_subcommand ( async {
tools ::compile ::compile ( flags , compile_flags ) . await
} ) ,
DenoSubcommand ::Coverage ( coverage_flags ) = > spawn_subcommand ( async {
tools ::coverage ::cover_files ( flags , coverage_flags ) . await
} ) ,
2023-06-14 22:29:19 +00:00
DenoSubcommand ::Fmt ( fmt_flags ) = > {
spawn_subcommand (
async move { tools ::fmt ::format ( flags , fmt_flags ) . await } ,
)
}
2022-08-19 23:37:05 +00:00
DenoSubcommand ::Init ( init_flags ) = > {
2023-05-17 21:49:57 +00:00
spawn_subcommand ( async { tools ::init ::init_project ( init_flags ) . await } )
2022-08-19 23:37:05 +00:00
}
2021-09-03 23:33:35 +00:00
DenoSubcommand ::Info ( info_flags ) = > {
2023-05-17 21:49:57 +00:00
spawn_subcommand ( async { tools ::info ::info ( flags , info_flags ) . await } )
}
DenoSubcommand ::Install ( install_flags ) = > spawn_subcommand ( async {
tools ::installer ::install_command ( flags , install_flags ) . await
} ) ,
2023-09-16 00:42:09 +00:00
DenoSubcommand ::Jupyter ( jupyter_flags ) = > spawn_subcommand ( async {
tools ::jupyter ::kernel ( flags , jupyter_flags ) . await
} ) ,
2023-05-17 21:49:57 +00:00
DenoSubcommand ::Uninstall ( uninstall_flags ) = > spawn_subcommand ( async {
tools ::installer ::uninstall ( uninstall_flags . name , uninstall_flags . root )
} ) ,
DenoSubcommand ::Lsp = > spawn_subcommand ( async { lsp ::start ( ) . await } ) ,
DenoSubcommand ::Lint ( lint_flags ) = > spawn_subcommand ( async {
2022-12-09 14:40:48 +00:00
if lint_flags . rules {
2023-07-25 21:24:06 +00:00
tools ::lint ::print_rules_list (
lint_flags . json ,
lint_flags . maybe_rules_tags ,
) ;
2023-05-17 21:49:57 +00:00
Ok ( ( ) )
2022-12-09 14:40:48 +00:00
} else {
2023-06-14 22:29:19 +00:00
tools ::lint ::lint ( flags , lint_flags ) . await
2022-12-09 14:40:48 +00:00
}
2023-05-17 21:49:57 +00:00
} ) ,
2021-09-03 23:33:35 +00:00
DenoSubcommand ::Repl ( repl_flags ) = > {
2023-05-17 21:49:57 +00:00
spawn_subcommand ( async move { tools ::repl ::run ( flags , repl_flags ) . await } )
2021-09-03 23:33:35 +00:00
}
2023-05-17 21:49:57 +00:00
DenoSubcommand ::Run ( run_flags ) = > spawn_subcommand ( async move {
2022-12-09 14:40:48 +00:00
if run_flags . is_stdin ( ) {
tools ::run ::run_from_stdin ( flags ) . await
} else {
2023-06-15 17:09:37 +00:00
tools ::run ::run_script ( flags , run_flags ) . await
2022-12-09 14:40:48 +00:00
}
2023-05-17 21:49:57 +00:00
} ) ,
DenoSubcommand ::Task ( task_flags ) = > spawn_subcommand ( async {
2022-12-09 14:40:48 +00:00
tools ::task ::execute_script ( flags , task_flags ) . await
2023-05-17 21:49:57 +00:00
} ) ,
2021-09-03 23:33:35 +00:00
DenoSubcommand ::Test ( test_flags ) = > {
2023-05-17 21:49:57 +00:00
spawn_subcommand ( async {
2023-06-15 17:09:37 +00:00
if let Some ( ref coverage_dir ) = test_flags . coverage_dir {
2023-05-17 21:49:57 +00:00
std ::fs ::create_dir_all ( coverage_dir )
. with_context ( | | format! ( " Failed creating: {coverage_dir} " ) ) ? ;
// this is set in order to ensure spawned processes use the same
// coverage directory
env ::set_var (
" DENO_UNSTABLE_COVERAGE_DIR " ,
PathBuf ::from ( coverage_dir ) . canonicalize ( ) ? ,
) ;
}
2022-12-09 14:40:48 +00:00
2023-06-15 17:09:37 +00:00
if test_flags . watch . is_some ( ) {
2023-06-14 22:29:19 +00:00
tools ::test ::run_tests_with_watch ( flags , test_flags ) . await
2023-05-17 21:49:57 +00:00
} else {
2023-06-14 22:29:19 +00:00
tools ::test ::run_tests ( flags , test_flags ) . await
2023-05-17 21:49:57 +00:00
}
} )
2021-09-03 23:33:35 +00:00
}
2021-12-21 14:49:27 +00:00
DenoSubcommand ::Completions ( completions_flags ) = > {
2023-05-17 21:49:57 +00:00
spawn_subcommand ( async move {
display ::write_to_stdout_ignore_sigpipe ( & completions_flags . buf )
} )
2022-12-09 14:40:48 +00:00
}
2023-05-17 21:49:57 +00:00
DenoSubcommand ::Types = > spawn_subcommand ( async move {
2024-01-14 17:29:17 +00:00
let types = tsc ::get_types_declaration_file_text ( ) ;
2023-05-17 21:49:57 +00:00
display ::write_to_stdout_ignore_sigpipe ( types . as_bytes ( ) )
} ) ,
2023-11-29 18:52:25 +00:00
#[ cfg(feature = " upgrade " ) ]
2023-05-17 21:49:57 +00:00
DenoSubcommand ::Upgrade ( upgrade_flags ) = > spawn_subcommand ( async {
tools ::upgrade ::upgrade ( flags , upgrade_flags ) . await
} ) ,
2023-11-29 18:52:25 +00:00
#[ cfg(not(feature = " upgrade " )) ]
DenoSubcommand ::Upgrade ( _ ) = > exit_with_message (
" This deno was built without the \" upgrade \" feature. Please upgrade using the installation method originally used to install Deno. " ,
1 ,
) ,
2023-05-17 21:49:57 +00:00
DenoSubcommand ::Vendor ( vendor_flags ) = > spawn_subcommand ( async {
tools ::vendor ::vendor ( flags , vendor_flags ) . await
} ) ,
2023-11-23 23:38:07 +00:00
// TODO:
DenoSubcommand ::Publish ( publish_flags ) = > spawn_subcommand ( async {
tools ::registry ::publish ( flags , publish_flags ) . await
} ) ,
2023-05-17 21:49:57 +00:00
} ;
handle . await ?
2020-11-26 14:17:45 +00:00
}
2021-12-20 13:49:05 +00:00
fn setup_panic_hook ( ) {
// This function does two things inside of the panic hook:
// - Tokio does not exit the process when a task panics, so we define a custom
// panic hook to implement this behaviour.
// - We print a message to stderr to indicate that this is a bug in Deno, and
// should be reported to us.
2021-09-07 23:34:27 +00:00
let orig_hook = std ::panic ::take_hook ( ) ;
std ::panic ::set_hook ( Box ::new ( move | panic_info | {
2021-12-20 13:49:05 +00:00
eprintln! ( " \n ============================================================ " ) ;
eprintln! ( " Deno has panicked. This is a bug in Deno. Please report this " ) ;
eprintln! ( " at https://github.com/denoland/deno/issues/new. " ) ;
eprintln! ( " If you can reliably reproduce this panic, include the " ) ;
eprintln! ( " reproduction steps and re-run with the RUST_BACKTRACE=1 env " ) ;
eprintln! ( " var set and include the backtrace in your report. " ) ;
eprintln! ( ) ;
2022-07-14 21:52:44 +00:00
eprintln! ( " Platform: {} {} " , env ::consts ::OS , env ::consts ::ARCH ) ;
2021-12-20 13:49:05 +00:00
eprintln! ( " Version: {} " , version ::deno ( ) ) ;
2022-07-14 21:52:44 +00:00
eprintln! ( " Args: {:?} " , env ::args ( ) . collect ::< Vec < _ > > ( ) ) ;
2021-12-20 13:49:05 +00:00
eprintln! ( ) ;
2021-09-07 23:34:27 +00:00
orig_hook ( panic_info ) ;
std ::process ::exit ( 1 ) ;
} ) ) ;
}
2023-11-29 18:52:25 +00:00
fn exit_with_message ( message : & str , code : i32 ) -> ! {
eprintln! (
" {}: {} " ,
colors ::red_bold ( " error " ) ,
message . trim_start_matches ( " error: " )
) ;
std ::process ::exit ( code ) ;
}
2021-01-07 18:06:08 +00:00
fn unwrap_or_exit < T > ( result : Result < T , AnyError > ) -> T {
match result {
Ok ( value ) = > value ,
Err ( error ) = > {
2023-01-27 15:43:16 +00:00
let mut error_string = format! ( " {error:?} " ) ;
2022-10-25 16:20:07 +00:00
let mut error_code = 1 ;
if let Some ( e ) = error . downcast_ref ::< JsError > ( ) {
error_string = format_js_error ( e ) ;
2024-01-22 21:31:12 +00:00
} else if let Some ( args ::LockfileError ::IntegrityCheckFailed ( e ) ) =
error . downcast_ref ::< args ::LockfileError > ( )
{
error_string = e . to_string ( ) ;
error_code = 10 ;
} else if let Some ( SnapshotFromLockfileError ::IntegrityCheckFailed ( e ) ) =
error . downcast_ref ::< SnapshotFromLockfileError > ( )
{
2022-10-25 16:20:07 +00:00
error_string = e . to_string ( ) ;
error_code = 10 ;
}
2023-11-29 18:52:25 +00:00
exit_with_message ( & error_string , error_code ) ;
2021-01-07 18:06:08 +00:00
}
}
}
2024-01-23 14:33:07 +00:00
pub ( crate ) fn unstable_exit_cb ( feature : & str , api_name : & str ) {
eprintln! (
" Unstable API '{api_name}'. The `--unstable-{}` flag must be provided. " ,
feature
) ;
2023-10-12 15:55:50 +00:00
std ::process ::exit ( 70 ) ;
}
2024-01-23 14:33:07 +00:00
// TODO(bartlomieju): remove when `--unstable` flag is removed.
pub ( crate ) fn unstable_warn_cb ( feature : & str , api_name : & str ) {
2023-10-12 15:55:50 +00:00
eprintln! (
2024-01-23 14:33:07 +00:00
" ⚠️ {} " ,
colors ::yellow ( format! (
" The `{}` API was used with `--unstable` flag. The `--unstable` flag is deprecated and will be removed in Deno 2.0. Use granular `--unstable-{}` instead. \n Learn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags " ,
api_name , feature
) )
2023-10-12 15:55:50 +00:00
) ;
}
2020-11-26 14:17:45 +00:00
pub fn main ( ) {
2021-12-20 13:49:05 +00:00
setup_panic_hook ( ) ;
2021-10-25 15:16:16 +00:00
2022-11-28 22:28:54 +00:00
util ::unix ::raise_fd_limit ( ) ;
util ::windows ::ensure_stdio_open ( ) ;
2020-11-26 14:17:45 +00:00
#[ cfg(windows) ]
colors ::enable_ansi ( ) ; // For Windows 10
2022-12-19 19:31:19 +00:00
deno_runtime ::permissions ::set_prompt_callbacks (
Box ::new ( util ::draw_thread ::DrawThread ::hide ) ,
Box ::new ( util ::draw_thread ::DrawThread ::show ) ,
) ;
2020-11-26 14:17:45 +00:00
let args : Vec < String > = env ::args ( ) . collect ( ) ;
2022-02-15 12:33:46 +00:00
2023-09-14 22:17:01 +00:00
// NOTE(lucacasonato): due to new PKU feature introduced in V8 11.6 we need to
// initalize the V8 platform on a parent thread of all threads that will spawn
// V8 isolates.
2022-12-09 14:40:48 +00:00
let future = async move {
2023-04-19 21:50:56 +00:00
let current_exe_path = current_exe ( ) ? ;
2022-02-15 12:33:46 +00:00
let standalone_res =
2023-04-19 21:50:56 +00:00
match standalone ::extract_standalone ( & current_exe_path , args . clone ( ) )
. await
{
2022-02-15 12:33:46 +00:00
Ok ( Some ( ( metadata , eszip ) ) ) = > standalone ::run ( eszip , metadata ) . await ,
Ok ( None ) = > Ok ( ( ) ) ,
Err ( err ) = > Err ( err ) ,
} ;
// TODO(bartlomieju): doesn't handle exit code set by the runtime properly
unwrap_or_exit ( standalone_res ) ;
2022-06-27 20:54:09 +00:00
let flags = match flags_from_vec ( args ) {
2022-02-15 12:33:46 +00:00
Ok ( flags ) = > flags ,
Err ( err @ clap ::Error { .. } )
2023-03-26 04:06:18 +00:00
if err . kind ( ) = = clap ::error ::ErrorKind ::DisplayHelp
| | err . kind ( ) = = clap ::error ::ErrorKind ::DisplayVersion = >
2022-02-15 12:33:46 +00:00
{
err . print ( ) . unwrap ( ) ;
std ::process ::exit ( 0 ) ;
}
Err ( err ) = > unwrap_or_exit ( Err ( AnyError ::from ( err ) ) ) ,
} ;
2023-01-25 04:03:03 +00:00
2024-01-23 14:33:07 +00:00
// TODO(bartlomieju): remove when `--unstable` flag is removed.
if flags . unstable_config . legacy_flag_enabled {
if matches! ( flags . subcommand , DenoSubcommand ::Check ( _ ) ) {
eprintln! (
" ⚠️ {} " ,
colors ::yellow (
" The `--unstable` flag is not needed for `deno check` anymore. "
)
) ;
} else {
eprintln! (
" ⚠️ {} " ,
colors ::yellow (
" The `--unstable` flag is deprecated and will be removed in Deno 2.0. Use granular `--unstable-*` flags instead. \n Learn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags "
)
) ;
}
}
2023-05-13 19:42:34 +00:00
let default_v8_flags = match flags . subcommand {
// Using same default as VSCode:
// https://github.com/microsoft/vscode/blob/48d4ba271686e8072fc6674137415bc80d936bc7/extensions/typescript-language-features/src/configuration/configuration.ts#L213-L214
DenoSubcommand ::Lsp = > vec! [ " --max-old-space-size=3072 " . to_string ( ) ] ,
2024-01-15 00:26:57 +00:00
_ = > {
2024-01-22 17:37:28 +00:00
if flags . unstable_config . legacy_flag_enabled
| | flags
. unstable_config
. features
. contains ( & " temporal " . to_string ( ) )
2024-01-15 00:26:57 +00:00
{
vec! [ " --harmony-temporal " . to_string ( ) ]
} else {
vec! [ ]
}
}
2023-05-13 19:42:34 +00:00
} ;
init_v8_flags ( & default_v8_flags , & flags . v8_flags , get_v8_flags_from_env ( ) ) ;
2023-09-14 22:17:01 +00:00
deno_core ::JsRuntime ::init_platform ( None ) ;
2021-05-11 04:54:10 +00:00
2022-11-28 22:28:54 +00:00
util ::logger ::init ( flags . log_level ) ;
2022-02-15 12:33:46 +00:00
2022-12-09 14:40:48 +00:00
run_subcommand ( flags ) . await
2022-02-15 12:33:46 +00:00
} ;
2020-05-11 21:33:36 +00:00
2023-06-09 11:52:51 +00:00
let exit_code =
unwrap_or_exit ( create_and_run_current_thread_with_maybe_metrics ( future ) ) ;
2021-11-27 23:45:38 +00:00
2021-12-11 14:56:45 +00:00
std ::process ::exit ( exit_code ) ;
2018-06-15 23:43:23 +00:00
}