From 427b73c3ec1e01ca8c670d403a85fcf31777d253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Tue, 23 Jan 2024 15:33:07 +0100 Subject: [PATCH] feat: warn when using --unstable, prefer granular flags (#21452) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit deprecates "--unstable" flag. When "--unstable" flag is encountered a warning like this is printed: ``` The `--unstable` flag is deprecated, use granular `--unstable-*` flags instead. Learn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags ``` When "--unstable" flag is used and an unstable API is called an additional warning like this is printed for each API call: ``` The `Deno.dlopen` API was used with `--unstable` flag. The `--unstable` flag is deprecated, use granular `--unstable-ffi` instead. Learn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags ``` When no "--unstable-*" flag is provided and an unstable API is called following warning is issued before exiting: ``` Unstable API 'Deno.dlopen'. The `--unstable-ffi` flag must be provided. ``` --------- Signed-off-by: Divy Srivastava Signed-off-by: Bartek Iwańczuk Co-authored-by: Divy Srivastava Co-authored-by: Asher Gomez --- cli/factory.rs | 5 +- cli/main.rs | 125 +++++------------- cli/tests/integration/doc_tests.rs | 2 +- cli/tests/integration/info_tests.rs | 8 +- cli/tests/integration/lint_tests.rs | 2 +- cli/tests/integration/npm_tests.rs | 15 ++- cli/tests/integration/run_tests.rs | 48 +++---- cli/tests/integration/test_tests.rs | 12 +- cli/tests/integration/watcher_tests.rs | 9 -- cli/tests/integration/worker_tests.rs | 2 +- .../child-process-fork/1.0.0/index.js | 2 +- .../testdata/run/ffi/unstable_ffi_1.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_10.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_11.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_12.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_13.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_14.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_15.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_16.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_17.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_18.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_19.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_2.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_3.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_4.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_5.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_6.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_7.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_8.js.out | 2 +- .../testdata/run/ffi/unstable_ffi_9.js.out | 2 +- .../run/unstable_worker_options.disabled.out | 2 +- ext/node/polyfills/child_process.ts | 3 +- runtime/lib.rs | 86 ++++++++++++ runtime/ops/bootstrap.rs | 18 +++ test_ffi/tests/integration_tests.rs | 8 +- test_napi/cleanup_hook_test.js | 2 +- 36 files changed, 210 insertions(+), 177 deletions(-) diff --git a/cli/factory.rs b/cli/factory.rs index bee805215d..a82cd3ab92 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -678,11 +678,10 @@ impl CliFactory { self.services.feature_checker.get_or_init(|| { let mut checker = FeatureChecker::default(); checker.set_exit_cb(Box::new(crate::unstable_exit_cb)); - // TODO(bartlomieju): enable, once we deprecate `--unstable` in favor - // of granular --unstable-* flags. - // feature_checker.set_warn_cb(Box::new(crate::unstable_warn_cb)); + checker.set_warn_cb(Box::new(crate::unstable_warn_cb)); if self.options.legacy_unstable_flag() { checker.enable_legacy_unstable(); + checker.warn_on_legacy_unstable(); } let unstable_features = self.options.unstable_features(); for (flag_name, _, _) in crate::UNSTABLE_GRANULAR_FLAGS { diff --git a/cli/main.rs b/cli/main.rs index fb88ad137a..ae89d4c946 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -33,6 +33,8 @@ use crate::util::display; use crate::util::v8::get_v8_flags_from_env; use crate::util::v8::init_v8_flags; +pub use deno_runtime::UNSTABLE_GRANULAR_FLAGS; + use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::error::JsError; @@ -279,85 +281,22 @@ fn unwrap_or_exit(result: Result) -> T { } } -// NOTE(bartlomieju): keep IDs in sync with `runtime/90_deno_ns.js` (search for `unstableFeatures`) -pub(crate) static UNSTABLE_GRANULAR_FLAGS: &[( - // flag name - &str, - // help text - &str, - // id to enable it in runtime/99_main.js - i32, -)] = &[ - ( - deno_runtime::deno_broadcast_channel::UNSTABLE_FEATURE_NAME, - "Enable unstable `BroadcastChannel` API", - 1, - ), - ( - deno_runtime::deno_cron::UNSTABLE_FEATURE_NAME, - "Enable unstable Deno.cron API", - 2, - ), - ( - deno_runtime::deno_ffi::UNSTABLE_FEATURE_NAME, - "Enable unstable FFI APIs", - 3, - ), - ( - deno_runtime::deno_fs::UNSTABLE_FEATURE_NAME, - "Enable unstable file system APIs", - 4, - ), - ( - deno_runtime::ops::http::UNSTABLE_FEATURE_NAME, - "Enable unstable HTTP APIs", - 5, - ), - ( - deno_runtime::deno_kv::UNSTABLE_FEATURE_NAME, - "Enable unstable Key-Value store APIs", - 6, - ), - ( - deno_runtime::deno_net::UNSTABLE_FEATURE_NAME, - "Enable unstable net APIs", - 7, - ), - ( - "temporal", - "Enable unstable Temporal API", - // Not used in JS - 8, - ), - ( - "unsafe-proto", - "Enable unsafe __proto__ support. This is a security risk.", - // This number is used directly in the JS code. Search - // for "unstableIds" to see where it's used. - 9, - ), - ( - deno_runtime::deno_webgpu::UNSTABLE_FEATURE_NAME, - "Enable unstable `WebGPU` API", - 10, - ), - ( - deno_runtime::ops::worker_host::UNSTABLE_FEATURE_NAME, - "Enable unstable Web Worker APIs", - 11, - ), -]; - -pub(crate) fn unstable_exit_cb(_feature: &str, api_name: &str) { - // TODO(bartlomieju): change to "The `--unstable-{feature}` flag must be provided.". - eprintln!("Unstable API '{api_name}'. The --unstable flag must be provided."); +pub(crate) fn unstable_exit_cb(feature: &str, api_name: &str) { + eprintln!( + "Unstable API '{api_name}'. The `--unstable-{}` flag must be provided.", + feature + ); std::process::exit(70); } -#[allow(dead_code)] -pub(crate) fn unstable_warn_cb(feature: &str) { +// TODO(bartlomieju): remove when `--unstable` flag is removed. +pub(crate) fn unstable_warn_cb(feature: &str, api_name: &str) { eprintln!( - "The `--unstable` flag is deprecated, use --unstable-{feature} instead." + "⚠️ {}", + 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.\nLearn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags", + api_name, feature + )) ); } @@ -404,6 +343,25 @@ pub fn main() { Err(err) => unwrap_or_exit(Err(AnyError::from(err))), }; + // 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.\nLearn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags" + ) + ); + } + } + 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 @@ -434,20 +392,3 @@ pub fn main() { std::process::exit(exit_code); } - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn unstable_granular_flag_names_sorted() { - let flags = UNSTABLE_GRANULAR_FLAGS - .iter() - .map(|(name, _, _)| name.to_string()) - .collect::>(); - let mut sorted_flags = flags.clone(); - sorted_flags.sort(); - // sort the flags by name so they appear nicely in the help text - assert_eq!(flags, sorted_flags); - } -} diff --git a/cli/tests/integration/doc_tests.rs b/cli/tests/integration/doc_tests.rs index 73a1122617..62fd2a5b44 100644 --- a/cli/tests/integration/doc_tests.rs +++ b/cli/tests/integration/doc_tests.rs @@ -28,7 +28,7 @@ fn deno_doc() { } itest!(deno_doc_import_map { - args: "doc --unstable --import-map=doc/import_map.json doc/use_import_map.js", + args: "doc --import-map=doc/import_map.json doc/use_import_map.js", output: "doc/use_import_map.out", }); diff --git a/cli/tests/integration/info_tests.rs b/cli/tests/integration/info_tests.rs index 6897458ac4..922fcee064 100644 --- a/cli/tests/integration/info_tests.rs +++ b/cli/tests/integration/info_tests.rs @@ -51,12 +51,12 @@ itest!(info_flag_location { }); itest!(info_json { - args: "info --json --unstable", + args: "info --json", output: "info/info_json.out", }); itest!(info_json_location { - args: "info --json --unstable --location https://deno.land", + args: "info --json --location https://deno.land", output: "info/info_json_location.out", }); @@ -67,7 +67,7 @@ itest!(info_flag_script_jsx { }); itest!(json_file { - args: "info --quiet --json --unstable info/json_output/main.ts", + args: "info --quiet --json info/json_output/main.ts", output: "info/json_output/main.out", exit_code: 0, }); @@ -79,7 +79,7 @@ itest!(import_map_info { }); itest!(info_json_deps_order { - args: "info --unstable --json info/076_info_json_deps_order.ts", + args: "info --json info/076_info_json_deps_order.ts", output: "info/076_info_json_deps_order.out", }); diff --git a/cli/tests/integration/lint_tests.rs b/cli/tests/integration/lint_tests.rs index e131df7139..b266fb5b74 100644 --- a/cli/tests/integration/lint_tests.rs +++ b/cli/tests/integration/lint_tests.rs @@ -4,7 +4,7 @@ use test_util::assert_contains; use test_util::TestContextBuilder; itest!(ignore_unexplicit_files { - args: "lint --unstable --ignore=./", + args: "lint --ignore=./", output_str: Some("error: No target files found.\n"), exit_code: 1, }); diff --git a/cli/tests/integration/npm_tests.rs b/cli/tests/integration/npm_tests.rs index 9840f27713..e3b1196b97 100644 --- a/cli/tests/integration/npm_tests.rs +++ b/cli/tests/integration/npm_tests.rs @@ -30,14 +30,14 @@ itest!(esm_module_eval { }); itest!(esm_module_deno_test { - args: "test --allow-read --allow-env --unstable npm/esm/test.js", + args: "test --allow-read --allow-env npm/esm/test.js", output: "npm/esm/test.out", 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", + args: "run --allow-read --allow-env --quiet --check=all npm/esm_import_cjs_default/main.ts", output: "npm/esm_import_cjs_default/main.out", envs: env_vars_for_npm_tests(), http_server: true, @@ -123,7 +123,7 @@ itest!(translate_cjs_to_esm { }); itest!(compare_globals { - args: "run --allow-read --unstable --check=all npm/compare_globals/main.ts", + args: "run --allow-read --check=all npm/compare_globals/main.ts", output: "npm/compare_globals/main.out", envs: env_vars_for_npm_tests(), http_server: true, @@ -160,14 +160,15 @@ itest!(child_process_fork_test { }); itest!(cjs_module_export_assignment { - args: "run -A --unstable --quiet --check=all npm/cjs_module_export_assignment/main.ts", + args: "run -A --quiet --check=all npm/cjs_module_export_assignment/main.ts", output: "npm/cjs_module_export_assignment/main.out", 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", + args: + "run -A --quiet --check=all npm/cjs_module_export_assignment_number/main.ts", output: "npm/cjs_module_export_assignment_number/main.out", envs: env_vars_for_npm_tests(), http_server: true, @@ -401,7 +402,7 @@ itest!(no_types_cjs { }); itest!(no_types_in_conditional_exports { - args: "run --check --unstable npm/no_types_in_conditional_exports/main.ts", + args: "run --check npm/no_types_in_conditional_exports/main.ts", output: "npm/no_types_in_conditional_exports/main.out", exit_code: 0, envs: env_vars_for_npm_tests(), @@ -1542,7 +1543,7 @@ fn auto_discover_lock_file() { let output = context .new_command() - .args("run --unstable -A npm:@denotest/bin/cli-esm test") + .args("run -A npm:@denotest/bin/cli-esm test") .run(); output .assert_matches_text( diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 466972c92e..03aa8893f6 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -143,9 +143,8 @@ itest!(_023_no_ext { output: "run/023_no_ext.out", }); -// TODO(lucacasonato): remove --unstable when permissions goes stable itest!(_025_hrtime { - args: "run --quiet --allow-hrtime --unstable --reload run/025_hrtime.ts", + args: "run --quiet --allow-hrtime --reload run/025_hrtime.ts", output: "run/025_hrtime.ts.out", }); @@ -199,14 +198,14 @@ itest!(_033_import_map_in_flag_has_precedence { itest!(_033_import_map_remote { args: - "run --quiet --reload --import-map=http://127.0.0.1:4545/import_maps/import_map_remote.json --unstable import_maps/test_remote.ts", + "run --quiet --reload --import-map=http://127.0.0.1:4545/import_maps/import_map_remote.json import_maps/test_remote.ts", output: "run/033_import_map_remote.out", http_server: true, }); itest!(_033_import_map_vendor_dir_remote { args: - "run --quiet --reload --import-map=http://127.0.0.1:4545/import_maps/import_map_remote.json --vendor --unstable $TESTDATA/import_maps/test_remote.ts", + "run --quiet --reload --import-map=http://127.0.0.1:4545/import_maps/import_map_remote.json --vendor $TESTDATA/import_maps/test_remote.ts", output: "run/033_import_map_remote.out", http_server: true, temp_cwd: true, @@ -250,9 +249,8 @@ itest!(_044_bad_resource { exit_code: 1, }); -// TODO(bartlomieju): remove --unstable once Deno.Command is stabilized itest!(_045_proxy { - args: "run -L debug --unstable --allow-net --allow-env --allow-run --allow-read --reload --quiet run/045_proxy_test.ts", + args: "run -L debug --allow-net --allow-env --allow-run --allow-read --reload --quiet run/045_proxy_test.ts", output: "run/045_proxy_test.ts.out", http_server: true, }); @@ -1442,43 +1440,42 @@ itest!(exit_error42 { }); itest!(set_exit_code_0 { - args: "run --no-check --unstable run/set_exit_code_0.ts", + args: "run --no-check run/set_exit_code_0.ts", output_str: Some(""), exit_code: 0, }); itest!(set_exit_code_1 { - args: "run --no-check --unstable run/set_exit_code_1.ts", + args: "run --no-check run/set_exit_code_1.ts", output_str: Some(""), exit_code: 42, }); itest!(set_exit_code_2 { - args: "run --no-check --unstable run/set_exit_code_2.ts", + args: "run --no-check run/set_exit_code_2.ts", output_str: Some(""), exit_code: 42, }); itest!(op_exit_op_set_exit_code_in_worker { - args: "run --no-check --unstable --allow-read run/op_exit_op_set_exit_code_in_worker.ts", + args: "run --no-check --allow-read run/op_exit_op_set_exit_code_in_worker.ts", exit_code: 21, output_str: Some(""), }); itest!(deno_exit_tampering { - args: "run --no-check --unstable run/deno_exit_tampering.ts", + args: "run --no-check run/deno_exit_tampering.ts", output_str: Some(""), exit_code: 42, }); itest!(heapstats { - args: "run --quiet --unstable --v8-flags=--expose-gc run/heapstats.js", + args: "run --quiet --v8-flags=--expose-gc run/heapstats.js", output: "run/heapstats.js.out", }); itest!(finalization_registry { - args: - "run --quiet --unstable --v8-flags=--expose-gc run/finalization_registry.js", + args: "run --quiet --v8-flags=--expose-gc run/finalization_registry.js", output: "run/finalization_registry.js.out", }); @@ -1733,12 +1730,12 @@ itest!(unstable_disabled_js { }); itest!(unstable_enabled_js { - args: "run --quiet --reload --unstable run/unstable.ts", + args: "run --quiet --reload --unstable-fs run/unstable.ts", output: "run/unstable_enabled_js.out", }); itest!(unstable_worker { - args: "run --reload --unstable --quiet --allow-read run/unstable_worker.ts", + args: "run --reload --quiet --allow-read run/unstable_worker.ts", output: "run/unstable_worker.ts.out", }); @@ -2237,7 +2234,7 @@ itest!(worker_drop_handle_race { }); itest!(worker_drop_handle_race_terminate { - args: "run --unstable run/worker_drop_handle_race_terminate.js", + args: "run run/worker_drop_handle_race_terminate.js", output: "run/worker_drop_handle_race_terminate.js.out", }); @@ -3045,7 +3042,7 @@ mod permissions { } itest!(tls_starttls { - args: "run --quiet --reload --allow-net --allow-read --unstable --cert tls/RootCA.pem run/tls_starttls.js", + args: "run --quiet --reload --allow-net --allow-read --cert tls/RootCA.pem run/tls_starttls.js", output: "run/tls.out", }); @@ -3610,8 +3607,7 @@ itest!(event_listener_error_immediate_exit { // https://github.com/denoland/deno/pull/14159#issuecomment-1092285446 itest!(event_listener_error_immediate_exit_worker { - args: - "run --quiet --unstable -A run/event_listener_error_immediate_exit_worker.ts", + args: "run --quiet -A run/event_listener_error_immediate_exit_worker.ts", output: "run/event_listener_error_immediate_exit_worker.ts.out", exit_code: 1, }); @@ -3691,7 +3687,7 @@ itest!(check_js_points_to_ts { }); itest!(no_prompt_flag { - args: "run --quiet --unstable --no-prompt run/no_prompt.ts", + args: "run --quiet --no-prompt run/no_prompt.ts", output_str: Some(""), }); @@ -3740,7 +3736,7 @@ itest!(queue_microtask_error_handled { }); itest!(spawn_stdout_inherit { - args: "run --quiet --unstable -A run/spawn_stdout_inherit.ts", + args: "run --quiet -A run/spawn_stdout_inherit.ts", output: "run/spawn_stdout_inherit.ts.out", }); @@ -3785,17 +3781,17 @@ itest!(test_and_bench_are_noops_in_run { #[cfg(not(target_os = "windows"))] itest!(spawn_kill_permissions { - args: "run --quiet --unstable --allow-run=cat spawn_kill_permissions.ts", + args: "run --quiet --allow-run=cat spawn_kill_permissions.ts", output_str: Some(""), }); itest!(followup_dyn_import_resolved { - args: "run --unstable --allow-read run/followup_dyn_import_resolves/main.ts", + args: "run --allow-read run/followup_dyn_import_resolves/main.ts", output: "run/followup_dyn_import_resolves/main.ts.out", }); itest!(allow_run_allowlist_resolution { - args: "run --quiet --unstable -A allow_run_allowlist_resolution.ts", + args: "run --quiet -A allow_run_allowlist_resolution.ts", output: "allow_run_allowlist_resolution.ts.out", }); @@ -3834,7 +3830,7 @@ itest!(nested_error { }); itest!(node_env_var_allowlist { - args: "run --unstable --no-prompt run/node_env_var_allowlist.ts", + args: "run --no-prompt run/node_env_var_allowlist.ts", output: "run/node_env_var_allowlist.ts.out", exit_code: 1, }); diff --git a/cli/tests/integration/test_tests.rs b/cli/tests/integration/test_tests.rs index 97aba80516..27bef80075 100644 --- a/cli/tests/integration/test_tests.rs +++ b/cli/tests/integration/test_tests.rs @@ -50,7 +50,7 @@ itest!(ignore { }); itest!(ignore_permissions { - args: "test --unstable test/ignore_permissions.ts", + args: "test test/ignore_permissions.ts", exit_code: 0, output: "test/ignore_permissions.out", }); @@ -200,25 +200,25 @@ itest!(no_check { }); itest!(no_run { - args: "test --unstable --no-run test/no_run.ts", + args: "test --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", + args: "test --allow-all test/allow_all.ts", exit_code: 0, output: "test/allow_all.out", }); itest!(allow_none { - args: "test --unstable test/allow_none.ts", + args: "test 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", + args: "test --trace-ops test/ops_sanitizer_unstable.ts", exit_code: 1, output: "test/ops_sanitizer_unstable.out", }); @@ -449,7 +449,7 @@ fn captured_output() { let context = TestContext::default(); let output = context .new_command() - .args("test --allow-run --allow-read --unstable test/captured_output.ts") + .args("test --allow-run --allow-read test/captured_output.ts") .env("NO_COLOR", "1") .run(); diff --git a/cli/tests/integration/watcher_tests.rs b/cli/tests/integration/watcher_tests.rs index 6732d52848..008df33859 100644 --- a/cli/tests/integration/watcher_tests.rs +++ b/cli/tests/integration/watcher_tests.rs @@ -216,7 +216,6 @@ async fn lint_watch_test() { .arg("lint") .arg(&badly_linted) .arg("--watch") - .arg("--unstable") .piped_output() .spawn() .unwrap(); @@ -273,7 +272,6 @@ async fn lint_watch_without_args_test() { .current_dir(t.path()) .arg("lint") .arg("--watch") - .arg("--unstable") .piped_output() .spawn() .unwrap(); @@ -365,7 +363,6 @@ async fn fmt_watch_test() { .arg("fmt") .arg(&badly_formatted) .arg("--watch") - .arg("--unstable") .piped_output() .spawn() .unwrap(); @@ -420,7 +417,6 @@ async fn fmt_watch_without_args_test() { .current_dir(t.path()) .arg("fmt") .arg("--watch") - .arg("--unstable") .piped_output() .spawn() .unwrap(); @@ -514,7 +510,6 @@ async fn bundle_js_watch() { .arg(&file_to_watch) .arg(&bundle) .arg("--watch") - .arg("--unstable") .env("NO_COLOR", "1") .piped_output() .spawn() @@ -586,7 +581,6 @@ async fn bundle_watch_not_exit() { .arg(&file_to_watch) .arg(&target_file) .arg("--watch") - .arg("--unstable") .env("NO_COLOR", "1") .piped_output() .spawn() @@ -891,7 +885,6 @@ async fn run_watch_with_import_map_and_relative_paths() { let mut child = util::deno_cmd() .current_dir(temp_directory.path()) .arg("run") - .arg("--unstable") .arg("--watch") .arg("--import-map") .arg(&import_map_path) @@ -1191,7 +1184,6 @@ async fn test_watch_module_graph_error_referrer() { .current_dir(util::testdata_path()) .arg("run") .arg("--watch") - .arg("--unstable") .arg(&file_to_watch) .env("NO_COLOR", "1") .piped_output() @@ -1315,7 +1307,6 @@ async fn bench_watch_basic() { .current_dir(util::testdata_path()) .arg("bench") .arg("--watch") - .arg("--unstable") .arg("--no-check") .arg(t.path()) .env("NO_COLOR", "1") diff --git a/cli/tests/integration/worker_tests.rs b/cli/tests/integration/worker_tests.rs index 7aa93118b2..573863d4f7 100644 --- a/cli/tests/integration/worker_tests.rs +++ b/cli/tests/integration/worker_tests.rs @@ -64,7 +64,7 @@ itest!(worker_permissions_remote_remote { }); itest!(worker_permissions_dynamic_remote { - args: "run --quiet --reload --allow-net --unstable workers/permissions_dynamic_remote.ts", + args: "run --quiet --reload --allow-net --unstable-worker-options workers/permissions_dynamic_remote.ts", output: "workers/permissions_dynamic_remote.ts.out", http_server: true, exit_code: 1, diff --git a/cli/tests/testdata/npm/registry/@denotest/child-process-fork/1.0.0/index.js b/cli/tests/testdata/npm/registry/@denotest/child-process-fork/1.0.0/index.js index 9f84afe354..0482be4043 100644 --- a/cli/tests/testdata/npm/registry/@denotest/child-process-fork/1.0.0/index.js +++ b/cli/tests/testdata/npm/registry/@denotest/child-process-fork/1.0.0/index.js @@ -2,7 +2,7 @@ const path = require("path"); function childProcessFork(path) { const command = new Deno.Command(Deno.execPath(), { - args: ["run", "--unstable", "-A", path], + args: ["run", "-A", path], env: { "DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE": Deno[Deno.internal].core.ops.op_npm_process_state(), } diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_1.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_1.js.out index 7c564be8cf..fe172c2c60 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_1.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_1.js.out @@ -1 +1 @@ -Unstable API 'Deno.dlopen'. The --unstable flag must be provided. +Unstable API 'Deno.dlopen'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_10.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_10.js.out index bf7e1bd4f7..b9fe500b52 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_10.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_10.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getInt16'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getInt16'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_11.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_11.js.out index 2d2d72666c..74039db43f 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_11.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_11.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getUint32'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getUint32'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_12.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_12.js.out index 377d8e4a5a..1a366b8c6f 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_12.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_12.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getInt32'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getInt32'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_13.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_13.js.out index 6ca67a6f22..93afbe5eda 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_13.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_13.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getBigUint64'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getBigUint64'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_14.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_14.js.out index 11fcd55806..7f4c900f8b 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_14.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_14.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getFloat32'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getFloat32'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_15.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_15.js.out index 3015e5c910..5e2c559685 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_15.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_15.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getFloat64'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getFloat64'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_16.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_16.js.out index d688707841..05362e5b31 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_16.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_16.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointer#value'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointer#value'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_17.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_17.js.out index 2949312436..c9d6ca8215 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_17.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_17.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getArrayBuffer'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getArrayBuffer'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_18.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_18.js.out index 6f7ea0d8f3..2474f86bd0 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_18.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_18.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointer#create'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointer#create'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_19.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_19.js.out index 15a99b9ab8..8d97f87e94 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_19.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_19.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointer#equals'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointer#equals'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_2.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_2.js.out index cc4cc3dc69..094a69b5b2 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_2.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_2.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafeFnPointer#call'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafeFnPointer#call'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_3.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_3.js.out index cc4cc3dc69..094a69b5b2 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_3.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_3.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafeFnPointer#call'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafeFnPointer#call'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_4.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_4.js.out index e0f40f2ee1..55bbc063d7 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_4.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_4.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointer#of'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointer#of'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_5.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_5.js.out index e3db6af26a..81dd950ac8 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_5.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_5.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#copyInto'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#copyInto'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_6.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_6.js.out index c59f51d040..b48fc264f3 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_6.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_6.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getCString'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getCString'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_7.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_7.js.out index 6ab413537d..935ebe195b 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_7.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_7.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getUint8'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getUint8'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_8.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_8.js.out index 338db26319..02883d0c38 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_8.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_8.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getInt8'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getInt8'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/ffi/unstable_ffi_9.js.out b/cli/tests/testdata/run/ffi/unstable_ffi_9.js.out index fb6d75f145..97ac970170 100644 --- a/cli/tests/testdata/run/ffi/unstable_ffi_9.js.out +++ b/cli/tests/testdata/run/ffi/unstable_ffi_9.js.out @@ -1 +1 @@ -Unstable API 'Deno.UnsafePointerView#getUint16'. The --unstable flag must be provided. +Unstable API 'Deno.UnsafePointerView#getUint16'. The `--unstable-ffi` flag must be provided. diff --git a/cli/tests/testdata/run/unstable_worker_options.disabled.out b/cli/tests/testdata/run/unstable_worker_options.disabled.out index 03f189c252..ba50ca5392 100644 --- a/cli/tests/testdata/run/unstable_worker_options.disabled.out +++ b/cli/tests/testdata/run/unstable_worker_options.disabled.out @@ -1 +1 @@ -Unstable API 'Worker.deno.permissions'. The --unstable flag must be provided. +Unstable API 'Worker.deno.permissions'. The `--unstable-worker-options` flag must be provided. diff --git a/ext/node/polyfills/child_process.ts b/ext/node/polyfills/child_process.ts index 0f45230d93..c88266cbe0 100644 --- a/ext/node/polyfills/child_process.ts +++ b/ext/node/polyfills/child_process.ts @@ -9,6 +9,7 @@ import { core, internals } from "ext:core/mod.js"; const { op_node_child_ipc_pipe, + op_bootstrap_unstable_args, } = core.ensureFastOps(); const { op_npm_process_state, @@ -130,7 +131,7 @@ export function fork( } args = [ "run", - "--unstable", // TODO(kt3k): Remove when npm: is stable + ...op_bootstrap_unstable_args(), "--node-modules-dir", "-A", ...stringifiedV8Flags, diff --git a/runtime/lib.rs b/runtime/lib.rs index 5aa4e21a1e..fd791974db 100644 --- a/runtime/lib.rs +++ b/runtime/lib.rs @@ -43,3 +43,89 @@ pub use worker_bootstrap::WorkerLogLevel; mod shared; pub use shared::runtime; + +// NOTE(bartlomieju): keep IDs in sync with `runtime/90_deno_ns.js` (search for `unstableFeatures`) +pub static UNSTABLE_GRANULAR_FLAGS: &[( + // flag name + &str, + // help text + &str, + // id to enable it in runtime/99_main.js + i32, +)] = &[ + ( + deno_broadcast_channel::UNSTABLE_FEATURE_NAME, + "Enable unstable `BroadcastChannel` API", + 1, + ), + ( + deno_cron::UNSTABLE_FEATURE_NAME, + "Enable unstable Deno.cron API", + 2, + ), + ( + deno_ffi::UNSTABLE_FEATURE_NAME, + "Enable unstable FFI APIs", + 3, + ), + ( + deno_fs::UNSTABLE_FEATURE_NAME, + "Enable unstable file system APIs", + 4, + ), + ( + ops::http::UNSTABLE_FEATURE_NAME, + "Enable unstable HTTP APIs", + 5, + ), + ( + deno_kv::UNSTABLE_FEATURE_NAME, + "Enable unstable Key-Value store APIs", + 6, + ), + ( + deno_net::UNSTABLE_FEATURE_NAME, + "Enable unstable net APIs", + 7, + ), + ( + "temporal", + "Enable unstable Temporal API", + // Not used in JS + 8, + ), + ( + "unsafe-proto", + "Enable unsafe __proto__ support. This is a security risk.", + // This number is used directly in the JS code. Search + // for "unstableIds" to see where it's used. + 9, + ), + ( + deno_webgpu::UNSTABLE_FEATURE_NAME, + "Enable unstable `WebGPU` API", + 10, + ), + ( + ops::worker_host::UNSTABLE_FEATURE_NAME, + "Enable unstable Web Worker APIs", + 11, + ), +]; + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn unstable_granular_flag_names_sorted() { + let flags = UNSTABLE_GRANULAR_FLAGS + .iter() + .map(|(name, _, _)| name.to_string()) + .collect::>(); + let mut sorted_flags = flags.clone(); + sorted_flags.sort(); + // sort the flags by name so they appear nicely in the help text + assert_eq!(flags, sorted_flags); + } +} diff --git a/runtime/ops/bootstrap.rs b/runtime/ops/bootstrap.rs index 1d4039d73a..7de532a9f5 100644 --- a/runtime/ops/bootstrap.rs +++ b/runtime/ops/bootstrap.rs @@ -17,6 +17,7 @@ deno_core::extension!( op_bootstrap_log_level, op_bootstrap_no_color, op_bootstrap_is_tty, + op_bootstrap_unstable_args, op_snapshot_options, ], options = { @@ -69,6 +70,23 @@ pub fn op_bootstrap_user_agent(state: &mut OpState) -> String { state.borrow::().user_agent.clone() } +#[op2] +#[serde] +pub fn op_bootstrap_unstable_args(state: &mut OpState) -> Vec { + let options = state.borrow::(); + if options.unstable { + return vec!["--unstable".to_string()]; + } + + let mut flags = Vec::new(); + for (name, _, id) in crate::UNSTABLE_GRANULAR_FLAGS.iter() { + if options.unstable_features.contains(id) { + flags.push(format!("--unstable-{}", name)); + } + } + flags +} + #[op2] #[string] pub fn op_bootstrap_language(state: &mut OpState) -> String { diff --git a/test_ffi/tests/integration_tests.rs b/test_ffi/tests/integration_tests.rs index a9a458d168..642fbed032 100644 --- a/test_ffi/tests/integration_tests.rs +++ b/test_ffi/tests/integration_tests.rs @@ -135,7 +135,7 @@ fn symbol_types() { let output = deno_cmd() .arg("check") - .arg("--unstable") + .arg("--unstable-ffi") .arg("--quiet") .arg("tests/ffi_types.ts") .env("NO_COLOR", "1") @@ -160,7 +160,7 @@ fn thread_safe_callback() { .arg("run") .arg("--allow-ffi") .arg("--allow-read") - .arg("--unstable") + .arg("--unstable-ffi") .arg("--quiet") .arg("tests/thread_safe_test.js") .env("NO_COLOR", "1") @@ -194,7 +194,7 @@ fn event_loop_integration() { .arg("run") .arg("--allow-ffi") .arg("--allow-read") - .arg("--unstable") + .arg("--unstable-ffi") .arg("--quiet") .arg("tests/event_loop_integration.ts") .env("NO_COLOR", "1") @@ -246,7 +246,7 @@ fn ffi_callback_errors_test() { .arg("run") .arg("--allow-ffi") .arg("--allow-read") - .arg("--unstable") + .arg("--unstable-ffi") .arg("--quiet") .arg("tests/ffi_callback_errors.ts") .env("NO_COLOR", "1") diff --git a/test_napi/cleanup_hook_test.js b/test_napi/cleanup_hook_test.js index bca3921a55..f1f9161758 100644 --- a/test_napi/cleanup_hook_test.js +++ b/test_napi/cleanup_hook_test.js @@ -15,7 +15,7 @@ if (import.meta.main) { "--allow-read", "--allow-run", "--allow-ffi", - "--unstable", + "--unstable-ffi", import.meta.url, ], }).output();