diff options
author | Leo Kettmeir <crowlkats@toaxl.com> | 2023-01-08 23:48:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-08 23:48:46 +0100 |
commit | c41d4ff90e09b63bd1894052352a5acba57b1704 (patch) | |
tree | 52be95551ed263c2f4831aaefc78bb6fdda6d89c /core | |
parent | 2be1282be42369e558cc77f75b22488ce7a8215e (diff) |
feat(core): allow specifying name and dependencies of an Extension (#17301)
Diffstat (limited to 'core')
-rw-r--r-- | core/examples/disable_ops.rs | 2 | ||||
-rw-r--r-- | core/examples/hello_world.rs | 2 | ||||
-rw-r--r-- | core/examples/http_bench_json_ops.rs | 2 | ||||
-rw-r--r-- | core/examples/panik.rs | 5 | ||||
-rw-r--r-- | core/examples/schedule_task.rs | 2 | ||||
-rw-r--r-- | core/examples/wasm.rs | 2 | ||||
-rw-r--r-- | core/extensions.rs | 40 | ||||
-rw-r--r-- | core/modules.rs | 4 | ||||
-rw-r--r-- | core/ops_builtin.rs | 2 | ||||
-rw-r--r-- | core/runtime.rs | 61 |
10 files changed, 89 insertions, 33 deletions
diff --git a/core/examples/disable_ops.rs b/core/examples/disable_ops.rs index a99568589..b9a5e7fca 100644 --- a/core/examples/disable_ops.rs +++ b/core/examples/disable_ops.rs @@ -7,7 +7,7 @@ use deno_core::JsRuntime; use deno_core::RuntimeOptions; fn main() { - let my_ext = Extension::builder() + let my_ext = Extension::builder("my_ext") .middleware(|op| match op.name { "op_print" => op.disable(), _ => op, diff --git a/core/examples/hello_world.rs b/core/examples/hello_world.rs index a1edbead0..50cbe4e2c 100644 --- a/core/examples/hello_world.rs +++ b/core/examples/hello_world.rs @@ -22,7 +22,7 @@ fn op_sum(nums: Vec<f64>) -> Result<f64, deno_core::error::AnyError> { fn main() { // Build a deno_core::Extension providing custom ops - let ext = Extension::builder() + let ext = Extension::builder("my_ext") .ops(vec![ // An op for summing an array of numbers // The op-layer automatically deserializes inputs diff --git a/core/examples/http_bench_json_ops.rs b/core/examples/http_bench_json_ops.rs index 23945c632..9a55a0823 100644 --- a/core/examples/http_bench_json_ops.rs +++ b/core/examples/http_bench_json_ops.rs @@ -117,7 +117,7 @@ impl From<tokio::net::TcpStream> for TcpStream { } fn create_js_runtime() -> JsRuntime { - let ext = deno_core::Extension::builder() + let ext = deno_core::Extension::builder("my_ext") .ops(vec![op_listen::decl(), op_accept::decl()]) .build(); diff --git a/core/examples/panik.rs b/core/examples/panik.rs index 76be108ec..1d2286a88 100644 --- a/core/examples/panik.rs +++ b/core/examples/panik.rs @@ -24,8 +24,9 @@ fn main() { panic!("panik !!!") } - let extensions = - vec![Extension::builder().ops(vec![op_panik::decl()]).build()]; + let extensions = vec![Extension::builder("my_ext") + .ops(vec![op_panik::decl()]) + .build()]; let mut rt = JsRuntime::new(RuntimeOptions { extensions, ..Default::default() diff --git a/core/examples/schedule_task.rs b/core/examples/schedule_task.rs index ba0f3ef0f..6a61619d8 100644 --- a/core/examples/schedule_task.rs +++ b/core/examples/schedule_task.rs @@ -18,7 +18,7 @@ use deno_core::*; type Task = Box<dyn FnOnce()>; fn main() { - let my_ext = Extension::builder() + let my_ext = Extension::builder("my_ext") .ops(vec![op_schedule_task::decl()]) .event_loop_middleware(|state_rc, cx| { let mut state = state_rc.borrow_mut(); diff --git a/core/examples/wasm.rs b/core/examples/wasm.rs index c4bb8b9ad..7c2d98bc9 100644 --- a/core/examples/wasm.rs +++ b/core/examples/wasm.rs @@ -51,7 +51,7 @@ fn op_set_wasm_mem( fn main() { // Build a deno_core::Extension providing custom ops - let ext = Extension::builder() + let ext = Extension::builder("my_ext") .ops(vec![op_wasm::decl(), op_set_wasm_mem::decl()]) .build(); diff --git a/core/extensions.rs b/core/extensions.rs index 6fca570df..437621c0e 100644 --- a/core/extensions.rs +++ b/core/extensions.rs @@ -42,13 +42,39 @@ pub struct Extension { event_loop_middleware: Option<Box<OpEventLoopFn>>, initialized: bool, enabled: bool, + name: &'static str, + deps: Option<Vec<&'static str>>, } // 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() + pub fn builder(name: &'static str) -> ExtensionBuilder { + ExtensionBuilder { + name, + ..Default::default() + } + } + + /// Check if dependencies have been loaded, and errors if either: + /// - The extension is depending on itself or an extension with the same name. + /// - A dependency hasn't been loaded yet. + pub fn check_dependencies(&self, previous_exts: &[&mut Extension]) { + if let Some(deps) = &self.deps { + 'dep_loop: for dep in deps { + if dep == &self.name { + panic!("Extension '{}' is either depending on itself or there is another extension with the same name", self.name); + } + + for ext in previous_exts { + if dep == &ext.name { + continue 'dep_loop; + } + } + + panic!("Extension '{}' is missing dependency '{dep}'", self.name); + } + } } /// returns JS source code to be loaded into the isolate (either at snapshotting, @@ -121,9 +147,16 @@ pub struct ExtensionBuilder { state: Option<Box<OpStateFn>>, middleware: Option<Box<OpMiddlewareFn>>, event_loop_middleware: Option<Box<OpEventLoopFn>>, + name: &'static str, + deps: Vec<&'static str>, } impl ExtensionBuilder { + pub fn dependencies(&mut self, dependencies: Vec<&'static str>) -> &mut Self { + self.deps.extend(dependencies); + self + } + pub fn js(&mut self, js_files: Vec<SourcePair>) -> &mut Self { self.js.extend(js_files); self @@ -161,6 +194,7 @@ impl ExtensionBuilder { 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)); + let deps = Some(std::mem::take(&mut self.deps)); Extension { js_files, ops, @@ -169,6 +203,8 @@ impl ExtensionBuilder { event_loop_middleware: self.event_loop_middleware.take(), initialized: false, enabled: true, + name: self.name, + deps, } } } diff --git a/core/modules.rs b/core/modules.rs index ff253db61..8abced200 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -1479,7 +1479,9 @@ import "/a.js"; 43 } - let ext = Extension::builder().ops(vec![op_test::decl()]).build(); + let ext = Extension::builder("test_ext") + .ops(vec![op_test::decl()]) + .build(); let mut runtime = JsRuntime::new(RuntimeOptions { extensions: vec![ext], diff --git a/core/ops_builtin.rs b/core/ops_builtin.rs index 6889c5dbc..905496025 100644 --- a/core/ops_builtin.rs +++ b/core/ops_builtin.rs @@ -17,7 +17,7 @@ use std::io::{stderr, stdout, Write}; use std::rc::Rc; pub(crate) fn init_builtins() -> Extension { - Extension::builder() + Extension::builder("deno_builtins") .js(include_js_files!( prefix "deno:core", "00_primordials.js", diff --git a/core/runtime.rs b/core/runtime.rs index 4a1302b3f..baa7de1a1 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -728,10 +728,9 @@ impl JsRuntime { /// Initializes JS of provided Extensions in the given realm fn init_extension_js(&mut self, realm: &JsRealm) -> Result<(), Error> { // Take extensions to avoid double-borrow - let mut extensions: Vec<Extension> = - std::mem::take(&mut self.extensions_with_js); - for m in extensions.iter_mut() { - let js_files = m.init_js(); + let extensions = std::mem::take(&mut self.extensions_with_js); + for ext in &extensions { + let js_files = ext.init_js(); for (filename, source) in js_files { // TODO(@AaronO): use JsRuntime::execute_static() here to move src off heap realm.execute_script(self.v8_isolate(), filename, source)?; @@ -752,6 +751,12 @@ impl JsRuntime { exts.extend(extensions); exts.extend(extensions_with_js); + for (ext, previous_exts) in + exts.iter().enumerate().map(|(i, ext)| (ext, &exts[..i])) + { + ext.check_dependencies(previous_exts); + } + // Middleware let middleware: Vec<Box<OpMiddlewareFn>> = exts .iter_mut() @@ -2554,7 +2559,7 @@ pub mod tests { fn setup(mode: Mode) -> (JsRuntime, Arc<AtomicUsize>) { let dispatch_count = Arc::new(AtomicUsize::new(0)); let dispatch_count2 = dispatch_count.clone(); - let ext = Extension::builder() + let ext = Extension::builder("test_ext") .ops(vec![op_test::decl()]) .state(move |state| { state.put(TestState { @@ -2976,7 +2981,9 @@ pub mod tests { } run_in_task(|cx| { - let ext = Extension::builder().ops(vec![op_err::decl()]).build(); + let ext = Extension::builder("test_ext") + .ops(vec![op_err::decl()]) + .build(); let mut runtime = JsRuntime::new(RuntimeOptions { extensions: vec![ext], get_error_class_fn: Some(&get_error_class_name), @@ -3428,7 +3435,7 @@ main(); } run_in_task(|cx| { - let ext = Extension::builder() + let ext = Extension::builder("test_ext") .ops(vec![op_err_sync::decl(), op_err_async::decl()]) .build(); let mut runtime = JsRuntime::new(RuntimeOptions { @@ -3596,7 +3603,7 @@ assertEquals(1, notify_return_value); Ok(()) } - let extension = Extension::builder() + let extension = Extension::builder("test_ext") .ops(vec![op_async_borrow::decl()]) .state(|state| { state.put(InnerState(42)); @@ -3631,7 +3638,7 @@ assertEquals(1, notify_return_value); Ok(()) } - let extension = Extension::builder() + let extension = Extension::builder("test_ext") .ops(vec![op_sync_serialize_object_with_numbers_as_keys::decl()]) .build(); @@ -3673,7 +3680,7 @@ Deno.core.ops.op_sync_serialize_object_with_numbers_as_keys({ Ok(()) } - let extension = Extension::builder() + let extension = Extension::builder("test_ext") .ops(vec![op_async_serialize_object_with_numbers_as_keys::decl()]) .build(); @@ -3712,7 +3719,7 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ Ok(()) } - let extension = Extension::builder() + let extension = Extension::builder("test_ext") .ops(vec![op_async_sleep::decl()]) .build(); @@ -3792,7 +3799,7 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ Ok(()) } - let extension = Extension::builder() + let extension = Extension::builder("test_ext") .ops(vec![op_macrotask::decl(), op_next_tick::decl()]) .build(); @@ -3922,7 +3929,7 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ Ok(()) } - let extension = Extension::builder() + let extension = Extension::builder("test_ext") .ops(vec![op_promise_reject::decl()]) .build(); @@ -3982,7 +3989,7 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ Ok(()) } - let extension = Extension::builder() + let extension = Extension::builder("test_ext") .ops(vec![op_promise_reject::decl()]) .build(); @@ -4051,7 +4058,9 @@ Deno.core.ops.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().ops(vec![op_err::decl()]).build(); + let ext = Extension::builder("test_ext") + .ops(vec![op_err::decl()]) + .build(); let mut runtime = JsRuntime::new(RuntimeOptions { extensions: vec![ext], ..Default::default() @@ -4076,7 +4085,9 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ Ok(x1 + x2 + x3 + x4) } - let ext = Extension::builder().ops(vec![op_add_4::decl()]).build(); + let ext = Extension::builder("test_ext") + .ops(vec![op_add_4::decl()]) + .build(); let mut runtime = JsRuntime::new(RuntimeOptions { extensions: vec![ext], ..Default::default() @@ -4095,7 +4106,7 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ Ok(42) } - let ext = Extension::builder() + let ext = Extension::builder("test_ext") .ops(vec![op_foo::decl().disable()]) .build(); let mut runtime = JsRuntime::new(RuntimeOptions { @@ -4125,7 +4136,7 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ Ok(b) } - let ext = Extension::builder() + let ext = Extension::builder("test_ext") .ops(vec![op_sum_take::decl(), op_boomerang::decl()]) .build(); @@ -4193,7 +4204,7 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ Ok(42) } - let ext = Extension::builder() + 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(); @@ -4245,7 +4256,9 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ } let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![Extension::builder().ops(vec![op_test::decl()]).build()], + extensions: vec![Extension::builder("test_ext") + .ops(vec![op_test::decl()]) + .build()], ..Default::default() }); let realm = runtime.create_realm().unwrap(); @@ -4275,7 +4288,9 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ let mut runtime = JsRuntime::new(RuntimeOptions { startup_snapshot: Some(Snapshot::Boxed(snapshot)), - extensions: vec![Extension::builder().ops(vec![op_test::decl()]).build()], + extensions: vec![Extension::builder("test_ext") + .ops(vec![op_test::decl()]) + .build()], ..Default::default() }); let realm = runtime.create_realm().unwrap(); @@ -4304,7 +4319,9 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({ } let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![Extension::builder().ops(vec![op_test::decl()]).build()], + extensions: vec![Extension::builder("test_ext") + .ops(vec![op_test::decl()]) + .build()], get_error_class_fn: Some(&|error| { crate::error::get_custom_error_class(error).unwrap() }), |