From e55b448730160a6e4df9815a268d4049ac89deab Mon Sep 17 00:00:00 2001 From: Matt Mastracci Date: Fri, 17 Mar 2023 12:22:15 -0600 Subject: [PATCH] feat(core) deno_core::extension! macro to simplify extension registration (#18210) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements two macros to simplify extension registration and centralize a lot of the boilerplate as a base for future improvements: * `deno_core::ops!` registers a block of `#[op]`s, optionally with type parameters, useful for places where we share lists of ops * `deno_core::extension!` is used to register an extension, and creates two methods that can be used at runtime/snapshot generation time: `init_ops` and `init_ops_and_esm`. --------- Co-authored-by: Bartek IwaƄczuk --- bench_util/benches/op_baseline.rs | 10 +- cli/build.rs | 295 ++++++++++++++++-------------- cli/lsp/testing/execution.rs | 6 +- cli/lsp/tsc.rs | 42 ++--- cli/ops/bench.rs | 38 ++-- cli/ops/mod.rs | 19 +- cli/ops/testing.rs | 44 +++-- cli/tools/bench.rs | 2 +- cli/tools/test.rs | 2 +- cli/tsc/mod.rs | 80 ++++---- core/extensions.rs | 257 ++++++++++++++++++++++++++ core/modules.rs | 7 +- core/ops_builtin.rs | 103 ++++++----- core/ops_builtin_v8.rs | 37 ---- core/runtime.rs | 166 ++++++++--------- ext/broadcast_channel/lib.rs | 62 ++----- ext/cache/lib.rs | 64 +++---- ext/console/lib.rs | 17 +- ext/crypto/lib.rs | 105 +++++------ ext/fetch/lib.rs | 97 ++++------ ext/ffi/lib.rs | 170 ++++++++--------- ext/flash/lib.rs | 111 +++++------ ext/fs/lib.rs | 161 ++++++++-------- ext/http/lib.rs | 47 ++--- ext/io/lib.rs | 120 +++++------- ext/napi/lib.rs | 123 +++++++------ ext/net/lib.rs | 86 ++++----- ext/net/ops.rs | 43 +---- ext/net/ops_tls.rs | 11 -- ext/node/lib.rs | 166 +++++++---------- ext/tls/lib.rs | 7 +- ext/url/benches/url_ops.rs | 4 +- ext/url/lib.rs | 44 ++--- ext/web/benches/encoding.rs | 12 +- ext/web/benches/timers_ops.rs | 9 +- ext/web/lib.rs | 156 +++++++--------- ext/webidl/benches/dict.rs | 2 +- ext/webidl/lib.rs | 13 +- ext/websocket/lib.rs | 88 +++------ ext/webstorage/lib.rs | 58 +++--- runtime/build.rs | 160 ++++++++-------- runtime/ops/fs_events.rs | 10 +- runtime/ops/http.rs | 14 +- runtime/ops/os/mod.rs | 82 ++++----- runtime/ops/permissions.rs | 18 +- runtime/ops/process.rs | 24 ++- runtime/ops/runtime.rs | 17 +- runtime/ops/signal.rs | 14 +- runtime/ops/tty.rs | 14 +- runtime/ops/web_worker.rs | 24 ++- runtime/ops/worker_host.rs | 65 ++++--- runtime/web_worker.rs | 107 ++++++----- runtime/worker.rs | 108 ++++++----- 53 files changed, 1690 insertions(+), 1851 deletions(-) diff --git a/bench_util/benches/op_baseline.rs b/bench_util/benches/op_baseline.rs index 8ed678b880..89fb3d2f3a 100644 --- a/bench_util/benches/op_baseline.rs +++ b/bench_util/benches/op_baseline.rs @@ -9,14 +9,10 @@ use deno_bench_util::bencher::Bencher; use deno_core::op; use deno_core::Extension; +deno_core::extension!(bench_setup, ops = [op_pi_json, op_pi_async, op_nop]); + fn setup() -> Vec { - vec![Extension::builder("bench_setup") - .ops(vec![ - op_pi_json::decl(), - op_pi_async::decl(), - op_nop::decl(), - ]) - .build()] + vec![bench_setup::init_ops()] } #[op] diff --git a/cli/build.rs b/cli/build.rs index 216969e39f..e4df856f79 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::>(); + let build_libs = state.borrow::>(); + 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, 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 { + let op_crate_libs = state.borrow::>(); + let path_dts = state.borrow::(); + 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::>(); - let build_libs = state.borrow::>(); - 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, 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 { - let op_crate_libs = state.borrow::>(); - let path_dts = state.borrow::(); - 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 = vec![ - deno_webidl::init(), - deno_console::init(), - deno_url::init_ops(), - deno_web::init_ops::( + let extensions: Vec = 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::( deno_web::BlobStore::default(), Default::default(), ), - deno_fetch::init_ops::(Default::default()), - deno_cache::init_ops::(None), - deno_websocket::init_ops::("".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::(Default::default()), + deno_cache::deno_cache::init_ops::(None), + deno_websocket::deno_websocket::init_ops::( + "".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::(false), - deno_net::init_ops::( + deno_ffi::deno_ffi::init_ops::(false), + deno_net::deno_net::init_ops::( None, false, // No --unstable. None, ), - deno_tls::init_ops(), - deno_napi::init_ops::(), - deno_http::init_ops(), - deno_io::init_ops(Default::default()), - deno_fs::init_ops::(false), - deno_flash::init_ops::(false), // No --unstable - deno_node::init_ops::(None), // No --unstable. - deno_node::init_polyfill_ops(), + deno_tls::deno_tls::init_ops(), + deno_napi::deno_napi::init_ops::(), + 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::(false), + deno_flash::deno_flash::init_ops::(false), // No --unstable + deno_node::deno_node_loading::init_ops::(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 af890cc0da..ee182c6900 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 335d91ed78..910d136913 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) -> 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) -> 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 + }, + 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 513ecc0d1f..7bd3f988a2 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, - 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, + 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 53f74ad1f2..562aa86492 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 { - 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 { diff --git a/cli/ops/testing.rs b/cli/ops/testing.rs index 9170e9400d..f32e961479 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 0aa7cc365c..6cc2a22f05 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 d200a30298..0d9637c3df 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 63b4e269d3..387fd3aa16 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, 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 { } }) .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, + root_map: HashMap, + remapped_specifiers: HashMap, + }, + 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 { 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 { } } -fn get_tsc_ops() -> Vec { - 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 { diff --git a/core/extensions.rs b/core/extensions.rs index 2c6e1669c6..71b9cdb4f5 100644 --- a/core/extensions.rs +++ b/core/extensions.rs @@ -65,6 +65,263 @@ impl OpDecl { } } +/// Declares a block of Deno `#[op]`s. The first parameter determines the name of the +/// op declaration block, and is usually `deno_ops`. This block generates a function that +/// returns a [`Vec`]. +/// +/// This can be either a compact form like: +/// +/// ```no_compile +/// # use deno_core::*; +/// #[op] +/// fn op_xyz() {} +/// +/// deno_core::ops!(deno_ops, [ +/// op_xyz +/// ]); +/// +/// // Use the ops: +/// deno_ops() +/// ``` +/// +/// ... or a parameterized form like so that allows passing a number of type parameters +/// to each `#[op]`: +/// +/// ```no_compile +/// # use deno_core::*; +/// #[op] +/// fn op_xyz

() where P: Clone {} +/// +/// deno_core::ops!(deno_ops, +/// parameters = [P: Clone], +/// ops = [ +/// op_xyz

+/// ] +/// ); +/// +/// // Use the ops, with `String` as the parameter `P`: +/// deno_ops::() +/// ``` +#[macro_export] +macro_rules! ops { + ($name:ident, parameters = [ $( $param:ident : $type:ident ),+ ], ops = [ $( $(#[$m:meta])* $( $op:ident )::+ $( < $op_param:ident > )? ),+ $(,)? ]) => { + pub(crate) fn $name < $( $param : $type + 'static ),+ > () -> Vec<$crate::OpDecl> { + vec![ + $( + $( #[ $m ] )* + $( $op )::+ :: decl $( :: <$op_param> )? () , + )+ + ] + } + }; + ($name:ident, [ $( $(#[$m:meta])* $( $op:ident )::+ ),+ $(,)? ] ) => { + pub(crate) fn $name() -> Vec<$crate::OpDecl> { + vec![ + $( $( #[ $m ] )* $( $op )::+ :: decl(), )+ + ] + } + } +} + +/// Defines a Deno extension. The first parameter is the name of the extension symbol namespace to create. This is the symbol you +/// will use to refer to the extension. +/// +/// Most extensions will define a combination of ops and ESM files, like so: +/// +/// ```no_compile +/// #[op] +/// fn op_xyz() { +/// } +/// +/// deno_core::extension!( +/// my_extension, +/// ops = [ op_xyz ], +/// esm = [ "my_script.js" ], +/// ); +/// ``` +/// +/// The following options are available for the [`extension`] macro: +/// +/// * deps: a comma-separated list of module dependencies, eg: `deps = [ my_other_extension ]` +/// * parameters: a comma-separated list of parameters and base traits, eg: `parameters = [ P: MyTrait ]` +/// * ops: a comma-separated list of [`OpDecl`]s to provide, eg: `ops = [ op_foo, op_bar ]` +/// * esm: a comma-separated list of ESM module filenames (see [`include_js_files`]), eg: `esm = [ dir "dir", "my_file.js" ]` +/// * esm_setup_script: see [`ExtensionBuilder::esm_setup_script`] +/// * js: a comma-separated list of JS filenames (see [`include_js_files`]), eg: `js = [ dir "dir", "my_file.js" ]` +/// * config: a structure-like definition for configuration parameters which will be required when initializing this extension, eg: `config = { my_param: Option }` +/// * middleware: an [`OpDecl`] middleware function with the signature `fn (OpDecl) -> OpDecl` +/// * state: a state initialization function, with the signature `fn (&mut OpState, ...) -> ()`, where `...` are parameters matching the fields of the config struct +/// * event_loop_middleware: an event-loop middleware function (see [`ExtensionBuilder::event_loop_middleware`]) +#[macro_export] +macro_rules! extension { + ( + $name:ident + $(, deps = [ $( $dep:ident ),* ] )? + $(, parameters = [ $( $param:ident : $type:ident ),+ ] )? + $(, ops_fn = $ops_symbol:ident $( < $ops_param:ident > )? )? + $(, ops = [ $( $(#[$m:meta])* $( $op:ident )::+ $( < $op_param:ident > )? ),+ $(,)? ] )? + $(, esm_entry_point = $esm_entry_point:literal )? + $(, esm = [ $( dir $dir_esm:literal , )? $( $esm:literal ),* $(,)? ] )? + $(, esm_setup_script = $esm_setup_script:expr )? + $(, js = [ $( dir $dir_js:literal , )? $( $js:literal ),* $(,)? ] )? + $(, config = { $( $config_id:ident : $config_type:ty ),* $(,)? } )? + $(, middleware = $middleware_fn:expr )? + $(, state = $state_fn:expr )? + $(, event_loop_middleware = $event_loop_middleware_fn:ident )? + $(, customizer = $customizer_fn:expr )? + $(,)? + ) => { + /// Extension struct for + #[doc = stringify!($name)] + /// . + #[allow(non_camel_case_types)] + pub struct $name { + } + + impl $name { + #[inline(always)] + fn ext() -> $crate::ExtensionBuilder { + $crate::Extension::builder_with_deps(stringify!($name), &[ $( $( stringify!($dep) ),* )? ]) + } + + /// If ESM or JS was specified, add those files to the extension. + #[inline(always)] + #[allow(unused_variables)] + fn with_js(ext: &mut $crate::ExtensionBuilder) { + $( ext.esm( + $crate::include_js_files!( $( dir $dir_esm , )? $( $esm , )* ) + ); )? + $( + ext.esm(vec![ExtensionFileSource { + specifier: "ext:setup".to_string(), + code: ExtensionFileSourceCode::IncludedInBinary($esm_setup_script), + }]); + )? + $( + ext.esm_entry_point($esm_entry_point); + )? + $( ext.js( + $crate::include_js_files!( $( dir $dir_js , )? $( $js , )* ) + ); )? + } + + // If ops were specified, add those ops to the extension. + #[inline(always)] + #[allow(unused_variables)] + fn with_ops $( < $( $param : $type + Clone + 'static ),+ > )?(ext: &mut $crate::ExtensionBuilder) { + // If individual ops are specified, roll them up into a vector and apply them + $( + let v = vec![ + $( + $( #[ $m ] )* + $( $op )::+ :: decl $( :: <$op_param> )? () + ),+ + ]; + ext.ops(v); + )? + + // Otherwise use the ops_fn, if provided + $crate::extension!(! __ops__ ext $( $ops_symbol $( < $ops_param > )? )? __eot__); + } + + // Includes the state and middleware functions, if defined. + #[inline(always)] + #[allow(unused_variables)] + fn with_state_and_middleware$( < $( $param : $type + Clone + 'static ),+ > )?(ext: &mut $crate::ExtensionBuilder, $( $( $config_id : $config_type ),* )? ) { + #[allow(unused_variables)] + let config = $crate::extension!(! __config__ $( parameters = [ $( $param : $type ),* ] )? $( config = { $( $config_id : $config_type ),* } )? ); + + $( + ext.state(move |state: &mut $crate::OpState| { + config.clone().call_callback(state, $state_fn) + }); + )? + + $( + ext.event_loop_middleware($event_loop_middleware_fn); + )? + + $( + ext.middleware($middleware_fn); + )? + } + + #[inline(always)] + #[allow(unused_variables)] + fn with_customizer(ext: &mut $crate::ExtensionBuilder) { + $( ($customizer_fn)(ext); )? + } + + #[allow(dead_code)] + pub fn init_js_only $( < $( $param : $type + Clone + 'static ),+ > )? () -> $crate::Extension { + let mut ext = Self::ext(); + // If esm or JS was specified, add JS files + Self::with_js(&mut ext); + Self::with_ops $( ::<($( $param ),+)> )?(&mut ext); + Self::with_customizer(&mut ext); + ext.build() + } + + #[allow(dead_code)] + pub fn init_ops_and_esm $( < $( $param : $type + Clone + 'static ),+ > )? ( $( $( $config_id : $config_type ),* )? ) -> $crate::Extension { + let mut ext = Self::ext(); + // If esm or JS was specified, add JS files + Self::with_js(&mut ext); + Self::with_ops $( ::<($( $param ),+)> )?(&mut ext); + Self::with_state_and_middleware $( ::<($( $param ),+)> )?(&mut ext, $( $( $config_id , )* )? ); + Self::with_customizer(&mut ext); + ext.build() + } + + #[allow(dead_code)] + pub fn init_ops $( < $( $param : $type + Clone + 'static ),+ > )? ( $( $( $config_id : $config_type ),* )? ) -> $crate::Extension { + let mut ext = Self::ext(); + Self::with_ops $( ::<($( $param ),+)> )?(&mut ext); + Self::with_state_and_middleware $( ::<($( $param ),+)> )?(&mut ext, $( $( $config_id , )* )? ); + Self::with_customizer(&mut ext); + ext.build() + } + } + }; + + (! __config__ $( parameters = [ $( $param:ident : $type:ident ),+ ] )? $( config = { $( $config_id:ident : $config_type:ty ),* } )? ) => { + { + #[doc(hidden)] + #[derive(Clone)] + struct Config $( < $( $param : $type + Clone + 'static ),+ > )? { + $( $( pub $config_id : $config_type , )* )? + $( __phantom_data: ::std::marker::PhantomData<($( $param ),+)>, )? + } + + impl $( < $( $param : $type + Clone + 'static ),+ > )? Config $( < $( $param ),+ > )? { + /// Call a function of |state, ...| using the fields of this configuration structure. + #[allow(dead_code)] + #[doc(hidden)] + #[inline(always)] + fn call_callback(self, state: &mut $crate::OpState, f: F) { + f(state, $( $( self. $config_id ),* )? ) + } + } + + Config { + $( $( $config_id , )* )? + $( __phantom_data: ::std::marker::PhantomData::<($( $param ),+)>::default() )? + } + } + }; + + (! __ops__ $ext:ident __eot__) => { + }; + + (! __ops__ $ext:ident $ops_symbol:ident __eot__) => { + $ext.ops($ops_symbol()) + }; + + (! __ops__ $ext:ident $ops_symbol:ident < $ops_param:ident > __eot__) => { + $ext.ops($ops_symbol::<$ops_param>()) + }; +} + #[derive(Default)] pub struct Extension { js_files: Option>, diff --git a/core/modules.rs b/core/modules.rs index e03f86c01b..ddd55199be 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -1649,7 +1649,6 @@ impl ModuleMap { #[cfg(test)] mod tests { use super::*; - use crate::Extension; use crate::JsRuntime; use crate::RuntimeOptions; use crate::Snapshot; @@ -1990,12 +1989,10 @@ import "/a.js"; 43 } - let ext = Extension::builder("test_ext") - .ops(vec![op_test::decl()]) - .build(); + deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![ext], + extensions: vec![test_ext::init_ops()], module_loader: Some(loader), ..Default::default() }); diff --git a/core/ops_builtin.rs b/core/ops_builtin.rs index 7b66ffaa48..668b44bc36 100644 --- a/core/ops_builtin.rs +++ b/core/ops_builtin.rs @@ -1,13 +1,11 @@ -use crate::ExtensionBuilder; // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use crate::error::format_file_name; use crate::error::type_error; -use crate::include_js_files; use crate::io::BufMutView; use crate::io::BufView; +use crate::ops_builtin_v8; use crate::ops_metrics::OpMetrics; use crate::resources::ResourceId; -use crate::Extension; use crate::OpState; use crate::Resource; use crate::ZeroCopyBuf; @@ -19,49 +17,62 @@ use std::io::stdout; use std::io::Write; use std::rc::Rc; -fn ext() -> ExtensionBuilder { - Extension::builder("core") -} - -fn ops(ext: &mut ExtensionBuilder) -> &mut ExtensionBuilder { - let mut ops = vec![ - op_close::decl(), - op_try_close::decl(), - op_print::decl(), - op_resources::decl(), - op_wasm_streaming_feed::decl(), - op_wasm_streaming_set_url::decl(), - op_void_sync::decl(), - op_void_async::decl(), - op_add::decl(), - // // TODO(@AaronO): track IO metrics for builtin streams - op_read::decl(), - op_read_all::decl(), - op_write::decl(), - op_write_all::decl(), - op_shutdown::decl(), - op_metrics::decl(), - op_format_file_name::decl(), - op_is_proxy::decl(), - op_str_byte_length::decl(), - ]; - ops.extend(crate::ops_builtin_v8::init_builtins_v8()); - ext.ops(ops) -} - -pub(crate) fn init_builtin_ops_and_esm() -> Extension { - ops(&mut ext()) - .js(include_js_files!( - "00_primordials.js", - "01_core.js", - "02_error.js", - )) - .build() -} - -pub(crate) fn init_builtin_ops() -> Extension { - ops(&mut ext()).build() -} +crate::extension!( + core, + ops = [ + op_close, + op_try_close, + op_print, + op_resources, + op_wasm_streaming_feed, + op_wasm_streaming_set_url, + op_void_sync, + op_void_async, + op_add, + // TODO(@AaronO): track IO metrics for builtin streams + op_read, + op_read_all, + op_write, + op_write_all, + op_shutdown, + op_metrics, + op_format_file_name, + op_is_proxy, + op_str_byte_length, + ops_builtin_v8::op_ref_op, + ops_builtin_v8::op_unref_op, + ops_builtin_v8::op_set_macrotask_callback, + ops_builtin_v8::op_set_next_tick_callback, + ops_builtin_v8::op_set_promise_reject_callback, + ops_builtin_v8::op_run_microtasks, + ops_builtin_v8::op_has_tick_scheduled, + ops_builtin_v8::op_set_has_tick_scheduled, + ops_builtin_v8::op_eval_context, + ops_builtin_v8::op_queue_microtask, + ops_builtin_v8::op_create_host_object, + ops_builtin_v8::op_encode, + ops_builtin_v8::op_decode, + ops_builtin_v8::op_serialize, + ops_builtin_v8::op_deserialize, + ops_builtin_v8::op_set_promise_hooks, + ops_builtin_v8::op_get_promise_details, + ops_builtin_v8::op_get_proxy_details, + ops_builtin_v8::op_memory_usage, + ops_builtin_v8::op_set_wasm_streaming_callback, + ops_builtin_v8::op_abort_wasm_streaming, + ops_builtin_v8::op_destructure_error, + ops_builtin_v8::op_dispatch_exception, + ops_builtin_v8::op_op_names, + ops_builtin_v8::op_apply_source_map, + ops_builtin_v8::op_set_format_exception_callback, + ops_builtin_v8::op_event_loop_has_more_work, + ops_builtin_v8::op_store_pending_promise_rejection, + ops_builtin_v8::op_remove_pending_promise_rejection, + ops_builtin_v8::op_has_pending_promise_rejection, + ops_builtin_v8::op_arraybuffer_was_detached, + ], + js = ["00_primordials.js", "01_core.js", "02_error.js"], +); /// Return map of resources with id as key /// and string representation as value. diff --git a/core/ops_builtin_v8.rs b/core/ops_builtin_v8.rs index 05250dc73c..3d7b4a996d 100644 --- a/core/ops_builtin_v8.rs +++ b/core/ops_builtin_v8.rs @@ -11,7 +11,6 @@ use crate::serde_v8::from_v8; use crate::source_map::apply_source_map as apply_source_map_; use crate::JsRealm; use crate::JsRuntime; -use crate::OpDecl; use crate::ZeroCopyBuf; use anyhow::Error; use deno_ops::op; @@ -21,42 +20,6 @@ use std::cell::RefCell; use v8::ValueDeserializerHelper; use v8::ValueSerializerHelper; -pub(crate) fn init_builtins_v8() -> Vec { - vec![ - op_ref_op::decl(), - op_unref_op::decl(), - op_set_macrotask_callback::decl(), - op_set_next_tick_callback::decl(), - op_set_promise_reject_callback::decl(), - op_run_microtasks::decl(), - op_has_tick_scheduled::decl(), - op_set_has_tick_scheduled::decl(), - op_eval_context::decl(), - op_queue_microtask::decl(), - op_create_host_object::decl(), - op_encode::decl(), - op_decode::decl(), - op_serialize::decl(), - op_deserialize::decl(), - op_set_promise_hooks::decl(), - op_get_promise_details::decl(), - op_get_proxy_details::decl(), - op_memory_usage::decl(), - op_set_wasm_streaming_callback::decl(), - op_abort_wasm_streaming::decl(), - op_destructure_error::decl(), - op_dispatch_exception::decl(), - op_op_names::decl(), - op_apply_source_map::decl(), - op_set_format_exception_callback::decl(), - op_event_loop_has_more_work::decl(), - op_store_pending_promise_rejection::decl(), - op_remove_pending_promise_rejection::decl(), - op_has_pending_promise_rejection::decl(), - op_arraybuffer_was_detached::decl(), - ] -} - fn to_v8_fn( scope: &mut v8::HandleScope, value: serde_v8::Value, diff --git a/core/runtime.rs b/core/runtime.rs index c19765dd95..1ea9c01684 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -323,11 +323,11 @@ impl JsRuntime { if !has_startup_snapshot { options .extensions - .insert(0, crate::ops_builtin::init_builtin_ops_and_esm()); + .insert(0, crate::ops_builtin::core::init_ops_and_esm()); } else { options .extensions - .insert(0, crate::ops_builtin::init_builtin_ops()); + .insert(0, crate::ops_builtin::core::init_ops()); } let ops = Self::collect_ops(&mut options.extensions); @@ -2683,7 +2683,7 @@ pub mod tests { } #[derive(Copy, Clone)] - enum Mode { + pub enum Mode { Async, AsyncDeferred, AsyncZeroCopy(bool), @@ -2728,18 +2728,22 @@ pub mod tests { fn setup(mode: Mode) -> (JsRuntime, Arc) { let dispatch_count = Arc::new(AtomicUsize::new(0)); - let dispatch_count2 = dispatch_count.clone(); - let ext = Extension::builder("test_ext") - .ops(vec![op_test::decl()]) - .state(move |state| { + deno_core::extension!( + test_ext, + ops = [op_test], + config = { + mode: Mode, + dispatch_count: Arc, + }, + state = |state, mode, dispatch_count| { state.put(TestState { mode, - dispatch_count: dispatch_count2.clone(), - }); - }) - .build(); + dispatch_count + }) + } + ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![ext], + extensions: vec![test_ext::init_ops(mode, dispatch_count.clone())], get_error_class_fn: Some(&|error| { crate::error::get_custom_error_class(error).unwrap() }), @@ -3149,11 +3153,9 @@ pub mod tests { "DOMExceptionOperationError" } - let ext = Extension::builder("test_ext") - .ops(vec![op_err::decl()]) - .build(); + deno_core::extension!(test_ext, ops = [op_err]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![ext], + extensions: vec![test_ext::init_ops()], get_error_class_fn: Some(&get_error_class_name), ..Default::default() }); @@ -3720,11 +3722,9 @@ main(); Err(anyhow!("original async error").context("higher-level async error")) } - let ext = Extension::builder("test_ext") - .ops(vec![op_err_sync::decl(), op_err_async::decl()]) - .build(); + deno_core::extension!(test_ext, ops = [op_err_sync, op_err_async]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![ext], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -3889,15 +3889,13 @@ assertEquals(1, notify_return_value); Ok(()) } - let extension = Extension::builder("test_ext") - .ops(vec![op_async_borrow::decl()]) - .state(|state| { - state.put(InnerState(42)); - }) - .build(); - + deno_core::extension!( + test_ext, + ops = [op_async_borrow], + state = |state| state.put(InnerState(42)) + ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![extension], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -3923,12 +3921,12 @@ assertEquals(1, notify_return_value); Ok(()) } - let extension = Extension::builder("test_ext") - .ops(vec![op_sync_serialize_object_with_numbers_as_keys::decl()]) - .build(); - + deno_core::extension!( + test_ext, + ops = [op_sync_serialize_object_with_numbers_as_keys] + ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![extension], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -3965,12 +3963,12 @@ Deno.core.ops.op_sync_serialize_object_with_numbers_as_keys({ Ok(()) } - let extension = Extension::builder("test_ext") - .ops(vec![op_async_serialize_object_with_numbers_as_keys::decl()]) - .build(); - + deno_core::extension!( + test_ext, + ops = [op_async_serialize_object_with_numbers_as_keys] + ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![extension], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4004,12 +4002,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(()) } - let extension = Extension::builder("test_ext") - .ops(vec![op_async_sleep::decl()]) - .build(); - + deno_core::extension!(test_ext, ops = [op_async_sleep]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![extension], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4084,12 +4079,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(()) } - let extension = Extension::builder("test_ext") - .ops(vec![op_macrotask::decl(), op_next_tick::decl()]) - .build(); - + deno_core::extension!(test_ext, ops = [op_macrotask, op_next_tick]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![extension], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4214,12 +4206,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(()) } - let extension = Extension::builder("test_ext") - .ops(vec![op_promise_reject::decl()]) - .build(); - + deno_core::extension!(test_ext, ops = [op_promise_reject]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![extension], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4321,9 +4310,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(()) } - let extension = Extension::builder("test_ext") - .ops(vec![op_promise_reject::decl()]) - .build(); + deno_core::extension!(test_ext, ops = [op_promise_reject]); #[derive(Default)] struct ModsLoader; @@ -4367,7 +4354,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { } let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![extension], + extensions: vec![test_ext::init_ops()], module_loader: Some(Rc::new(ModsLoader)), ..Default::default() }); @@ -4390,11 +4377,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok([(1, 2), (3, 4)].into_iter().collect()) // Maps can't have non-string keys in serde_v8 } - let ext = Extension::builder("test_ext") - .ops(vec![op_err::decl()]) - .build(); + deno_core::extension!(test_ext, ops = [op_err]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![ext], + extensions: vec![test_ext::init_ops()], ..Default::default() }); assert!(runtime @@ -4417,11 +4402,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(x1 + x2 + x3 + x4) } - let ext = Extension::builder("test_ext") - .ops(vec![op_add_4::decl()]) - .build(); + deno_core::extension!(test_ext, ops = [op_add_4]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![ext], + extensions: vec![test_ext::init_ops()], ..Default::default() }); let r = runtime @@ -4438,11 +4421,13 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(42) } - let ext = Extension::builder("test_ext") - .ops(vec![op_foo::decl().disable()]) - .build(); + fn ops() -> Vec { + vec![op_foo::decl().disable()] + } + + deno_core::extension!(test_ext, ops_fn = ops); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![ext], + extensions: vec![test_ext::init_ops()], ..Default::default() }); let r = runtime @@ -4468,12 +4453,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(b) } - let ext = Extension::builder("test_ext") - .ops(vec![op_sum_take::decl(), op_boomerang::decl()]) - .build(); - + deno_core::extension!(test_ext, ops = [op_sum_take, op_boomerang]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![ext], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4536,12 +4518,13 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(42) } - let ext = Extension::builder("test_ext") - .ops(vec![op_foo::decl(), op_bar::decl()]) - .middleware(|op| if op.is_unstable { op.disable() } else { op }) - .build(); + deno_core::extension!( + test_ext, + ops = [op_foo, op_bar], + middleware = |op| if op.is_unstable { op.disable() } else { op } + ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![ext], + extensions: vec![test_ext::init_ops()], ..Default::default() }); runtime @@ -4587,10 +4570,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(String::from("Test")) } + deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![Extension::builder("test_ext") - .ops(vec![op_test::decl()]) - .build()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); let realm = runtime.create_realm().unwrap(); @@ -4618,11 +4600,10 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { Ok(String::from("Test")) } + deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { startup_snapshot: Some(Snapshot::Boxed(snapshot)), - extensions: vec![Extension::builder("test_ext") - .ops(vec![op_test::decl()]) - .build()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); let realm = runtime.create_realm().unwrap(); @@ -4650,10 +4631,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { } } + deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![Extension::builder("test_ext") - .ops(vec![op_test::decl()]) - .build()], + extensions: vec![test_ext::init_ops()], get_error_class_fn: Some(&|error| { crate::error::get_custom_error_class(error).unwrap() }), @@ -4699,10 +4679,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { } } + deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![Extension::builder("test_ext") - .ops(vec![op_test::decl()]) - .build()], + extensions: vec![test_ext::init_ops()], get_error_class_fn: Some(&|error| { crate::error::get_custom_error_class(error).unwrap() }), @@ -4759,10 +4738,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { futures::future::pending().await } + deno_core::extension!(test_ext, ops = [op_pending]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![Extension::builder("test_ext") - .ops(vec![op_pending::decl()]) - .build()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); diff --git a/ext/broadcast_channel/lib.rs b/ext/broadcast_channel/lib.rs index 14884e99c0..3df11566f3 100644 --- a/ext/broadcast_channel/lib.rs +++ b/ext/broadcast_channel/lib.rs @@ -2,7 +2,6 @@ mod in_memory_broadcast_channel; -use deno_core::ExtensionBuilder; pub use in_memory_broadcast_channel::InMemoryBroadcastChannel; pub use in_memory_broadcast_channel::InMemoryBroadcastChannelResource; @@ -12,9 +11,7 @@ use std::rc::Rc; use async_trait::async_trait; use deno_core::error::AnyError; -use deno_core::include_js_files; use deno_core::op; -use deno_core::Extension; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; @@ -107,46 +104,25 @@ where bc.recv(&resource).await } -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps( - env!("CARGO_PKG_NAME"), - &["deno_webidl", "deno_web"], - ) -} - -fn ops( - ext: &mut ExtensionBuilder, - bc: BC, - unstable: bool, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - op_broadcast_subscribe::decl::(), - op_broadcast_unsubscribe::decl::(), - op_broadcast_send::decl::(), - op_broadcast_recv::decl::(), - ]) - .state(move |state| { - state.put(bc.clone()); - state.put(Unstable(unstable)); - }) -} - -pub fn init_ops_and_esm( - bc: BC, - unstable: bool, -) -> Extension { - ops::(&mut ext(), bc, unstable) - .esm(include_js_files!("01_broadcast_channel.js",)) - .build() -} - -pub fn init_ops( - bc: BC, - unstable: bool, -) -> Extension { - ops::(&mut ext(), bc, unstable).build() -} +deno_core::extension!(deno_broadcast_channel, + deps = [ deno_webidl, deno_web ], + parameters = [BC: BroadcastChannel], + ops = [ + op_broadcast_subscribe, + op_broadcast_unsubscribe, + op_broadcast_send, + op_broadcast_recv, + ], + esm = [ "01_broadcast_channel.js" ], + config = { + bc: BC, + unstable: bool, + }, + state = |state, bc, unstable| { + state.put(bc); + state.put(Unstable(unstable)); + }, +); pub fn get_declaration() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) diff --git a/ext/cache/lib.rs b/ext/cache/lib.rs index a89296df92..eaf56c8b70 100644 --- a/ext/cache/lib.rs +++ b/ext/cache/lib.rs @@ -7,13 +7,10 @@ use std::sync::Arc; use async_trait::async_trait; use deno_core::error::AnyError; -use deno_core::include_js_files; use deno_core::op; use deno_core::serde::Deserialize; use deno_core::serde::Serialize; use deno_core::ByteString; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; @@ -23,46 +20,27 @@ pub use sqlite::SqliteBackedCache; #[derive(Clone)] pub struct CreateCache(pub Arc C>); -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps( - env!("CARGO_PKG_NAME"), - &["deno_webidl", "deno_web", "deno_url", "deno_fetch"], - ) -} - -fn ops( - ext: &mut ExtensionBuilder, - maybe_create_cache: Option>, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - op_cache_storage_open::decl::(), - op_cache_storage_has::decl::(), - op_cache_storage_delete::decl::(), - op_cache_put::decl::(), - op_cache_match::decl::(), - op_cache_delete::decl::(), - ]) - .state(move |state| { - if let Some(create_cache) = maybe_create_cache.clone() { - state.put(create_cache); - } - }) -} - -pub fn init_ops_and_esm( - maybe_create_cache: Option>, -) -> Extension { - ops::(&mut ext(), maybe_create_cache) - .esm(include_js_files!("01_cache.js",)) - .build() -} - -pub fn init_ops( - maybe_create_cache: Option>, -) -> Extension { - ops::(&mut ext(), maybe_create_cache).build() -} +deno_core::extension!(deno_cache, + deps = [ deno_webidl, deno_web, deno_url, deno_fetch ], + parameters=[CA: Cache], + ops = [ + op_cache_storage_open, + op_cache_storage_has, + op_cache_storage_delete, + op_cache_put, + op_cache_match, + op_cache_delete, + ], + esm = [ "01_cache.js" ], + config = { + maybe_create_cache: Option>, + }, + state = |state, maybe_create_cache| { + if let Some(create_cache) = maybe_create_cache { + state.put(create_cache); + } + }, +); pub fn get_declaration() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_cache.d.ts") diff --git a/ext/console/lib.rs b/ext/console/lib.rs index a9a30c3289..a45b856cd9 100644 --- a/ext/console/lib.rs +++ b/ext/console/lib.rs @@ -1,22 +1,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -use deno_core::include_js_files; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use std::path::PathBuf; -fn ext() -> ExtensionBuilder { - Extension::builder(env!("CARGO_PKG_NAME")) -} -pub fn init() -> Extension { - ext().build() -} - -pub fn init_esm() -> Extension { - ext() - .esm(include_js_files!("01_colors.js", "02_console.js",)) - .build() -} +deno_core::extension!(deno_console, esm = ["01_colors.js", "02_console.js"],); pub fn get_declaration() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_console.d.ts") diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs index 89ca8e0d64..48c5acf4a2 100644 --- a/ext/crypto/lib.rs +++ b/ext/crypto/lib.rs @@ -8,11 +8,8 @@ use deno_core::error::custom_error; use deno_core::error::not_supported; use deno_core::error::type_error; use deno_core::error::AnyError; -use deno_core::include_js_files; use deno_core::op; -use deno_core::ExtensionBuilder; -use deno_core::Extension; use deno_core::OpState; use deno_core::ZeroCopyBuf; use serde::Deserialize; @@ -73,65 +70,49 @@ use crate::key::CryptoNamedCurve; use crate::key::HkdfOutput; use crate::shared::RawKeyData; -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps( - env!("CARGO_PKG_NAME"), - &["deno_webidl", "deno_web"], - ) -} - -fn ops( - ext: &mut ExtensionBuilder, - maybe_seed: Option, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - op_crypto_get_random_values::decl(), - op_crypto_generate_key::decl(), - op_crypto_sign_key::decl(), - op_crypto_verify_key::decl(), - op_crypto_derive_bits::decl(), - op_crypto_import_key::decl(), - op_crypto_export_key::decl(), - op_crypto_encrypt::decl(), - op_crypto_decrypt::decl(), - op_crypto_subtle_digest::decl(), - op_crypto_random_uuid::decl(), - op_crypto_wrap_key::decl(), - op_crypto_unwrap_key::decl(), - op_crypto_base64url_decode::decl(), - op_crypto_base64url_encode::decl(), - x25519::op_generate_x25519_keypair::decl(), - x25519::op_derive_bits_x25519::decl(), - x25519::op_import_spki_x25519::decl(), - x25519::op_import_pkcs8_x25519::decl(), - ed25519::op_generate_ed25519_keypair::decl(), - ed25519::op_import_spki_ed25519::decl(), - ed25519::op_import_pkcs8_ed25519::decl(), - ed25519::op_sign_ed25519::decl(), - ed25519::op_verify_ed25519::decl(), - ed25519::op_export_spki_ed25519::decl(), - ed25519::op_export_pkcs8_ed25519::decl(), - ed25519::op_jwk_x_ed25519::decl(), - x25519::op_export_spki_x25519::decl(), - x25519::op_export_pkcs8_x25519::decl(), - ]) - .state(move |state| { - if let Some(seed) = maybe_seed { - state.put(StdRng::seed_from_u64(seed)); - } - }) -} - -pub fn init_ops_and_esm(maybe_seed: Option) -> Extension { - ops(&mut ext(), maybe_seed) - .esm(include_js_files!("00_crypto.js", "01_webidl.js",)) - .build() -} - -pub fn init_ops(maybe_seed: Option) -> Extension { - ops(&mut ext(), maybe_seed).build() -} +deno_core::extension!(deno_crypto, + deps = [ deno_webidl, deno_web ], + ops = [ + op_crypto_get_random_values, + op_crypto_generate_key, + op_crypto_sign_key, + op_crypto_verify_key, + op_crypto_derive_bits, + op_crypto_import_key, + op_crypto_export_key, + op_crypto_encrypt, + op_crypto_decrypt, + op_crypto_subtle_digest, + op_crypto_random_uuid, + op_crypto_wrap_key, + op_crypto_unwrap_key, + op_crypto_base64url_decode, + op_crypto_base64url_encode, + x25519::op_generate_x25519_keypair, + x25519::op_derive_bits_x25519, + x25519::op_import_spki_x25519, + x25519::op_import_pkcs8_x25519, + ed25519::op_generate_ed25519_keypair, + ed25519::op_import_spki_ed25519, + ed25519::op_import_pkcs8_ed25519, + ed25519::op_sign_ed25519, + ed25519::op_verify_ed25519, + ed25519::op_export_spki_ed25519, + ed25519::op_export_pkcs8_ed25519, + ed25519::op_jwk_x_ed25519, + x25519::op_export_spki_x25519, + x25519::op_export_pkcs8_x25519, + ], + esm = [ "00_crypto.js", "01_webidl.js" ], + config = { + maybe_seed: Option, + }, + state = |state, maybe_seed| { + if let Some(seed) = maybe_seed { + state.put(StdRng::seed_from_u64(seed)); + } + }, +); #[op] pub fn op_crypto_base64url_decode(data: String) -> ZeroCopyBuf { diff --git a/ext/fetch/lib.rs b/ext/fetch/lib.rs index 20885dda57..4cd5d68c8f 100644 --- a/ext/fetch/lib.rs +++ b/ext/fetch/lib.rs @@ -10,10 +10,8 @@ use deno_core::futures::stream::Peekable; use deno_core::futures::Future; use deno_core::futures::Stream; use deno_core::futures::StreamExt; -use deno_core::include_js_files; use deno_core::op; use deno_core::BufView; -use deno_core::ExtensionBuilder; use deno_core::WriteOutcome; use deno_core::url::Url; @@ -24,7 +22,6 @@ use deno_core::CancelFuture; use deno_core::CancelHandle; use deno_core::CancelTryFuture; use deno_core::Canceled; -use deno_core::Extension; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -93,65 +90,41 @@ impl Default for Options { } } -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps( - env!("CARGO_PKG_NAME"), - &["deno_webidl", "deno_web", "deno_url", "deno_console"], - ) -} - -fn ops( - ext: &mut ExtensionBuilder, - options: Options, -) -> &mut ExtensionBuilder -where - FP: FetchPermissions + 'static, -{ - ext - .ops(vec![ - op_fetch::decl::(), - op_fetch_send::decl(), - op_fetch_custom_client::decl::(), - ]) - .state(move |state| { - state.put::(options.clone()); - state.put::({ - create_http_client( - options.user_agent.clone(), - options.root_cert_store.clone(), - vec![], - options.proxy.clone(), - options.unsafely_ignore_certificate_errors.clone(), - options.client_cert_chain_and_key.clone(), - ) - .unwrap() - }); - }) -} - -pub fn init_ops_and_esm(options: Options) -> Extension -where - FP: FetchPermissions + 'static, -{ - ops::(&mut ext(), options) - .esm(include_js_files!( - "20_headers.js", - "21_formdata.js", - "22_body.js", - "22_http_client.js", - "23_request.js", - "23_response.js", - "26_fetch.js", - )) - .build() -} - -pub fn init_ops(options: Options) -> Extension -where - FP: FetchPermissions + 'static, -{ - ops::(&mut ext(), options).build() -} +deno_core::extension!(deno_fetch, + deps = [ deno_webidl, deno_web, deno_url, deno_console ], + parameters = [FP: FetchPermissions], + ops = [ + op_fetch, + op_fetch_send, + op_fetch_custom_client, + ], + esm = [ + "20_headers.js", + "21_formdata.js", + "22_body.js", + "22_http_client.js", + "23_request.js", + "23_response.js", + "26_fetch.js" + ], + config = { + options: Options, + }, + state = |state, options| { + state.put::(options.clone()); + state.put::({ + create_http_client( + options.user_agent, + options.root_cert_store, + vec![], + options.proxy, + options.unsafely_ignore_certificate_errors, + options.client_cert_chain_and_key + ) + .unwrap() + }); + }, +); pub type CancelableResponseFuture = Pin>>; diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs index 2b90cd1c43..1fd01c9d25 100644 --- a/ext/ffi/lib.rs +++ b/ext/ffi/lib.rs @@ -2,10 +2,7 @@ use deno_core::error::AnyError; use deno_core::futures::channel::mpsc; -use deno_core::include_js_files; use deno_core::v8; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use std::cell::RefCell; @@ -82,92 +79,83 @@ pub(crate) struct FfiState { pub(crate) async_work_receiver: mpsc::UnboundedReceiver, } -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps(env!("CARGO_PKG_NAME"), &["deno_web"]) -} - -fn ops( - ext: &mut ExtensionBuilder, - unstable: bool, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - op_ffi_load::decl::

(), - op_ffi_get_static::decl(), - op_ffi_call_nonblocking::decl(), - op_ffi_call_ptr::decl::

(), - op_ffi_call_ptr_nonblocking::decl::

(), - op_ffi_ptr_create::decl::

(), - op_ffi_ptr_equals::decl::

(), - op_ffi_ptr_of::decl::

(), - op_ffi_ptr_offset::decl::

(), - op_ffi_ptr_value::decl::

(), - op_ffi_get_buf::decl::

(), - op_ffi_buf_copy_into::decl::

(), - op_ffi_cstr_read::decl::

(), - op_ffi_read_bool::decl::

(), - op_ffi_read_u8::decl::

(), - op_ffi_read_i8::decl::

(), - op_ffi_read_u16::decl::

(), - op_ffi_read_i16::decl::

(), - op_ffi_read_u32::decl::

(), - op_ffi_read_i32::decl::

(), - op_ffi_read_u64::decl::

(), - op_ffi_read_i64::decl::

(), - op_ffi_read_f32::decl::

(), - op_ffi_read_f64::decl::

(), - op_ffi_read_ptr::decl::

(), - op_ffi_unsafe_callback_create::decl::

(), - op_ffi_unsafe_callback_ref::decl(), - ]) - .event_loop_middleware(|op_state_rc, _cx| { - // FFI callbacks coming in from other threads will call in and get queued. - let mut maybe_scheduling = false; - - let mut work_items: Vec = vec![]; - - { - let mut op_state = op_state_rc.borrow_mut(); - let ffi_state = op_state.borrow_mut::(); - - while let Ok(Some(async_work_fut)) = - ffi_state.async_work_receiver.try_next() - { - // Move received items to a temporary vector so that we can drop the `op_state` borrow before we do the work. - work_items.push(async_work_fut); - maybe_scheduling = true; - } - - drop(op_state); - } - while let Some(async_work_fut) = work_items.pop() { - async_work_fut(); - } - - maybe_scheduling - }) - .state(move |state| { - // Stolen from deno_webgpu, is there a better option? - state.put(Unstable(unstable)); - - let (async_work_sender, async_work_receiver) = - mpsc::unbounded::(); - - state.put(FfiState { - async_work_receiver, - async_work_sender, - }); - }) -} - -pub fn init_ops_and_esm( - unstable: bool, -) -> Extension { - ops::

(&mut ext(), unstable) - .esm(include_js_files!("00_ffi.js",)) - .build() -} - -pub fn init_ops(unstable: bool) -> Extension { - ops::

(&mut ext(), unstable).build() +deno_core::extension!(deno_ffi, + deps = [ deno_web ], + parameters = [P: FfiPermissions], + ops = [ + op_ffi_load

, + op_ffi_get_static, + op_ffi_call_nonblocking, + op_ffi_call_ptr

, + op_ffi_call_ptr_nonblocking

, + op_ffi_ptr_create

, + op_ffi_ptr_equals

, + op_ffi_ptr_of

, + op_ffi_ptr_offset

, + op_ffi_ptr_value

, + op_ffi_get_buf

, + op_ffi_buf_copy_into

, + op_ffi_cstr_read

, + op_ffi_read_bool

, + op_ffi_read_u8

, + op_ffi_read_i8

, + op_ffi_read_u16

, + op_ffi_read_i16

, + op_ffi_read_u32

, + op_ffi_read_i32

, + op_ffi_read_u64

, + op_ffi_read_i64

, + op_ffi_read_f32

, + op_ffi_read_f64

, + op_ffi_read_ptr

, + op_ffi_unsafe_callback_create

, + op_ffi_unsafe_callback_ref, + ], + esm = [ "00_ffi.js" ], + config = { + unstable: bool, + }, + state = |state, unstable| { + // Stolen from deno_webgpu, is there a better option? + state.put(Unstable(unstable)); + + let (async_work_sender, async_work_receiver) = + mpsc::unbounded::(); + + state.put(FfiState { + async_work_receiver, + async_work_sender, + }); + }, + event_loop_middleware = event_loop_middleware, +); + +fn event_loop_middleware( + op_state_rc: Rc>, + _cx: &mut std::task::Context, +) -> bool { + // FFI callbacks coming in from other threads will call in and get queued. + let mut maybe_scheduling = false; + + let mut work_items: Vec = vec![]; + + { + let mut op_state = op_state_rc.borrow_mut(); + let ffi_state = op_state.borrow_mut::(); + + while let Ok(Some(async_work_fut)) = + ffi_state.async_work_receiver.try_next() + { + // Move received items to a temporary vector so that we can drop the `op_state` borrow before we do the work. + work_items.push(async_work_fut); + maybe_scheduling = true; + } + + drop(op_state); + } + while let Some(async_work_fut) = work_items.pop() { + async_work_fut(); + } + + maybe_scheduling } diff --git a/ext/flash/lib.rs b/ext/flash/lib.rs index 77b8b6791c..6f11e14afa 100644 --- a/ext/flash/lib.rs +++ b/ext/flash/lib.rs @@ -16,8 +16,6 @@ use deno_core::v8::fast_api; use deno_core::ByteString; use deno_core::CancelFuture; use deno_core::CancelHandle; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use deno_core::StringOrBuffer; use deno_core::ZeroCopyBuf; @@ -1527,66 +1525,49 @@ pub trait FlashPermissions { ) -> Result<(), AnyError>; } -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps( - env!("CARGO_PKG_NAME"), - &[ - "deno_web", - "deno_net", - "deno_fetch", - "deno_websocket", - "deno_http", - ], - ) -} - -fn ops( - ext: &mut ExtensionBuilder, - unstable: bool, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - op_flash_serve::decl::

(), - op_node_unstable_flash_serve::decl::

(), - op_flash_respond::decl(), - op_flash_respond_async::decl(), - op_flash_respond_chunked::decl(), - op_flash_method::decl(), - op_flash_path::decl(), - op_flash_headers::decl(), - op_flash_addr::decl(), - op_flash_next::decl(), - op_flash_next_server::decl(), - op_flash_next_async::decl(), - op_flash_read_body::decl(), - op_flash_upgrade_websocket::decl(), - op_flash_drive_server::decl(), - op_flash_wait_for_listening::decl(), - op_flash_first_packet::decl(), - op_flash_has_body_stream::decl(), - op_flash_close_server::decl(), - op_flash_make_request::decl(), - op_flash_write_resource::decl(), - op_try_flash_respond_chunked::decl(), - ]) - .state(move |op_state| { - op_state.put(Unstable(unstable)); - op_state.put(FlashContext { - next_server_id: 0, - join_handles: HashMap::default(), - servers: HashMap::default(), - }); - }) -} - -pub fn init_ops_and_esm( - unstable: bool, -) -> Extension { - ops::

(&mut ext(), unstable) - .esm(deno_core::include_js_files!("01_http.js",)) - .build() -} - -pub fn init_ops(unstable: bool) -> Extension { - ops::

(&mut ext(), unstable).build() -} +deno_core::extension!(deno_flash, + deps = [ + deno_web, + deno_net, + deno_fetch, + deno_websocket, + deno_http + ], + parameters = [P: FlashPermissions], + ops = [ + op_flash_serve

, + op_node_unstable_flash_serve

, + op_flash_respond, + op_flash_respond_async, + op_flash_respond_chunked, + op_flash_method, + op_flash_path, + op_flash_headers, + op_flash_addr, + op_flash_next, + op_flash_next_server, + op_flash_next_async, + op_flash_read_body, + op_flash_upgrade_websocket, + op_flash_drive_server, + op_flash_wait_for_listening, + op_flash_first_packet, + op_flash_has_body_stream, + op_flash_close_server, + op_flash_make_request, + op_flash_write_resource, + op_try_flash_respond_chunked, + ], + esm = [ "01_http.js" ], + config = { + unstable: bool, + }, + state = |state, unstable| { + state.put(Unstable(unstable)); + state.put(FlashContext { + next_server_id: 0, + join_handles: HashMap::default(), + servers: HashMap::default(), + }); + }, +); diff --git a/ext/fs/lib.rs b/ext/fs/lib.rs index 746d40dffb..48b0e34957 100644 --- a/ext/fs/lib.rs +++ b/ext/fs/lib.rs @@ -4,12 +4,9 @@ use deno_core::error::custom_error; use deno_core::error::type_error; use deno_core::error::AnyError; -use deno_core::include_js_files; use deno_core::op; use deno_core::CancelFuture; use deno_core::CancelHandle; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use deno_core::ResourceId; use deno_core::ZeroCopyBuf; @@ -118,92 +115,78 @@ use deno_core::error::generic_error; #[cfg(not(unix))] use deno_core::error::not_supported; -fn ext() -> ExtensionBuilder { - Extension::builder("deno_fs") -} - -fn ops( - ext: &mut ExtensionBuilder, - unstable: bool, -) -> &mut ExtensionBuilder { - ext - .state(move |state| { - state.put(UnstableChecker { unstable }); - }) - .ops(vec![ - op_open_sync::decl::

(), - op_open_async::decl::

(), - op_write_file_sync::decl::

(), - op_write_file_async::decl::

(), - op_seek_sync::decl(), - op_seek_async::decl(), - op_fdatasync_sync::decl(), - op_fdatasync_async::decl(), - op_fsync_sync::decl(), - op_fsync_async::decl(), - op_fstat_sync::decl(), - op_fstat_async::decl(), - op_flock_sync::decl(), - op_flock_async::decl(), - op_funlock_sync::decl(), - op_funlock_async::decl(), - op_umask::decl(), - op_chdir::decl::

(), - op_mkdir_sync::decl::

(), - op_mkdir_async::decl::

(), - op_chmod_sync::decl::

(), - op_chmod_async::decl::

(), - op_chown_sync::decl::

(), - op_chown_async::decl::

(), - op_remove_sync::decl::

(), - op_remove_async::decl::

(), - op_copy_file_sync::decl::

(), - op_copy_file_async::decl::

(), - op_stat_sync::decl::

(), - op_stat_async::decl::

(), - op_realpath_sync::decl::

(), - op_realpath_async::decl::

(), - op_read_dir_sync::decl::

(), - op_read_dir_async::decl::

(), - op_rename_sync::decl::

(), - op_rename_async::decl::

(), - op_link_sync::decl::

(), - op_link_async::decl::

(), - op_symlink_sync::decl::

(), - op_symlink_async::decl::

(), - op_read_link_sync::decl::

(), - op_read_link_async::decl::

(), - op_ftruncate_sync::decl(), - op_ftruncate_async::decl(), - op_truncate_sync::decl::

(), - op_truncate_async::decl::

(), - op_make_temp_dir_sync::decl::

(), - op_make_temp_dir_async::decl::

(), - op_make_temp_file_sync::decl::

(), - op_make_temp_file_async::decl::

(), - op_cwd::decl::

(), - op_futime_sync::decl(), - op_futime_async::decl(), - op_utime_sync::decl::

(), - op_utime_async::decl::

(), - op_readfile_sync::decl::

(), - op_readfile_text_sync::decl::

(), - op_readfile_async::decl::

(), - op_readfile_text_async::decl::

(), - ]) -} - -pub fn init_ops_and_esm( - unstable: bool, -) -> Extension { - ops::

(&mut ext(), unstable) - .esm(include_js_files!("30_fs.js",)) - .build() -} - -pub fn init_ops(unstable: bool) -> Extension { - ops::

(&mut ext(), unstable).build() -} +deno_core::extension!(deno_fs, + deps = [ deno_web, deno_io ], + parameters = [P: FsPermissions], + ops = [ + op_open_sync

, + op_open_async

, + op_write_file_sync

, + op_write_file_async

, + op_seek_sync, + op_seek_async, + op_fdatasync_sync, + op_fdatasync_async, + op_fsync_sync, + op_fsync_async, + op_fstat_sync, + op_fstat_async, + op_flock_sync, + op_flock_async, + op_funlock_sync, + op_funlock_async, + op_umask, + op_chdir

, + op_mkdir_sync

, + op_mkdir_async

, + op_chmod_sync

, + op_chmod_async

, + op_chown_sync

, + op_chown_async

, + op_remove_sync

, + op_remove_async

, + op_copy_file_sync

, + op_copy_file_async

, + op_stat_sync

, + op_stat_async

, + op_realpath_sync

, + op_realpath_async

, + op_read_dir_sync

, + op_read_dir_async

, + op_rename_sync

, + op_rename_async

, + op_link_sync

, + op_link_async

, + op_symlink_sync

, + op_symlink_async

, + op_read_link_sync

, + op_read_link_async

, + op_ftruncate_sync, + op_ftruncate_async, + op_truncate_sync

, + op_truncate_async

, + op_make_temp_dir_sync

, + op_make_temp_dir_async

, + op_make_temp_file_sync

, + op_make_temp_file_async

, + op_cwd

, + op_futime_sync, + op_futime_async, + op_utime_sync

, + op_utime_async

, + op_readfile_sync

, + op_readfile_text_sync

, + op_readfile_async

, + op_readfile_text_async

, + ], + esm = [ "30_fs.js" ], + config = { + unstable: bool + }, + state = |state, unstable| { + state.put(UnstableChecker { unstable }); + }, +); fn default_err_mapper(err: Error, desc: String) -> Error { Error::new(err.kind(), format!("{err}, {desc}")) diff --git a/ext/http/lib.rs b/ext/http/lib.rs index 11bd91aa41..20436a82d3 100644 --- a/ext/http/lib.rs +++ b/ext/http/lib.rs @@ -19,7 +19,6 @@ use deno_core::futures::stream::Peekable; use deno_core::futures::FutureExt; use deno_core::futures::StreamExt; use deno_core::futures::TryFutureExt; -use deno_core::include_js_files; use deno_core::op; use deno_core::AsyncRefCell; use deno_core::AsyncResult; @@ -28,8 +27,6 @@ use deno_core::ByteString; use deno_core::CancelFuture; use deno_core::CancelHandle; use deno_core::CancelTryFuture; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -78,35 +75,21 @@ use crate::reader_stream::ShutdownHandle; pub mod compressible; mod reader_stream; -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps( - env!("CARGO_PKG_NAME"), - &["deno_web", "deno_net", "deno_fetch", "deno_websocket"], - ) -} - -fn ops(ext: &mut ExtensionBuilder) -> &mut ExtensionBuilder { - ext.ops(vec![ - op_http_accept::decl(), - op_http_write_headers::decl(), - op_http_headers::decl(), - op_http_write::decl(), - op_http_write_resource::decl(), - op_http_shutdown::decl(), - op_http_websocket_accept_header::decl(), - op_http_upgrade_websocket::decl(), - ]) -} - -pub fn init_ops_and_esm() -> Extension { - ops(&mut ext()) - .esm(include_js_files!("01_http.js",)) - .build() -} - -pub fn init_ops() -> Extension { - ops(&mut ext()).build() -} +deno_core::extension!( + deno_http, + deps = [deno_web, deno_net, deno_fetch, deno_websocket], + ops = [ + op_http_accept, + op_http_write_headers, + op_http_headers, + op_http_write, + op_http_write_resource, + op_http_shutdown, + op_http_websocket_accept_header, + op_http_upgrade_websocket, + ], + esm = ["01_http.js"], +); pub enum HttpSocketAddr { IpSocket(std::net::SocketAddr), diff --git a/ext/io/lib.rs b/ext/io/lib.rs index 92f681f1ec..bfbb1d94f0 100644 --- a/ext/io/lib.rs +++ b/ext/io/lib.rs @@ -2,7 +2,6 @@ use deno_core::error::resource_unavailable; use deno_core::error::AnyError; -use deno_core::include_js_files; use deno_core::op; use deno_core::parking_lot::Mutex; use deno_core::AsyncMutFuture; @@ -12,8 +11,6 @@ use deno_core::BufMutView; use deno_core::BufView; use deno_core::CancelHandle; use deno_core::CancelTryFuture; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -79,80 +76,61 @@ pub static STDERR_HANDLE: Lazy = Lazy::new(|| { unsafe { StdFile::from_raw_handle(GetStdHandle(winbase::STD_ERROR_HANDLE)) } }); -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps("deno_io", &["deno_web"]) -} +deno_core::extension!(deno_io, + deps = [ deno_web ], + ops = [op_read_sync, op_write_sync], + esm = [ "12_io.js" ], + config = { + stdio: Rc>>, + }, + middleware = |op| match op.name { + "op_print" => op_print::decl(), + _ => op, + }, + state = |state, stdio| { + let stdio = stdio + .borrow_mut() + .take() + .expect("Extension only supports being used once."); + let t = &mut state.resource_table; -fn ops( - ext: &mut ExtensionBuilder, - stdio: Rc>>, -) -> &mut ExtensionBuilder { - ext - .ops(vec![op_read_sync::decl(), op_write_sync::decl()]) - .middleware(|op| match op.name { - "op_print" => op_print::decl(), - _ => op, - }) - .state(move |state| { - let stdio = stdio - .borrow_mut() - .take() - .expect("Extension only supports being used once."); - let t = &mut state.resource_table; - - let rid = t.add(StdFileResource::stdio( - match stdio.stdin { - StdioPipe::Inherit => StdFileResourceInner { - kind: StdFileResourceKind::Stdin, - file: STDIN_HANDLE.try_clone().unwrap(), - }, - StdioPipe::File(pipe) => StdFileResourceInner::file(pipe), + let rid = t.add(StdFileResource::stdio( + match stdio.stdin { + StdioPipe::Inherit => StdFileResourceInner { + kind: StdFileResourceKind::Stdin, + file: STDIN_HANDLE.try_clone().unwrap(), }, - "stdin", - )); - assert_eq!(rid, 0, "stdin must have ResourceId 0"); + StdioPipe::File(pipe) => StdFileResourceInner::file(pipe), + }, + "stdin", + )); + assert_eq!(rid, 0, "stdin must have ResourceId 0"); - let rid = t.add(StdFileResource::stdio( - match stdio.stdout { - StdioPipe::Inherit => StdFileResourceInner { - kind: StdFileResourceKind::Stdout, - file: STDOUT_HANDLE.try_clone().unwrap(), - }, - StdioPipe::File(pipe) => StdFileResourceInner::file(pipe), + let rid = t.add(StdFileResource::stdio( + match stdio.stdout { + StdioPipe::Inherit => StdFileResourceInner { + kind: StdFileResourceKind::Stdout, + file: STDOUT_HANDLE.try_clone().unwrap(), }, - "stdout", - )); - assert_eq!(rid, 1, "stdout must have ResourceId 1"); + StdioPipe::File(pipe) => StdFileResourceInner::file(pipe), + }, + "stdout", + )); + assert_eq!(rid, 1, "stdout must have ResourceId 1"); - let rid = t.add(StdFileResource::stdio( - match stdio.stderr { - StdioPipe::Inherit => StdFileResourceInner { - kind: StdFileResourceKind::Stderr, - file: STDERR_HANDLE.try_clone().unwrap(), - }, - StdioPipe::File(pipe) => StdFileResourceInner::file(pipe), + let rid = t.add(StdFileResource::stdio( + match stdio.stderr { + StdioPipe::Inherit => StdFileResourceInner { + kind: StdFileResourceKind::Stderr, + file: STDERR_HANDLE.try_clone().unwrap(), }, - "stderr", - )); - assert_eq!(rid, 2, "stderr must have ResourceId 2"); - }) -} - -pub fn init_ops_and_esm(stdio: Stdio) -> Extension { - // todo(dsheret): don't do this? Taking out the writers was necessary to prevent invalid handle panics - let stdio = Rc::new(RefCell::new(Some(stdio))); - - ops(&mut ext(), stdio) - .esm(include_js_files!("12_io.js",)) - .build() -} - -pub fn init_ops(stdio: Stdio) -> Extension { - // todo(dsheret): don't do this? Taking out the writers was necessary to prevent invalid handle panics - let stdio = Rc::new(RefCell::new(Some(stdio))); - - ops(&mut ext(), stdio).build() -} + StdioPipe::File(pipe) => StdFileResourceInner::file(pipe), + }, + "stderr", + )); + assert_eq!(rid, 2, "stderr must have ResourceId 2"); + }, +); pub enum StdioPipe { Inherit, diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs index 41004638e1..2e7ceed673 100644 --- a/ext/napi/lib.rs +++ b/ext/napi/lib.rs @@ -13,7 +13,6 @@ use deno_core::futures::StreamExt; use deno_core::op; use deno_core::parking_lot::Mutex; use deno_core::serde_v8; -use deno_core::Extension; use deno_core::OpState; use std::cell::RefCell; use std::ffi::CString; @@ -514,72 +513,78 @@ impl Env { } } -pub fn init_ops() -> Extension { - Extension::builder(env!("CARGO_PKG_NAME")) - .ops(vec![op_napi_open::decl::

()]) - .event_loop_middleware(|op_state_rc, cx| { - // `work` can call back into the runtime. It can also schedule an async task - // but we don't know that now. We need to make the runtime re-poll to make - // sure no pending NAPI tasks exist. - let mut maybe_scheduling = false; +deno_core::extension!(deno_napi, + parameters = [P: NapiPermissions], + ops = [ + op_napi_open

+ ], + state = |state| { + let (async_work_sender, async_work_receiver) = + mpsc::unbounded::(); + let (threadsafe_function_sender, threadsafe_function_receiver) = + mpsc::unbounded::(); + state.put(NapiState { + pending_async_work: Vec::new(), + async_work_sender, + async_work_receiver, + threadsafe_function_sender, + threadsafe_function_receiver, + active_threadsafe_functions: 0, + env_cleanup_hooks: Rc::new(RefCell::new(vec![])), + tsfn_ref_counters: Arc::new(Mutex::new(vec![])), + }); + }, + event_loop_middleware = event_loop_middleware, +); - { - let mut op_state = op_state_rc.borrow_mut(); - let napi_state = op_state.borrow_mut::(); +fn event_loop_middleware( + op_state_rc: Rc>, + cx: &mut std::task::Context, +) -> bool { + // `work` can call back into the runtime. It can also schedule an async task + // but we don't know that now. We need to make the runtime re-poll to make + // sure no pending NAPI tasks exist. + let mut maybe_scheduling = false; - while let Poll::Ready(Some(async_work_fut)) = - napi_state.async_work_receiver.poll_next_unpin(cx) - { - napi_state.pending_async_work.push(async_work_fut); - } + { + let mut op_state = op_state_rc.borrow_mut(); + let napi_state = op_state.borrow_mut::(); - if napi_state.active_threadsafe_functions > 0 { - maybe_scheduling = true; - } + while let Poll::Ready(Some(async_work_fut)) = + napi_state.async_work_receiver.poll_next_unpin(cx) + { + napi_state.pending_async_work.push(async_work_fut); + } - let tsfn_ref_counters = napi_state.tsfn_ref_counters.lock().clone(); - for (_id, counter) in tsfn_ref_counters.iter() { - if counter.load(std::sync::atomic::Ordering::SeqCst) > 0 { - maybe_scheduling = true; - break; - } - } + if napi_state.active_threadsafe_functions > 0 { + maybe_scheduling = true; + } + + let tsfn_ref_counters = napi_state.tsfn_ref_counters.lock().clone(); + for (_id, counter) in tsfn_ref_counters.iter() { + if counter.load(std::sync::atomic::Ordering::SeqCst) > 0 { + maybe_scheduling = true; + break; } + } + } - loop { - let maybe_work = { - let mut op_state = op_state_rc.borrow_mut(); - let napi_state = op_state.borrow_mut::(); - napi_state.pending_async_work.pop() - }; + loop { + let maybe_work = { + let mut op_state = op_state_rc.borrow_mut(); + let napi_state = op_state.borrow_mut::(); + napi_state.pending_async_work.pop() + }; - if let Some(work) = maybe_work { - work(); - maybe_scheduling = true; - } else { - break; - } - } + if let Some(work) = maybe_work { + work(); + maybe_scheduling = true; + } else { + break; + } + } - maybe_scheduling - }) - .state(move |state| { - let (async_work_sender, async_work_receiver) = - mpsc::unbounded::(); - let (threadsafe_function_sender, threadsafe_function_receiver) = - mpsc::unbounded::(); - state.put(NapiState { - pending_async_work: Vec::new(), - async_work_sender, - async_work_receiver, - threadsafe_function_sender, - threadsafe_function_receiver, - active_threadsafe_functions: 0, - env_cleanup_hooks: Rc::new(RefCell::new(vec![])), - tsfn_ref_counters: Arc::new(Mutex::new(vec![])), - }); - }) - .build() + maybe_scheduling } pub trait NapiPermissions { diff --git a/ext/net/lib.rs b/ext/net/lib.rs index 4703b05cc1..76ed02706a 100644 --- a/ext/net/lib.rs +++ b/ext/net/lib.rs @@ -8,9 +8,6 @@ pub mod ops_unix; pub mod resolve_addr; use deno_core::error::AnyError; -use deno_core::include_js_files; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use deno_tls::rustls::RootCertStore; use std::cell::RefCell; @@ -78,55 +75,48 @@ pub struct DefaultTlsOptions { /// would override previously used alias. pub struct UnsafelyIgnoreCertificateErrors(pub Option>); -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps(env!("CARGO_PKG_NAME"), &["deno_web"]) -} +deno_core::extension!(deno_net, + deps = [ deno_web ], + parameters = [ P: NetPermissions ], + ops = [ + ops::op_net_accept_tcp, + ops::op_net_connect_tcp

, + ops::op_net_listen_tcp

, + ops::op_net_listen_udp

, + ops::op_node_unstable_net_listen_udp

, + ops::op_net_recv_udp, + ops::op_net_send_udp

, + ops::op_dns_resolve

, + ops::op_set_nodelay, + ops::op_set_keepalive, -fn ops( - ext: &mut ExtensionBuilder, - root_cert_store: Option, - unstable: bool, - unsafely_ignore_certificate_errors: Option>, -) -> &mut ExtensionBuilder { - let mut ops = ops::init::

(); - ops.extend(ops_tls::init::

()); + ops_tls::op_tls_start

, + ops_tls::op_net_connect_tls

, + ops_tls::op_net_listen_tls

, + ops_tls::op_net_accept_tls, + ops_tls::op_tls_handshake, - ext.ops(ops).state(move |state| { + #[cfg(unix)] ops_unix::op_net_accept_unix, + #[cfg(unix)] ops_unix::op_net_connect_unix

, + #[cfg(unix)] ops_unix::op_net_listen_unix

, + #[cfg(unix)] ops_unix::op_net_listen_unixpacket

, + #[cfg(unix)] ops_unix::op_node_unstable_net_listen_unixpacket

, + #[cfg(unix)] ops_unix::op_net_recv_unixpacket, + #[cfg(unix)] ops_unix::op_net_send_unixpacket

, + ], + esm = [ "01_net.js", "02_tls.js" ], + config = { + root_cert_store: Option, + unstable: bool, + unsafely_ignore_certificate_errors: Option>, + }, + state = |state, root_cert_store, unstable, unsafely_ignore_certificate_errors| { state.put(DefaultTlsOptions { - root_cert_store: root_cert_store.clone(), + root_cert_store, }); state.put(UnstableChecker { unstable }); state.put(UnsafelyIgnoreCertificateErrors( - unsafely_ignore_certificate_errors.clone(), + unsafely_ignore_certificate_errors, )); - }) -} - -pub fn init_ops_and_esm( - root_cert_store: Option, - unstable: bool, - unsafely_ignore_certificate_errors: Option>, -) -> Extension { - ops::

( - &mut ext(), - root_cert_store, - unstable, - unsafely_ignore_certificate_errors, - ) - .esm(include_js_files!("01_net.js", "02_tls.js",)) - .build() -} - -pub fn init_ops( - root_cert_store: Option, - unstable: bool, - unsafely_ignore_certificate_errors: Option>, -) -> Extension { - ops::

( - &mut ext(), - root_cert_store, - unstable, - unsafely_ignore_certificate_errors, - ) - .build() -} + }, +); diff --git a/ext/net/ops.rs b/ext/net/ops.rs index 8ac08119ae..c094ddac2b 100644 --- a/ext/net/ops.rs +++ b/ext/net/ops.rs @@ -15,7 +15,6 @@ use deno_core::AsyncRefCell; use deno_core::ByteString; use deno_core::CancelHandle; use deno_core::CancelTryFuture; -use deno_core::OpDecl; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -44,35 +43,6 @@ use trust_dns_resolver::error::ResolveErrorKind; use trust_dns_resolver::system_conf; use trust_dns_resolver::AsyncResolver; -pub fn init() -> Vec { - vec![ - op_net_accept_tcp::decl(), - #[cfg(unix)] - crate::ops_unix::op_net_accept_unix::decl(), - op_net_connect_tcp::decl::

(), - #[cfg(unix)] - crate::ops_unix::op_net_connect_unix::decl::

(), - op_net_listen_tcp::decl::

(), - op_net_listen_udp::decl::

(), - op_node_unstable_net_listen_udp::decl::

(), - #[cfg(unix)] - crate::ops_unix::op_net_listen_unix::decl::

(), - #[cfg(unix)] - crate::ops_unix::op_net_listen_unixpacket::decl::

(), - #[cfg(unix)] - crate::ops_unix::op_node_unstable_net_listen_unixpacket::decl::

(), - op_net_recv_udp::decl(), - #[cfg(unix)] - crate::ops_unix::op_net_recv_unixpacket::decl(), - op_net_send_udp::decl::

(), - #[cfg(unix)] - crate::ops_unix::op_net_send_unixpacket::decl::

(), - op_dns_resolve::decl::

(), - op_set_nodelay::decl(), - op_set_keepalive::decl(), - ] -} - #[derive(Serialize, Clone, Debug)] #[serde(rename_all = "camelCase")] pub struct TlsHandshakeInfo { @@ -650,7 +620,6 @@ fn rdata_to_return_record( mod tests { use super::*; use crate::UnstableChecker; - use deno_core::Extension; use deno_core::JsRuntime; use deno_core::RuntimeOptions; use socket2::SockRef; @@ -906,15 +875,17 @@ mod tests { let listener = TcpListener::bind(addr).await.unwrap(); let _ = listener.accept().await; }); - let my_ext = Extension::builder("test_ext") - .state(move |state| { + + deno_core::extension!( + test_ext, + state = |state| { state.put(TestPermission {}); state.put(UnstableChecker { unstable: true }); - }) - .build(); + } + ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![my_ext], + extensions: vec![test_ext::init_ops()], ..Default::default() }); diff --git a/ext/net/ops_tls.rs b/ext/net/ops_tls.rs index f550569a15..c0cfb8674f 100644 --- a/ext/net/ops_tls.rs +++ b/ext/net/ops_tls.rs @@ -31,7 +31,6 @@ use deno_core::AsyncResult; use deno_core::ByteString; use deno_core::CancelHandle; use deno_core::CancelTryFuture; -use deno_core::OpDecl; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -653,16 +652,6 @@ impl Write for ImplementWriteTrait<'_, TcpStream> { } } -pub fn init() -> Vec { - vec![ - op_tls_start::decl::

(), - op_net_connect_tls::decl::

(), - op_net_listen_tls::decl::

(), - op_net_accept_tls::decl(), - op_tls_handshake::decl(), - ] -} - #[derive(Debug)] pub struct TlsStreamResource { rd: AsyncRefCell, diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 318667d59b..06138cf4cb 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -1,11 +1,8 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; -use deno_core::include_js_files; use deno_core::located_script_name; use deno_core::op; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::JsRuntime; use once_cell::sync::Lazy; use std::collections::HashSet; @@ -96,41 +93,32 @@ fn op_node_build_os() -> String { .to_string() } -fn ext_polyfill() -> ExtensionBuilder { - Extension::builder_with_deps(env!("CARGO_PKG_NAME"), &["deno_io", "deno_fs"]) -} - -fn ops_polyfill(ext: &mut ExtensionBuilder) -> &mut ExtensionBuilder { - ext.ops(vec![ - crypto::op_node_cipheriv_encrypt::decl(), - crypto::op_node_cipheriv_final::decl(), - crypto::op_node_create_cipheriv::decl(), - crypto::op_node_create_hash::decl(), - crypto::op_node_hash_update::decl(), - crypto::op_node_hash_update_str::decl(), - crypto::op_node_hash_digest::decl(), - crypto::op_node_hash_digest_hex::decl(), - crypto::op_node_hash_clone::decl(), - crypto::op_node_private_encrypt::decl(), - crypto::op_node_private_decrypt::decl(), - crypto::op_node_public_encrypt::decl(), - winerror::op_node_sys_to_uv_error::decl(), - v8::op_v8_cached_data_version_tag::decl(), - v8::op_v8_get_heap_statistics::decl(), - idna::op_node_idna_domain_to_ascii::decl(), - idna::op_node_idna_domain_to_unicode::decl(), - idna::op_node_idna_punycode_decode::decl(), - idna::op_node_idna_punycode_encode::decl(), - op_node_build_os::decl(), - ]) -} - -pub fn init_polyfill_ops() -> Extension { - ops_polyfill(&mut ext_polyfill()).build() -} - -pub fn init_polyfill_ops_and_esm() -> Extension { - let esm_files = include_js_files!( +deno_core::extension!(deno_node, + deps = [ deno_io, deno_fs ], + ops = [ + crypto::op_node_cipheriv_encrypt, + crypto::op_node_cipheriv_final, + crypto::op_node_create_cipheriv, + crypto::op_node_create_hash, + crypto::op_node_hash_update, + crypto::op_node_hash_update_str, + crypto::op_node_hash_digest, + crypto::op_node_hash_digest_hex, + crypto::op_node_hash_clone, + crypto::op_node_private_encrypt, + crypto::op_node_private_decrypt, + crypto::op_node_public_encrypt, + winerror::op_node_sys_to_uv_error, + v8::op_v8_cached_data_version_tag, + v8::op_v8_get_heap_statistics, + idna::op_node_idna_domain_to_ascii, + idna::op_node_idna_domain_to_unicode, + idna::op_node_idna_punycode_decode, + idna::op_node_idna_punycode_encode, + op_node_build_os, + ], + esm_entry_point = "ext:deno_node/module_all.ts", + esm = [ dir "polyfills", "_core.ts", "_events.mjs", @@ -352,71 +340,45 @@ pub fn init_polyfill_ops_and_esm() -> Extension { "wasi.ts", "worker_threads.ts", "zlib.ts", - ); + ], +); - ops_polyfill(&mut ext_polyfill()) - .esm(esm_files) - .esm_entry_point("ext:deno_node/module_all.ts") - .build() -} - -fn ext() -> ExtensionBuilder { - Extension::builder("deno_node_loading") -} - -fn ops( - ext: &mut ExtensionBuilder, - maybe_npm_resolver: Option>, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - ops::op_require_init_paths::decl(), - ops::op_require_node_module_paths::decl::

(), - ops::op_require_proxy_path::decl(), - ops::op_require_is_deno_dir_package::decl(), - ops::op_require_resolve_deno_dir::decl(), - ops::op_require_is_request_relative::decl(), - ops::op_require_resolve_lookup_paths::decl(), - ops::op_require_try_self_parent_path::decl::

(), - ops::op_require_try_self::decl::

(), - ops::op_require_real_path::decl::

(), - ops::op_require_path_is_absolute::decl(), - ops::op_require_path_dirname::decl(), - ops::op_require_stat::decl::

(), - ops::op_require_path_resolve::decl(), - ops::op_require_path_basename::decl(), - ops::op_require_read_file::decl::

(), - ops::op_require_as_file_path::decl(), - ops::op_require_resolve_exports::decl::

(), - ops::op_require_read_closest_package_json::decl::

(), - ops::op_require_read_package_scope::decl::

(), - ops::op_require_package_imports_resolve::decl::

(), - ops::op_require_break_on_next_statement::decl(), - ]) - .state(move |state| { - if let Some(npm_resolver) = maybe_npm_resolver.clone() { - state.put(npm_resolver); - } - }) -} - -pub fn init_ops_and_esm( - maybe_npm_resolver: Option>, -) -> Extension { - ops::

(&mut ext(), maybe_npm_resolver) - .esm(include_js_files!( - "01_node.js", - "02_require.js", - "module_es_shim.js", - )) - .build() -} - -pub fn init_ops( - maybe_npm_resolver: Option>, -) -> Extension { - ops::

(&mut ext(), maybe_npm_resolver).build() -} +deno_core::extension!(deno_node_loading, + parameters = [P: NodePermissions], + ops = [ + ops::op_require_init_paths, + ops::op_require_node_module_paths

, + ops::op_require_proxy_path, + ops::op_require_is_deno_dir_package, + ops::op_require_resolve_deno_dir, + ops::op_require_is_request_relative, + ops::op_require_resolve_lookup_paths, + ops::op_require_try_self_parent_path

, + ops::op_require_try_self

, + ops::op_require_real_path

, + ops::op_require_path_is_absolute, + ops::op_require_path_dirname, + ops::op_require_stat

, + ops::op_require_path_resolve, + ops::op_require_path_basename, + ops::op_require_read_file

, + ops::op_require_as_file_path, + ops::op_require_resolve_exports

, + ops::op_require_read_closest_package_json

, + ops::op_require_read_package_scope

, + ops::op_require_package_imports_resolve

, + ops::op_require_break_on_next_statement, + ], + esm = ["01_node.js", "02_require.js", "module_es_shim.js"], + config = { + maybe_npm_resolver: Option>, + }, + state = |state, maybe_npm_resolver| { + if let Some(npm_resolver) = maybe_npm_resolver.clone() { + state.put(npm_resolver); + } + }, +); pub async fn initialize_runtime( js_runtime: &mut JsRuntime, diff --git a/ext/tls/lib.rs b/ext/tls/lib.rs index fb4e8759d9..123d35acf0 100644 --- a/ext/tls/lib.rs +++ b/ext/tls/lib.rs @@ -10,7 +10,6 @@ use deno_core::anyhow::anyhow; use deno_core::error::custom_error; use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; -use deno_core::Extension; use rustls::client::HandshakeSignatureValid; use rustls::client::ServerCertVerified; @@ -35,10 +34,8 @@ use std::io::Cursor; use std::sync::Arc; use std::time::SystemTime; -/// This extension has no runtime apis, it only exports some shared native functions. -pub fn init_ops() -> Extension { - Extension::builder(env!("CARGO_PKG_NAME")).build() -} +// This extension has no runtime apis, it only exports some shared native functions. +deno_core::extension!(deno_tls); struct DefaultSignatureVerification; diff --git a/ext/url/benches/url_ops.rs b/ext/url/benches/url_ops.rs index 7dc2651b2e..4096a6a929 100644 --- a/ext/url/benches/url_ops.rs +++ b/ext/url/benches/url_ops.rs @@ -11,8 +11,8 @@ use deno_core::ExtensionFileSourceCode; fn setup() -> Vec { vec![ - deno_webidl::init_esm(), - deno_url::init_ops_and_esm(), + deno_webidl::deno_webidl::init_ops_and_esm(), + deno_url::deno_url::init_ops_and_esm(), Extension::builder("bench_setup") .esm(vec![ExtensionFileSource { specifier: "ext:setup".to_string(), diff --git a/ext/url/lib.rs b/ext/url/lib.rs index 8a20c9bc6a..cfb6497c3b 100644 --- a/ext/url/lib.rs +++ b/ext/url/lib.rs @@ -4,13 +4,10 @@ mod urlpattern; use deno_core::error::type_error; use deno_core::error::AnyError; -use deno_core::include_js_files; use deno_core::op; use deno_core::url::form_urlencoded; use deno_core::url::quirks; use deno_core::url::Url; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use deno_core::ZeroCopyBuf; use std::path::PathBuf; @@ -18,32 +15,21 @@ use std::path::PathBuf; use crate::urlpattern::op_urlpattern_parse; use crate::urlpattern::op_urlpattern_process_match_input; -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps(env!("CARGO_PKG_NAME"), &["deno_webidl"]) -} - -fn ops(ext: &mut ExtensionBuilder) -> &mut ExtensionBuilder { - ext.ops(vec![ - op_url_reparse::decl(), - op_url_parse::decl(), - op_url_get_serialization::decl(), - op_url_parse_with_base::decl(), - op_url_parse_search_params::decl(), - op_url_stringify_search_params::decl(), - op_urlpattern_parse::decl(), - op_urlpattern_process_match_input::decl(), - ]) -} - -pub fn init_ops_and_esm() -> Extension { - ops(&mut ext()) - .esm(include_js_files!("00_url.js", "01_urlpattern.js",)) - .build() -} - -pub fn init_ops() -> Extension { - ops(&mut ext()).build() -} +deno_core::extension!( + deno_url, + deps = [deno_webidl], + ops = [ + op_url_reparse, + op_url_parse, + op_url_get_serialization, + op_url_parse_with_base, + op_url_parse_search_params, + op_url_stringify_search_params, + op_urlpattern_parse, + op_urlpattern_process_match_input + ], + esm = ["00_url.js", "01_urlpattern.js"], +); /// Parse `href` with a `base_href`. Fills the out `buf` with URL components. #[op] diff --git a/ext/web/benches/encoding.rs b/ext/web/benches/encoding.rs index feb3097850..2deba07f33 100644 --- a/ext/web/benches/encoding.rs +++ b/ext/web/benches/encoding.rs @@ -10,6 +10,7 @@ use deno_core::ExtensionFileSourceCode; use deno_core::OpState; use deno_web::BlobStore; +#[derive(Clone)] struct Permissions; impl deno_web::TimersPermission for Permissions { @@ -23,10 +24,13 @@ impl deno_web::TimersPermission for Permissions { fn setup() -> Vec { vec![ - deno_webidl::init_esm(), - deno_url::init_ops_and_esm(), - deno_console::init_esm(), - deno_web::init_ops_and_esm::(BlobStore::default(), None), + deno_webidl::deno_webidl::init_ops_and_esm(), + deno_url::deno_url::init_ops_and_esm(), + deno_console::deno_console::init_ops_and_esm(), + deno_web::deno_web::init_ops_and_esm::( + BlobStore::default(), + None, + ), Extension::builder("bench_setup") .esm(vec![ExtensionFileSource { specifier: "ext:setup".to_string(), diff --git a/ext/web/benches/timers_ops.rs b/ext/web/benches/timers_ops.rs index e1e97df650..372a317c98 100644 --- a/ext/web/benches/timers_ops.rs +++ b/ext/web/benches/timers_ops.rs @@ -10,6 +10,7 @@ use deno_core::ExtensionFileSourceCode; use deno_core::OpState; use deno_web::BlobStore; +#[derive(Clone)] struct Permissions; impl deno_web::TimersPermission for Permissions { @@ -21,10 +22,10 @@ impl deno_web::TimersPermission for Permissions { fn setup() -> Vec { vec![ - deno_webidl::init_esm(), - deno_url::init_ops_and_esm(), - deno_console::init_esm(), - deno_web::init_ops_and_esm::(BlobStore::default(), None), + deno_webidl::deno_webidl::init_ops_and_esm(), + deno_url::deno_url::init_ops_and_esm(), + deno_console::deno_console::init_ops_and_esm(), + deno_web::deno_web::init_ops_and_esm::(BlobStore::default(), None), Extension::builder("bench_setup") .esm(vec![ ExtensionFileSource { diff --git a/ext/web/lib.rs b/ext/web/lib.rs index dfc5ece725..f3a22d6236 100644 --- a/ext/web/lib.rs +++ b/ext/web/lib.rs @@ -8,15 +8,12 @@ mod timers; use deno_core::error::range_error; use deno_core::error::type_error; use deno_core::error::AnyError; -use deno_core::include_js_files; use deno_core::op; use deno_core::serde_v8; use deno_core::url::Url; use deno_core::v8; use deno_core::ByteString; use deno_core::CancelHandle; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; @@ -58,93 +55,72 @@ use crate::timers::op_timer_handle; use crate::timers::StartTime; pub use crate::timers::TimersPermission; -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps( - env!("CARGO_PKG_NAME"), - &["deno_webidl", "deno_console", "deno_url"], - ) -} - -fn ops( - ext: &mut ExtensionBuilder, - blob_store: BlobStore, - maybe_location: Option, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - op_base64_decode::decl(), - op_base64_encode::decl(), - op_base64_atob::decl(), - op_base64_btoa::decl(), - op_encoding_normalize_label::decl(), - op_encoding_decode_single::decl(), - op_encoding_decode_utf8::decl(), - op_encoding_new_decoder::decl(), - op_encoding_decode::decl(), - op_encoding_encode_into::decl(), - op_encode_binary_string::decl(), - op_blob_create_part::decl(), - op_blob_slice_part::decl(), - op_blob_read_part::decl(), - op_blob_remove_part::decl(), - op_blob_create_object_url::decl(), - op_blob_revoke_object_url::decl(), - op_blob_from_object_url::decl(), - op_message_port_create_entangled::decl(), - op_message_port_post_message::decl(), - op_message_port_recv_message::decl(), - compression::op_compression_new::decl(), - compression::op_compression_write::decl(), - compression::op_compression_finish::decl(), - op_now::decl::

(), - op_timer_handle::decl(), - op_cancel_handle::decl(), - op_sleep::decl(), - op_transfer_arraybuffer::decl(), - ]) - .state(move |state| { - state.put(blob_store.clone()); - if let Some(location) = maybe_location.clone() { - state.put(Location(location)); - } - state.put(StartTime::now()); - }) -} - -pub fn init_ops_and_esm( - blob_store: BlobStore, - maybe_location: Option, -) -> Extension { - ops::

(&mut ext(), blob_store, maybe_location) - .esm(include_js_files!( - "00_infra.js", - "01_dom_exception.js", - "01_mimesniff.js", - "02_event.js", - "02_structured_clone.js", - "02_timers.js", - "03_abort_signal.js", - "04_global_interfaces.js", - "05_base64.js", - "06_streams.js", - "08_text_encoding.js", - "09_file.js", - "10_filereader.js", - "11_blob_url.js", - "12_location.js", - "13_message_port.js", - "14_compression.js", - "15_performance.js", - )) - .build() -} - -pub fn init_ops( - blob_store: BlobStore, - maybe_location: Option, -) -> Extension { - ops::

(&mut ext(), blob_store, maybe_location).build() -} +deno_core::extension!(deno_web, + deps = [ deno_webidl, deno_console, deno_url ], + parameters = [P: TimersPermission], + ops = [ + op_base64_decode, + op_base64_encode, + op_base64_atob, + op_base64_btoa, + op_encoding_normalize_label, + op_encoding_decode_single, + op_encoding_decode_utf8, + op_encoding_new_decoder, + op_encoding_decode, + op_encoding_encode_into, + op_encode_binary_string, + op_blob_create_part, + op_blob_slice_part, + op_blob_read_part, + op_blob_remove_part, + op_blob_create_object_url, + op_blob_revoke_object_url, + op_blob_from_object_url, + op_message_port_create_entangled, + op_message_port_post_message, + op_message_port_recv_message, + compression::op_compression_new, + compression::op_compression_write, + compression::op_compression_finish, + op_now

, + op_timer_handle, + op_cancel_handle, + op_sleep, + op_transfer_arraybuffer, + ], + esm = [ + "00_infra.js", + "01_dom_exception.js", + "01_mimesniff.js", + "02_event.js", + "02_structured_clone.js", + "02_timers.js", + "03_abort_signal.js", + "04_global_interfaces.js", + "05_base64.js", + "06_streams.js", + "08_text_encoding.js", + "09_file.js", + "10_filereader.js", + "11_blob_url.js", + "12_location.js", + "13_message_port.js", + "14_compression.js", + "15_performance.js", + ], + config = { + blob_store: BlobStore, + maybe_location: Option, + }, + state = |state, blob_store, maybe_location| { + state.put(blob_store); + if let Some(location) = maybe_location { + state.put(Location(location)); + } + state.put(StartTime::now()); + } +); #[op] fn op_base64_decode(input: String) -> Result { diff --git a/ext/webidl/benches/dict.rs b/ext/webidl/benches/dict.rs index 2ed9adf780..89a83ddaaf 100644 --- a/ext/webidl/benches/dict.rs +++ b/ext/webidl/benches/dict.rs @@ -11,7 +11,7 @@ use deno_core::ExtensionFileSourceCode; fn setup() -> Vec { vec![ - deno_webidl::init_esm(), + deno_webidl::deno_webidl::init_ops_and_esm(), Extension::builder("deno_webidl_bench") .esm(vec![ExtensionFileSource { specifier: "ext:setup".to_string(), diff --git a/ext/webidl/lib.rs b/ext/webidl/lib.rs index 42559e501d..332bea8156 100644 --- a/ext/webidl/lib.rs +++ b/ext/webidl/lib.rs @@ -1,14 +1,3 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use deno_core::include_js_files; -use deno_core::Extension; - -pub fn init() -> Extension { - Extension::builder(env!("CARGO_PKG_NAME")).build() -} - -pub fn init_esm() -> Extension { - Extension::builder(env!("CARGO_PKG_NAME")) - .esm(include_js_files!("00_webidl.js",)) - .build() -} +deno_core::extension!(deno_webidl, esm = ["00_webidl.js"],); diff --git a/ext/websocket/lib.rs b/ext/websocket/lib.rs index dbbeae21f8..e480d7f4c6 100644 --- a/ext/websocket/lib.rs +++ b/ext/websocket/lib.rs @@ -7,16 +7,13 @@ use deno_core::futures::stream::SplitSink; use deno_core::futures::stream::SplitStream; use deno_core::futures::SinkExt; use deno_core::futures::StreamExt; -use deno_core::include_js_files; use deno_core::op; -use deno_core::ExtensionBuilder; use deno_core::url; use deno_core::AsyncRefCell; use deno_core::ByteString; use deno_core::CancelFuture; use deno_core::CancelHandle; -use deno_core::Extension; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -498,67 +495,30 @@ pub async fn op_ws_next_event( Ok(res) } -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps( - env!("CARGO_PKG_NAME"), - &["deno_url", "deno_webidl"], - ) -} - -fn ops( - ext: &mut ExtensionBuilder, - user_agent: String, - root_cert_store: Option, - unsafely_ignore_certificate_errors: Option>, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - op_ws_check_permission_and_cancel_handle::decl::

