diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/build.rs | 295 | ||||
-rw-r--r-- | cli/lsp/testing/execution.rs | 6 | ||||
-rw-r--r-- | cli/lsp/tsc.rs | 42 | ||||
-rw-r--r-- | cli/ops/bench.rs | 38 | ||||
-rw-r--r-- | cli/ops/mod.rs | 19 | ||||
-rw-r--r-- | cli/ops/testing.rs | 44 | ||||
-rw-r--r-- | cli/tools/bench.rs | 2 | ||||
-rw-r--r-- | cli/tools/test.rs | 2 | ||||
-rw-r--r-- | cli/tsc/mod.rs | 80 |
9 files changed, 277 insertions, 251 deletions
diff --git a/cli/build.rs b/cli/build.rs index 216969e39..e4df856f7 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -1,11 +1,13 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use std::cell::RefCell; use std::env; use std::path::PathBuf; +use std::rc::Rc; -use deno_core::include_js_files; use deno_core::snapshot_util::*; use deno_core::Extension; +use deno_core::ExtensionBuilder; use deno_core::ExtensionFileSource; use deno_core::ExtensionFileSourceCode; use deno_runtime::deno_cache::SqliteBackedCache; @@ -33,6 +35,105 @@ mod ts { specifier: String, } + #[op] + fn op_build_info(state: &mut OpState) -> Value { + let build_specifier = "asset:///bootstrap.ts"; + + let node_built_in_module_names = SUPPORTED_BUILTIN_NODE_MODULES + .iter() + .map(|s| s.name) + .collect::<Vec<&str>>(); + let build_libs = state.borrow::<Vec<&str>>(); + json!({ + "buildSpecifier": build_specifier, + "libs": build_libs, + "nodeBuiltInModuleNames": node_built_in_module_names, + }) + } + + #[op] + fn op_is_node_file() -> bool { + false + } + + #[op] + fn op_script_version( + _state: &mut OpState, + _args: Value, + ) -> Result<Option<String>, AnyError> { + Ok(Some("1".to_string())) + } + + #[op] + // using the same op that is used in `tsc.rs` for loading modules and reading + // files, but a slightly different implementation at build time. + fn op_load(state: &mut OpState, args: LoadArgs) -> Result<Value, AnyError> { + let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>(); + let path_dts = state.borrow::<PathBuf>(); + let re_asset = + Regex::new(r"asset:/{3}lib\.(\S+)\.d\.ts").expect("bad regex"); + let build_specifier = "asset:///bootstrap.ts"; + + // we need a basic file to send to tsc to warm it up. + if args.specifier == build_specifier { + Ok(json!({ + "data": r#"Deno.writeTextFile("hello.txt", "hello deno!");"#, + "version": "1", + // this corresponds to `ts.ScriptKind.TypeScript` + "scriptKind": 3 + })) + // specifiers come across as `asset:///lib.{lib_name}.d.ts` and we need to + // parse out just the name so we can lookup the asset. + } else if let Some(caps) = re_asset.captures(&args.specifier) { + if let Some(lib) = caps.get(1).map(|m| m.as_str()) { + // if it comes from an op crate, we were supplied with the path to the + // file. + let path = if let Some(op_crate_lib) = op_crate_libs.get(lib) { + PathBuf::from(op_crate_lib).canonicalize()? + // otherwise we will generate the path ourself + } else { + path_dts.join(format!("lib.{lib}.d.ts")) + }; + let data = std::fs::read_to_string(path)?; + Ok(json!({ + "data": data, + "version": "1", + // this corresponds to `ts.ScriptKind.TypeScript` + "scriptKind": 3 + })) + } else { + Err(custom_error( + "InvalidSpecifier", + format!("An invalid specifier was requested: {}", args.specifier), + )) + } + } else { + Err(custom_error( + "InvalidSpecifier", + format!("An invalid specifier was requested: {}", args.specifier), + )) + } + } + + deno_core::extension!(deno_tsc, + ops = [op_build_info, op_is_node_file, op_load, op_script_version], + js = [ + dir "tsc", + "00_typescript.js", + "99_main_compiler.js", + ], + config = { + op_crate_libs: HashMap<&'static str, PathBuf>, + build_libs: Vec<&'static str>, + path_dts: PathBuf, + }, + state = |state, op_crate_libs, build_libs, path_dts| { + state.put(op_crate_libs); + state.put(build_libs); + state.put(path_dts); + }, + ); + pub fn create_compiler_snapshot(snapshot_path: PathBuf, cwd: &Path) { // libs that are being provided by op crates. let mut op_crate_libs = HashMap::new(); @@ -158,110 +259,15 @@ mod ts { ) .unwrap(); - #[op] - fn op_build_info(state: &mut OpState) -> Value { - let build_specifier = "asset:///bootstrap.ts"; - - let node_built_in_module_names = SUPPORTED_BUILTIN_NODE_MODULES - .iter() - .map(|s| s.name) - .collect::<Vec<&str>>(); - let build_libs = state.borrow::<Vec<&str>>(); - json!({ - "buildSpecifier": build_specifier, - "libs": build_libs, - "nodeBuiltInModuleNames": node_built_in_module_names, - }) - } - - #[op] - fn op_is_node_file() -> bool { - false - } - - #[op] - fn op_script_version( - _state: &mut OpState, - _args: Value, - ) -> Result<Option<String>, AnyError> { - Ok(Some("1".to_string())) - } - - #[op] - // using the same op that is used in `tsc.rs` for loading modules and reading - // files, but a slightly different implementation at build time. - fn op_load(state: &mut OpState, args: LoadArgs) -> Result<Value, AnyError> { - let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>(); - let path_dts = state.borrow::<PathBuf>(); - let re_asset = - Regex::new(r"asset:/{3}lib\.(\S+)\.d\.ts").expect("bad regex"); - let build_specifier = "asset:///bootstrap.ts"; - - // we need a basic file to send to tsc to warm it up. - if args.specifier == build_specifier { - Ok(json!({ - "data": r#"Deno.writeTextFile("hello.txt", "hello deno!");"#, - "version": "1", - // this corresponds to `ts.ScriptKind.TypeScript` - "scriptKind": 3 - })) - // specifiers come across as `asset:///lib.{lib_name}.d.ts` and we need to - // parse out just the name so we can lookup the asset. - } else if let Some(caps) = re_asset.captures(&args.specifier) { - if let Some(lib) = caps.get(1).map(|m| m.as_str()) { - // if it comes from an op crate, we were supplied with the path to the - // file. - let path = if let Some(op_crate_lib) = op_crate_libs.get(lib) { - PathBuf::from(op_crate_lib).canonicalize()? - // otherwise we are will generate the path ourself - } else { - path_dts.join(format!("lib.{lib}.d.ts")) - }; - let data = std::fs::read_to_string(path)?; - Ok(json!({ - "data": data, - "version": "1", - // this corresponds to `ts.ScriptKind.TypeScript` - "scriptKind": 3 - })) - } else { - Err(custom_error( - "InvalidSpecifier", - format!("An invalid specifier was requested: {}", args.specifier), - )) - } - } else { - Err(custom_error( - "InvalidSpecifier", - format!("An invalid specifier was requested: {}", args.specifier), - )) - } - } - - let tsc_extension = Extension::builder("deno_tsc") - .ops(vec![ - op_build_info::decl(), - op_is_node_file::decl(), - op_load::decl(), - op_script_version::decl(), - ]) - .js(include_js_files! { - dir "tsc", - "00_typescript.js", - "99_main_compiler.js", - }) - .state(move |state| { - state.put(op_crate_libs.clone()); - state.put(build_libs.clone()); - state.put(path_dts.clone()); - }) - .build(); - create_snapshot(CreateSnapshotOptions { cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"), snapshot_path, startup_snapshot: None, - extensions: vec![tsc_extension], + extensions: vec![deno_tsc::init_ops_and_esm( + op_crate_libs, + build_libs, + path_dts, + )], // NOTE(bartlomieju): Compressing the TSC snapshot in debug build took // ~45s on M1 MacBook Pro; without compression it took ~1s. @@ -304,61 +310,66 @@ mod ts { } } +// FIXME(bartlomieju): information about which extensions were +// already snapshotted is not preserved in the snapshot. This should be +// fixed, so we can reliably depend on that information. +// deps = [runtime] +deno_core::extension!( + cli, + esm = [ + dir "js", + "40_testing.js" + ], + customizer = |ext: &mut ExtensionBuilder| { + ext.esm(vec![ExtensionFileSource { + specifier: "runtime/js/99_main.js".to_string(), + code: ExtensionFileSourceCode::LoadedFromFsDuringSnapshot( + std::path::PathBuf::from(deno_runtime::js::PATH_FOR_99_MAIN_JS), + ), + }]); + } +); + fn create_cli_snapshot(snapshot_path: PathBuf) { // NOTE(bartlomieju): ordering is important here, keep it in sync with // `runtime/worker.rs`, `runtime/web_worker.rs` and `runtime/build.rs`! - let mut extensions: Vec<Extension> = vec![ - deno_webidl::init(), - deno_console::init(), - deno_url::init_ops(), - deno_web::init_ops::<PermissionsContainer>( + let extensions: Vec<Extension> = vec![ + deno_webidl::deno_webidl::init_ops(), + deno_console::deno_console::init_ops(), + deno_url::deno_url::init_ops(), + deno_web::deno_web::init_ops::<PermissionsContainer>( deno_web::BlobStore::default(), Default::default(), ), - deno_fetch::init_ops::<PermissionsContainer>(Default::default()), - deno_cache::init_ops::<SqliteBackedCache>(None), - deno_websocket::init_ops::<PermissionsContainer>("".to_owned(), None, None), - deno_webstorage::init_ops(None), - deno_crypto::init_ops(None), - deno_broadcast_channel::init_ops( + deno_fetch::deno_fetch::init_ops::<PermissionsContainer>(Default::default()), + deno_cache::deno_cache::init_ops::<SqliteBackedCache>(None), + deno_websocket::deno_websocket::init_ops::<PermissionsContainer>( + "".to_owned(), + None, + None, + ), + deno_webstorage::deno_webstorage::init_ops(None), + deno_crypto::deno_crypto::init_ops(None), + deno_broadcast_channel::deno_broadcast_channel::init_ops( deno_broadcast_channel::InMemoryBroadcastChannel::default(), false, // No --unstable. ), - deno_ffi::init_ops::<PermissionsContainer>(false), - deno_net::init_ops::<PermissionsContainer>( + deno_ffi::deno_ffi::init_ops::<PermissionsContainer>(false), + deno_net::deno_net::init_ops::<PermissionsContainer>( None, false, // No --unstable. None, ), - deno_tls::init_ops(), - deno_napi::init_ops::<PermissionsContainer>(), - deno_http::init_ops(), - deno_io::init_ops(Default::default()), - deno_fs::init_ops::<PermissionsContainer>(false), - deno_flash::init_ops::<PermissionsContainer>(false), // No --unstable - deno_node::init_ops::<PermissionsContainer>(None), // No --unstable. - deno_node::init_polyfill_ops(), + deno_tls::deno_tls::init_ops(), + deno_napi::deno_napi::init_ops::<PermissionsContainer>(), + deno_http::deno_http::init_ops(), + deno_io::deno_io::init_ops(Rc::new(RefCell::new(Some(Default::default())))), + deno_fs::deno_fs::init_ops::<PermissionsContainer>(false), + deno_flash::deno_flash::init_ops::<PermissionsContainer>(false), // No --unstable + deno_node::deno_node_loading::init_ops::<PermissionsContainer>(None), // No --unstable. + deno_node::deno_node::init_ops(), + cli::init_ops_and_esm(), // NOTE: This needs to be init_ops_and_esm! ]; - let mut esm_files = include_js_files!( - dir "js", - "40_testing.js", - ); - esm_files.push(ExtensionFileSource { - specifier: "runtime/js/99_main.js".to_string(), - code: ExtensionFileSourceCode::LoadedFromFsDuringSnapshot( - std::path::PathBuf::from(deno_runtime::js::PATH_FOR_99_MAIN_JS), - ), - }); - extensions.push( - Extension::builder("cli") - // FIXME(bartlomieju): information about which extensions were - // already snapshotted is not preserved in the snapshot. This should be - // fixed, so we can reliably depend on that information. - // .dependencies(vec!["runtime"]) - .esm(esm_files) - .build(), - ); - create_snapshot(CreateSnapshotOptions { cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"), snapshot_path, diff --git a/cli/lsp/testing/execution.rs b/cli/lsp/testing/execution.rs index af890cc0d..ee182c690 100644 --- a/cli/lsp/testing/execution.rs +++ b/cli/lsp/testing/execution.rs @@ -165,7 +165,11 @@ async fn test_specifier( &ps, specifier.clone(), PermissionsContainer::new(permissions), - vec![ops::testing::init(sender, fail_fast_tracker, filter)], + vec![ops::testing::deno_test::init_ops( + sender, + fail_fast_tracker, + filter, + )], Stdio { stdin: StdioPipe::Inherit, stdout, diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index 335d91ed7..910d13691 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -37,7 +37,6 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::url::Url; -use deno_core::Extension; use deno_core::JsRuntime; use deno_core::ModuleSpecifier; use deno_core::OpState; @@ -2819,31 +2818,32 @@ fn op_script_version( /// server. fn js_runtime(performance: Arc<Performance>) -> JsRuntime { JsRuntime::new(RuntimeOptions { - extensions: vec![init_extension(performance)], + extensions: vec![deno_tsc::init_ops(performance)], startup_snapshot: Some(tsc::compiler_snapshot()), ..Default::default() }) } -fn init_extension(performance: Arc<Performance>) -> Extension { - Extension::builder("deno_tsc") - .ops(vec![ - op_is_cancelled::decl(), - op_is_node_file::decl(), - op_load::decl(), - op_resolve::decl(), - op_respond::decl(), - op_script_names::decl(), - op_script_version::decl(), - ]) - .state(move |state| { - state.put(State::new( - Arc::new(StateSnapshot::default()), - performance.clone(), - )); - }) - .build() -} +deno_core::extension!(deno_tsc, + ops = [ + op_is_cancelled, + op_is_node_file, + op_load, + op_resolve, + op_respond, + op_script_names, + op_script_version, + ], + config = { + performance: Arc<Performance> + }, + state = |state, performance| { + state.put(State::new( + Arc::new(StateSnapshot::default()), + performance, + )); + }, +); /// Instruct a language server runtime to start the language server and provide /// it with a minimal bootstrap configuration. diff --git a/cli/ops/bench.rs b/cli/ops/bench.rs index 513ecc0d1..7bd3f988a 100644 --- a/cli/ops/bench.rs +++ b/cli/ops/bench.rs @@ -7,7 +7,6 @@ use std::time; use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::op; -use deno_core::Extension; use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_runtime::permissions::create_child_permissions; @@ -22,25 +21,24 @@ use crate::tools::bench::BenchDescription; use crate::tools::bench::BenchEvent; use crate::tools::test::TestFilter; -pub fn init( - sender: UnboundedSender<BenchEvent>, - filter: TestFilter, -) -> Extension { - Extension::builder("deno_bench") - .ops(vec![ - op_pledge_test_permissions::decl(), - op_restore_test_permissions::decl(), - op_get_bench_origin::decl(), - op_register_bench::decl(), - op_dispatch_bench_event::decl(), - op_bench_now::decl(), - ]) - .state(move |state| { - state.put(sender.clone()); - state.put(filter.clone()); - }) - .build() -} +deno_core::extension!(deno_bench, + ops = [ + op_pledge_test_permissions, + op_restore_test_permissions, + op_get_bench_origin, + op_register_bench, + op_dispatch_bench_event, + op_bench_now, + ], + config = { + sender: UnboundedSender<BenchEvent>, + filter: TestFilter, + }, + state = |state, sender, filter| { + state.put(sender); + state.put(filter); + }, +); #[derive(Clone)] struct PermissionsHolder(Uuid, PermissionsContainer); diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs index 53f74ad1f..562aa8649 100644 --- a/cli/ops/mod.rs +++ b/cli/ops/mod.rs @@ -10,17 +10,18 @@ pub mod bench; pub mod testing; pub fn cli_exts(ps: ProcState) -> Vec<Extension> { - vec![init_proc_state(ps)] + vec![deno_cli::init_ops(ps)] } -fn init_proc_state(ps: ProcState) -> Extension { - Extension::builder("deno_cli") - .ops(vec![op_npm_process_state::decl()]) - .state(move |state| { - state.put(ps.clone()); - }) - .build() -} +deno_core::extension!(deno_cli, + ops = [op_npm_process_state], + config = { + ps: ProcState, + }, + state = |state, ps| { + state.put(ps); + }, +); #[op] fn op_npm_process_state(state: &mut OpState) -> Result<String, AnyError> { diff --git a/cli/ops/testing.rs b/cli/ops/testing.rs index 9170e9400..f32e96147 100644 --- a/cli/ops/testing.rs +++ b/cli/ops/testing.rs @@ -12,7 +12,6 @@ use crate::tools::test::TestStepDescription; use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::op; -use deno_core::Extension; use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_runtime::permissions::create_child_permissions; @@ -25,28 +24,27 @@ use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use uuid::Uuid; -pub fn init( - sender: TestEventSender, - fail_fast_tracker: FailFastTracker, - filter: TestFilter, -) -> Extension { - Extension::builder("deno_test") - .ops(vec![ - op_pledge_test_permissions::decl(), - op_restore_test_permissions::decl(), - op_get_test_origin::decl(), - 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()); - }) - .build() -} +deno_core::extension!(deno_test, + ops = [ + op_pledge_test_permissions, + op_restore_test_permissions, + op_get_test_origin, + op_register_test, + op_register_test_step, + op_dispatch_test_event, + op_tests_should_stop, + ], + config = { + sender: TestEventSender, + fail_fast_tracker: FailFastTracker, + filter: TestFilter, + }, + state = |state, sender, fail_fast_tracker, filter| { + state.put(sender); + state.put(fail_fast_tracker); + state.put(filter); + }, +); #[derive(Clone)] struct PermissionsHolder(Uuid, PermissionsContainer); diff --git a/cli/tools/bench.rs b/cli/tools/bench.rs index 0aa7cc365..6cc2a22f0 100644 --- a/cli/tools/bench.rs +++ b/cli/tools/bench.rs @@ -441,7 +441,7 @@ async fn bench_specifier( &ps, specifier, PermissionsContainer::new(permissions), - vec![ops::bench::init(channel, filter)], + vec![ops::bench::deno_bench::init_ops(channel, filter)], Default::default(), ) .await?; diff --git a/cli/tools/test.rs b/cli/tools/test.rs index d200a3029..0d9637c3d 100644 --- a/cli/tools/test.rs +++ b/cli/tools/test.rs @@ -723,7 +723,7 @@ async fn test_specifier( ps, specifier, PermissionsContainer::new(permissions), - vec![ops::testing::init( + vec![ops::testing::deno_test::init_ops( sender, fail_fast_tracker, options.filter, diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs index 63b4e269d..387fd3aa1 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -22,7 +22,6 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::serde_v8; -use deno_core::Extension; use deno_core::JsRuntime; use deno_core::ModuleSpecifier; use deno_core::OpState; @@ -35,12 +34,14 @@ use deno_graph::ModuleGraph; use deno_graph::ResolutionResolved; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::permissions::PermissionsContainer; +use lsp_types::Url; use once_cell::sync::Lazy; use std::borrow::Cow; use std::collections::HashMap; use std::fmt; use std::path::Path; use std::path::PathBuf; +use std::rc::Rc; use std::sync::Arc; mod diagnostics; @@ -114,12 +115,12 @@ pub fn get_types_declaration_file_text(unstable: bool) -> String { } fn get_asset_texts_from_new_runtime() -> Result<Vec<AssetText>, AnyError> { + deno_core::extension!(deno_cli_tsc, ops_fn = deno_ops,); + // the assets are stored within the typescript isolate, so take them out of there let mut runtime = JsRuntime::new(RuntimeOptions { startup_snapshot: Some(compiler_snapshot()), - extensions: vec![Extension::builder("deno_cli_tsc") - .ops(get_tsc_ops()) - .build()], + extensions: vec![deno_cli_tsc::init_ops()], ..Default::default() }); let global = @@ -825,26 +826,28 @@ pub fn exec(request: Request) -> Result<Response, AnyError> { } }) .collect(); - let mut runtime = JsRuntime::new(RuntimeOptions { - startup_snapshot: Some(compiler_snapshot()), - extensions: vec![Extension::builder("deno_cli_tsc") - .ops(get_tsc_ops()) - .state(move |state| { - state.put(State::new( - request.graph.clone(), - request.hash_data.clone(), - request.maybe_npm_resolver.clone(), - request.maybe_tsbuildinfo.clone(), - root_map.clone(), - remapped_specifiers.clone(), - std::env::current_dir() - .context("Unable to get CWD") - .unwrap(), - )); - }) - .build()], - ..Default::default() - }); + + deno_core::extension!(deno_cli_tsc, + ops_fn = deno_ops, + config = { + request: Rc<Request>, + root_map: HashMap<String, Url>, + remapped_specifiers: HashMap<String, Url>, + }, + state = |state, request, root_map, remapped_specifiers| { + state.put(State::new( + request.graph.clone(), + request.hash_data.clone(), + request.maybe_npm_resolver.clone(), + request.maybe_tsbuildinfo.clone(), + root_map, + remapped_specifiers, + std::env::current_dir() + .context("Unable to get CWD") + .unwrap(), + )); + }, + ); let startup_source = "globalThis.startup({ legacyFlag: false })"; let request_value = json!({ @@ -855,6 +858,16 @@ pub fn exec(request: Request) -> Result<Response, AnyError> { let request_str = request_value.to_string(); let exec_source = format!("globalThis.exec({request_str})"); + let mut runtime = JsRuntime::new(RuntimeOptions { + startup_snapshot: Some(compiler_snapshot()), + extensions: vec![deno_cli_tsc::init_ops( + Rc::new(request), + root_map, + remapped_specifiers, + )], + ..Default::default() + }); + runtime .execute_script(&located_script_name!(), startup_source) .context("Could not properly start the compiler runtime.")?; @@ -879,16 +892,17 @@ pub fn exec(request: Request) -> Result<Response, AnyError> { } } -fn get_tsc_ops() -> Vec<deno_core::OpDecl> { - vec![ - op_create_hash::decl(), - op_emit::decl(), - op_is_node_file::decl(), - op_load::decl(), - op_resolve::decl(), - op_respond::decl(), +deno_core::ops!( + deno_ops, + [ + op_create_hash, + op_emit, + op_is_node_file, + op_load, + op_resolve, + op_respond, ] -} +); #[cfg(test)] mod tests { |