summaryrefslogtreecommitdiff
path: root/core/runtime.rs
diff options
context:
space:
mode:
authorAaron O'Mullan <aaron.omullan@gmail.com>2021-04-28 18:41:50 +0200
committerGitHub <noreply@github.com>2021-04-28 18:41:50 +0200
commit0260b488fbba9a43c64641428d3603b8761067a4 (patch)
tree66ce487f9241a3b91942dd048c7e43cb192bf9e8 /core/runtime.rs
parentb28f9445aae85dbf86033300cfcb55e404529a23 (diff)
core: introduce extensions (#9800)
Extensions allow declarative extensions to "JsRuntime" (ops, state, JS or middleware). This allows for: - `op_crates` to be plug-and-play & self-contained, reducing complexity leaked to consumers - op middleware (like metrics_op) to be opt-in and for new middleware (unstable, tracing,...) - `MainWorker` and `WebWorker` to be composable, allowing users to extend workers with their ops whilst benefiting from the other infrastructure (inspector, etc...) In short extensions improve deno's modularity, reducing complexity and leaky abstractions for embedders and the internal codebase.
Diffstat (limited to 'core/runtime.rs')
-rw-r--r--core/runtime.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/core/runtime.rs b/core/runtime.rs
index 1981df5f3..51b231eb0 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -20,6 +20,8 @@ use crate::modules::NoopModuleLoader;
use crate::modules::PrepareLoadFuture;
use crate::modules::RecursiveModuleLoad;
use crate::ops::*;
+use crate::Extension;
+use crate::OpMiddlewareFn;
use crate::OpPayload;
use crate::OpResponse;
use crate::OpState;
@@ -84,6 +86,7 @@ pub struct JsRuntime {
snapshot_creator: Option<v8::SnapshotCreator>,
has_snapshotted: bool,
allocations: IsolateAllocations,
+ extensions: Vec<Extension>,
}
struct DynImportModEvaluate {
@@ -189,6 +192,10 @@ pub struct RuntimeOptions {
/// executed tries to load modules.
pub module_loader: Option<Rc<dyn ModuleLoader>>,
+ /// JsRuntime extensions, not to be confused with ES modules
+ /// these are sets of ops and other JS code to be initialized.
+ pub extensions: Vec<Extension>,
+
/// V8 snapshot that should be loaded on startup.
///
/// Currently can't be used with `will_snapshot`.
@@ -303,6 +310,7 @@ impl JsRuntime {
snapshot_creator: maybe_snapshot_creator,
has_snapshotted: false,
allocations: IsolateAllocations::default(),
+ extensions: options.extensions,
};
if !has_startup_snapshot {
@@ -357,6 +365,57 @@ impl JsRuntime {
.unwrap();
}
+ /// Initializes JS of provided Extensions
+ // NOTE: this will probably change when streamlining snapshot flow
+ pub fn init_extension_js(&mut self) -> Result<(), AnyError> {
+ // Take extensions to avoid double-borrow
+ let mut extensions: Vec<Extension> = std::mem::take(&mut self.extensions);
+ for m in extensions.iter_mut() {
+ let js_files = m.init_js();
+ for (filename, source) in js_files {
+ // TODO(@AaronO): use JsRuntime::execute_static() here to move src off heap
+ self.execute(filename, source)?;
+ }
+ }
+ // Restore extensions
+ self.extensions = extensions;
+
+ Ok(())
+ }
+
+ /// Initializes ops of provided Extensions
+ // NOTE: this will probably change when streamlining snapshot flow
+ pub fn init_extension_ops(&mut self) -> Result<(), AnyError> {
+ let op_state = self.op_state();
+ // Take extensions to avoid double-borrow
+ let mut extensions: Vec<Extension> = std::mem::take(&mut self.extensions);
+
+ // Middleware
+ let middleware: Vec<Box<OpMiddlewareFn>> = extensions
+ .iter_mut()
+ .filter_map(|e| e.init_middleware())
+ .collect();
+ // macroware wraps an opfn in all the middleware
+ let macroware =
+ move |name, opfn| middleware.iter().fold(opfn, |opfn, m| m(name, opfn));
+
+ // Register ops
+ for e in extensions.iter_mut() {
+ e.init_state(&mut op_state.borrow_mut())?;
+ // Register each op after middlewaring it
+ let mut ops = e.init_ops().unwrap_or_default();
+ for (name, opfn) in ops {
+ self.register_op(name, macroware(name, opfn));
+ }
+ }
+ // Sync ops cache
+ self.sync_ops_cache();
+ // Restore extensions
+ self.extensions = extensions;
+
+ Ok(())
+ }
+
/// Grabs a reference to core.js' handleAsyncMsgFromRust
fn init_recv_cb(&mut self) {
let scope = &mut self.handle_scope();