(), - op_ws_create::decl::

(), - op_ws_send::decl(), - op_ws_close::decl(), - op_ws_next_event::decl(), - ]) - .state(move |state| { - state.put::(WsUserAgent(user_agent.clone())); - state.put(UnsafelyIgnoreCertificateErrors( - unsafely_ignore_certificate_errors.clone(), - )); - state.put::(WsRootStore(root_cert_store.clone())); - }) -} - -pub fn init_ops_and_esm( - user_agent: String, - root_cert_store: Option, - unsafely_ignore_certificate_errors: Option>, -) -> Extension { - ops::

( - &mut ext(), - user_agent, - root_cert_store, - unsafely_ignore_certificate_errors, - ) - .esm(include_js_files!( - "01_websocket.js", - "02_websocketstream.js", - )) - .build() -} - -pub fn init_ops( - user_agent: String, - root_cert_store: Option, - unsafely_ignore_certificate_errors: Option>, -) -> Extension { - ops::

( - &mut ext(), - user_agent, - root_cert_store, - unsafely_ignore_certificate_errors, - ) - .build() -} +deno_core::extension!(deno_websocket, + deps = [ deno_url, deno_webidl ], + parameters = [P: WebSocketPermissions], + ops = [ + op_ws_check_permission_and_cancel_handle

, + op_ws_create

, + op_ws_send, + op_ws_close, + op_ws_next_event, + ], + esm = [ "01_websocket.js", "02_websocketstream.js" ], + config = { + user_agent: String, + root_cert_store: Option, + unsafely_ignore_certificate_errors: Option> + }, + state = |state, user_agent, root_cert_store, unsafely_ignore_certificate_errors| { + state.put::(WsUserAgent(user_agent)); + state.put(UnsafelyIgnoreCertificateErrors( + unsafely_ignore_certificate_errors, + )); + state.put::(WsRootStore(root_cert_store)); + }, +); pub fn get_declaration() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_websocket.d.ts") diff --git a/ext/webstorage/lib.rs b/ext/webstorage/lib.rs index f3caddbaf0..6cdc7bbff9 100644 --- a/ext/webstorage/lib.rs +++ b/ext/webstorage/lib.rs @@ -6,10 +6,7 @@ use std::fmt; use std::path::PathBuf; use deno_core::error::AnyError; -use deno_core::include_js_files; use deno_core::op; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use rusqlite::params; use rusqlite::Connection; @@ -22,40 +19,27 @@ struct OriginStorageDir(PathBuf); const MAX_STORAGE_BYTES: usize = 10 * 1024 * 1024; -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps(env!("CARGO_PKG_NAME"), &["deno_webidl"]) -} - -fn ops( - ext: &mut ExtensionBuilder, - origin_storage_dir: Option, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - op_webstorage_length::decl(), - op_webstorage_key::decl(), - op_webstorage_set::decl(), - op_webstorage_get::decl(), - op_webstorage_remove::decl(), - op_webstorage_clear::decl(), - op_webstorage_iterate_keys::decl(), - ]) - .state(move |state| { - if let Some(origin_storage_dir) = &origin_storage_dir { - state.put(OriginStorageDir(origin_storage_dir.clone())); - } - }) -} - -pub fn init_ops_and_esm(origin_storage_dir: Option) -> Extension { - ops(&mut ext(), origin_storage_dir) - .esm(include_js_files!("01_webstorage.js",)) - .build() -} - -pub fn init_ops(origin_storage_dir: Option) -> Extension { - ops(&mut ext(), origin_storage_dir).build() -} +deno_core::extension!(deno_webstorage, + deps = [ deno_webidl ], + ops = [ + op_webstorage_length, + op_webstorage_key, + op_webstorage_set, + op_webstorage_get, + op_webstorage_remove, + op_webstorage_clear, + op_webstorage_iterate_keys, + ], + esm = [ "01_webstorage.js" ], + config = { + origin_storage_dir: Option + }, + state = |state, origin_storage_dir| { + if let Some(origin_storage_dir) = origin_storage_dir { + state.put(OriginStorageDir(origin_storage_dir)); + } + }, +); pub fn get_declaration() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_webstorage.d.ts") diff --git a/runtime/build.rs b/runtime/build.rs index 63bc3439e3..c1837de827 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -8,18 +8,18 @@ use std::path::PathBuf; not(feature = "dont_create_runtime_snapshot") ))] mod startup_snapshot { - use std::path::Path; - use super::*; use deno_ast::MediaType; use deno_ast::ParseParams; use deno_ast::SourceTextInfo; use deno_cache::SqliteBackedCache; use deno_core::error::AnyError; - use deno_core::include_js_files; use deno_core::snapshot_util::*; use deno_core::Extension; use deno_core::ExtensionFileSource; + use std::cell::RefCell; + use std::path::Path; + use std::rc::Rc; fn transpile_ts_for_snapshotting( file_source: &ExtensionFileSource, @@ -58,6 +58,7 @@ mod startup_snapshot { Ok(transpiled_source.text) } + #[derive(Clone)] struct Permissions; impl deno_fetch::FetchPermissions for Permissions { @@ -200,36 +201,30 @@ mod startup_snapshot { } } - fn create_runtime_snapshot( - snapshot_path: PathBuf, - maybe_additional_extension: Option, - ) { - let runtime_extension = Extension::builder_with_deps( - "runtime", - &[ - "deno_webidl", - "deno_console", - "deno_url", - "deno_tls", - "deno_web", - "deno_fetch", - "deno_cache", - "deno_websocket", - "deno_webstorage", - "deno_crypto", - "deno_broadcast_channel", - // FIXME(bartlomieju): this should be reenabled - // "deno_node", - "deno_ffi", - "deno_net", - "deno_napi", - "deno_http", - "deno_flash", - "deno_io", - "deno_fs", - ], - ) - .esm(include_js_files!( + deno_core::extension!(runtime, + deps = [ + deno_webidl, + deno_console, + deno_url, + deno_tls, + deno_web, + deno_fetch, + deno_cache, + deno_websocket, + deno_webstorage, + deno_crypto, + deno_broadcast_channel, + // FIXME(bartlomieju): this should be reenabled + // "deno_node", + deno_ffi, + deno_net, + deno_napi, + deno_http, + deno_flash, + deno_io, + deno_fs + ], + esm = [ dir "js", "01_errors.js", "01_version.ts", @@ -245,55 +240,72 @@ mod startup_snapshot { "40_tty.js", "41_prompt.js", "90_deno_ns.js", - "98_global_scope.js", - )) - .build(); + "98_global_scope.js" + ], + ); + #[cfg(not(feature = "snapshot_from_snapshot"))] + deno_core::extension!( + runtime_main, + deps = [runtime], + customizer = |ext: &mut deno_core::ExtensionBuilder| { + ext.esm(vec![ExtensionFileSource { + specifier: "js/99_main.js".to_string(), + code: deno_core::ExtensionFileSourceCode::IncludedInBinary( + include_str!("js/99_main.js"), + ), + }]); + } + ); + + pub fn create_runtime_snapshot(snapshot_path: PathBuf) { // NOTE(bartlomieju): ordering is important here, keep it in sync with // `runtime/worker.rs`, `runtime/web_worker.rs` and `cli/build.rs`! - let mut extensions: Vec = vec![ - deno_webidl::init_esm(), - deno_console::init_esm(), - deno_url::init_ops_and_esm(), - deno_web::init_ops_and_esm::( + let extensions: Vec = vec![ + deno_webidl::deno_webidl::init_ops_and_esm(), + deno_console::deno_console::init_ops_and_esm(), + deno_url::deno_url::init_ops_and_esm(), + deno_web::deno_web::init_ops_and_esm::( deno_web::BlobStore::default(), Default::default(), ), - deno_fetch::init_ops_and_esm::(Default::default()), - deno_cache::init_ops_and_esm::(None), - deno_websocket::init_ops_and_esm::( + deno_fetch::deno_fetch::init_ops_and_esm::( + Default::default(), + ), + deno_cache::deno_cache::init_ops_and_esm::(None), + deno_websocket::deno_websocket::init_ops_and_esm::( "".to_owned(), None, None, ), - deno_webstorage::init_ops_and_esm(None), - deno_crypto::init_ops_and_esm(None), - deno_broadcast_channel::init_ops_and_esm( + deno_webstorage::deno_webstorage::init_ops_and_esm(None), + deno_crypto::deno_crypto::init_ops_and_esm(None), + deno_broadcast_channel::deno_broadcast_channel::init_ops_and_esm( deno_broadcast_channel::InMemoryBroadcastChannel::default(), false, // No --unstable. ), - deno_ffi::init_ops_and_esm::(false), - deno_net::init_ops_and_esm::( + deno_ffi::deno_ffi::init_ops_and_esm::(false), + deno_net::deno_net::init_ops_and_esm::( None, false, // No --unstable. None, ), - deno_tls::init_ops(), - deno_napi::init_ops::(), - deno_http::init_ops_and_esm(), - deno_io::init_ops_and_esm(Default::default()), - deno_fs::init_ops_and_esm::(false), - deno_flash::init_ops_and_esm::(false), // No --unstable - runtime_extension, + deno_tls::deno_tls::init_ops_and_esm(), + deno_napi::deno_napi::init_ops_and_esm::(), + deno_http::deno_http::init_ops_and_esm(), + deno_io::deno_io::init_ops_and_esm(Rc::new(RefCell::new(Some( + Default::default(), + )))), + deno_fs::deno_fs::init_ops_and_esm::(false), + deno_flash::deno_flash::init_ops_and_esm::(false), // No --unstable + runtime::init_ops_and_esm(), // FIXME(bartlomieju): these extensions are specified last, because they // depend on `runtime`, even though it should be other way around - deno_node::init_ops_and_esm::(None), - deno_node::init_polyfill_ops_and_esm(), + deno_node::deno_node_loading::init_ops_and_esm::(None), + deno_node::deno_node::init_ops_and_esm(), + #[cfg(not(feature = "snapshot_from_snapshot"))] + runtime_main::init_ops_and_esm(), ]; - if let Some(additional_extension) = maybe_additional_extension { - extensions.push(additional_extension); - } - create_snapshot(CreateSnapshotOptions { cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"), snapshot_path, @@ -303,28 +315,6 @@ mod startup_snapshot { snapshot_module_load_cb: Some(Box::new(transpile_ts_for_snapshotting)), }); } - - pub fn build_snapshot(runtime_snapshot_path: PathBuf) { - #[allow(unused_mut, unused_assignments)] - let mut maybe_additional_extension = None; - - #[cfg(not(feature = "snapshot_from_snapshot"))] - { - use deno_core::ExtensionFileSourceCode; - maybe_additional_extension = Some( - Extension::builder_with_deps("runtime_main", &["runtime"]) - .esm(vec![ExtensionFileSource { - specifier: "js/99_main.js".to_string(), - code: ExtensionFileSourceCode::IncludedInBinary(include_str!( - "js/99_main.js" - )), - }]) - .build(), - ); - } - - create_runtime_snapshot(runtime_snapshot_path, maybe_additional_extension); - } } fn main() { @@ -351,5 +341,5 @@ fn main() { not(feature = "docsrs"), not(feature = "dont_create_runtime_snapshot") ))] - startup_snapshot::build_snapshot(runtime_snapshot_path) + startup_snapshot::create_runtime_snapshot(runtime_snapshot_path) } diff --git a/runtime/ops/fs_events.rs b/runtime/ops/fs_events.rs index e550d204c3..05cc22152f 100644 --- a/runtime/ops/fs_events.rs +++ b/runtime/ops/fs_events.rs @@ -13,7 +13,6 @@ use deno_core::ResourceId; use deno_core::op; -use deno_core::Extension; use notify::event::Event as NotifyEvent; use notify::Error as NotifyError; use notify::EventKind; @@ -29,11 +28,10 @@ use std::path::PathBuf; use std::rc::Rc; use tokio::sync::mpsc; -pub fn init() -> Extension { - Extension::builder("deno_fs_events") - .ops(vec![op_fs_events_open::decl(), op_fs_events_poll::decl()]) - .build() -} +deno_core::extension!( + deno_fs_events, + ops = [op_fs_events_open, op_fs_events_poll] +); struct FsEventsResource { #[allow(unused)] diff --git a/runtime/ops/http.rs b/runtime/ops/http.rs index 51562589ea..b9899b4e3f 100644 --- a/runtime/ops/http.rs +++ b/runtime/ops/http.rs @@ -8,7 +8,6 @@ use deno_core::error::bad_resource_id; use deno_core::error::custom_error; use deno_core::error::AnyError; use deno_core::op; -use deno_core::Extension; use deno_core::OpState; use deno_core::RcRef; use deno_core::ResourceId; @@ -28,15 +27,10 @@ use deno_net::io::UnixStreamResource; #[cfg(unix)] use tokio::net::UnixStream; -pub fn init() -> Extension { - Extension::builder("deno_http_runtime") - .ops(vec![ - op_http_start::decl(), - op_http_upgrade::decl(), - op_flash_upgrade_http::decl(), - ]) - .build() -} +deno_core::extension!( + deno_http_runtime, + ops = [op_http_start, op_http_upgrade, op_flash_upgrade_http], +); #[op] fn op_http_start( diff --git a/runtime/ops/os/mod.rs b/runtime/ops/os/mod.rs index b2c67db5cd..87181654b3 100644 --- a/runtime/ops/os/mod.rs +++ b/runtime/ops/os/mod.rs @@ -8,8 +8,6 @@ use deno_core::error::AnyError; use deno_core::op; use deno_core::url::Url; use deno_core::v8; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use deno_node::NODE_ENV_VAR_ALLOWLIST; use serde::Serialize; @@ -18,47 +16,49 @@ use std::env; mod sys_info; -fn init_ops(builder: &mut ExtensionBuilder) -> &mut ExtensionBuilder { - builder.ops(vec![ - op_env::decl(), - op_exec_path::decl(), - op_exit::decl(), - op_delete_env::decl(), - op_get_env::decl(), - op_gid::decl(), - op_hostname::decl(), - op_loadavg::decl(), - op_network_interfaces::decl(), - op_os_release::decl(), - op_os_uptime::decl(), - op_node_unstable_os_uptime::decl(), - op_set_env::decl(), - op_set_exit_code::decl(), - op_system_memory_info::decl(), - op_uid::decl(), - op_runtime_memory_usage::decl(), - ]) -} +deno_core::ops!( + deno_ops, + [ + op_env, + op_exec_path, + op_exit, + op_delete_env, + op_get_env, + op_gid, + op_hostname, + op_loadavg, + op_network_interfaces, + op_os_release, + op_os_uptime, + op_node_unstable_os_uptime, + op_set_env, + op_set_exit_code, + op_system_memory_info, + op_uid, + op_runtime_memory_usage, + ] +); -pub fn init(exit_code: ExitCode) -> Extension { - let mut builder = Extension::builder("deno_os"); - init_ops(&mut builder) - .state(move |state| { - state.put::(exit_code.clone()); - }) - .build() -} +deno_core::extension!( + deno_os, + ops_fn = deno_ops, + config = { + exit_code: ExitCode, + }, + state = |state, exit_code| { + state.put::(exit_code); + }, +); -pub fn init_for_worker() -> Extension { - let mut builder = Extension::builder("deno_os_worker"); - init_ops(&mut builder) - .middleware(|op| match op.name { - "op_exit" => noop_op::decl(), - "op_set_exit_code" => noop_op::decl(), - _ => op, - }) - .build() -} +deno_core::extension!( + deno_os_worker, + ops_fn = deno_ops, + middleware = |op| match op.name { + "op_exit" => noop_op::decl(), + "op_set_exit_code" => noop_op::decl(), + _ => op, + }, +); #[op] fn noop_op() -> Result<(), AnyError> { diff --git a/runtime/ops/permissions.rs b/runtime/ops/permissions.rs index 3c48c1e8dd..c08d11e4af 100644 --- a/runtime/ops/permissions.rs +++ b/runtime/ops/permissions.rs @@ -7,20 +7,18 @@ use deno_core::error::uri_error; use deno_core::error::AnyError; use deno_core::op; use deno_core::url; -use deno_core::Extension; use deno_core::OpState; use serde::Deserialize; use std::path::Path; -pub fn init() -> Extension { - Extension::builder("deno_permissions") - .ops(vec![ - op_query_permission::decl(), - op_revoke_permission::decl(), - op_request_permission::decl(), - ]) - .build() -} +deno_core::extension!( + deno_permissions, + ops = [ + op_query_permission, + op_revoke_permission, + op_request_permission, + ] +); #[derive(Deserialize)] pub struct PermissionArgs { diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs index 20db96af98..a15b63f808 100644 --- a/runtime/ops/process.rs +++ b/runtime/ops/process.rs @@ -7,7 +7,6 @@ use deno_core::op; use deno_core::serde_json; use deno_core::AsyncMutFuture; use deno_core::AsyncRefCell; -use deno_core::Extension; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -99,18 +98,17 @@ impl StdioOrRid { } } -pub fn init_ops() -> Extension { - Extension::builder("deno_process") - .ops(vec![ - op_spawn_child::decl(), - op_spawn_wait::decl(), - op_spawn_sync::decl(), - deprecated::op_run::decl(), - deprecated::op_run_status::decl(), - deprecated::op_kill::decl(), - ]) - .build() -} +deno_core::extension!( + deno_process, + ops = [ + op_spawn_child, + op_spawn_wait, + op_spawn_sync, + deprecated::op_run, + deprecated::op_run_status, + deprecated::op_kill, + ] +); struct ChildResource(tokio::process::Child); diff --git a/runtime/ops/runtime.rs b/runtime/ops/runtime.rs index 5ce9966e02..564d2279bf 100644 --- a/runtime/ops/runtime.rs +++ b/runtime/ops/runtime.rs @@ -3,18 +3,17 @@ use crate::permissions::PermissionsContainer; use deno_core::error::AnyError; use deno_core::op; -use deno_core::Extension; use deno_core::ModuleSpecifier; use deno_core::OpState; -pub fn init(main_module: ModuleSpecifier) -> Extension { - Extension::builder("deno_runtime") - .ops(vec![op_main_module::decl()]) - .state(move |state| { - state.put::(main_module.clone()); - }) - .build() -} +deno_core::extension!( + deno_runtime, + ops = [op_main_module], + config = { main_module: ModuleSpecifier }, + state = |state, main_module| { + state.put::(main_module); + } +); #[op] fn op_main_module(state: &mut OpState) -> Result { diff --git a/runtime/ops/signal.rs b/runtime/ops/signal.rs index c2105a64e1..9cc261d854 100644 --- a/runtime/ops/signal.rs +++ b/runtime/ops/signal.rs @@ -5,7 +5,6 @@ use deno_core::op; use deno_core::AsyncRefCell; use deno_core::CancelFuture; use deno_core::CancelHandle; -use deno_core::Extension; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -30,15 +29,10 @@ use tokio::signal::windows::CtrlBreak; #[cfg(windows)] use tokio::signal::windows::CtrlC; -pub fn init() -> Extension { - Extension::builder("deno_signal") - .ops(vec![ - op_signal_bind::decl(), - op_signal_unbind::decl(), - op_signal_poll::decl(), - ]) - .build() -} +deno_core::extension!( + deno_signal, + ops = [op_signal_bind, op_signal_unbind, op_signal_poll] +); #[cfg(unix)] /// The resource for signal stream. diff --git a/runtime/ops/tty.rs b/runtime/ops/tty.rs index d577a67557..60144e408a 100644 --- a/runtime/ops/tty.rs +++ b/runtime/ops/tty.rs @@ -2,7 +2,6 @@ use deno_core::error::AnyError; use deno_core::op; -use deno_core::Extension; use deno_core::OpState; use deno_io::StdFileResource; use std::io::Error; @@ -33,15 +32,10 @@ fn get_windows_handle( Ok(handle) } -pub fn init() -> Extension { - Extension::builder("deno_tty") - .ops(vec![ - op_stdin_set_raw::decl(), - op_isatty::decl(), - op_console_size::decl(), - ]) - .build() -} +deno_core::extension!( + deno_tty, + ops = [op_stdin_set_raw, op_isatty, op_console_size] +); // ref: #[cfg(windows)] diff --git a/runtime/ops/web_worker.rs b/runtime/ops/web_worker.rs index 6176154247..45137913e4 100644 --- a/runtime/ops/web_worker.rs +++ b/runtime/ops/web_worker.rs @@ -8,7 +8,6 @@ use deno_core::error::AnyError; use deno_core::op; use deno_core::CancelFuture; -use deno_core::Extension; use deno_core::OpState; use deno_web::JsMessageData; use std::cell::RefCell; @@ -16,18 +15,17 @@ use std::rc::Rc; use self::sync_fetch::op_worker_sync_fetch; -pub fn init() -> Extension { - Extension::builder("deno_web_worker") - .ops(vec![ - op_worker_post_message::decl(), - op_worker_recv_message::decl(), - // Notify host that guest worker closes. - op_worker_close::decl(), - op_worker_get_type::decl(), - op_worker_sync_fetch::decl(), - ]) - .build() -} +deno_core::extension!( + deno_web_worker, + ops = [ + op_worker_post_message, + op_worker_recv_message, + // Notify host that guest worker closes. + op_worker_close, + op_worker_get_type, + op_worker_sync_fetch, + ] +); #[op] fn op_worker_post_message( diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs index 6007a3260b..de7e02e186 100644 --- a/runtime/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs @@ -18,7 +18,6 @@ use deno_core::op; use deno_core::serde::Deserialize; use deno_core::CancelFuture; use deno_core::CancelHandle; -use deno_core::Extension; use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_web::JsMessageData; @@ -88,39 +87,39 @@ impl Drop for WorkerThread { pub type WorkersTable = HashMap; -pub fn init( - create_web_worker_cb: Arc, - preload_module_cb: Arc, - pre_execute_module_cb: Arc, - format_js_error_fn: Option>, -) -> Extension { - Extension::builder("deno_worker_host") - .state(move |state| { - state.put::(WorkersTable::default()); - state.put::(WorkerId::default()); +deno_core::extension!( + deno_worker_host, + ops = [ + op_create_worker, + op_host_terminate_worker, + op_host_post_message, + op_host_recv_ctrl, + op_host_recv_message, + ], + config = { + create_web_worker_cb: Arc, + preload_module_cb: Arc, + pre_execute_module_cb: Arc, + format_js_error_fn: Option>, + }, + state = |state, create_web_worker_cb, preload_module_cb, pre_execute_module_cb, format_js_error_fn| { + state.put::(WorkersTable::default()); + state.put::(WorkerId::default()); - let create_web_worker_cb_holder = - CreateWebWorkerCbHolder(create_web_worker_cb.clone()); - state.put::(create_web_worker_cb_holder); - let preload_module_cb_holder = - PreloadModuleCbHolder(preload_module_cb.clone()); - state.put::(preload_module_cb_holder); - let pre_execute_module_cb_holder = - PreExecuteModuleCbHolder(pre_execute_module_cb.clone()); - state.put::(pre_execute_module_cb_holder); - let format_js_error_fn_holder = - FormatJsErrorFnHolder(format_js_error_fn.clone()); - state.put::(format_js_error_fn_holder); - }) - .ops(vec![ - op_create_worker::decl(), - op_host_terminate_worker::decl(), - op_host_post_message::decl(), - op_host_recv_ctrl::decl(), - op_host_recv_message::decl(), - ]) - .build() -} + let create_web_worker_cb_holder = + CreateWebWorkerCbHolder(create_web_worker_cb.clone()); + state.put::(create_web_worker_cb_holder); + let preload_module_cb_holder = + PreloadModuleCbHolder(preload_module_cb.clone()); + state.put::(preload_module_cb_holder); + let pre_execute_module_cb_holder = + PreExecuteModuleCbHolder(pre_execute_module_cb.clone()); + state.put::(pre_execute_module_cb_holder); + let format_js_error_fn_holder = + FormatJsErrorFnHolder(format_js_error_fn.clone()); + state.put::(format_js_error_fn_holder); + } +); #[derive(Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index b6caba194e..a78e7078b3 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -368,16 +368,22 @@ impl WebWorker { worker_id: WorkerId, mut options: WebWorkerOptions, ) -> (Self, SendableWebWorkerHandle) { + deno_core::extension!(deno_permissions_web_worker, + config = { + permissions: PermissionsContainer, + unstable: bool, + enable_testing_features: bool, + }, + state = |state, permissions, unstable, enable_testing_features| { + state.put::(permissions); + state.put(ops::UnstableChecker { unstable }); + state.put(ops::TestingFeaturesEnabled(enable_testing_features)); + }, + ); + // Permissions: many ops depend on this let unstable = options.bootstrap.unstable; let enable_testing_features = options.bootstrap.enable_testing_features; - let perm_ext = Extension::builder("deno_permissions_web_worker") - .state(move |state| { - state.put::(permissions.clone()); - state.put(ops::UnstableChecker { unstable }); - state.put(ops::TestingFeaturesEnabled(enable_testing_features)); - }) - .build(); let create_cache = options.cache_storage_dir.map(|storage_dir| { let create_cache_fn = move || SqliteBackedCache::new(storage_dir.clone()); CreateCache(Arc::new(create_cache_fn)) @@ -387,68 +393,75 @@ impl WebWorker { // `runtime/build.rs`, `runtime/worker.rs` and `cli/build.rs`! let mut extensions: Vec = vec![ // Web APIs - deno_webidl::init(), - deno_console::init(), - deno_url::init_ops(), - deno_web::init_ops::( + deno_webidl::deno_webidl::init_ops(), + deno_console::deno_console::init_ops(), + deno_url::deno_url::init_ops(), + deno_web::deno_web::init_ops::( options.blob_store.clone(), Some(main_module.clone()), ), - deno_fetch::init_ops::(deno_fetch::Options { - user_agent: options.bootstrap.user_agent.clone(), - root_cert_store: options.root_cert_store.clone(), - unsafely_ignore_certificate_errors: options - .unsafely_ignore_certificate_errors - .clone(), - file_fetch_handler: Rc::new(deno_fetch::FsFetchHandler), - ..Default::default() - }), - deno_cache::init_ops::(create_cache), - deno_websocket::init_ops::( + deno_fetch::deno_fetch::init_ops::( + deno_fetch::Options { + user_agent: options.bootstrap.user_agent.clone(), + root_cert_store: options.root_cert_store.clone(), + unsafely_ignore_certificate_errors: options + .unsafely_ignore_certificate_errors + .clone(), + file_fetch_handler: Rc::new(deno_fetch::FsFetchHandler), + ..Default::default() + }, + ), + deno_cache::deno_cache::init_ops::(create_cache), + deno_websocket::deno_websocket::init_ops::( options.bootstrap.user_agent.clone(), options.root_cert_store.clone(), options.unsafely_ignore_certificate_errors.clone(), ), - deno_webstorage::init_ops(None).disable(), - deno_crypto::init_ops(options.seed), - deno_broadcast_channel::init_ops( + deno_webstorage::deno_webstorage::init_ops(None).disable(), + deno_crypto::deno_crypto::init_ops(options.seed), + deno_broadcast_channel::deno_broadcast_channel::init_ops( options.broadcast_channel.clone(), unstable, ), - deno_ffi::init_ops::(unstable), - deno_net::init_ops::( + deno_ffi::deno_ffi::init_ops::(unstable), + deno_net::deno_net::init_ops::( options.root_cert_store.clone(), unstable, options.unsafely_ignore_certificate_errors.clone(), ), - deno_tls::init_ops(), - deno_napi::init_ops::(), - deno_http::init_ops(), - deno_io::init_ops(options.stdio), - deno_fs::init_ops::(unstable), - deno_flash::init_ops::(unstable), - deno_node::init_ops::(options.npm_resolver), - deno_node::init_polyfill_ops(), + deno_tls::deno_tls::init_ops(), + deno_napi::deno_napi::init_ops::(), + deno_http::deno_http::init_ops(), + deno_io::deno_io::init_ops(Rc::new(RefCell::new(Some(options.stdio)))), + deno_fs::deno_fs::init_ops::(unstable), + deno_flash::deno_flash::init_ops::(unstable), + deno_node::deno_node_loading::init_ops::( + options.npm_resolver, + ), + deno_node::deno_node::init_ops(), // Runtime ops that are always initialized for WebWorkers - ops::web_worker::init(), - ops::runtime::init(main_module.clone()), - ops::worker_host::init( + ops::web_worker::deno_web_worker::init_ops(), + ops::runtime::deno_runtime::init_ops(main_module.clone()), + ops::worker_host::deno_worker_host::init_ops( options.create_web_worker_cb.clone(), options.preload_module_cb.clone(), options.pre_execute_module_cb.clone(), options.format_js_error_fn.clone(), ), - ops::fs_events::init(), - ops::os::init_for_worker(), - ops::permissions::init(), - ops::process::init_ops(), - ops::signal::init(), - ops::tty::init(), - ops::http::init(), + ops::fs_events::deno_fs_events::init_ops(), + ops::os::deno_os_worker::init_ops(), + ops::permissions::deno_permissions::init_ops(), + ops::process::deno_process::init_ops(), + ops::signal::deno_signal::init_ops(), + ops::tty::deno_tty::init_ops(), + ops::http::deno_http_runtime::init_ops(), + deno_permissions_web_worker::init_ops( + permissions, + unstable, + enable_testing_features, + ), ]; - extensions.push(perm_ext); - // Append exts extensions.extend(std::mem::take(&mut options.extensions)); diff --git a/runtime/worker.rs b/runtime/worker.rs index b7c05f7e12..8a7f5711d1 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -1,5 +1,6 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use std::cell::RefCell; use std::pin::Pin; use std::rc::Rc; use std::sync::atomic::AtomicI32; @@ -187,16 +188,22 @@ impl MainWorker { permissions: PermissionsContainer, mut options: WorkerOptions, ) -> Self { + deno_core::extension!(deno_permissions_worker, + config = { + permissions: PermissionsContainer, + unstable: bool, + enable_testing_features: bool, + }, + state = |state, permissions, unstable, enable_testing_features| { + state.put::(permissions); + state.put(ops::UnstableChecker { unstable }); + state.put(ops::TestingFeaturesEnabled(enable_testing_features)); + }, + ); + // Permissions: many ops depend on this let unstable = options.bootstrap.unstable; let enable_testing_features = options.bootstrap.enable_testing_features; - let perm_ext = Extension::builder("deno_permissions_worker") - .state(move |state| { - state.put::(permissions.clone()); - state.put(ops::UnstableChecker { unstable }); - state.put(ops::TestingFeaturesEnabled(enable_testing_features)); - }) - .build(); let exit_code = ExitCode(Arc::new(AtomicI32::new(0))); let create_cache = options.cache_storage_dir.map(|storage_dir| { let create_cache_fn = move || SqliteBackedCache::new(storage_dir.clone()); @@ -207,67 +214,76 @@ impl MainWorker { // `runtime/build.rs`, `runtime/web_worker.rs` and `cli/build.rs`! let mut extensions = vec![ // Web APIs - deno_webidl::init(), - deno_console::init(), - deno_url::init_ops(), - deno_web::init_ops::( + deno_webidl::deno_webidl::init_ops(), + deno_console::deno_console::init_ops(), + deno_url::deno_url::init_ops(), + deno_web::deno_web::init_ops::( options.blob_store.clone(), options.bootstrap.location.clone(), ), - deno_fetch::init_ops::(deno_fetch::Options { - user_agent: options.bootstrap.user_agent.clone(), - root_cert_store: options.root_cert_store.clone(), - unsafely_ignore_certificate_errors: options - .unsafely_ignore_certificate_errors - .clone(), - file_fetch_handler: Rc::new(deno_fetch::FsFetchHandler), - ..Default::default() - }), - deno_cache::init_ops::(create_cache), - deno_websocket::init_ops::( + deno_fetch::deno_fetch::init_ops::( + deno_fetch::Options { + user_agent: options.bootstrap.user_agent.clone(), + root_cert_store: options.root_cert_store.clone(), + unsafely_ignore_certificate_errors: options + .unsafely_ignore_certificate_errors + .clone(), + file_fetch_handler: Rc::new(deno_fetch::FsFetchHandler), + ..Default::default() + }, + ), + deno_cache::deno_cache::init_ops::(create_cache), + deno_websocket::deno_websocket::init_ops::( options.bootstrap.user_agent.clone(), options.root_cert_store.clone(), options.unsafely_ignore_certificate_errors.clone(), ), - deno_webstorage::init_ops(options.origin_storage_dir.clone()), - deno_crypto::init_ops(options.seed), - deno_broadcast_channel::init_ops( + deno_webstorage::deno_webstorage::init_ops( + options.origin_storage_dir.clone(), + ), + deno_crypto::deno_crypto::init_ops(options.seed), + deno_broadcast_channel::deno_broadcast_channel::init_ops( options.broadcast_channel.clone(), unstable, ), - deno_ffi::init_ops::(unstable), - deno_net::init_ops::( + deno_ffi::deno_ffi::init_ops::(unstable), + deno_net::deno_net::init_ops::( options.root_cert_store.clone(), unstable, options.unsafely_ignore_certificate_errors.clone(), ), - deno_tls::init_ops(), - deno_napi::init_ops::(), - deno_http::init_ops(), - deno_io::init_ops(options.stdio), - deno_fs::init_ops::(unstable), - deno_flash::init_ops::(unstable), - deno_node::init_ops::(options.npm_resolver), - deno_node::init_polyfill_ops(), + deno_tls::deno_tls::init_ops(), + deno_napi::deno_napi::init_ops::(), + deno_http::deno_http::init_ops(), + deno_io::deno_io::init_ops(Rc::new(RefCell::new(Some(options.stdio)))), + deno_fs::deno_fs::init_ops::(unstable), + deno_flash::deno_flash::init_ops::(unstable), + deno_node::deno_node_loading::init_ops::( + options.npm_resolver, + ), + deno_node::deno_node::init_ops(), // Ops from this crate - ops::runtime::init(main_module.clone()), - ops::worker_host::init( + ops::runtime::deno_runtime::init_ops(main_module.clone()), + ops::worker_host::deno_worker_host::init_ops( options.create_web_worker_cb.clone(), options.web_worker_preload_module_cb.clone(), options.web_worker_pre_execute_module_cb.clone(), options.format_js_error_fn.clone(), ), - ops::fs_events::init(), - ops::os::init(exit_code.clone()), - ops::permissions::init(), - ops::process::init_ops(), - ops::signal::init(), - ops::tty::init(), - ops::http::init(), + ops::fs_events::deno_fs_events::init_ops(), + ops::os::deno_os::init_ops(exit_code.clone()), + ops::permissions::deno_permissions::init_ops(), + ops::process::deno_process::init_ops(), + ops::signal::deno_signal::init_ops(), + ops::tty::deno_tty::init_ops(), + ops::http::deno_http_runtime::init_ops(), + deno_permissions_worker::init_ops( + permissions, + unstable, + enable_testing_features, + ), ]; - extensions.push(perm_ext); - extensions.extend(std::mem::take(&mut options.extensions)); #[cfg(not(feature = "dont_create_runtime_snapshot"))]