diff --git a/core/extensions.rs b/core/extensions.rs index eb6f6f719c..134aab5d41 100644 --- a/core/extensions.rs +++ b/core/extensions.rs @@ -15,38 +15,13 @@ pub struct Extension { initialized: bool, } -impl Extension { - pub fn new( - js_files: Option>, - ops: Option>, - opstate_fn: Option>, - middleware_fn: Option>, - ) -> Self { - Self { - js_files, - ops, - opstate_fn, - middleware_fn, - initialized: false, - } - } - - pub fn pure_js(js_files: Vec) -> Self { - Self::new(Some(js_files), None, None, None) - } - - pub fn with_ops( - js_files: Vec, - ops: Vec, - opstate_fn: Option>, - ) -> Self { - Self::new(Some(js_files), Some(ops), opstate_fn, None) - } -} - // Note: this used to be a trait, but we "downgraded" it to a single concrete type // for the initial iteration, it will likely become a trait in the future impl Extension { + pub fn builder() -> ExtensionBuilder { + Default::default() + } + /// returns JS source code to be loaded into the isolate (either at snapshotting, /// or at startup). as a vector of a tuple of the file name, and the source code. pub(crate) fn init_js(&self) -> Vec { @@ -81,6 +56,54 @@ impl Extension { } } +// Provides a convenient builder pattern to declare Extensions +#[derive(Default)] +pub struct ExtensionBuilder { + js: Vec, + ops: Vec, + state: Option>, + middleware: Option>, +} + +impl ExtensionBuilder { + pub fn js(&mut self, js_files: Vec) -> &mut Self { + self.js.extend(js_files); + self + } + + pub fn ops(&mut self, ops: Vec) -> &mut Self { + self.ops.extend(ops); + self + } + + pub fn state(&mut self, opstate_fn: F) -> &mut Self + where + F: Fn(&mut OpState) -> Result<(), AnyError> + 'static, + { + self.state = Some(Box::new(opstate_fn)); + self + } + + pub fn middleware(&mut self, middleware_fn: F) -> &mut Self + where + F: Fn(&'static str, Box) -> Box + 'static, + { + self.middleware = Some(Box::new(middleware_fn)); + self + } + + pub fn build(&mut self) -> Extension { + let js_files = Some(std::mem::take(&mut self.js)); + let ops = Some(std::mem::take(&mut self.ops)); + Extension { + js_files, + ops, + opstate_fn: self.state.take(), + middleware_fn: self.middleware.take(), + initialized: false, + } + } +} /// Helps embed JS files in an extension. Returns Vec<(&'static str, &'static str)> /// representing the filename and source code. /// diff --git a/op_crates/console/lib.rs b/op_crates/console/lib.rs index 4d6a213f28..4f64bb108a 100644 --- a/op_crates/console/lib.rs +++ b/op_crates/console/lib.rs @@ -5,11 +5,13 @@ use deno_core::Extension; use std::path::PathBuf; pub fn init() -> Extension { - Extension::pure_js(include_js_files!( - prefix "deno:op_crates/console", - "01_colors.js", - "02_console.js", - )) + Extension::builder() + .js(include_js_files!( + prefix "deno:op_crates/console", + "01_colors.js", + "02_console.js", + )) + .build() } pub fn get_declaration() -> PathBuf { diff --git a/op_crates/crypto/lib.rs b/op_crates/crypto/lib.rs index d5b0a30bc6..5432205483 100644 --- a/op_crates/crypto/lib.rs +++ b/op_crates/crypto/lib.rs @@ -16,22 +16,22 @@ use std::path::PathBuf; pub use rand; // Re-export rand pub fn init(maybe_seed: Option) -> Extension { - Extension::with_ops( - include_js_files!( + Extension::builder() + .js(include_js_files!( prefix "deno:op_crates/crypto", "01_crypto.js", - ), - vec![( + )) + .ops(vec![( "op_crypto_get_random_values", op_sync(op_crypto_get_random_values), - )], - Some(Box::new(move |state| { + )]) + .state(move |state| { if let Some(seed) = maybe_seed { state.put(StdRng::seed_from_u64(seed)); } Ok(()) - })), - ) + }) + .build() } pub fn op_crypto_get_random_values( diff --git a/op_crates/fetch/lib.rs b/op_crates/fetch/lib.rs index 7033a416c8..861fc6e54d 100644 --- a/op_crates/fetch/lib.rs +++ b/op_crates/fetch/lib.rs @@ -56,8 +56,8 @@ pub fn init( user_agent: String, ca_data: Option>, ) -> Extension { - Extension::with_ops( - include_js_files!( + Extension::builder() + .js(include_js_files!( prefix "deno:op_crates/fetch", "01_fetch_util.js", "11_streams.js", @@ -68,15 +68,15 @@ pub fn init( "23_request.js", "23_response.js", "26_fetch.js", - ), - vec![ + )) + .ops(vec![ ("op_fetch", op_sync(op_fetch::

)), ("op_fetch_send", op_async(op_fetch_send)), ("op_fetch_request_write", op_async(op_fetch_request_write)), ("op_fetch_response_read", op_async(op_fetch_response_read)), ("op_create_http_client", op_sync(op_create_http_client::

)), - ], - Some(Box::new(move |state| { + ]) + .state(move |state| { state.put::({ create_http_client(user_agent.clone(), ca_data.clone()).unwrap() }); @@ -85,8 +85,8 @@ pub fn init( user_agent: user_agent.clone(), }); Ok(()) - })), - ) + }) + .build() } pub struct HttpClientDefaults { diff --git a/op_crates/file/lib.rs b/op_crates/file/lib.rs index 19bb8b19b9..ccde34adae 100644 --- a/op_crates/file/lib.rs +++ b/op_crates/file/lib.rs @@ -88,14 +88,14 @@ pub fn init( blob_url_store: BlobUrlStore, maybe_location: Option, ) -> Extension { - Extension::with_ops( - include_js_files!( + Extension::builder() + .js(include_js_files!( prefix "deno:op_crates/file", "01_file.js", "02_filereader.js", "03_blob_url.js", - ), - vec![ + )) + .ops(vec![ ( "op_file_create_object_url", op_sync(op_file_create_object_url), @@ -104,15 +104,15 @@ pub fn init( "op_file_revoke_object_url", op_sync(op_file_revoke_object_url), ), - ], - Some(Box::new(move |state| { + ]) + .state(move |state| { state.put(blob_url_store.clone()); if let Some(location) = maybe_location.clone() { state.put(Location(location)); } Ok(()) - })), - ) + }) + .build() } pub fn get_declaration() -> PathBuf { diff --git a/op_crates/timers/lib.rs b/op_crates/timers/lib.rs index 6359b20f0c..62f5953fa2 100644 --- a/op_crates/timers/lib.rs +++ b/op_crates/timers/lib.rs @@ -13,6 +13,7 @@ use deno_core::futures; use deno_core::futures::channel::oneshot; use deno_core::futures::FutureExt; use deno_core::futures::TryFutureExt; +use deno_core::include_js_files; use deno_core::op_async; use deno_core::op_sync; use deno_core::Extension; @@ -41,24 +42,24 @@ impl TimersPermission for NoTimersPermission { } pub fn init() -> Extension { - Extension::with_ops( - vec![( - "deno:op_crates/timers/01_timers.js", - include_str!("01_timers.js"), - )], - vec![ + Extension::builder() + .js(include_js_files!( + prefix "deno:op_crates/timers", + "01_timers.js", + )) + .ops(vec![ ("op_global_timer_stop", op_sync(op_global_timer_stop)), ("op_global_timer_start", op_sync(op_global_timer_start)), ("op_global_timer", op_async(op_global_timer)), ("op_now", op_sync(op_now::

)), ("op_sleep_sync", op_sync(op_sleep_sync::

)), - ], - Some(Box::new(|state| { + ]) + .state(|state| { state.put(GlobalTimer::default()); state.put(StartTime::now()); Ok(()) - })), - ) + }) + .build() } pub type StartTime = Instant; diff --git a/op_crates/url/lib.rs b/op_crates/url/lib.rs index 49e34c47d5..1d7a9b08be 100644 --- a/op_crates/url/lib.rs +++ b/op_crates/url/lib.rs @@ -17,12 +17,12 @@ use std::panic::catch_unwind; use std::path::PathBuf; pub fn init() -> Extension { - Extension::with_ops( - include_js_files!( + Extension::builder() + .js(include_js_files!( prefix "deno:op_crates/url", "00_url.js", - ), - vec![ + )) + .ops(vec![ ("op_url_parse", op_sync(op_url_parse)), ( "op_url_parse_search_params", @@ -32,9 +32,8 @@ pub fn init() -> Extension { "op_url_stringify_search_params", op_sync(op_url_stringify_search_params), ), - ], - None, - ) + ]) + .build() } #[derive(Deserialize)] diff --git a/op_crates/web/lib.rs b/op_crates/web/lib.rs index 7fd8221eb7..a2612743e7 100644 --- a/op_crates/web/lib.rs +++ b/op_crates/web/lib.rs @@ -6,17 +6,19 @@ use std::path::PathBuf; /// Load and execute the javascript code. pub fn init() -> Extension { - Extension::pure_js(include_js_files!( - prefix "deno:op_crates/web", - "00_infra.js", - "01_dom_exception.js", - "01_mimesniff.js", - "02_event.js", - "03_abort_signal.js", - "04_global_interfaces.js", - "08_text_encoding.js", - "12_location.js", - )) + Extension::builder() + .js(include_js_files!( + prefix "deno:op_crates/web", + "00_infra.js", + "01_dom_exception.js", + "01_mimesniff.js", + "02_event.js", + "03_abort_signal.js", + "04_global_interfaces.js", + "08_text_encoding.js", + "12_location.js", + )) + .build() } pub fn get_declaration() -> PathBuf { diff --git a/op_crates/webgpu/lib.rs b/op_crates/webgpu/lib.rs index a9cbbb882c..b5b2905b2f 100644 --- a/op_crates/webgpu/lib.rs +++ b/op_crates/webgpu/lib.rs @@ -95,22 +95,22 @@ impl Resource for WebGpuQuerySet { } pub fn init(unstable: bool) -> Extension { - Extension::with_ops( - include_js_files!( + Extension::builder() + .js(include_js_files!( prefix "deno:op_crates/webgpu", "01_webgpu.js", "02_idl_types.js", - ), - declare_webgpu_ops(), - Some(Box::new(move |state| { + )) + .ops(declare_webgpu_ops()) + .state(move |state| { // TODO: check & possibly streamline this // Unstable might be able to be OpMiddleware // let unstable_checker = state.borrow::(); // let unstable = unstable_checker.unstable; state.put(Unstable(unstable)); Ok(()) - })), - ) + }) + .build() } pub fn get_declaration() -> PathBuf { diff --git a/op_crates/webidl/lib.rs b/op_crates/webidl/lib.rs index a1a404dbdf..c73c60bab1 100644 --- a/op_crates/webidl/lib.rs +++ b/op_crates/webidl/lib.rs @@ -1,11 +1,14 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +use deno_core::include_js_files; use deno_core::Extension; /// Load and execute the javascript code. pub fn init() -> Extension { - Extension::pure_js(vec![( - "deno:op_crates/webidl/00_webidl.js", - include_str!("00_webidl.js"), - )]) + Extension::builder() + .js(include_js_files!( + prefix "deno:op_crates/webidl", + "00_webidl.js", + )) + .build() } diff --git a/op_crates/websocket/lib.rs b/op_crates/websocket/lib.rs index c682c6b2fb..b81b1701d9 100644 --- a/op_crates/websocket/lib.rs +++ b/op_crates/websocket/lib.rs @@ -340,12 +340,12 @@ pub fn init( user_agent: String, ca_data: Option>, ) -> Extension { - Extension::with_ops( - include_js_files!( + Extension::builder() + .js(include_js_files!( prefix "deno:op_crates/websocket", "01_websocket.js", - ), - vec![ + )) + .ops(vec![ ( "op_ws_check_permission", op_sync(op_ws_check_permission::

), @@ -354,15 +354,15 @@ pub fn init( ("op_ws_send", op_async(op_ws_send)), ("op_ws_close", op_async(op_ws_close)), ("op_ws_next_event", op_async(op_ws_next_event)), - ], - Some(Box::new(move |state| { + ]) + .state(move |state| { state.put::(WsUserAgent(user_agent.clone())); if let Some(ca_data) = ca_data.clone() { state.put::(WsCaData(ca_data)); } Ok(()) - })), - ) + }) + .build() } pub fn get_declaration() -> PathBuf { diff --git a/runtime/metrics.rs b/runtime/metrics.rs index efc2cb4571..f3f48e55e2 100644 --- a/runtime/metrics.rs +++ b/runtime/metrics.rs @@ -10,15 +10,14 @@ use deno_core::OpState; use deno_core::ZeroCopyBuf; pub fn init() -> Extension { - Extension::new( - None, - Some(vec![("op_metrics", op_sync(op_metrics))]), - Some(Box::new(|state| { + Extension::builder() + .ops(vec![("op_metrics", op_sync(op_metrics))]) + .state(|state| { state.put(RuntimeMetrics::default()); Ok(()) - })), - Some(Box::new(metrics_op)), - ) + }) + .middleware(metrics_op) + .build() } #[derive(serde::Serialize)]