From 0260b488fbba9a43c64641428d3603b8761067a4 Mon Sep 17 00:00:00 2001 From: Aaron O'Mullan Date: Wed, 28 Apr 2021 18:41:50 +0200 Subject: [PATCH] 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. --- cli/tests/unit/metrics_test.ts | 9 + core/extensions.rs | 105 ++++++++ core/lib.rs | 4 + core/runtime.rs | 59 +++++ op_crates/console/lib.rs | 24 +- op_crates/crypto/lib.rs | 31 ++- op_crates/fetch/lib.rs | 81 +++---- op_crates/file/lib.rs | 47 ++-- op_crates/timers/lib.rs | 35 ++- op_crates/url/benches/url_ops.rs | 22 +- op_crates/url/lib.rs | 33 ++- op_crates/web/lib.rs | 53 ++-- op_crates/webgpu/lib.rs | 360 +++++++++++++++++++++++++-- op_crates/webidl/lib.rs | 11 +- op_crates/websocket/lib.rs | 40 ++- runtime/build.rs | 31 ++- runtime/metrics.rs | 45 ++++ runtime/ops/crypto.rs | 18 -- runtime/ops/fetch.rs | 40 --- runtime/ops/file.rs | 23 -- runtime/ops/mod.rs | 7 - runtime/ops/runtime.rs | 32 --- runtime/ops/timers.rs | 28 --- runtime/ops/url.rs | 14 -- runtime/ops/webgpu.rs | 405 ------------------------------- runtime/ops/websocket.rs | 33 --- runtime/web_worker.rs | 53 ++-- runtime/worker.rs | 49 ++-- 28 files changed, 857 insertions(+), 835 deletions(-) create mode 100644 core/extensions.rs delete mode 100644 runtime/ops/crypto.rs delete mode 100644 runtime/ops/fetch.rs delete mode 100644 runtime/ops/file.rs delete mode 100644 runtime/ops/timers.rs delete mode 100644 runtime/ops/url.rs delete mode 100644 runtime/ops/webgpu.rs delete mode 100644 runtime/ops/websocket.rs diff --git a/cli/tests/unit/metrics_test.ts b/cli/tests/unit/metrics_test.ts index 9fa37e99bd..25c63dbc16 100644 --- a/cli/tests/unit/metrics_test.ts +++ b/cli/tests/unit/metrics_test.ts @@ -69,3 +69,12 @@ unitTest( assert(metrics.opsDispatchedAsync === metrics.opsCompletedAsync); }, ); + +// Test that ops from op_crates have metrics (via OpMiddleware) +unitTest(function metricsForOpCrates(): void { + const _ = new URL("https://deno.land"); + + const m1 = Deno.metrics().ops["op_url_parse"]; + assert(m1.opsDispatched > 0); + assert(m1.opsCompleted > 0); +}); diff --git a/core/extensions.rs b/core/extensions.rs new file mode 100644 index 0000000000..eb6f6f719c --- /dev/null +++ b/core/extensions.rs @@ -0,0 +1,105 @@ +use crate::error::AnyError; +use crate::{OpFn, OpState}; + +pub type SourcePair = (&'static str, &'static str); +pub type OpPair = (&'static str, Box); +pub type OpMiddlewareFn = dyn Fn(&'static str, Box) -> Box; +pub type OpStateFn = dyn Fn(&mut OpState) -> Result<(), AnyError>; + +#[derive(Default)] +pub struct Extension { + js_files: Option>, + ops: Option>, + opstate_fn: Option>, + middleware_fn: Option>, + 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 { + /// 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 { + match &self.js_files { + Some(files) => files.clone(), + None => vec![], + } + } + + /// Called at JsRuntime startup to initialize ops in the isolate. + pub(crate) fn init_ops(&mut self) -> Option> { + // TODO(@AaronO): maybe make op registration idempotent + if self.initialized { + panic!("init_ops called twice: not idempotent or correct"); + } + self.initialized = true; + + self.ops.take() + } + + /// Allows setting up the initial op-state of an isolate at startup. + pub(crate) fn init_state(&self, state: &mut OpState) -> Result<(), AnyError> { + match &self.opstate_fn { + Some(ofn) => ofn(state), + None => Ok(()), + } + } + + /// init_middleware lets us middleware op registrations, it's called before init_ops + pub(crate) fn init_middleware(&mut self) -> Option> { + self.middleware_fn.take() + } +} + +/// Helps embed JS files in an extension. Returns Vec<(&'static str, &'static str)> +/// representing the filename and source code. +/// +/// Example: +/// ```ignore +/// include_js_files!( +/// prefix "deno:op_crates/hello", +/// "01_hello.js", +/// "02_goodbye.js", +/// ) +/// ``` +#[macro_export] +macro_rules! include_js_files { + (prefix $prefix:literal, $($file:literal,)+) => { + vec![ + $(( + concat!($prefix, "/", $file), + include_str!($file), + ),)+ + ] + }; +} diff --git a/core/lib.rs b/core/lib.rs index 9b4ba230b7..37055bcc8d 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -3,6 +3,7 @@ mod async_cancel; mod async_cell; mod bindings; pub mod error; +mod extensions; mod flags; mod gotham_state; mod module_specifier; @@ -75,6 +76,9 @@ pub use crate::runtime::JsErrorCreateFn; pub use crate::runtime::JsRuntime; pub use crate::runtime::RuntimeOptions; pub use crate::runtime::Snapshot; +// pub use crate::runtime_modules::include_js_files!; +pub use crate::extensions::Extension; +pub use crate::extensions::OpMiddlewareFn; pub use crate::zero_copy_buf::ZeroCopyBuf; pub fn v8_version() -> &'static str { diff --git a/core/runtime.rs b/core/runtime.rs index 1981df5f30..51b231eb0c 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, has_snapshotted: bool, allocations: IsolateAllocations, + extensions: Vec, } struct DynImportModEvaluate { @@ -189,6 +192,10 @@ pub struct RuntimeOptions { /// executed tries to load modules. pub module_loader: Option>, + /// JsRuntime extensions, not to be confused with ES modules + /// these are sets of ops and other JS code to be initialized. + pub extensions: Vec, + /// 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 = 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 = std::mem::take(&mut self.extensions); + + // Middleware + let middleware: Vec> = 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(); diff --git a/op_crates/console/lib.rs b/op_crates/console/lib.rs index a972f62129..4d6a213f28 100644 --- a/op_crates/console/lib.rs +++ b/op_crates/console/lib.rs @@ -1,23 +1,15 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_core::JsRuntime; +use deno_core::include_js_files; +use deno_core::Extension; use std::path::PathBuf; -/// Load and execute the javascript code. -pub fn init(isolate: &mut JsRuntime) { - let files = vec![ - ( - "deno:op_crates/console/01_colors.js", - include_str!("01_colors.js"), - ), - ( - "deno:op_crates/console/02_console.js", - include_str!("02_console.js"), - ), - ]; - for (url, source_code) in files { - isolate.execute(url, source_code).unwrap(); - } +pub fn init() -> Extension { + Extension::pure_js(include_js_files!( + prefix "deno:op_crates/console", + "01_colors.js", + "02_console.js", + )) } pub fn get_declaration() -> PathBuf { diff --git a/op_crates/crypto/lib.rs b/op_crates/crypto/lib.rs index 8b4d34a7c8..d5b0a30bc6 100644 --- a/op_crates/crypto/lib.rs +++ b/op_crates/crypto/lib.rs @@ -2,25 +2,36 @@ use deno_core::error::null_opbuf; use deno_core::error::AnyError; -use deno_core::JsRuntime; +use deno_core::include_js_files; +use deno_core::op_sync; +use deno_core::Extension; use deno_core::OpState; use deno_core::ZeroCopyBuf; use rand::rngs::StdRng; use rand::thread_rng; use rand::Rng; +use rand::SeedableRng; use std::path::PathBuf; pub use rand; // Re-export rand -/// Execute this crates' JS source files. -pub fn init(isolate: &mut JsRuntime) { - let files = vec![( - "deno:op_crates/crypto/01_crypto.js", - include_str!("01_crypto.js"), - )]; - for (url, source_code) in files { - isolate.execute(url, source_code).unwrap(); - } +pub fn init(maybe_seed: Option) -> Extension { + Extension::with_ops( + include_js_files!( + prefix "deno:op_crates/crypto", + "01_crypto.js", + ), + vec![( + "op_crypto_get_random_values", + op_sync(op_crypto_get_random_values), + )], + Some(Box::new(move |state| { + if let Some(seed) = maybe_seed { + state.put(StdRng::seed_from_u64(seed)); + } + Ok(()) + })), + ) } pub fn op_crypto_get_random_values( diff --git a/op_crates/fetch/lib.rs b/op_crates/fetch/lib.rs index ad96dea462..7033a416c8 100644 --- a/op_crates/fetch/lib.rs +++ b/op_crates/fetch/lib.rs @@ -8,12 +8,15 @@ use deno_core::error::AnyError; 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_async; +use deno_core::op_sync; use deno_core::url::Url; use deno_core::AsyncRefCell; use deno_core::CancelFuture; use deno_core::CancelHandle; use deno_core::CancelTryFuture; -use deno_core::JsRuntime; +use deno_core::Extension; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -49,49 +52,41 @@ use tokio_util::io::StreamReader; pub use reqwest; // Re-export reqwest -/// Execute this crates' JS source files. -pub fn init(isolate: &mut JsRuntime) { - let files = vec![ - ( - "deno:op_crates/fetch/01_fetch_util.js", - include_str!("01_fetch_util.js"), +pub fn init( + user_agent: String, + ca_data: Option>, +) -> Extension { + Extension::with_ops( + include_js_files!( + prefix "deno:op_crates/fetch", + "01_fetch_util.js", + "11_streams.js", + "20_headers.js", + "21_formdata.js", + "22_body.js", + "22_http_client.js", + "23_request.js", + "23_response.js", + "26_fetch.js", ), - ( - "deno:op_crates/fetch/11_streams.js", - include_str!("11_streams.js"), - ), - ( - "deno:op_crates/fetch/20_headers.js", - include_str!("20_headers.js"), - ), - ( - "deno:op_crates/fetch/21_formdata.js", - include_str!("21_formdata.js"), - ), - ( - "deno:op_crates/fetch/22_body.js", - include_str!("22_body.js"), - ), - ( - "deno:op_crates/fetch/22_http_client.js", - include_str!("22_http_client.js"), - ), - ( - "deno:op_crates/fetch/23_request.js", - include_str!("23_request.js"), - ), - ( - "deno:op_crates/fetch/23_response.js", - include_str!("23_response.js"), - ), - ( - "deno:op_crates/fetch/26_fetch.js", - include_str!("26_fetch.js"), - ), - ]; - for (url, source_code) in files { - isolate.execute(url, source_code).expect(url); - } + 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.put::({ + create_http_client(user_agent.clone(), ca_data.clone()).unwrap() + }); + state.put::(HttpClientDefaults { + ca_data: ca_data.clone(), + user_agent: user_agent.clone(), + }); + Ok(()) + })), + ) } pub struct HttpClientDefaults { diff --git a/op_crates/file/lib.rs b/op_crates/file/lib.rs index ea519046f1..19bb8b19b9 100644 --- a/op_crates/file/lib.rs +++ b/op_crates/file/lib.rs @@ -2,8 +2,10 @@ use deno_core::error::null_opbuf; use deno_core::error::AnyError; +use deno_core::include_js_files; +use deno_core::op_sync; use deno_core::url::Url; -use deno_core::JsRuntime; +use deno_core::Extension; use deno_core::ModuleSpecifier; use deno_core::ZeroCopyBuf; use std::collections::HashMap; @@ -82,22 +84,35 @@ pub fn op_file_revoke_object_url( Ok(()) } -/// Load and execute the javascript code. -pub fn init(isolate: &mut JsRuntime) { - let files = vec![ - ("deno:op_crates/file/01_file.js", include_str!("01_file.js")), - ( - "deno:op_crates/file/02_filereader.js", - include_str!("02_filereader.js"), +pub fn init( + blob_url_store: BlobUrlStore, + maybe_location: Option, +) -> Extension { + Extension::with_ops( + include_js_files!( + prefix "deno:op_crates/file", + "01_file.js", + "02_filereader.js", + "03_blob_url.js", ), - ( - "deno:op_crates/file/03_blob_url.js", - include_str!("03_blob_url.js"), - ), - ]; - for (url, source_code) in files { - isolate.execute(url, source_code).unwrap(); - } + vec![ + ( + "op_file_create_object_url", + op_sync(op_file_create_object_url), + ), + ( + "op_file_revoke_object_url", + op_sync(op_file_revoke_object_url), + ), + ], + Some(Box::new(move |state| { + state.put(blob_url_store.clone()); + if let Some(location) = maybe_location.clone() { + state.put(Location(location)); + } + Ok(()) + })), + ) } pub fn get_declaration() -> PathBuf { diff --git a/op_crates/timers/lib.rs b/op_crates/timers/lib.rs index 047b6923c5..6359b20f0c 100644 --- a/op_crates/timers/lib.rs +++ b/op_crates/timers/lib.rs @@ -13,6 +13,9 @@ use deno_core::futures; use deno_core::futures::channel::oneshot; use deno_core::futures::FutureExt; use deno_core::futures::TryFutureExt; +use deno_core::op_async; +use deno_core::op_sync; +use deno_core::Extension; use deno_core::OpState; use deno_core::ZeroCopyBuf; use std::cell::RefCell; @@ -28,12 +31,34 @@ pub trait TimersPermission { fn check_unstable(&self, state: &OpState, api_name: &'static str); } -pub fn init(rt: &mut deno_core::JsRuntime) { - rt.execute( - "deno:op_crates/timers/01_timers.js", - include_str!("01_timers.js"), +pub struct NoTimersPermission; + +impl TimersPermission for NoTimersPermission { + fn allow_hrtime(&mut self) -> bool { + false + } + fn check_unstable(&self, _: &OpState, _: &'static str) {} +} + +pub fn init() -> Extension { + Extension::with_ops( + vec![( + "deno:op_crates/timers/01_timers.js", + include_str!("01_timers.js"), + )], + 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.put(GlobalTimer::default()); + state.put(StartTime::now()); + Ok(()) + })), ) - .unwrap(); } pub type StartTime = Instant; diff --git a/op_crates/url/benches/url_ops.rs b/op_crates/url/benches/url_ops.rs index 0f584de900..8d5498540f 100644 --- a/op_crates/url/benches/url_ops.rs +++ b/op_crates/url/benches/url_ops.rs @@ -1,21 +1,14 @@ use bencher::{benchmark_group, benchmark_main, Bencher}; -use deno_core::op_sync; use deno_core::v8; use deno_core::JsRuntime; +use deno_core::RuntimeOptions; fn create_js_runtime() -> JsRuntime { - let mut runtime = JsRuntime::new(Default::default()); - runtime.register_op("op_url_parse", op_sync(deno_url::op_url_parse)); - runtime.register_op( - "op_url_parse_search_params", - op_sync(deno_url::op_url_parse_search_params), - ); - runtime.register_op( - "op_url_stringify_search_params", - op_sync(deno_url::op_url_stringify_search_params), - ); - runtime.sync_ops_cache(); + let mut runtime = JsRuntime::new(RuntimeOptions { + extensions: vec![deno_url::init()], + ..Default::default() + }); runtime .execute( @@ -23,7 +16,10 @@ fn create_js_runtime() -> JsRuntime { "globalThis.__bootstrap = (globalThis.__bootstrap || {});", ) .unwrap(); - deno_url::init(&mut runtime); + + runtime.init_extension_js().unwrap(); + runtime.init_extension_ops().unwrap(); + runtime .execute("setup", "const { URL } = globalThis.__bootstrap.url;") .unwrap(); diff --git a/op_crates/url/lib.rs b/op_crates/url/lib.rs index 04663e411a..49e34c47d5 100644 --- a/op_crates/url/lib.rs +++ b/op_crates/url/lib.rs @@ -4,16 +4,39 @@ use deno_core::error::generic_error; use deno_core::error::type_error; use deno_core::error::uri_error; use deno_core::error::AnyError; +use deno_core::include_js_files; +use deno_core::op_sync; use deno_core::url::form_urlencoded; use deno_core::url::quirks; use deno_core::url::Url; -use deno_core::JsRuntime; +use deno_core::Extension; use deno_core::ZeroCopyBuf; use serde::Deserialize; use serde::Serialize; use std::panic::catch_unwind; use std::path::PathBuf; +pub fn init() -> Extension { + Extension::with_ops( + include_js_files!( + prefix "deno:op_crates/url", + "00_url.js", + ), + vec![ + ("op_url_parse", op_sync(op_url_parse)), + ( + "op_url_parse_search_params", + op_sync(op_url_parse_search_params), + ), + ( + "op_url_stringify_search_params", + op_sync(op_url_stringify_search_params), + ), + ], + None, + ) +} + #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct UrlParseArgs { @@ -146,14 +169,6 @@ pub fn op_url_stringify_search_params( Ok(search) } -/// Load and execute the javascript code. -pub fn init(isolate: &mut JsRuntime) { - let files = vec![("deno:op_crates/url/00_url.js", include_str!("00_url.js"))]; - for (url, source_code) in files { - isolate.execute(url, source_code).unwrap(); - } -} - pub fn get_declaration() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_url.d.ts") } diff --git a/op_crates/web/lib.rs b/op_crates/web/lib.rs index a609dc4cd3..7fd8221eb7 100644 --- a/op_crates/web/lib.rs +++ b/op_crates/web/lib.rs @@ -1,47 +1,22 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_core::JsRuntime; +use deno_core::include_js_files; +use deno_core::Extension; use std::path::PathBuf; /// Load and execute the javascript code. -pub fn init(isolate: &mut JsRuntime) { - let files = vec![ - ( - "deno:op_crates/web/00_infra.js", - include_str!("00_infra.js"), - ), - ( - "deno:op_crates/web/01_dom_exception.js", - include_str!("01_dom_exception.js"), - ), - ( - "deno:op_crates/web/01_mimesniff.js", - include_str!("01_mimesniff.js"), - ), - ( - "deno:op_crates/web/02_event.js", - include_str!("02_event.js"), - ), - ( - "deno:op_crates/web/03_abort_signal.js", - include_str!("03_abort_signal.js"), - ), - ( - "deno:op_crates/web/04_global_interfaces.js", - include_str!("04_global_interfaces.js"), - ), - ( - "deno:op_crates/web/08_text_encoding.js", - include_str!("08_text_encoding.js"), - ), - ( - "deno:op_crates/web/12_location.js", - include_str!("12_location.js"), - ), - ]; - for (url, source_code) in files { - isolate.execute(url, source_code).unwrap(); - } +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", + )) } pub fn get_declaration() -> PathBuf { diff --git a/op_crates/webgpu/lib.rs b/op_crates/webgpu/lib.rs index 62ec08ce77..a9cbbb882c 100644 --- a/op_crates/webgpu/lib.rs +++ b/op_crates/webgpu/lib.rs @@ -2,6 +2,11 @@ use deno_core::error::AnyError; use deno_core::error::{bad_resource_id, not_supported}; +use deno_core::include_js_files; +use deno_core::op_async; +use deno_core::op_sync; +use deno_core::Extension; +use deno_core::OpFn; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; @@ -89,21 +94,23 @@ impl Resource for WebGpuQuerySet { } } -/// Execute this crates' JS source files. -pub fn init(isolate: &mut deno_core::JsRuntime) { - let files = vec![ - ( - "deno:op_crates/webgpu/01_webgpu.js", - include_str!("01_webgpu.js"), +pub fn init(unstable: bool) -> Extension { + Extension::with_ops( + include_js_files!( + prefix "deno:op_crates/webgpu", + "01_webgpu.js", + "02_idl_types.js", ), - ( - "deno:op_crates/webgpu/02_idl_types.js", - include_str!("02_idl_types.js"), - ), - ]; - for (url, source_code) in files { - isolate.execute(url, source_code).unwrap(); - } + declare_webgpu_ops(), + Some(Box::new(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(()) + })), + ) } pub fn get_declaration() -> PathBuf { @@ -537,3 +544,328 @@ pub fn op_webgpu_create_query_set( Ok(WebGpuResult::rid_err(rid, maybe_err)) } + +fn declare_webgpu_ops() -> Vec<(&'static str, Box)> { + vec![ + // Request device/adapter + ( + "op_webgpu_request_adapter", + op_async(op_webgpu_request_adapter), + ), + ( + "op_webgpu_request_device", + op_async(op_webgpu_request_device), + ), + // Query Set + ( + "op_webgpu_create_query_set", + op_sync(op_webgpu_create_query_set), + ), + // buffer + ( + "op_webgpu_create_buffer", + op_sync(buffer::op_webgpu_create_buffer), + ), + ( + "op_webgpu_buffer_get_mapped_range", + op_sync(buffer::op_webgpu_buffer_get_mapped_range), + ), + ( + "op_webgpu_buffer_unmap", + op_sync(buffer::op_webgpu_buffer_unmap), + ), + // buffer async + ( + "op_webgpu_buffer_get_map_async", + op_async(buffer::op_webgpu_buffer_get_map_async), + ), + // remaining sync ops + + // texture + ( + "op_webgpu_create_texture", + op_sync(texture::op_webgpu_create_texture), + ), + ( + "op_webgpu_create_texture_view", + op_sync(texture::op_webgpu_create_texture_view), + ), + // sampler + ( + "op_webgpu_create_sampler", + op_sync(sampler::op_webgpu_create_sampler), + ), + // binding + ( + "op_webgpu_create_bind_group_layout", + op_sync(binding::op_webgpu_create_bind_group_layout), + ), + ( + "op_webgpu_create_pipeline_layout", + op_sync(binding::op_webgpu_create_pipeline_layout), + ), + ( + "op_webgpu_create_bind_group", + op_sync(binding::op_webgpu_create_bind_group), + ), + // pipeline + ( + "op_webgpu_create_compute_pipeline", + op_sync(pipeline::op_webgpu_create_compute_pipeline), + ), + ( + "op_webgpu_compute_pipeline_get_bind_group_layout", + op_sync(pipeline::op_webgpu_compute_pipeline_get_bind_group_layout), + ), + ( + "op_webgpu_create_render_pipeline", + op_sync(pipeline::op_webgpu_create_render_pipeline), + ), + ( + "op_webgpu_render_pipeline_get_bind_group_layout", + op_sync(pipeline::op_webgpu_render_pipeline_get_bind_group_layout), + ), + // command_encoder + ( + "op_webgpu_create_command_encoder", + op_sync(command_encoder::op_webgpu_create_command_encoder), + ), + ( + "op_webgpu_command_encoder_begin_render_pass", + op_sync(command_encoder::op_webgpu_command_encoder_begin_render_pass), + ), + ( + "op_webgpu_command_encoder_begin_compute_pass", + op_sync(command_encoder::op_webgpu_command_encoder_begin_compute_pass), + ), + ( + "op_webgpu_command_encoder_copy_buffer_to_buffer", + op_sync(command_encoder::op_webgpu_command_encoder_copy_buffer_to_buffer), + ), + ( + "op_webgpu_command_encoder_copy_buffer_to_texture", + op_sync( + command_encoder::op_webgpu_command_encoder_copy_buffer_to_texture, + ), + ), + ( + "op_webgpu_command_encoder_copy_texture_to_buffer", + op_sync( + command_encoder::op_webgpu_command_encoder_copy_texture_to_buffer, + ), + ), + ( + "op_webgpu_command_encoder_copy_texture_to_texture", + op_sync( + command_encoder::op_webgpu_command_encoder_copy_texture_to_texture, + ), + ), + ( + "op_webgpu_command_encoder_push_debug_group", + op_sync(command_encoder::op_webgpu_command_encoder_push_debug_group), + ), + ( + "op_webgpu_command_encoder_pop_debug_group", + op_sync(command_encoder::op_webgpu_command_encoder_pop_debug_group), + ), + ( + "op_webgpu_command_encoder_insert_debug_marker", + op_sync(command_encoder::op_webgpu_command_encoder_insert_debug_marker), + ), + ( + "op_webgpu_command_encoder_write_timestamp", + op_sync(command_encoder::op_webgpu_command_encoder_write_timestamp), + ), + ( + "op_webgpu_command_encoder_resolve_query_set", + op_sync(command_encoder::op_webgpu_command_encoder_resolve_query_set), + ), + ( + "op_webgpu_command_encoder_finish", + op_sync(command_encoder::op_webgpu_command_encoder_finish), + ), + // render_pass + ( + "op_webgpu_render_pass_set_viewport", + op_sync(render_pass::op_webgpu_render_pass_set_viewport), + ), + ( + "op_webgpu_render_pass_set_scissor_rect", + op_sync(render_pass::op_webgpu_render_pass_set_scissor_rect), + ), + ( + "op_webgpu_render_pass_set_blend_color", + op_sync(render_pass::op_webgpu_render_pass_set_blend_color), + ), + ( + "op_webgpu_render_pass_set_stencil_reference", + op_sync(render_pass::op_webgpu_render_pass_set_stencil_reference), + ), + ( + "op_webgpu_render_pass_begin_pipeline_statistics_query", + op_sync( + render_pass::op_webgpu_render_pass_begin_pipeline_statistics_query, + ), + ), + ( + "op_webgpu_render_pass_end_pipeline_statistics_query", + op_sync(render_pass::op_webgpu_render_pass_end_pipeline_statistics_query), + ), + ( + "op_webgpu_render_pass_write_timestamp", + op_sync(render_pass::op_webgpu_render_pass_write_timestamp), + ), + ( + "op_webgpu_render_pass_execute_bundles", + op_sync(render_pass::op_webgpu_render_pass_execute_bundles), + ), + ( + "op_webgpu_render_pass_end_pass", + op_sync(render_pass::op_webgpu_render_pass_end_pass), + ), + ( + "op_webgpu_render_pass_set_bind_group", + op_sync(render_pass::op_webgpu_render_pass_set_bind_group), + ), + ( + "op_webgpu_render_pass_push_debug_group", + op_sync(render_pass::op_webgpu_render_pass_push_debug_group), + ), + ( + "op_webgpu_render_pass_pop_debug_group", + op_sync(render_pass::op_webgpu_render_pass_pop_debug_group), + ), + ( + "op_webgpu_render_pass_insert_debug_marker", + op_sync(render_pass::op_webgpu_render_pass_insert_debug_marker), + ), + ( + "op_webgpu_render_pass_set_pipeline", + op_sync(render_pass::op_webgpu_render_pass_set_pipeline), + ), + ( + "op_webgpu_render_pass_set_index_buffer", + op_sync(render_pass::op_webgpu_render_pass_set_index_buffer), + ), + ( + "op_webgpu_render_pass_set_vertex_buffer", + op_sync(render_pass::op_webgpu_render_pass_set_vertex_buffer), + ), + ( + "op_webgpu_render_pass_draw", + op_sync(render_pass::op_webgpu_render_pass_draw), + ), + ( + "op_webgpu_render_pass_draw_indexed", + op_sync(render_pass::op_webgpu_render_pass_draw_indexed), + ), + ( + "op_webgpu_render_pass_draw_indirect", + op_sync(render_pass::op_webgpu_render_pass_draw_indirect), + ), + ( + "op_webgpu_render_pass_draw_indexed_indirect", + op_sync(render_pass::op_webgpu_render_pass_draw_indexed_indirect), + ), + // compute_pass + ( + "op_webgpu_compute_pass_set_pipeline", + op_sync(compute_pass::op_webgpu_compute_pass_set_pipeline), + ), + ( + "op_webgpu_compute_pass_dispatch", + op_sync(compute_pass::op_webgpu_compute_pass_dispatch), + ), + ( + "op_webgpu_compute_pass_dispatch_indirect", + op_sync(compute_pass::op_webgpu_compute_pass_dispatch_indirect), + ), + ( + "op_webgpu_compute_pass_end_pass", + op_sync(compute_pass::op_webgpu_compute_pass_end_pass), + ), + ( + "op_webgpu_compute_pass_set_bind_group", + op_sync(compute_pass::op_webgpu_compute_pass_set_bind_group), + ), + ( + "op_webgpu_compute_pass_push_debug_group", + op_sync(compute_pass::op_webgpu_compute_pass_push_debug_group), + ), + ( + "op_webgpu_compute_pass_pop_debug_group", + op_sync(compute_pass::op_webgpu_compute_pass_pop_debug_group), + ), + ( + "op_webgpu_compute_pass_insert_debug_marker", + op_sync(compute_pass::op_webgpu_compute_pass_insert_debug_marker), + ), + // bundle + ( + "op_webgpu_create_render_bundle_encoder", + op_sync(bundle::op_webgpu_create_render_bundle_encoder), + ), + ( + "op_webgpu_render_bundle_encoder_finish", + op_sync(bundle::op_webgpu_render_bundle_encoder_finish), + ), + ( + "op_webgpu_render_bundle_encoder_set_bind_group", + op_sync(bundle::op_webgpu_render_bundle_encoder_set_bind_group), + ), + ( + "op_webgpu_render_bundle_encoder_push_debug_group", + op_sync(bundle::op_webgpu_render_bundle_encoder_push_debug_group), + ), + ( + "op_webgpu_render_bundle_encoder_pop_debug_group", + op_sync(bundle::op_webgpu_render_bundle_encoder_pop_debug_group), + ), + ( + "op_webgpu_render_bundle_encoder_insert_debug_marker", + op_sync(bundle::op_webgpu_render_bundle_encoder_insert_debug_marker), + ), + ( + "op_webgpu_render_bundle_encoder_set_pipeline", + op_sync(bundle::op_webgpu_render_bundle_encoder_set_pipeline), + ), + ( + "op_webgpu_render_bundle_encoder_set_index_buffer", + op_sync(bundle::op_webgpu_render_bundle_encoder_set_index_buffer), + ), + ( + "op_webgpu_render_bundle_encoder_set_vertex_buffer", + op_sync(bundle::op_webgpu_render_bundle_encoder_set_vertex_buffer), + ), + ( + "op_webgpu_render_bundle_encoder_draw", + op_sync(bundle::op_webgpu_render_bundle_encoder_draw), + ), + ( + "op_webgpu_render_bundle_encoder_draw_indexed", + op_sync(bundle::op_webgpu_render_bundle_encoder_draw_indexed), + ), + ( + "op_webgpu_render_bundle_encoder_draw_indirect", + op_sync(bundle::op_webgpu_render_bundle_encoder_draw_indirect), + ), + // queue + ( + "op_webgpu_queue_submit", + op_sync(queue::op_webgpu_queue_submit), + ), + ( + "op_webgpu_write_buffer", + op_sync(queue::op_webgpu_write_buffer), + ), + ( + "op_webgpu_write_texture", + op_sync(queue::op_webgpu_write_texture), + ), + // shader + ( + "op_webgpu_create_shader_module", + op_sync(shader::op_webgpu_create_shader_module), + ), + ] +} diff --git a/op_crates/webidl/lib.rs b/op_crates/webidl/lib.rs index 7e617c7a76..a1a404dbdf 100644 --- a/op_crates/webidl/lib.rs +++ b/op_crates/webidl/lib.rs @@ -1,14 +1,11 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_core::JsRuntime; +use deno_core::Extension; /// Load and execute the javascript code. -pub fn init(isolate: &mut JsRuntime) { - let files = vec![( +pub fn init() -> Extension { + Extension::pure_js(vec![( "deno:op_crates/webidl/00_webidl.js", include_str!("00_webidl.js"), - )]; - for (url, source_code) in files { - isolate.execute(url, source_code).unwrap(); - } + )]) } diff --git a/op_crates/websocket/lib.rs b/op_crates/websocket/lib.rs index a2454b8e33..c682c6b2fb 100644 --- a/op_crates/websocket/lib.rs +++ b/op_crates/websocket/lib.rs @@ -9,11 +9,14 @@ 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_async; +use deno_core::op_sync; use deno_core::url; use deno_core::AsyncRefCell; use deno_core::CancelFuture; use deno_core::CancelHandle; -use deno_core::JsRuntime; +use deno_core::Extension; use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; @@ -333,14 +336,33 @@ pub async fn op_ws_next_event( Ok(res) } -/// Load and execute the javascript code. -pub fn init(isolate: &mut JsRuntime) { - isolate - .execute( - "deno:op_crates/websocket/01_websocket.js", - include_str!("01_websocket.js"), - ) - .unwrap(); +pub fn init( + user_agent: String, + ca_data: Option>, +) -> Extension { + Extension::with_ops( + include_js_files!( + prefix "deno:op_crates/websocket", + "01_websocket.js", + ), + vec![ + ( + "op_ws_check_permission", + op_sync(op_ws_check_permission::

), + ), + ("op_ws_create", op_async(op_ws_create::

)), + ("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.put::(WsUserAgent(user_agent.clone())); + if let Some(ca_data) = ca_data.clone() { + state.put::(WsCaData(ca_data)); + } + Ok(()) + })), + ) } pub fn get_declaration() -> PathBuf { diff --git a/runtime/build.rs b/runtime/build.rs index efa9494939..591ebaab77 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -1,5 +1,6 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +use deno_core::Extension; use deno_core::JsRuntime; use deno_core::RuntimeOptions; use std::env; @@ -13,17 +14,8 @@ fn create_snapshot( snapshot_path: &Path, files: Vec, ) { - // Initialization order matters. - deno_webidl::init(&mut js_runtime); - deno_console::init(&mut js_runtime); - deno_timers::init(&mut js_runtime); - deno_url::init(&mut js_runtime); - deno_web::init(&mut js_runtime); - deno_file::init(&mut js_runtime); - deno_fetch::init(&mut js_runtime); - deno_websocket::init(&mut js_runtime); - deno_crypto::init(&mut js_runtime); - deno_webgpu::init(&mut js_runtime); + js_runtime.init_extension_js().unwrap(); + // TODO(nayeemrmn): https://github.com/rust-lang/cargo/issues/3946 to get the // workspace root. let display_root = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap(); @@ -47,8 +39,25 @@ fn create_snapshot( } fn create_runtime_snapshot(snapshot_path: &Path, files: Vec) { + let extensions: Vec = vec![ + deno_webidl::init(), + deno_console::init(), + deno_url::init(), + deno_web::init(), + deno_file::init(Default::default(), Default::default()), + deno_fetch::init::("".to_owned(), None), + deno_websocket::init::( + "".to_owned(), + None, + ), + deno_crypto::init(None), + deno_webgpu::init(false), + deno_timers::init::(), + ]; + let js_runtime = JsRuntime::new(RuntimeOptions { will_snapshot: true, + extensions, ..Default::default() }); create_snapshot(js_runtime, snapshot_path, files); diff --git a/runtime/metrics.rs b/runtime/metrics.rs index a80ec5e21e..efc2cb4571 100644 --- a/runtime/metrics.rs +++ b/runtime/metrics.rs @@ -1,6 +1,51 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +use crate::ops::UnstableChecker; +use deno_core::error::AnyError; +use deno_core::op_sync; use deno_core::serde::Serialize; +use deno_core::serde_json::json; +use deno_core::serde_json::Value; +use deno_core::Extension; +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| { + state.put(RuntimeMetrics::default()); + Ok(()) + })), + Some(Box::new(metrics_op)), + ) +} + +#[derive(serde::Serialize)] +struct MetricsReturn { + combined: OpMetrics, + ops: Value, +} + +#[allow(clippy::unnecessary_wraps)] +fn op_metrics( + state: &mut OpState, + _args: (), + _zero_copy: Option, +) -> Result { + let m = state.borrow::(); + let combined = m.combined_metrics(); + let unstable_checker = state.borrow::(); + let maybe_ops = if unstable_checker.unstable { + Some(&m.ops) + } else { + None + }; + Ok(MetricsReturn { + combined, + ops: json!(maybe_ops), + }) +} #[derive(Default, Debug)] pub struct RuntimeMetrics { pub ops: HashMap<&'static str, OpMetrics>, diff --git a/runtime/ops/crypto.rs b/runtime/ops/crypto.rs deleted file mode 100644 index 432cc0185c..0000000000 --- a/runtime/ops/crypto.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_crypto::op_crypto_get_random_values; -use deno_crypto::rand::rngs::StdRng; -use deno_crypto::rand::SeedableRng; - -pub fn init(rt: &mut deno_core::JsRuntime, maybe_seed: Option) { - if let Some(seed) = maybe_seed { - let rng = StdRng::seed_from_u64(seed); - let op_state = rt.op_state(); - let mut state = op_state.borrow_mut(); - state.put::(rng); - } - super::reg_sync( - rt, - "op_crypto_get_random_values", - op_crypto_get_random_values, - ); -} diff --git a/runtime/ops/fetch.rs b/runtime/ops/fetch.rs deleted file mode 100644 index 17656974a3..0000000000 --- a/runtime/ops/fetch.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::permissions::Permissions; -use deno_fetch::reqwest; -use deno_fetch::HttpClientDefaults; - -pub fn init( - rt: &mut deno_core::JsRuntime, - user_agent: String, - ca_data: Option>, -) { - { - let op_state = rt.op_state(); - let mut state = op_state.borrow_mut(); - state.put::({ - deno_fetch::create_http_client(user_agent.clone(), ca_data.clone()) - .unwrap() - }); - state.put::(HttpClientDefaults { - user_agent, - ca_data, - }); - } - super::reg_sync(rt, "op_fetch", deno_fetch::op_fetch::); - super::reg_async(rt, "op_fetch_send", deno_fetch::op_fetch_send); - super::reg_async( - rt, - "op_fetch_request_write", - deno_fetch::op_fetch_request_write, - ); - super::reg_async( - rt, - "op_fetch_response_read", - deno_fetch::op_fetch_response_read, - ); - super::reg_sync( - rt, - "op_create_http_client", - deno_fetch::op_create_http_client::, - ); -} diff --git a/runtime/ops/file.rs b/runtime/ops/file.rs deleted file mode 100644 index 8f471ebbd1..0000000000 --- a/runtime/ops/file.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_core::url::Url; -use deno_file::op_file_create_object_url; -use deno_file::op_file_revoke_object_url; -use deno_file::BlobUrlStore; -use deno_file::Location; - -pub fn init( - rt: &mut deno_core::JsRuntime, - blob_url_store: BlobUrlStore, - maybe_location: Option, -) { - { - let op_state = rt.op_state(); - let mut op_state = op_state.borrow_mut(); - op_state.put(blob_url_store); - if let Some(location) = maybe_location { - op_state.put(Location(location)); - } - } - super::reg_sync(rt, "op_file_create_object_url", op_file_create_object_url); - super::reg_sync(rt, "op_file_revoke_object_url", op_file_revoke_object_url); -} diff --git a/runtime/ops/mod.rs b/runtime/ops/mod.rs index 825950d65e..c46f82af63 100644 --- a/runtime/ops/mod.rs +++ b/runtime/ops/mod.rs @@ -1,8 +1,5 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -pub mod crypto; -pub mod fetch; -pub mod file; pub mod fs; pub mod fs_events; pub mod http; @@ -16,14 +13,10 @@ pub mod plugin; pub mod process; pub mod runtime; pub mod signal; -pub mod timers; pub mod tls; pub mod tty; -pub mod url; mod utils; pub mod web_worker; -pub mod webgpu; -pub mod websocket; pub mod worker_host; use crate::metrics::metrics_op; diff --git a/runtime/ops/runtime.rs b/runtime/ops/runtime.rs index a02bf4548e..7d84fadff6 100644 --- a/runtime/ops/runtime.rs +++ b/runtime/ops/runtime.rs @@ -1,13 +1,8 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::metrics::OpMetrics; -use crate::metrics::RuntimeMetrics; -use crate::ops::UnstableChecker; use crate::permissions::Permissions; use deno_core::error::AnyError; use deno_core::error::Context; -use deno_core::serde_json::json; -use deno_core::serde_json::Value; use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_core::ZeroCopyBuf; @@ -19,7 +14,6 @@ pub fn init(rt: &mut deno_core::JsRuntime, main_module: ModuleSpecifier) { state.put::(main_module); } super::reg_sync(rt, "op_main_module", op_main_module); - super::reg_sync(rt, "op_metrics", op_metrics); } fn op_main_module( @@ -41,32 +35,6 @@ fn op_main_module( Ok(main) } -#[derive(serde::Serialize)] -struct MetricsReturn { - combined: OpMetrics, - ops: Value, -} - -#[allow(clippy::unnecessary_wraps)] -fn op_metrics( - state: &mut OpState, - _args: (), - _zero_copy: Option, -) -> Result { - let m = state.borrow::(); - let combined = m.combined_metrics(); - let unstable_checker = state.borrow::(); - let maybe_ops = if unstable_checker.unstable { - Some(&m.ops) - } else { - None - }; - Ok(MetricsReturn { - combined, - ops: json!(maybe_ops), - }) -} - pub fn ppid() -> i64 { #[cfg(windows)] { diff --git a/runtime/ops/timers.rs b/runtime/ops/timers.rs deleted file mode 100644 index 3401c36f1f..0000000000 --- a/runtime/ops/timers.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::permissions::Permissions; - -pub fn init(rt: &mut deno_core::JsRuntime) { - { - let op_state = rt.op_state(); - let mut state = op_state.borrow_mut(); - state.put(deno_timers::GlobalTimer::default()); - state.put(deno_timers::StartTime::now()); - } - super::reg_sync( - rt, - "op_global_timer_stop", - deno_timers::op_global_timer_stop, - ); - super::reg_sync( - rt, - "op_global_timer_start", - deno_timers::op_global_timer_start, - ); - super::reg_async(rt, "op_global_timer", deno_timers::op_global_timer); - super::reg_sync(rt, "op_now", deno_timers::op_now::); - super::reg_sync( - rt, - "op_sleep_sync", - deno_timers::op_sleep_sync::, - ); -} diff --git a/runtime/ops/url.rs b/runtime/ops/url.rs deleted file mode 100644 index 5168a7242a..0000000000 --- a/runtime/ops/url.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_url::op_url_parse; -use deno_url::op_url_parse_search_params; -use deno_url::op_url_stringify_search_params; - -pub fn init(rt: &mut deno_core::JsRuntime) { - super::reg_sync(rt, "op_url_parse", op_url_parse); - super::reg_sync(rt, "op_url_parse_search_params", op_url_parse_search_params); - super::reg_sync( - rt, - "op_url_stringify_search_params", - op_url_stringify_search_params, - ); -} diff --git a/runtime/ops/webgpu.rs b/runtime/ops/webgpu.rs deleted file mode 100644 index 55c6d18173..0000000000 --- a/runtime/ops/webgpu.rs +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_webgpu::*; - -pub fn init(rt: &mut deno_core::JsRuntime) { - { - let op_state = rt.op_state(); - let mut state = op_state.borrow_mut(); - let unstable_checker = state.borrow::(); - let unstable = unstable_checker.unstable; - state.put(Unstable(unstable)); - } - - super::reg_async(rt, "op_webgpu_request_adapter", op_webgpu_request_adapter); - super::reg_async(rt, "op_webgpu_request_device", op_webgpu_request_device); - super::reg_sync(rt, "op_webgpu_create_query_set", op_webgpu_create_query_set); - - { - // buffer - super::reg_sync( - rt, - "op_webgpu_create_buffer", - buffer::op_webgpu_create_buffer, - ); - super::reg_async( - rt, - "op_webgpu_buffer_get_map_async", - buffer::op_webgpu_buffer_get_map_async, - ); - super::reg_sync( - rt, - "op_webgpu_buffer_get_mapped_range", - buffer::op_webgpu_buffer_get_mapped_range, - ); - super::reg_sync( - rt, - "op_webgpu_buffer_unmap", - buffer::op_webgpu_buffer_unmap, - ); - } - { - // texture - super::reg_sync( - rt, - "op_webgpu_create_texture", - texture::op_webgpu_create_texture, - ); - super::reg_sync( - rt, - "op_webgpu_create_texture_view", - texture::op_webgpu_create_texture_view, - ); - } - { - // sampler - super::reg_sync( - rt, - "op_webgpu_create_sampler", - sampler::op_webgpu_create_sampler, - ); - } - { - // binding - super::reg_sync( - rt, - "op_webgpu_create_bind_group_layout", - binding::op_webgpu_create_bind_group_layout, - ); - super::reg_sync( - rt, - "op_webgpu_create_pipeline_layout", - binding::op_webgpu_create_pipeline_layout, - ); - super::reg_sync( - rt, - "op_webgpu_create_bind_group", - binding::op_webgpu_create_bind_group, - ); - } - { - // pipeline - super::reg_sync( - rt, - "op_webgpu_create_compute_pipeline", - pipeline::op_webgpu_create_compute_pipeline, - ); - super::reg_sync( - rt, - "op_webgpu_compute_pipeline_get_bind_group_layout", - pipeline::op_webgpu_compute_pipeline_get_bind_group_layout, - ); - super::reg_sync( - rt, - "op_webgpu_create_render_pipeline", - pipeline::op_webgpu_create_render_pipeline, - ); - super::reg_sync( - rt, - "op_webgpu_render_pipeline_get_bind_group_layout", - pipeline::op_webgpu_render_pipeline_get_bind_group_layout, - ); - } - { - // command_encoder - super::reg_sync( - rt, - "op_webgpu_create_command_encoder", - command_encoder::op_webgpu_create_command_encoder, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_begin_render_pass", - command_encoder::op_webgpu_command_encoder_begin_render_pass, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_begin_compute_pass", - command_encoder::op_webgpu_command_encoder_begin_compute_pass, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_copy_buffer_to_buffer", - command_encoder::op_webgpu_command_encoder_copy_buffer_to_buffer, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_copy_buffer_to_texture", - command_encoder::op_webgpu_command_encoder_copy_buffer_to_texture, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_copy_texture_to_buffer", - command_encoder::op_webgpu_command_encoder_copy_texture_to_buffer, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_copy_texture_to_texture", - command_encoder::op_webgpu_command_encoder_copy_texture_to_texture, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_push_debug_group", - command_encoder::op_webgpu_command_encoder_push_debug_group, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_pop_debug_group", - command_encoder::op_webgpu_command_encoder_pop_debug_group, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_insert_debug_marker", - command_encoder::op_webgpu_command_encoder_insert_debug_marker, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_write_timestamp", - command_encoder::op_webgpu_command_encoder_write_timestamp, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_resolve_query_set", - command_encoder::op_webgpu_command_encoder_resolve_query_set, - ); - super::reg_sync( - rt, - "op_webgpu_command_encoder_finish", - command_encoder::op_webgpu_command_encoder_finish, - ); - } - { - // render_pass - super::reg_sync( - rt, - "op_webgpu_render_pass_set_viewport", - render_pass::op_webgpu_render_pass_set_viewport, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_set_scissor_rect", - render_pass::op_webgpu_render_pass_set_scissor_rect, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_set_blend_color", - render_pass::op_webgpu_render_pass_set_blend_color, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_set_stencil_reference", - render_pass::op_webgpu_render_pass_set_stencil_reference, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_begin_pipeline_statistics_query", - render_pass::op_webgpu_render_pass_begin_pipeline_statistics_query, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_end_pipeline_statistics_query", - render_pass::op_webgpu_render_pass_end_pipeline_statistics_query, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_write_timestamp", - render_pass::op_webgpu_render_pass_write_timestamp, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_execute_bundles", - render_pass::op_webgpu_render_pass_execute_bundles, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_end_pass", - render_pass::op_webgpu_render_pass_end_pass, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_set_bind_group", - render_pass::op_webgpu_render_pass_set_bind_group, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_push_debug_group", - render_pass::op_webgpu_render_pass_push_debug_group, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_pop_debug_group", - render_pass::op_webgpu_render_pass_pop_debug_group, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_insert_debug_marker", - render_pass::op_webgpu_render_pass_insert_debug_marker, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_set_pipeline", - render_pass::op_webgpu_render_pass_set_pipeline, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_set_index_buffer", - render_pass::op_webgpu_render_pass_set_index_buffer, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_set_vertex_buffer", - render_pass::op_webgpu_render_pass_set_vertex_buffer, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_draw", - render_pass::op_webgpu_render_pass_draw, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_draw_indexed", - render_pass::op_webgpu_render_pass_draw_indexed, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_draw_indirect", - render_pass::op_webgpu_render_pass_draw_indirect, - ); - super::reg_sync( - rt, - "op_webgpu_render_pass_draw_indexed_indirect", - render_pass::op_webgpu_render_pass_draw_indexed_indirect, - ); - } - { - // compute_pass - super::reg_sync( - rt, - "op_webgpu_compute_pass_set_pipeline", - compute_pass::op_webgpu_compute_pass_set_pipeline, - ); - super::reg_sync( - rt, - "op_webgpu_compute_pass_dispatch", - compute_pass::op_webgpu_compute_pass_dispatch, - ); - super::reg_sync( - rt, - "op_webgpu_compute_pass_dispatch_indirect", - compute_pass::op_webgpu_compute_pass_dispatch_indirect, - ); - super::reg_sync( - rt, - "op_webgpu_compute_pass_end_pass", - compute_pass::op_webgpu_compute_pass_end_pass, - ); - super::reg_sync( - rt, - "op_webgpu_compute_pass_set_bind_group", - compute_pass::op_webgpu_compute_pass_set_bind_group, - ); - super::reg_sync( - rt, - "op_webgpu_compute_pass_push_debug_group", - compute_pass::op_webgpu_compute_pass_push_debug_group, - ); - super::reg_sync( - rt, - "op_webgpu_compute_pass_pop_debug_group", - compute_pass::op_webgpu_compute_pass_pop_debug_group, - ); - super::reg_sync( - rt, - "op_webgpu_compute_pass_insert_debug_marker", - compute_pass::op_webgpu_compute_pass_insert_debug_marker, - ); - } - { - // bundle - super::reg_sync( - rt, - "op_webgpu_create_render_bundle_encoder", - bundle::op_webgpu_create_render_bundle_encoder, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_finish", - bundle::op_webgpu_render_bundle_encoder_finish, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_set_bind_group", - bundle::op_webgpu_render_bundle_encoder_set_bind_group, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_push_debug_group", - bundle::op_webgpu_render_bundle_encoder_push_debug_group, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_pop_debug_group", - bundle::op_webgpu_render_bundle_encoder_pop_debug_group, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_insert_debug_marker", - bundle::op_webgpu_render_bundle_encoder_insert_debug_marker, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_set_pipeline", - bundle::op_webgpu_render_bundle_encoder_set_pipeline, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_set_index_buffer", - bundle::op_webgpu_render_bundle_encoder_set_index_buffer, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_set_vertex_buffer", - bundle::op_webgpu_render_bundle_encoder_set_vertex_buffer, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_draw", - bundle::op_webgpu_render_bundle_encoder_draw, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_draw_indexed", - bundle::op_webgpu_render_bundle_encoder_draw_indexed, - ); - super::reg_sync( - rt, - "op_webgpu_render_bundle_encoder_draw_indirect", - bundle::op_webgpu_render_bundle_encoder_draw_indirect, - ); - } - { - // queue - super::reg_sync( - rt, - "op_webgpu_queue_submit", - queue::op_webgpu_queue_submit, - ); - super::reg_sync( - rt, - "op_webgpu_write_buffer", - queue::op_webgpu_write_buffer, - ); - super::reg_sync( - rt, - "op_webgpu_write_texture", - queue::op_webgpu_write_texture, - ); - } - { - // shader - super::reg_sync( - rt, - "op_webgpu_create_shader_module", - shader::op_webgpu_create_shader_module, - ); - } -} diff --git a/runtime/ops/websocket.rs b/runtime/ops/websocket.rs deleted file mode 100644 index 1c44f8b80b..0000000000 --- a/runtime/ops/websocket.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::permissions::Permissions; -use deno_websocket::op_ws_check_permission; -use deno_websocket::op_ws_close; -use deno_websocket::op_ws_create; -use deno_websocket::op_ws_next_event; -use deno_websocket::op_ws_send; -use deno_websocket::WsCaData; -use deno_websocket::WsUserAgent; - -pub fn init( - rt: &mut deno_core::JsRuntime, - user_agent: String, - ca_data: Option>, -) { - { - let op_state = rt.op_state(); - let mut state = op_state.borrow_mut(); - state.put::(WsUserAgent(user_agent)); - if let Some(ca_data) = ca_data { - state.put::(WsCaData(ca_data)); - } - } - super::reg_sync( - rt, - "op_ws_check_permission", - op_ws_check_permission::, - ); - super::reg_async(rt, "op_ws_create", op_ws_create::); - super::reg_async(rt, "op_ws_send", op_ws_send); - super::reg_async(rt, "op_ws_close", op_ws_close); - super::reg_async(rt, "op_ws_next_event", op_ws_next_event); -} diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index f6f88f59b3..5feb0212ce 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -3,7 +3,7 @@ use crate::colors; use crate::inspector::DenoInspector; use crate::inspector::InspectorServer; use crate::js; -use crate::metrics::RuntimeMetrics; +use crate::metrics; use crate::ops; use crate::permissions::Permissions; use crate::tokio_util::create_basic_runtime; @@ -18,6 +18,7 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::url::Url; use deno_core::v8; +use deno_core::Extension; use deno_core::GetErrorClassFn; use deno_core::JsErrorCreateFn; use deno_core::JsRuntime; @@ -176,11 +177,37 @@ impl WebWorker { worker_id: u32, options: &WebWorkerOptions, ) -> Self { + let extensions: Vec = vec![ + // Web APIs + deno_webidl::init(), + deno_console::init(), + deno_url::init(), + deno_web::init(), + deno_file::init( + options.blob_url_store.clone(), + Some(main_module.clone()), + ), + deno_fetch::init::( + options.user_agent.clone(), + options.ca_data.clone(), + ), + deno_websocket::init::( + options.user_agent.clone(), + options.ca_data.clone(), + ), + deno_crypto::init(options.seed), + deno_webgpu::init(options.unstable), + deno_timers::init::(), + // Metrics + metrics::init(), + ]; + let mut js_runtime = JsRuntime::new(RuntimeOptions { module_loader: Some(options.module_loader.clone()), startup_snapshot: Some(js::deno_isolate_init()), js_error_create_fn: options.js_error_create_fn.clone(), get_error_class_fn: options.get_error_class_fn, + extensions, ..Default::default() }); @@ -220,21 +247,16 @@ impl WebWorker { { let op_state = js_runtime.op_state(); let mut op_state = op_state.borrow_mut(); - op_state.put(RuntimeMetrics::default()); op_state.put::(permissions); op_state.put(ops::UnstableChecker { unstable: options.unstable, }); } + js_runtime.init_extension_ops().unwrap(); + ops::web_worker::init(js_runtime, sender.clone(), handle); - ops::runtime::init(js_runtime, main_module.clone()); - ops::fetch::init( - js_runtime, - options.user_agent.clone(), - options.ca_data.clone(), - ); - ops::timers::init(js_runtime); + ops::runtime::init(js_runtime, main_module); ops::worker_host::init( js_runtime, Some(sender), @@ -242,20 +264,7 @@ impl WebWorker { ); ops::reg_sync(js_runtime, "op_close", deno_core::op_close); ops::reg_sync(js_runtime, "op_resources", deno_core::op_resources); - ops::url::init(js_runtime); - ops::file::init( - js_runtime, - options.blob_url_store.clone(), - Some(main_module), - ); ops::io::init(js_runtime); - ops::webgpu::init(js_runtime); - ops::websocket::init( - js_runtime, - options.user_agent.clone(), - options.ca_data.clone(), - ); - ops::crypto::init(js_runtime, options.seed); if options.use_deno_namespace { ops::fs_events::init(js_runtime); diff --git a/runtime/worker.rs b/runtime/worker.rs index 6dbf8e7ec8..fddaf1f01d 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -4,7 +4,7 @@ use crate::inspector::DenoInspector; use crate::inspector::InspectorServer; use crate::inspector::InspectorSession; use crate::js; -use crate::metrics::RuntimeMetrics; +use crate::metrics; use crate::ops; use crate::permissions::Permissions; use deno_core::error::AnyError; @@ -15,6 +15,7 @@ use deno_core::futures::stream::StreamExt; use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::url::Url; +use deno_core::Extension; use deno_core::GetErrorClassFn; use deno_core::JsErrorCreateFn; use deno_core::JsRuntime; @@ -77,11 +78,35 @@ impl MainWorker { permissions: Permissions, options: &WorkerOptions, ) -> Self { + // Internal modules + let extensions: Vec = vec![ + // Web APIs + deno_webidl::init(), + deno_console::init(), + deno_url::init(), + deno_web::init(), + deno_file::init(options.blob_url_store.clone(), options.location.clone()), + deno_fetch::init::( + options.user_agent.clone(), + options.ca_data.clone(), + ), + deno_websocket::init::( + options.user_agent.clone(), + options.ca_data.clone(), + ), + deno_crypto::init(options.seed), + deno_webgpu::init(options.unstable), + deno_timers::init::(), + // Metrics + metrics::init(), + ]; + let mut js_runtime = JsRuntime::new(RuntimeOptions { module_loader: Some(options.module_loader.clone()), startup_snapshot: Some(js::deno_isolate_init()), js_error_create_fn: options.js_error_create_fn.clone(), get_error_class_fn: options.get_error_class_fn, + extensions, ..Default::default() }); @@ -109,34 +134,22 @@ impl MainWorker { { let op_state = js_runtime.op_state(); let mut op_state = op_state.borrow_mut(); - op_state.put(RuntimeMetrics::default()); op_state.put::(permissions); op_state.put(ops::UnstableChecker { unstable: options.unstable, }); } + js_runtime.init_extension_ops().unwrap(); + ops::runtime::init(js_runtime, main_module); - ops::fetch::init( - js_runtime, - options.user_agent.clone(), - options.ca_data.clone(), - ); - ops::timers::init(js_runtime); ops::worker_host::init( js_runtime, None, options.create_web_worker_cb.clone(), ); - ops::crypto::init(js_runtime, options.seed); ops::reg_sync(js_runtime, "op_close", deno_core::op_close); ops::reg_sync(js_runtime, "op_resources", deno_core::op_resources); - ops::url::init(js_runtime); - ops::file::init( - js_runtime, - options.blob_url_store.clone(), - options.location.clone(), - ); ops::fs_events::init(js_runtime); ops::fs::init(js_runtime); ops::http::init(js_runtime); @@ -149,12 +162,6 @@ impl MainWorker { ops::signal::init(js_runtime); ops::tls::init(js_runtime); ops::tty::init(js_runtime); - ops::webgpu::init(js_runtime); - ops::websocket::init( - js_runtime, - options.user_agent.clone(), - options.ca_data.clone(), - ); } { let op_state = js_runtime.op_state();