summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-03-14 23:14:15 +0530
committerGitHub <noreply@github.com>2022-03-14 18:44:15 +0100
commitb4e42953e1d243f2eda20e5be6b845d60b7bf688 (patch)
tree10b3bfff165f9c04f9174c7c399d44b9b724c3b3
parent4e3ed37037a2aa1edeac260dc3463a81d9cf9b88 (diff)
feat(core): codegen ops (#13861)
Co-authored-by: Aaron O'Mullan <aaron.omullan@gmail.com>
-rw-r--r--Cargo.lock21
-rw-r--r--Cargo.toml1
-rw-r--r--bench_util/benches/op_baseline.rs33
-rw-r--r--cli/build.rs156
-rw-r--r--cli/lsp/tsc.rs115
-rw-r--r--cli/ops/bench.rs23
-rw-r--r--cli/ops/errors.rs11
-rw-r--r--cli/ops/runtime_compiler.rs8
-rw-r--r--cli/ops/testing.rs20
-rw-r--r--cli/tsc.rs183
-rw-r--r--cli/tsc/99_main_compiler.js1
-rw-r--r--core/01_core.js25
-rw-r--r--core/Cargo.toml1
-rw-r--r--core/bindings.rs370
-rw-r--r--core/error_codes.rs2
-rw-r--r--core/examples/disable_ops.rs2
-rw-r--r--core/examples/hello_world.rs34
-rw-r--r--core/examples/http_bench_json_ops.js4
-rw-r--r--core/examples/http_bench_json_ops.rs13
-rw-r--r--core/examples/schedule_task.rs12
-rw-r--r--core/extensions.rs9
-rw-r--r--core/lib.rs31
-rw-r--r--core/modules.rs41
-rw-r--r--core/ops.rs147
-rw-r--r--core/ops_builtin.rs94
-rw-r--r--core/ops_json.rs166
-rw-r--r--core/ops_metrics.rs12
-rw-r--r--core/runtime.rs293
-rw-r--r--ext/broadcast_channel/lib.rs49
-rw-r--r--ext/crypto/decrypt.rs2
-rw-r--r--ext/crypto/encrypt.rs3
-rw-r--r--ext/crypto/export_key.rs2
-rw-r--r--ext/crypto/generate_key.rs2
-rw-r--r--ext/crypto/import_key.rs3
-rw-r--r--ext/crypto/lib.rs41
-rw-r--r--ext/fetch/lib.rs16
-rw-r--r--ext/ffi/lib.rs61
-rw-r--r--ext/http/lib.rs31
-rw-r--r--ext/net/lib.rs5
-rw-r--r--ext/net/ops.rs34
-rw-r--r--ext/net/ops_tls.rs19
-rw-r--r--ext/url/lib.rs27
-rw-r--r--ext/url/urlpattern.rs3
-rw-r--r--ext/web/blob.rs9
-rw-r--r--ext/web/compression.rs4
-rw-r--r--ext/web/lib.rs88
-rw-r--r--ext/web/message_port.rs5
-rw-r--r--ext/web/timers.rs6
-rw-r--r--ext/webgpu/src/binding.rs4
-rw-r--r--ext/webgpu/src/buffer.rs6
-rw-r--r--ext/webgpu/src/bundle.rs13
-rw-r--r--ext/webgpu/src/command_encoder.rs15
-rw-r--r--ext/webgpu/src/compute_pass.rs12
-rw-r--r--ext/webgpu/src/lib.rs414
-rw-r--r--ext/webgpu/src/pipeline.rs5
-rw-r--r--ext/webgpu/src/queue.rs4
-rw-r--r--ext/webgpu/src/render_pass.rs21
-rw-r--r--ext/webgpu/src/sampler.rs2
-rw-r--r--ext/webgpu/src/shader.rs2
-rw-r--r--ext/webgpu/src/texture.rs3
-rw-r--r--ext/websocket/lib.rs22
-rw-r--r--ext/webstorage/lib.rs26
-rw-r--r--ops/Cargo.toml17
-rw-r--r--ops/README.md16
-rw-r--r--ops/lib.rs264
-rw-r--r--runtime/ops/fs.rs163
-rw-r--r--runtime/ops/fs_events.rs11
-rw-r--r--runtime/ops/http.rs5
-rw-r--r--runtime/ops/io.rs9
-rw-r--r--runtime/ops/os.rs42
-rw-r--r--runtime/ops/permissions.rs11
-rw-r--r--runtime/ops/process.rs13
-rw-r--r--runtime/ops/runtime.rs5
-rw-r--r--runtime/ops/signal.rs16
-rw-r--r--runtime/ops/tty.rs11
-rw-r--r--runtime/ops/web_worker.rs18
-rw-r--r--runtime/ops/web_worker/sync_fetch.rs2
-rw-r--r--runtime/ops/worker_host.rs22
78 files changed, 1751 insertions, 1661 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1f5aa7883..0319d4d76 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -856,6 +856,7 @@ version = "0.122.0"
dependencies = [
"anyhow",
"deno_ast",
+ "deno_ops",
"futures",
"indexmap",
"libc",
@@ -1020,6 +1021,16 @@ dependencies = [
]
[[package]]
+name = "deno_ops"
+version = "0.1.1"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
+[[package]]
name = "deno_runtime"
version = "0.48.0"
dependencies = [
@@ -2926,6 +2937,16 @@ dependencies = [
]
[[package]]
+name = "proc-macro-crate"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
+dependencies = [
+ "thiserror",
+ "toml",
+]
+
+[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index b76cd5971..57b93944e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,7 @@ members = [
"bench_util",
"cli",
"core",
+ "ops",
"runtime",
"serde_v8",
"test_ffi",
diff --git a/bench_util/benches/op_baseline.rs b/bench_util/benches/op_baseline.rs
index 10b5a6f6e..929e573cd 100644
--- a/bench_util/benches/op_baseline.rs
+++ b/bench_util/benches/op_baseline.rs
@@ -3,11 +3,9 @@ use deno_bench_util::bencher::{benchmark_group, Bencher};
use deno_bench_util::{bench_js_async, bench_js_sync};
use deno_core::error::AnyError;
-use deno_core::op_async;
-use deno_core::op_sync;
-use deno_core::serialize_op_result;
+use deno_core::op;
+
use deno_core::Extension;
-use deno_core::Op;
use deno_core::OpState;
use std::cell::RefCell;
@@ -16,17 +14,25 @@ use std::rc::Rc;
fn setup() -> Vec<Extension> {
vec![Extension::builder()
.ops(vec![
- ("pi_json", op_sync(|_, _: (), _: ()| Ok(314159))),
- ("pi_async", op_async(op_pi_async)),
- (
- "nop",
- Box::new(|state, _| Op::Sync(serialize_op_result(Ok(9), state))),
- ),
+ op_pi_json::decl(),
+ op_pi_async::decl(),
+ op_nop::decl(),
])
.build()]
}
+#[op]
+fn op_nop(_: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
+ Ok(())
+}
+
+#[op]
+fn op_pi_json(_: &mut OpState, _: (), _: ()) -> Result<i64, AnyError> {
+ Ok(314159)
+}
+
// this is a function since async closures aren't stable
+#[op]
async fn op_pi_async(
_: Rc<RefCell<OpState>>,
_: (),
@@ -36,15 +42,15 @@ async fn op_pi_async(
}
fn bench_op_pi_json(b: &mut Bencher) {
- bench_js_sync(b, r#"Deno.core.opSync("pi_json", null);"#, setup);
+ bench_js_sync(b, r#"Deno.core.opSync("op_pi_json", null);"#, setup);
}
fn bench_op_nop(b: &mut Bencher) {
- bench_js_sync(b, r#"Deno.core.opSync("nop", null, null, null);"#, setup);
+ bench_js_sync(b, r#"Deno.core.opSync("op_nop", null, null, null);"#, setup);
}
fn bench_op_async(b: &mut Bencher) {
- bench_js_async(b, r#"Deno.core.opAsync("pi_async", null);"#, setup);
+ bench_js_async(b, r#"Deno.core.opAsync("op_pi_async", null);"#, setup);
}
fn bench_is_proxy(b: &mut Bencher) {
@@ -58,4 +64,5 @@ benchmark_group!(
bench_op_async,
bench_is_proxy
);
+
bench_or_profile!(benches);
diff --git a/cli/build.rs b/cli/build.rs
index 26b27a955..f1eb1829c 100644
--- a/cli/build.rs
+++ b/cli/build.rs
@@ -1,11 +1,14 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::custom_error;
-use deno_core::op_sync;
+use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::serde::Deserialize;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
+use deno_core::Extension;
use deno_core::JsRuntime;
+use deno_core::OpState;
use deno_core::RuntimeOptions;
use regex::Regex;
use std::collections::HashMap;
@@ -185,79 +188,112 @@ fn create_compiler_snapshot(
build_libs.push(op_lib.to_owned());
}
- let re_asset = Regex::new(r"asset:/{3}lib\.(\S+)\.d\.ts").expect("bad regex");
- let build_specifier = "asset:///bootstrap.ts";
+ #[op]
+ fn op_build_info(
+ state: &mut OpState,
+ _args: Value,
+ _: (),
+ ) -> Result<Value, AnyError> {
+ let build_specifier = "asset:///bootstrap.ts";
+ let build_libs = state.borrow::<Vec<&str>>();
+ Ok(json!({
+ "buildSpecifier": build_specifier,
+ "libs": build_libs,
+ }))
+ }
- let mut js_runtime = JsRuntime::new(RuntimeOptions {
- will_snapshot: true,
- ..Default::default()
- });
- js_runtime.register_op(
- "op_build_info",
- op_sync(move |_state, _args: Value, _: ()| {
- Ok(json!({
- "buildSpecifier": build_specifier,
- "libs": build_libs,
- }))
- }),
- );
- js_runtime.register_op(
- "op_cwd",
- op_sync(move |_state, _args: Value, _: ()| Ok(json!("cache:///"))),
- );
- // As of TypeScript 4.5, it tries to detect the existence of substitute lib
- // files, which we currently don't use, so we just return false.
- js_runtime.register_op(
- "op_exists",
- op_sync(move |_state, _args: LoadArgs, _: ()| Ok(json!(false))),
- );
+ #[op]
+ fn op_cwd(
+ _state: &mut OpState,
+ _args: Value,
+ _: (),
+ ) -> Result<Value, AnyError> {
+ Ok(json!("cache:///"))
+ }
+
+ #[op]
+ fn op_exists(
+ _state: &mut OpState,
+ _args: Value,
+ _: (),
+ ) -> Result<Value, AnyError> {
+ Ok(json!(false))
+ }
+
+ #[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.
- js_runtime.register_op(
- "op_load",
- op_sync(move |_state, args: LoadArgs, _: ()| {
- // we need a basic file to send to tsc to warm it up.
- if args.specifier == build_specifier {
+ fn op_load(
+ state: &mut OpState,
+ args: LoadArgs,
+ _: (),
+ ) -> Result<Value, AnyError> {
+ let op_crate_libs = state.borrow::<HashMap<&str, &str>>();
+ let path_dts = state.borrow::<PathBuf>();
+ 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#"console.log("hello deno!");"#,
+ "hash": "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().unwrap()
+ // otherwise we are will generate the path ourself
+ } else {
+ path_dts.join(format!("lib.{}.d.ts", lib))
+ };
+ let data = std::fs::read_to_string(path)?;
Ok(json!({
- "data": r#"console.log("hello deno!");"#,
+ "data": data,
"hash": "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().unwrap()
- // otherwise we are will generate the path ourself
- } else {
- path_dts.join(format!("lib.{}.d.ts", lib))
- };
- let data = std::fs::read_to_string(path)?;
- Ok(json!({
- "data": data,
- "hash": "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),
))
}
- }),
- );
- js_runtime.sync_ops_cache();
+ } else {
+ Err(custom_error(
+ "InvalidSpecifier",
+ format!("An invalid specifier was requested: {}", args.specifier),
+ ))
+ }
+ }
+ let js_runtime = JsRuntime::new(RuntimeOptions {
+ will_snapshot: true,
+ extensions: vec![Extension::builder()
+ .ops(vec![
+ op_build_info::decl(),
+ op_cwd::decl(),
+ op_exists::decl(),
+ op_load::decl(),
+ ])
+ .state(move |state| {
+ state.put(op_crate_libs.clone());
+ state.put(build_libs.clone());
+ state.put(path_dts.clone());
+
+ Ok(())
+ })
+ .build()],
+ ..Default::default()
+ });
+
create_snapshot(js_runtime, snapshot_path, files);
}
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index b849f44e9..648045f4e 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -27,7 +27,7 @@ use deno_core::anyhow::anyhow;
use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::located_script_name;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::parking_lot::Mutex;
use deno_core::resolve_url;
use deno_core::serde::de;
@@ -40,7 +40,7 @@ use deno_core::url::Url;
use deno_core::Extension;
use deno_core::JsRuntime;
use deno_core::ModuleSpecifier;
-use deno_core::OpFn;
+use deno_core::OpState;
use deno_core::RuntimeOptions;
use deno_runtime::tokio_util::create_basic_runtime;
use log::error;
@@ -2502,19 +2502,6 @@ fn normalize_specifier<S: AsRef<str>>(
.map_err(|err| err.into())
}
-// buffer-less json_sync ops
-fn op_lsp<F, V, R>(op_fn: F) -> Box<OpFn>
-where
- F: Fn(&mut State, V) -> Result<R, AnyError> + 'static,
- V: de::DeserializeOwned,
- R: Serialize + 'static,
-{
- op_sync(move |s, args, _: ()| {
- let state = s.borrow_mut::<State>();
- op_fn(state, args)
- })
-}
-
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct SourceSnapshotArgs {
@@ -2524,10 +2511,13 @@ struct SourceSnapshotArgs {
/// The language service is dropping a reference to a source file snapshot, and
/// we can drop our version of that document.
+#[op]
fn op_dispose(
- state: &mut State,
+ state: &mut OpState,
args: SourceSnapshotArgs,
+ _: (),
) -> Result<bool, AnyError> {
+ let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_dispose", Some(&args));
let specifier = state.normalize_specifier(&args.specifier)?;
state.snapshots.remove(&(specifier, args.version.into()));
@@ -2541,7 +2531,13 @@ struct SpecifierArgs {
specifier: String,
}
-fn op_exists(state: &mut State, args: SpecifierArgs) -> Result<bool, AnyError> {
+#[op]
+fn op_exists(
+ state: &mut OpState,
+ args: SpecifierArgs,
+ _: (),
+) -> Result<bool, AnyError> {
+ let state = state.borrow_mut::<State>();
// we don't measure the performance of op_exists anymore because as of TS 4.5
// it is noisy with all the checking for custom libs, that we can't see the
// forrest for the trees as well as it compounds any lsp performance
@@ -2569,10 +2565,13 @@ struct GetChangeRangeArgs {
/// The language service wants to compare an old snapshot with a new snapshot to
/// determine what source has changed.
+#[op]
fn op_get_change_range(
- state: &mut State,
+ state: &mut OpState,
args: GetChangeRangeArgs,
+ _: (),
) -> Result<Value, AnyError> {
+ let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_get_change_range", Some(&args));
let specifier = state.normalize_specifier(&args.specifier)?;
cache_snapshot(state, &specifier, args.version.clone())?;
@@ -2613,10 +2612,13 @@ fn op_get_change_range(
r
}
+#[op]
fn op_get_length(
- state: &mut State,
+ state: &mut OpState,
args: SourceSnapshotArgs,
+ _: (),
) -> Result<usize, AnyError> {
+ let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_get_length", Some(&args));
let specifier = state.normalize_specifier(args.specifier)?;
let r = if let Some(Some(asset)) =
@@ -2644,10 +2646,13 @@ struct GetTextArgs {
end: usize,
}
+#[op]
fn op_get_text(
- state: &mut State,
+ state: &mut OpState,
args: GetTextArgs,
+ _: (),
) -> Result<String, AnyError> {
+ let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_get_text", Some(&args));
let specifier = state.normalize_specifier(args.specifier)?;
let maybe_asset = state.state_snapshot.assets.get_cached(&specifier);
@@ -2664,14 +2669,23 @@ fn op_get_text(
Ok(text::slice(content, args.start..args.end).to_string())
}
-fn op_is_cancelled(state: &mut State, _: ()) -> Result<bool, AnyError> {
+#[op]
+fn op_is_cancelled(
+ state: &mut OpState,
+ _: (),
+ _: (),
+) -> Result<bool, AnyError> {
+ let state = state.borrow_mut::<State>();
Ok(state.token.is_cancelled())
}
+#[op]
fn op_load(
- state: &mut State,
+ state: &mut OpState,
args: SpecifierArgs,
+ _: (),
) -> Result<Option<String>, AnyError> {
+ let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_load", Some(&args));
let specifier = state.normalize_specifier(args.specifier)?;
let document = state.state_snapshot.documents.get(&specifier);
@@ -2679,10 +2693,13 @@ fn op_load(
Ok(document.map(|d| d.content().to_string()))
}
+#[op]
fn op_resolve(
- state: &mut State,
+ state: &mut OpState,
args: ResolveArgs,
+ _: (),
) -> Result<Vec<Option<(String, String)>>, AnyError> {
+ let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_resolve", Some(&args));
let referrer = state.normalize_specifier(&args.base)?;
@@ -2713,15 +2730,24 @@ fn op_resolve(
result
}
-fn op_respond(state: &mut State, args: Response) -> Result<bool, AnyError> {
+#[op]
+fn op_respond(
+ state: &mut OpState,
+ args: Response,
+ _: (),
+) -> Result<bool, AnyError> {
+ let state = state.borrow_mut::<State>();
state.response = Some(args);
Ok(true)
}
+#[op]
fn op_script_names(
- state: &mut State,
+ state: &mut OpState,
_args: Value,
+ _: (),
) -> Result<Vec<ModuleSpecifier>, AnyError> {
+ let state = state.borrow_mut::<State>();
Ok(
state
.state_snapshot
@@ -2739,10 +2765,13 @@ struct ScriptVersionArgs {
specifier: String,
}
+#[op]
fn op_script_version(
- state: &mut State,
+ state: &mut OpState,
args: ScriptVersionArgs,
+ _: (),
) -> Result<Option<String>, AnyError> {
+ let state = state.borrow_mut::<State>();
// this op is very "noisy" and measuring its performance is not useful, so we
// don't measure it uniquely anymore.
let specifier = state.normalize_specifier(args.specifier)?;
@@ -2776,17 +2805,17 @@ fn js_runtime(performance: Arc<Performance>) -> JsRuntime {
fn init_extension(performance: Arc<Performance>) -> Extension {
Extension::builder()
.ops(vec![
- ("op_dispose", op_lsp(op_dispose)),
- ("op_exists", op_lsp(op_exists)),
- ("op_get_change_range", op_lsp(op_get_change_range)),
- ("op_get_length", op_lsp(op_get_length)),
- ("op_get_text", op_lsp(op_get_text)),
- ("op_is_cancelled", op_lsp(op_is_cancelled)),
- ("op_load", op_lsp(op_load)),
- ("op_resolve", op_lsp(op_resolve)),
- ("op_respond", op_lsp(op_respond)),
- ("op_script_names", op_lsp(op_script_names)),
- ("op_script_version", op_lsp(op_script_version)),
+ op_dispose::decl(),
+ op_exists::decl(),
+ op_get_change_range::decl(),
+ op_get_length::decl(),
+ op_get_text::decl(),
+ op_is_cancelled::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(
@@ -3832,7 +3861,7 @@ mod tests {
#[test]
fn test_op_exists() {
- let (_, state_snapshot, _) = setup(
+ let (mut rt, state_snapshot, _) = setup(
false,
json!({
"target": "esnext",
@@ -3843,12 +3872,16 @@ mod tests {
&[],
);
let performance = Arc::new(Performance::default());
- let mut state = State::new(state_snapshot, performance);
- let actual = op_exists(
- &mut state,
+ let state = State::new(state_snapshot, performance);
+ let op_state = rt.op_state();
+ let mut op_state = op_state.borrow_mut();
+ op_state.put(state);
+ let actual = op_exists::call(
+ &mut op_state,
SpecifierArgs {
specifier: "/error/unknown:something/index.d.ts".to_string(),
},
+ (),
);
assert!(actual.is_ok());
let actual = actual.unwrap();
diff --git a/cli/ops/bench.rs b/cli/ops/bench.rs
index b535e1236..ab15a2b4b 100644
--- a/cli/ops/bench.rs
+++ b/cli/ops/bench.rs
@@ -1,7 +1,7 @@
use crate::tools::bench::BenchEvent;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::Extension;
use deno_core::ModuleSpecifier;
use deno_core::OpState;
@@ -15,17 +15,11 @@ use uuid::Uuid;
pub fn init(sender: UnboundedSender<BenchEvent>) -> Extension {
Extension::builder()
.ops(vec![
- (
- "op_pledge_test_permissions",
- op_sync(op_pledge_test_permissions),
- ),
- (
- "op_restore_test_permissions",
- op_sync(op_restore_test_permissions),
- ),
- ("op_get_bench_origin", op_sync(op_get_bench_origin)),
- ("op_dispatch_bench_event", op_sync(op_dispatch_bench_event)),
- ("op_bench_now", op_sync(op_bench_now)),
+ op_pledge_test_permissions::decl(),
+ op_restore_test_permissions::decl(),
+ op_get_bench_origin::decl(),
+ op_dispatch_bench_event::decl(),
+ op_bench_now::decl(),
])
.state(move |state| {
state.put(sender.clone());
@@ -37,6 +31,7 @@ pub fn init(sender: UnboundedSender<BenchEvent>) -> Extension {
#[derive(Clone)]
struct PermissionsHolder(Uuid, Permissions);
+#[op]
pub fn op_pledge_test_permissions(
state: &mut OpState,
args: ChildPermissionsArg,
@@ -55,6 +50,7 @@ pub fn op_pledge_test_permissions(
Ok(token)
}
+#[op]
pub fn op_restore_test_permissions(
state: &mut OpState,
token: Uuid,
@@ -73,6 +69,7 @@ pub fn op_restore_test_permissions(
}
}
+#[op]
fn op_get_bench_origin(
state: &mut OpState,
_: (),
@@ -81,6 +78,7 @@ fn op_get_bench_origin(
Ok(state.borrow::<ModuleSpecifier>().to_string())
}
+#[op]
fn op_dispatch_bench_event(
state: &mut OpState,
event: BenchEvent,
@@ -92,6 +90,7 @@ fn op_dispatch_bench_event(
Ok(())
}
+#[op]
fn op_bench_now(state: &mut OpState, _: (), _: ()) -> Result<u64, AnyError> {
let ns = state.borrow::<time::Instant>().elapsed().as_nanos();
let ns_u64 = u64::try_from(ns)?;
diff --git a/cli/ops/errors.rs b/cli/ops/errors.rs
index a9193b0cd..c215ade41 100644
--- a/cli/ops/errors.rs
+++ b/cli/ops/errors.rs
@@ -6,7 +6,7 @@ use crate::proc_state::ProcState;
use crate::source_maps::get_orig_position;
use crate::source_maps::CachedMaps;
use deno_core::error::AnyError;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
@@ -19,9 +19,9 @@ use std::collections::HashMap;
pub fn init() -> Extension {
Extension::builder()
.ops(vec![
- ("op_apply_source_map", op_sync(op_apply_source_map)),
- ("op_format_diagnostic", op_sync(op_format_diagnostic)),
- ("op_format_file_name", op_sync(op_format_file_name)),
+ op_apply_source_map::decl(),
+ op_format_diagnostic::decl(),
+ op_format_file_name::decl(),
])
.build()
}
@@ -42,6 +42,7 @@ struct AppliedSourceMap {
column_number: u32,
}
+#[op]
fn op_apply_source_map(
state: &mut OpState,
args: ApplySourceMap,
@@ -66,6 +67,7 @@ fn op_apply_source_map(
})
}
+#[op]
fn op_format_diagnostic(
_state: &mut OpState,
args: Value,
@@ -75,6 +77,7 @@ fn op_format_diagnostic(
Ok(json!(diagnostic.to_string()))
}
+#[op]
fn op_format_file_name(
_state: &mut OpState,
file_name: String,
diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs
index 3df93862d..6fb8d688c 100644
--- a/cli/ops/runtime_compiler.rs
+++ b/cli/ops/runtime_compiler.rs
@@ -16,7 +16,8 @@ use deno_core::anyhow::Context;
use deno_core::error::custom_error;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
-use deno_core::op_async;
+
+use deno_core::op;
use deno_core::parking_lot::RwLock;
use deno_core::resolve_url_or_path;
use deno_core::serde_json;
@@ -35,9 +36,7 @@ use std::rc::Rc;
use std::sync::Arc;
pub fn init() -> Extension {
- Extension::builder()
- .ops(vec![("op_emit", op_async(op_emit))])
- .build()
+ Extension::builder().ops(vec![op_emit::decl()]).build()
}
#[derive(Debug, Deserialize)]
@@ -141,6 +140,7 @@ fn to_maybe_jsx_import_source_module(
}
}
+#[op]
async fn op_emit(
state: Rc<RefCell<OpState>>,
args: EmitArgs,
diff --git a/cli/ops/testing.rs b/cli/ops/testing.rs
index b8995db83..ebaa819e1 100644
--- a/cli/ops/testing.rs
+++ b/cli/ops/testing.rs
@@ -1,7 +1,7 @@
use crate::tools::test::TestEvent;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::Extension;
use deno_core::ModuleSpecifier;
use deno_core::OpState;
@@ -14,16 +14,10 @@ use uuid::Uuid;
pub fn init(sender: UnboundedSender<TestEvent>) -> Extension {
Extension::builder()
.ops(vec![
- (
- "op_pledge_test_permissions",
- op_sync(op_pledge_test_permissions),
- ),
- (
- "op_restore_test_permissions",
- op_sync(op_restore_test_permissions),
- ),
- ("op_get_test_origin", op_sync(op_get_test_origin)),
- ("op_dispatch_test_event", op_sync(op_dispatch_test_event)),
+ op_pledge_test_permissions::decl(),
+ op_restore_test_permissions::decl(),
+ op_get_test_origin::decl(),
+ op_dispatch_test_event::decl(),
])
.state(move |state| {
state.put(sender.clone());
@@ -35,6 +29,7 @@ pub fn init(sender: UnboundedSender<TestEvent>) -> Extension {
#[derive(Clone)]
struct PermissionsHolder(Uuid, Permissions);
+#[op]
pub fn op_pledge_test_permissions(
state: &mut OpState,
args: ChildPermissionsArg,
@@ -53,6 +48,7 @@ pub fn op_pledge_test_permissions(
Ok(token)
}
+#[op]
pub fn op_restore_test_permissions(
state: &mut OpState,
token: Uuid,
@@ -71,6 +67,7 @@ pub fn op_restore_test_permissions(
}
}
+#[op]
fn op_get_test_origin(
state: &mut OpState,
_: (),
@@ -79,6 +76,7 @@ fn op_get_test_origin(
Ok(state.borrow::<ModuleSpecifier>().to_string())
}
+#[op]
fn op_dispatch_test_event(
state: &mut OpState,
event: TestEvent,
diff --git a/cli/tsc.rs b/cli/tsc.rs
index 421d95dc5..ddb8a442e 100644
--- a/cli/tsc.rs
+++ b/cli/tsc.rs
@@ -11,18 +11,18 @@ use deno_core::anyhow::anyhow;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use deno_core::located_script_name;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::parking_lot::RwLock;
use deno_core::resolve_url_or_path;
-use deno_core::serde::de;
use deno_core::serde::Deserialize;
use deno_core::serde::Serialize;
use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
+use deno_core::Extension;
use deno_core::JsRuntime;
use deno_core::ModuleSpecifier;
-use deno_core::OpFn;
+use deno_core::OpState;
use deno_core::RuntimeOptions;
use deno_core::Snapshot;
use deno_graph::Resolved;
@@ -298,18 +298,6 @@ fn normalize_specifier(specifier: &str) -> Result<ModuleSpecifier, AnyError> {
.map_err(|err| err.into())
}
-fn op<F, V, R>(op_fn: F) -> Box<OpFn>
-where
- F: Fn(&mut State, V) -> Result<R, AnyError> + 'static,
- V: de::DeserializeOwned,
- R: Serialize + 'static,
-{
- op_sync(move |s, args, _: ()| {
- let state = s.borrow_mut::<State>();
- op_fn(state, args)
- })
-}
-
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct CreateHashArgs {
@@ -318,7 +306,13 @@ struct CreateHashArgs {
data: String,
}
-fn op_create_hash(state: &mut State, args: Value) -> Result<Value, AnyError> {
+#[op]
+fn op_create_hash(
+ s: &mut OpState,
+ args: Value,
+ _: (),
+) -> Result<Value, AnyError> {
+ let state = s.borrow_mut::<State>();
let v: CreateHashArgs = serde_json::from_value(args)
.context("Invalid request from JavaScript for \"op_create_hash\".")?;
let mut data = vec![v.data.as_bytes().to_owned()];
@@ -327,7 +321,9 @@ fn op_create_hash(state: &mut State, args: Value) -> Result<Value, AnyError> {
Ok(json!({ "hash": hash }))
}
-fn op_cwd(state: &mut State, _args: Value) -> Result<String, AnyError> {
+#[op]
+fn op_cwd(s: &mut OpState, _args: Value, _: ()) -> Result<String, AnyError> {
+ let state = s.borrow_mut::<State>();
if let Some(config_specifier) = &state.maybe_config_specifier {
let cwd = config_specifier.join("./")?;
Ok(cwd.to_string())
@@ -350,7 +346,13 @@ struct EmitArgs {
maybe_specifiers: Option<Vec<String>>,
}
-fn op_emit(state: &mut State, args: EmitArgs) -> Result<Value, AnyError> {
+#[op]
+fn op_emit(
+ state: &mut OpState,
+ args: EmitArgs,
+ _: (),
+) -> Result<Value, AnyError> {
+ let state = state.borrow_mut::<State>();
match args.file_name.as_ref() {
"deno:///.tsbuildinfo" => state.maybe_tsbuildinfo = Some(args.data),
_ => {
@@ -403,7 +405,13 @@ struct ExistsArgs {
specifier: String,
}
-fn op_exists(state: &mut State, args: ExistsArgs) -> Result<bool, AnyError> {
+#[op]
+fn op_exists(
+ state: &mut OpState,
+ args: ExistsArgs,
+ _: (),
+) -> Result<bool, AnyError> {
+ let state = state.borrow_mut::<State>();
let graph_data = state.graph_data.read();
if let Ok(specifier) = normalize_specifier(&args.specifier) {
if specifier.scheme() == "asset" || specifier.scheme() == "data" {
@@ -443,7 +451,9 @@ fn as_ts_script_kind(media_type: &MediaType) -> i32 {
}
}
-fn op_load(state: &mut State, args: Value) -> Result<Value, AnyError> {
+#[op]
+fn op_load(state: &mut OpState, args: Value, _: ()) -> Result<Value, AnyError> {
+ let state = state.borrow_mut::<State>();
let v: LoadArgs = serde_json::from_value(args)
.context("Invalid request from JavaScript for \"op_load\".")?;
let specifier = normalize_specifier(&v.specifier)
@@ -507,7 +517,13 @@ pub struct ResolveArgs {
pub specifiers: Vec<String>,
}
-fn op_resolve(state: &mut State, args: ResolveArgs) -> Result<Value, AnyError> {
+#[op]
+fn op_resolve(
+ state: &mut OpState,
+ args: ResolveArgs,
+ _: (),
+) -> Result<Value, AnyError> {
+ let state = state.borrow_mut::<State>();
let mut resolved: Vec<(String, String)> = Vec::new();
let referrer = if let Some(remapped_specifier) =
state.remapped_specifiers.get(&args.base)
@@ -612,7 +628,13 @@ struct RespondArgs {
pub stats: emit::Stats,
}
-fn op_respond(state: &mut State, args: Value) -> Result<Value, AnyError> {
+#[op]
+fn op_respond(
+ state: &mut OpState,
+ args: Value,
+ _: (),
+) -> Result<Value, AnyError> {
+ let state = state.borrow_mut::<State>();
let v: RespondArgs = serde_json::from_value(args)
.context("Error converting the result for \"op_respond\".")?;
state.maybe_response = Some(v);
@@ -623,10 +645,6 @@ fn op_respond(state: &mut State, args: Value) -> Result<Value, AnyError> {
/// contains information, like any emitted files, diagnostics, statistics and
/// optionally an updated TypeScript build info.
pub(crate) fn exec(request: Request) -> Result<Response, AnyError> {
- let mut runtime = JsRuntime::new(RuntimeOptions {
- startup_snapshot: Some(compiler_snapshot()),
- ..Default::default()
- });
// tsc cannot handle root specifiers that don't have one of the "acceptable"
// extensions. Therefore, we have to check the root modules against their
// extensions and remap any that are unacceptable to tsc and add them to the
@@ -654,28 +672,32 @@ pub(crate) fn exec(request: Request) -> Result<Response, AnyError> {
}
})
.collect();
-
- {
- let op_state = runtime.op_state();
- let mut op_state = op_state.borrow_mut();
- op_state.put(State::new(
- request.graph_data,
- request.hash_data.clone(),
- request.maybe_config_specifier.clone(),
- request.maybe_tsbuildinfo.clone(),
- root_map,
- remapped_specifiers,
- ));
- }
-
- runtime.register_op("op_cwd", op(op_cwd));
- runtime.register_op("op_create_hash", op(op_create_hash));
- runtime.register_op("op_emit", op(op_emit));
- runtime.register_op("op_exists", op(op_exists));
- runtime.register_op("op_load", op(op_load));
- runtime.register_op("op_resolve", op(op_resolve));
- runtime.register_op("op_respond", op(op_respond));
- runtime.sync_ops_cache();
+ let mut runtime = JsRuntime::new(RuntimeOptions {
+ startup_snapshot: Some(compiler_snapshot()),
+ extensions: vec![Extension::builder()
+ .ops(vec![
+ op_cwd::decl(),
+ op_create_hash::decl(),
+ op_emit::decl(),
+ op_exists::decl(),
+ op_load::decl(),
+ op_resolve::decl(),
+ op_respond::decl(),
+ ])
+ .state(move |state| {
+ state.put(State::new(
+ request.graph_data.clone(),
+ request.hash_data.clone(),
+ request.maybe_config_specifier.clone(),
+ request.maybe_tsbuildinfo.clone(),
+ root_map.clone(),
+ remapped_specifiers.clone(),
+ ));
+ Ok(())
+ })
+ .build()],
+ ..Default::default()
+ });
let startup_source = "globalThis.startup({ legacyFlag: false })";
let request_value = json!({
@@ -720,6 +742,7 @@ mod tests {
use crate::diagnostics::DiagnosticCategory;
use crate::emit::Stats;
use deno_core::futures::future;
+ use deno_core::OpState;
use deno_graph::ModuleKind;
use std::fs;
@@ -757,7 +780,7 @@ mod tests {
maybe_specifier: Option<ModuleSpecifier>,
maybe_hash_data: Option<Vec<Vec<u8>>>,
maybe_tsbuildinfo: Option<String>,
- ) -> State {
+ ) -> OpState {
let specifier = maybe_specifier
.unwrap_or_else(|| resolve_url_or_path("file:///main.ts").unwrap());
let hash_data = maybe_hash_data.unwrap_or_else(|| vec![b"".to_vec()]);
@@ -774,14 +797,17 @@ mod tests {
None,
)
.await;
- State::new(
+ let state = State::new(
Arc::new(RwLock::new((&graph).into())),
hash_data,
None,
maybe_tsbuildinfo,
HashMap::new(),
HashMap::new(),
- )
+ );
+ let mut op_state = OpState::new(1);
+ op_state.put(state);
+ op_state
}
async fn test_exec(
@@ -852,9 +878,12 @@ mod tests {
#[tokio::test]
async fn test_create_hash() {
let mut state = setup(None, Some(vec![b"something".to_vec()]), None).await;
- let actual =
- op_create_hash(&mut state, json!({ "data": "some sort of content" }))
- .expect("could not invoke op");
+ let actual = op_create_hash::call(
+ &mut state,
+ json!({ "data": "some sort of content" }),
+ (),
+ )
+ .expect("could not invoke op");
assert_eq!(
actual,
json!({"hash": "ae92df8f104748768838916857a1623b6a3c593110131b0a00f81ad9dac16511"})
@@ -898,16 +927,18 @@ mod tests {
#[tokio::test]
async fn test_emit() {
let mut state = setup(None, None, None).await;
- let actual = op_emit(
+ let actual = op_emit::call(
&mut state,
EmitArgs {
data: "some file content".to_string(),
file_name: "cache:///some/file.js".to_string(),
maybe_specifiers: Some(vec!["file:///some/file.ts".to_string()]),
},
+ (),
)
.expect("should have invoked op");
assert_eq!(actual, json!(true));
+ let state = state.borrow::<State>();
assert_eq!(state.emitted_files.len(), 1);
assert!(state.maybe_tsbuildinfo.is_none());
assert_eq!(
@@ -926,7 +957,7 @@ mod tests {
#[tokio::test]
async fn test_emit_strange_specifier() {
let mut state = setup(None, None, None).await;
- let actual = op_emit(
+ let actual = op_emit::call(
&mut state,
EmitArgs {
data: "some file content".to_string(),
@@ -935,9 +966,11 @@ mod tests {
vec!["file:///some/file.ts?q=.json".to_string()],
),
},
+ (),
)
.expect("should have invoked op");
assert_eq!(actual, json!(true));
+ let state = state.borrow::<State>();
assert_eq!(state.emitted_files.len(), 1);
assert!(state.maybe_tsbuildinfo.is_none());
assert_eq!(
@@ -956,16 +989,18 @@ mod tests {
#[tokio::test]
async fn test_emit_tsbuildinfo() {
let mut state = setup(None, None, None).await;
- let actual = op_emit(
+ let actual = op_emit::call(
&mut state,
EmitArgs {
data: "some file content".to_string(),
file_name: "deno:///.tsbuildinfo".to_string(),
maybe_specifiers: None,
},
+ (),
)
.expect("should have invoked op");
assert_eq!(actual, json!(true));
+ let state = state.borrow::<State>();
assert_eq!(state.emitted_files.len(), 0);
assert_eq!(
state.maybe_tsbuildinfo,
@@ -981,9 +1016,10 @@ mod tests {
Some("some content".to_string()),
)
.await;
- let actual = op_load(
+ let actual = op_load::call(
&mut state,
json!({ "specifier": "https://deno.land/x/mod.ts"}),
+ (),
)
.expect("should have invoked op");
assert_eq!(
@@ -1012,9 +1048,12 @@ mod tests {
Some("some content".to_string()),
)
.await;
- let value =
- op_load(&mut state, json!({ "specifier": "asset:///lib.dom.d.ts" }))
- .expect("should have invoked op");
+ let value = op_load::call(
+ &mut state,
+ json!({ "specifier": "asset:///lib.dom.d.ts" }),
+ (),
+ )
+ .expect("should have invoked op");
let actual: LoadResponse =
serde_json::from_value(value).expect("failed to deserialize");
let expected = get_asset("lib.dom.d.ts").unwrap();
@@ -1031,9 +1070,12 @@ mod tests {
Some("some content".to_string()),
)
.await;
- let actual =
- op_load(&mut state, json!({ "specifier": "deno:///.tsbuildinfo"}))
- .expect("should have invoked op");
+ let actual = op_load::call(
+ &mut state,
+ json!({ "specifier": "deno:///.tsbuildinfo"}),
+ (),
+ )
+ .expect("should have invoked op");
assert_eq!(
actual,
json!({
@@ -1047,9 +1089,10 @@ mod tests {
#[tokio::test]
async fn test_load_missing_specifier() {
let mut state = setup(None, None, None).await;
- let actual = op_load(
+ let actual = op_load::call(
&mut state,
json!({ "specifier": "https://deno.land/x/mod.ts"}),
+ (),
)
.expect("should have invoked op");
assert_eq!(
@@ -1070,12 +1113,13 @@ mod tests {
None,
)
.await;
- let actual = op_resolve(
+ let actual = op_resolve::call(
&mut state,
ResolveArgs {
base: "https://deno.land/x/a.ts".to_string(),
specifiers: vec!["./b.ts".to_string()],
},
+ (),
)
.expect("should have invoked op");
assert_eq!(actual, json!([["https://deno.land/x/b.ts", ".ts"]]));
@@ -1089,12 +1133,13 @@ mod tests {
None,
)
.await;
- let actual = op_resolve(
+ let actual = op_resolve::call(
&mut state,
ResolveArgs {
base: "https://deno.land/x/a.ts".to_string(),
specifiers: vec!["./bad.ts".to_string()],
},
+ (),
)
.expect("should have not errored");
assert_eq!(
@@ -1106,7 +1151,7 @@ mod tests {
#[tokio::test]
async fn test_respond() {
let mut state = setup(None, None, None).await;
- let actual = op_respond(
+ let actual = op_respond::call(
&mut state,
json!({
"diagnostics": [
@@ -1118,9 +1163,11 @@ mod tests {
],
"stats": [["a", 12]]
}),
+ (),
)
.expect("should have invoked op");
assert_eq!(actual, json!(true));
+ let state = state.borrow::<State>();
assert_eq!(
state.maybe_response,
Some(RespondArgs {
diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js
index 7215360a0..c124703a8 100644
--- a/cli/tsc/99_main_compiler.js
+++ b/cli/tsc/99_main_compiler.js
@@ -921,6 +921,7 @@ delete Object.prototype.__proto__;
// A build time only op that provides some setup information that is used to
// ensure the snapshot is setup properly.
/** @type {{ buildSpecifier: string; libs: string[] }} */
+
const { buildSpecifier, libs } = core.opSync("op_build_info", {});
for (const lib of libs) {
const specifier = `lib.${lib}.d.ts`;
diff --git a/core/01_core.js b/core/01_core.js
index b6c72e5d2..747d69241 100644
--- a/core/01_core.js
+++ b/core/01_core.js
@@ -16,7 +16,6 @@
ErrorCaptureStackTrace,
Promise,
ObjectEntries,
- ObjectFreeze,
ObjectFromEntries,
MapPrototypeGet,
MapPrototypeDelete,
@@ -27,11 +26,12 @@
ObjectAssign,
SymbolFor,
} = window.__bootstrap.primordials;
+ const ops = window.Deno.core.ops;
+ const opIds = Object.keys(ops).reduce((a, v, i) => ({ ...a, [v]: i }), {});
// Available on start due to bindings.
- const { opcallSync, opcallAsync, refOp_, unrefOp_ } = window.Deno.core;
+ const { refOp_, unrefOp_ } = window.Deno.core;
- let opsCache = {};
const errorMap = {};
// Builtin v8 / JS errors
registerErrorClass("Error", Error);
@@ -110,15 +110,6 @@
return promiseRing[idx] != NO_PROMISE;
}
- function ops() {
- return opsCache;
- }
-
- function syncOpsCache() {
- // op id 0 is a special value to retrieve the map of registered ops.
- opsCache = ObjectFreeze(ObjectFromEntries(opcallSync(0)));
- }
-
function opresolve() {
for (let i = 0; i < arguments.length; i += 2) {
const promiseId = arguments[i];
@@ -160,7 +151,7 @@
function opAsync(opName, arg1 = null, arg2 = null) {
const promiseId = nextPromiseId++;
- const maybeError = opcallAsync(opsCache[opName], promiseId, arg1, arg2);
+ const maybeError = ops[opName](opIds[opName], promiseId, arg1, arg2);
// Handle sync error (e.g: error parsing args)
if (maybeError) return unwrapOpResult(maybeError);
let p = PromisePrototypeThen(setPromise(promiseId), unwrapOpResult);
@@ -179,8 +170,8 @@
return p;
}
- function opSync(opName, arg1 = null, arg2 = null) {
- return unwrapOpResult(opcallSync(opsCache[opName], arg1, arg2));
+ function opSync(opName, arg1, arg2) {
+ return unwrapOpResult(ops[opName](opIds[opName], arg1, arg2));
}
function refOp(promiseId) {
@@ -228,7 +219,7 @@
function metrics() {
const [aggregate, perOps] = opSync("op_metrics");
aggregate.ops = ObjectFromEntries(ArrayPrototypeMap(
- ObjectEntries(opsCache),
+ ObjectEntries(opIds),
([opName, opId]) => [opName, perOps[opId]],
));
return aggregate;
@@ -257,7 +248,6 @@
const core = ObjectAssign(globalThis.Deno.core, {
opAsync,
opSync,
- ops,
close,
tryClose,
read,
@@ -269,7 +259,6 @@
registerErrorBuilder,
registerErrorClass,
opresolve,
- syncOpsCache,
BadResource,
BadResourcePrototype,
Interrupted,
diff --git a/core/Cargo.toml b/core/Cargo.toml
index db18b025e..b8ae6bff4 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -14,6 +14,7 @@ path = "lib.rs"
[dependencies]
anyhow = "1.0.55"
+deno_ops = { path = "../ops", version = "0.1.0" }
futures = "0.3.21"
indexmap = "1.7.0"
libc = "0.2.106"
diff --git a/core/bindings.rs b/core/bindings.rs
index f84711abf..4e5c68675 100644
--- a/core/bindings.rs
+++ b/core/bindings.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::error::is_instance_of_error;
+use crate::extensions::OpPair;
use crate::modules::get_module_type_from_assertions;
use crate::modules::parse_import_assertions;
use crate::modules::validate_import_assertions;
@@ -8,21 +9,18 @@ use crate::modules::ImportAssertionsKind;
use crate::modules::ModuleMap;
use crate::resolve_url_or_path;
use crate::JsRuntime;
-use crate::Op;
-use crate::OpId;
-use crate::OpPayload;
-use crate::OpResult;
-use crate::OpTable;
+use crate::OpState;
use crate::PromiseId;
use crate::ZeroCopyBuf;
use anyhow::Error;
use log::debug;
-use once_cell::sync::Lazy;
use serde::Deserialize;
use serde::Serialize;
use serde_v8::to_v8;
use std::cell::RefCell;
use std::option::Option;
+use std::os::raw::c_void;
+use std::rc::Rc;
use url::Url;
use v8::HandleScope;
use v8::Local;
@@ -31,88 +29,88 @@ use v8::SharedArrayBuffer;
use v8::ValueDeserializerHelper;
use v8::ValueSerializerHelper;
-const UNDEFINED_OP_ID_MSG: &str =
- "invalid op id: received `undefined` instead of an integer.
-This error is often caused by a typo in an op name, or not calling
-JsRuntime::sync_ops_cache() after JsRuntime initialization.";
-
-pub static EXTERNAL_REFERENCES: Lazy<v8::ExternalReferences> =
- Lazy::new(|| {
- v8::ExternalReferences::new(&[
- v8::ExternalReference {
- function: opcall_async.map_fn_to(),
- },
- v8::ExternalReference {
- function: opcall_sync.map_fn_to(),
- },
- v8::ExternalReference {
- function: ref_op.map_fn_to(),
- },
- v8::ExternalReference {
- function: unref_op.map_fn_to(),
- },
- v8::ExternalReference {
- function: set_macrotask_callback.map_fn_to(),
- },
- v8::ExternalReference {
- function: set_nexttick_callback.map_fn_to(),
- },
- v8::ExternalReference {
- function: set_promise_reject_callback.map_fn_to(),
- },
- v8::ExternalReference {
- function: set_uncaught_exception_callback.map_fn_to(),
- },
- v8::ExternalReference {
- function: run_microtasks.map_fn_to(),
- },
- v8::ExternalReference {
- function: has_tick_scheduled.map_fn_to(),
- },
- v8::ExternalReference {
- function: set_has_tick_scheduled.map_fn_to(),
- },
- v8::ExternalReference {
- function: eval_context.map_fn_to(),
- },
- v8::ExternalReference {
- function: queue_microtask.map_fn_to(),
- },
- v8::ExternalReference {
- function: create_host_object.map_fn_to(),
- },
- v8::ExternalReference {
- function: encode.map_fn_to(),
- },
- v8::ExternalReference {
- function: decode.map_fn_to(),
- },
- v8::ExternalReference {
- function: serialize.map_fn_to(),
- },
- v8::ExternalReference {
- function: deserialize.map_fn_to(),
- },
- v8::ExternalReference {
- function: get_promise_details.map_fn_to(),
- },
- v8::ExternalReference {
- function: get_proxy_details.map_fn_to(),
- },
- v8::ExternalReference {
- function: is_proxy.map_fn_to(),
- },
- v8::ExternalReference {
- function: memory_usage.map_fn_to(),
- },
- v8::ExternalReference {
- function: call_console.map_fn_to(),
- },
- v8::ExternalReference {
- function: set_wasm_streaming_callback.map_fn_to(),
- },
- ])
+pub fn external_references(
+ ops: &[OpPair],
+ op_state: Rc<RefCell<OpState>>,
+) -> v8::ExternalReferences {
+ let mut refs = vec![
+ v8::ExternalReference {
+ function: ref_op.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: unref_op.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: set_macrotask_callback.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: set_nexttick_callback.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: set_promise_reject_callback.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: set_uncaught_exception_callback.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: run_microtasks.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: has_tick_scheduled.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: set_has_tick_scheduled.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: eval_context.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: queue_microtask.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: create_host_object.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: encode.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: decode.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: serialize.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: deserialize.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: get_promise_details.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: get_proxy_details.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: is_proxy.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: memory_usage.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: call_console.map_fn_to(),
+ },
+ v8::ExternalReference {
+ function: set_wasm_streaming_callback.map_fn_to(),
+ },
+ ];
+ let op_refs = ops
+ .iter()
+ .map(|(_, opref)| v8::ExternalReference { function: *opref });
+ refs.extend(op_refs);
+ let raw_op_state = Rc::as_ptr(&op_state) as *mut c_void;
+ refs.push(v8::ExternalReference {
+ pointer: raw_op_state,
});
+ v8::ExternalReferences::new(&refs)
+}
pub fn script_origin<'a>(
s: &mut v8::HandleScope<'a>,
@@ -154,6 +152,9 @@ pub fn module_origin<'a>(
pub fn initialize_context<'s>(
scope: &mut v8::HandleScope<'s, ()>,
+ ops: &[OpPair],
+ snapshot_loaded: bool,
+ op_state: Rc<RefCell<OpState>>,
) -> v8::Local<'s, v8::Context> {
let scope = &mut v8::EscapableHandleScope::new(scope);
@@ -162,17 +163,43 @@ pub fn initialize_context<'s>(
let scope = &mut v8::ContextScope::new(scope, context);
- // global.Deno = { core: {} };
let deno_key = v8::String::new(scope, "Deno").unwrap();
+ let core_key = v8::String::new(scope, "core").unwrap();
+ let ops_key = v8::String::new(scope, "ops").unwrap();
+ // Snapshot already registered `Deno.core.ops` but
+ // extensions may provide ops that aren't part of the snapshot.
+ //
+ // TODO(@littledivy): This is extra complexity for
+ // a really weird usecase. Remove this once all
+ // tsc ops are static at snapshot time.
+ if snapshot_loaded {
+ // Grab Deno.core.ops object
+ let deno_val = global.get(scope, deno_key.into()).unwrap();
+ let deno_val = v8::Local::<v8::Object>::try_from(deno_val)
+ .expect("`Deno` not in global scope.");
+ let core_val = deno_val.get(scope, core_key.into()).unwrap();
+ let core_val = v8::Local::<v8::Object>::try_from(core_val)
+ .expect("`Deno.core` not in global scope");
+ let ops_val = core_val.get(scope, ops_key.into()).unwrap();
+ let ops_val = v8::Local::<v8::Object>::try_from(ops_val)
+ .expect("`Deno.core.ops` not in global scope");
+
+ let raw_op_state = Rc::as_ptr(&op_state) as *const c_void;
+ for (name, opfn) in ops {
+ set_func_raw(scope, ops_val, name, *opfn, raw_op_state);
+ }
+ return scope.escape(context);
+ }
+
+ // global.Deno = { core: { ops: {} } };
let deno_val = v8::Object::new(scope);
global.set(scope, deno_key.into(), deno_val.into());
- let core_key = v8::String::new(scope, "core").unwrap();
let core_val = v8::Object::new(scope);
deno_val.set(scope, core_key.into(), core_val.into());
+ let ops_val = v8::Object::new(scope);
+ core_val.set(scope, ops_key.into(), ops_val.into());
// Bind functions to Deno.core.*
- set_func(scope, core_val, "opcallSync", opcall_sync);
- set_func(scope, core_val, "opcallAsync", opcall_async);
set_func(scope, core_val, "refOp_", ref_op);
set_func(scope, core_val, "unrefOp_", unref_op);
set_func(
@@ -227,10 +254,14 @@ pub fn initialize_context<'s>(
// Direct bindings on `window`.
set_func(scope, global, "queueMicrotask", queue_microtask);
+ // Bind functions to Deno.core.ops.*
+ let raw_op_state = Rc::as_ptr(&op_state) as *const c_void;
+ for (name, opfn) in ops {
+ set_func_raw(scope, ops_val, name, *opfn, raw_op_state);
+ }
scope.escape(context)
}
-#[inline(always)]
pub fn set_func(
scope: &mut v8::HandleScope<'_>,
obj: v8::Local<v8::Object>,
@@ -238,8 +269,26 @@ pub fn set_func(
callback: impl v8::MapFnTo<v8::FunctionCallback>,
) {
let key = v8::String::new(scope, name).unwrap();
- let tmpl = v8::FunctionTemplate::new(scope, callback);
- let val = tmpl.get_function(scope).unwrap();
+ let val = v8::Function::new(scope, callback).unwrap();
+ val.set_name(key);
+ obj.set(scope, key.into(), val.into());
+}
+
+// Register a raw v8::FunctionCallback
+// with some external data.
+pub fn set_func_raw(
+ scope: &mut v8::HandleScope<'_>,
+ obj: v8::Local<v8::Object>,
+ name: &'static str,
+ callback: v8::FunctionCallback,
+ external_data: *const c_void,
+) {
+ let key = v8::String::new(scope, name).unwrap();
+ let external = v8::External::new(scope, external_data as *mut c_void);
+ let val = v8::Function::builder_raw(callback)
+ .data(external.into())
+ .build(scope)
+ .unwrap();
val.set_name(key);
obj.set(scope, key.into(), val.into());
}
@@ -460,137 +509,6 @@ pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) {
}
}
-fn opcall_sync<'s>(
- scope: &mut v8::HandleScope<'s>,
- args: v8::FunctionCallbackArguments,
- mut rv: v8::ReturnValue,
-) {
- let state_rc = JsRuntime::state(scope);
- let state = state_rc.borrow_mut();
-
- let op_id = match v8::Local::<v8::Integer>::try_from(args.get(0))
- .map(|l| l.value() as OpId)
- .map_err(Error::from)
- {
- Ok(op_id) => op_id,
- Err(err) => {
- let msg = if args.get(0).is_undefined() {
- UNDEFINED_OP_ID_MSG.to_string()
- } else {
- format!("invalid op id: {}", err)
- };
- throw_type_error(scope, msg);
- return;
- }
- };
-
- // opcall(0) returns obj of all ops, handle as special case
- if op_id == 0 {
- // TODO: Serialize as HashMap when serde_v8 supports maps ...
- let ops = OpTable::op_entries(state.op_state.clone());
- rv.set(to_v8(scope, ops).unwrap());
- return;
- }
-
- // Deserializable args (may be structured args or ZeroCopyBuf)
- let a = args.get(1);
- let b = args.get(2);
-
- let payload = OpPayload {
- scope,
- a,
- b,
- op_id,
- promise_id: 0,
- };
- let op = OpTable::route_op(op_id, state.op_state.clone(), payload);
- match op {
- Op::Sync(result) => {
- state.op_state.borrow().tracker.track_sync(op_id);
- rv.set(result.to_v8(scope).unwrap());
- }
- Op::NotFound => {
- throw_type_error(scope, format!("Unknown op id: {}", op_id));
- }
- // Async ops (ref or unref)
- _ => {
- throw_type_error(
- scope,
- format!("Can not call an async op [{}] with opSync()", op_id),
- );
- }
- }
-}
-
-fn opcall_async<'s>(
- scope: &mut v8::HandleScope<'s>,
- args: v8::FunctionCallbackArguments,
- mut rv: v8::ReturnValue,
-) {
- let state_rc = JsRuntime::state(scope);
- let mut state = state_rc.borrow_mut();
-
- let op_id = match v8::Local::<v8::Integer>::try_from(args.get(0))
- .map(|l| l.value() as OpId)
- .map_err(Error::from)
- {
- Ok(op_id) => op_id,
- Err(err) => {
- let msg = if args.get(0).is_undefined() {
- UNDEFINED_OP_ID_MSG.to_string()
- } else {
- format!("invalid op id: {}", err)
- };
- throw_type_error(scope, msg);
- return;
- }
- };
-
- // PromiseId
- let arg1 = args.get(1);
- let promise_id = v8::Local::<v8::Integer>::try_from(arg1)
- .map(|l| l.value() as PromiseId)
- .map_err(Error::from);
- // Fail if promise id invalid (not an int)
- let promise_id: PromiseId = match promise_id {
- Ok(promise_id) => promise_id,
- Err(err) => {
- throw_type_error(scope, format!("invalid promise id: {}", err));
- return;
- }
- };
-
- // Deserializable args (may be structured args or ZeroCopyBuf)
- let a = args.get(2);
- let b = args.get(3);
-
- let payload = OpPayload {
- scope,
- a,
- b,
- op_id,
- promise_id,
- };
- let op = OpTable::route_op(op_id, state.op_state.clone(), payload);
- match op {
- Op::Sync(result) => match result {
- OpResult::Ok(_) => throw_type_error(
- scope,
- format!("Can not call a sync op [{}] with opAsync()", op_id),
- ),
- OpResult::Err(_) => rv.set(result.to_v8(scope).unwrap()),
- },
- Op::Async(fut) => {
- state.op_state.borrow().tracker.track_async(op_id);
- state.pending_ops.push(fut);
- state.have_unpolled_ops = true;
- }
- Op::NotFound => {
- throw_type_error(scope, format!("Unknown op id: {}", op_id));
- }
- }
-}
-
fn ref_op<'s>(
scope: &mut v8::HandleScope<'s>,
args: v8::FunctionCallbackArguments,
@@ -1471,7 +1389,7 @@ fn is_proxy(
rv.set(v8::Boolean::new(scope, args.get(0).is_proxy()).into())
}
-fn throw_type_error(scope: &mut v8::HandleScope, message: impl AsRef<str>) {
+pub fn throw_type_error(scope: &mut v8::HandleScope, message: impl AsRef<str>) {
let message = v8::String::new(scope, message.as_ref()).unwrap();
let exception = v8::Exception::type_error(scope, message);
scope.throw_exception(exception);
diff --git a/core/error_codes.rs b/core/error_codes.rs
index 43a6c4391..b34cbe639 100644
--- a/core/error_codes.rs
+++ b/core/error_codes.rs
@@ -1,6 +1,6 @@
use anyhow::Error;
-pub(crate) fn get_error_code(err: &Error) -> Option<&'static str> {
+pub fn get_error_code(err: &Error) -> Option<&'static str> {
err
.downcast_ref::<std::io::Error>()
.map(|e| match e.raw_os_error() {
diff --git a/core/examples/disable_ops.rs b/core/examples/disable_ops.rs
index 0612845c8..9565d6e7f 100644
--- a/core/examples/disable_ops.rs
+++ b/core/examples/disable_ops.rs
@@ -9,7 +9,7 @@ use deno_core::RuntimeOptions;
fn main() {
let my_ext = Extension::builder()
.middleware(|name, opfn| match name {
- "op_print" => deno_core::void_op_sync(),
+ "op_print" => deno_core::void_op_sync::v8_cb(),
_ => opfn,
})
.build();
diff --git a/core/examples/hello_world.rs b/core/examples/hello_world.rs
index 42c9779f3..bfca5447c 100644
--- a/core/examples/hello_world.rs
+++ b/core/examples/hello_world.rs
@@ -2,27 +2,37 @@
//! This example shows you how to define ops in Rust and then call them from
//! JavaScript.
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::Extension;
use deno_core::JsRuntime;
+use deno_core::OpState;
use deno_core::RuntimeOptions;
+// This is a hack to make the `#[op]` macro work with
+// deno_core examples.
+// You can remove this:
+use deno_core::*;
+
+#[op]
+fn op_sum(
+ _state: &mut OpState,
+ nums: Vec<f64>,
+ _: (),
+) -> Result<f64, deno_core::error::AnyError> {
+ // Sum inputs
+ let sum = nums.iter().fold(0.0, |a, v| a + v);
+ // return as a Result<f64, AnyError>
+ Ok(sum)
+}
+
fn main() {
// Build a deno_core::Extension providing custom ops
let ext = Extension::builder()
.ops(vec![
// An op for summing an array of numbers
- (
- "op_sum",
- // The op-layer automatically deserializes inputs
- // and serializes the returned Result & value
- op_sync(|_state, nums: Vec<f64>, _: ()| {
- // Sum inputs
- let sum = nums.iter().fold(0.0, |a, v| a + v);
- // return as a Result<f64, AnyError>
- Ok(sum)
- }),
- ),
+ // The op-layer automatically deserializes inputs
+ // and serializes the returned Result & value
+ op_sum::decl(),
])
.build();
diff --git a/core/examples/http_bench_json_ops.js b/core/examples/http_bench_json_ops.js
index 22e1b468c..5b16776f4 100644
--- a/core/examples/http_bench_json_ops.js
+++ b/core/examples/http_bench_json_ops.js
@@ -11,12 +11,12 @@ const responseBuf = new Uint8Array(
/** Listens on 0.0.0.0:4500, returns rid. */
function listen() {
- return Deno.core.opSync("listen");
+ return Deno.core.opSync("op_listen");
}
/** Accepts a connection, returns rid. */
function accept(serverRid) {
- return Deno.core.opAsync("accept", serverRid);
+ return Deno.core.opAsync("op_accept", serverRid);
}
async function serve(rid) {
diff --git a/core/examples/http_bench_json_ops.rs b/core/examples/http_bench_json_ops.rs
index 9e60df4a4..3f608eeae 100644
--- a/core/examples/http_bench_json_ops.rs
+++ b/core/examples/http_bench_json_ops.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::anyhow::Error;
+use deno_core::op;
use deno_core::AsyncRefCell;
use deno_core::AsyncResult;
use deno_core::CancelHandle;
@@ -17,6 +18,11 @@ use std::rc::Rc;
use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt;
+// This is a hack to make the `#[op]` macro work with
+// deno_core examples.
+// You can remove this:
+use deno_core::*;
+
struct Logger;
impl log::Log for Logger {
@@ -119,10 +125,7 @@ impl From<tokio::net::TcpStream> for TcpStream {
fn create_js_runtime() -> JsRuntime {
let ext = deno_core::Extension::builder()
- .ops(vec![
- ("listen", deno_core::op_sync(op_listen)),
- ("accept", deno_core::op_async(op_accept)),
- ])
+ .ops(vec![op_listen::decl(), op_accept::decl()])
.build();
JsRuntime::new(deno_core::RuntimeOptions {
@@ -131,6 +134,7 @@ fn create_js_runtime() -> JsRuntime {
})
}
+#[op]
fn op_listen(state: &mut OpState, _: (), _: ()) -> Result<ResourceId, Error> {
log::debug!("listen");
let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap();
@@ -141,6 +145,7 @@ fn op_listen(state: &mut OpState, _: (), _: ()) -> Result<ResourceId, Error> {
Ok(rid)
}
+#[op]
async fn op_accept(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
diff --git a/core/examples/schedule_task.rs b/core/examples/schedule_task.rs
index 2f4909b4f..3ada86417 100644
--- a/core/examples/schedule_task.rs
+++ b/core/examples/schedule_task.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::anyhow::Error;
+use deno_core::op;
use deno_core::Extension;
use deno_core::JsRuntime;
use deno_core::OpState;
@@ -9,14 +10,16 @@ use futures::channel::mpsc;
use futures::stream::StreamExt;
use std::task::Poll;
+// This is a hack to make the `#[op]` macro work with
+// deno_core examples.
+// You can remove this:
+use deno_core::*;
+
type Task = Box<dyn FnOnce()>;
fn main() {
let my_ext = Extension::builder()
- .ops(vec![(
- "op_schedule_task",
- deno_core::op_sync(op_schedule_task),
- )])
+ .ops(vec![op_schedule_task::decl()])
.event_loop_middleware(|state, cx| {
let recv = state.borrow_mut::<mpsc::UnboundedReceiver<Task>>();
let mut ref_loop = false;
@@ -58,6 +61,7 @@ fn main() {
runtime.block_on(future).unwrap();
}
+#[op]
fn op_schedule_task(state: &mut OpState, i: u8, _: ()) -> Result<(), Error> {
let tx = state.borrow_mut::<mpsc::UnboundedSender<Task>>();
tx.unbounded_send(Box::new(move || println!("Hello, world! x{}", i)))
diff --git a/core/extensions.rs b/core/extensions.rs
index 031cb073a..7361165f0 100644
--- a/core/extensions.rs
+++ b/core/extensions.rs
@@ -1,12 +1,13 @@
-use crate::OpFn;
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::OpState;
use anyhow::Error;
use std::task::Context;
pub type SourcePair = (&'static str, Box<SourceLoadFn>);
pub type SourceLoadFn = dyn Fn() -> Result<String, Error>;
-pub type OpPair = (&'static str, Box<OpFn>);
-pub type OpMiddlewareFn = dyn Fn(&'static str, Box<OpFn>) -> Box<OpFn>;
+pub type OpFnRef = v8::FunctionCallback;
+pub type OpPair = (&'static str, OpFnRef);
+pub type OpMiddlewareFn = dyn Fn(&'static str, OpFnRef) -> OpFnRef;
pub type OpStateFn = dyn Fn(&mut OpState) -> Result<(), Error>;
pub type OpEventLoopFn = dyn Fn(&mut OpState, &mut Context) -> bool;
@@ -108,7 +109,7 @@ impl ExtensionBuilder {
pub fn middleware<F>(&mut self, middleware_fn: F) -> &mut Self
where
- F: Fn(&'static str, Box<OpFn>) -> Box<OpFn> + 'static,
+ F: Fn(&'static str, OpFnRef) -> OpFnRef + 'static,
{
self.middleware = Some(Box::new(middleware_fn));
self
diff --git a/core/lib.rs b/core/lib.rs
index 2f46c1ffc..29cdbba01 100644
--- a/core/lib.rs
+++ b/core/lib.rs
@@ -13,7 +13,6 @@ mod modules;
mod normalize_path;
mod ops;
mod ops_builtin;
-mod ops_json;
mod ops_metrics;
mod resources;
mod runtime;
@@ -44,6 +43,10 @@ pub use crate::async_cell::AsyncRefCell;
pub use crate::async_cell::AsyncRefFuture;
pub use crate::async_cell::RcLike;
pub use crate::async_cell::RcRef;
+pub use crate::extensions::Extension;
+pub use crate::extensions::ExtensionBuilder;
+pub use crate::extensions::OpMiddlewareFn;
+pub use crate::extensions::OpPair;
pub use crate::flags::v8_set_flags;
pub use crate::inspector::InspectorMsg;
pub use crate::inspector::InspectorMsgKind;
@@ -65,24 +68,21 @@ pub use crate::modules::ModuleSourceFuture;
pub use crate::modules::ModuleType;
pub use crate::modules::NoopModuleLoader;
pub use crate::normalize_path::normalize_path;
-pub use crate::ops::serialize_op_result;
pub use crate::ops::Op;
pub use crate::ops::OpAsyncFuture;
pub use crate::ops::OpCall;
+pub use crate::ops::OpError;
pub use crate::ops::OpFn;
pub use crate::ops::OpId;
-pub use crate::ops::OpPayload;
pub use crate::ops::OpResult;
pub use crate::ops::OpState;
-pub use crate::ops::OpTable;
pub use crate::ops::PromiseId;
pub use crate::ops_builtin::op_close;
pub use crate::ops_builtin::op_print;
pub use crate::ops_builtin::op_resources;
-pub use crate::ops_json::op_async;
-pub use crate::ops_json::op_sync;
-pub use crate::ops_json::void_op_async;
-pub use crate::ops_json::void_op_sync;
+pub use crate::ops_builtin::void_op_async;
+pub use crate::ops_builtin::void_op_sync;
+pub use crate::ops_metrics::OpsTracker;
pub use crate::resources::AsyncResult;
pub use crate::resources::Resource;
pub use crate::resources::ResourceId;
@@ -95,16 +95,21 @@ pub use crate::runtime::JsRuntime;
pub use crate::runtime::RuntimeOptions;
pub use crate::runtime::SharedArrayBufferStore;
pub use crate::runtime::Snapshot;
-// pub use crate::runtime_modules::include_js_files!;
-pub use crate::extensions::Extension;
-pub use crate::extensions::ExtensionBuilder;
-pub use crate::extensions::OpMiddlewareFn;
-pub use crate::extensions::OpPair;
+pub use deno_ops::op;
pub fn v8_version() -> &'static str {
v8::V8::get_version()
}
+/// An internal module re-exporting funcs used by the #[op] (`deno_ops`) macro
+#[doc(hidden)]
+pub mod _ops {
+ pub use super::bindings::throw_type_error;
+ pub use super::error_codes::get_error_code;
+ pub use super::ops::to_op_result;
+ pub use super::runtime::queue_async_op;
+}
+
/// A helper macro that will return a call site in Rust code. Should be
/// used when executing internal one-line scripts for JsRuntime lifecycle.
///
diff --git a/core/modules.rs b/core/modules.rs
index d4a0a86ef..7c5274193 100644
--- a/core/modules.rs
+++ b/core/modules.rs
@@ -1073,13 +1073,11 @@ impl ModuleMap {
#[cfg(test)]
mod tests {
use super::*;
- use crate::ops::OpCall;
- use crate::serialize_op_result;
+ use crate::error::AnyError;
use crate::Extension;
use crate::JsRuntime;
- use crate::Op;
- use crate::OpPayload;
use crate::RuntimeOptions;
+ use deno_ops::op;
use futures::future::FutureExt;
use parking_lot::Mutex;
use std::fmt;
@@ -1088,6 +1086,10 @@ mod tests {
use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
+ // deno_ops macros generate code assuming deno_core in scope.
+ mod deno_core {
+ pub use crate::*;
+ }
// TODO(ry) Sadly FuturesUnordered requires the current task to be set. So
// even though we are only using poll() in these tests and not Tokio, we must
@@ -1401,20 +1403,16 @@ import "/a.js";
let loader = Rc::new(ModsLoader::default());
let resolve_count = loader.count.clone();
- let dispatch_count = Arc::new(AtomicUsize::new(0));
- let dispatch_count_ = dispatch_count.clone();
+ static DISPATCH_COUNT: AtomicUsize = AtomicUsize::new(0);
- let op_test = move |state, payload: OpPayload| -> Op {
- dispatch_count_.fetch_add(1, Ordering::Relaxed);
- let (control, _): (u8, ()) = payload.deserialize().unwrap();
+ #[op]
+ fn op_test(_: &mut OpState, control: u8, _: ()) -> Result<u8, AnyError> {
+ DISPATCH_COUNT.fetch_add(1, Ordering::Relaxed);
assert_eq!(control, 42);
- let resp = (0, 1, serialize_op_result(Ok(43), state));
- Op::Async(OpCall::ready(resp))
- };
+ Ok(43)
+ }
- let ext = Extension::builder()
- .ops(vec![("op_test", Box::new(op_test))])
- .build();
+ let ext = Extension::builder().ops(vec![op_test::decl()]).build();
let mut runtime = JsRuntime::new(RuntimeOptions {
extensions: vec![ext],
@@ -1435,7 +1433,7 @@ import "/a.js";
)
.unwrap();
- assert_eq!(dispatch_count.load(Ordering::Relaxed), 0);
+ assert_eq!(DISPATCH_COUNT.load(Ordering::Relaxed), 0);
let module_map_rc = JsRuntime::module_map(runtime.v8_isolate());
@@ -1452,12 +1450,12 @@ import "/a.js";
import { b } from './b.js'
if (b() != 'b') throw Error();
let control = 42;
- Deno.core.opAsync("op_test", control);
+ Deno.core.opSync("op_test", control);
"#,
)
.unwrap();
- assert_eq!(dispatch_count.load(Ordering::Relaxed), 0);
+ assert_eq!(DISPATCH_COUNT.load(Ordering::Relaxed), 0);
let imports = module_map.get_requested_modules(mod_a);
assert_eq!(
imports,
@@ -1481,14 +1479,14 @@ import "/a.js";
};
runtime.instantiate_module(mod_b).unwrap();
- assert_eq!(dispatch_count.load(Ordering::Relaxed), 0);
+ assert_eq!(DISPATCH_COUNT.load(Ordering::Relaxed), 0);
assert_eq!(resolve_count.load(Ordering::SeqCst), 1);
runtime.instantiate_module(mod_a).unwrap();
- assert_eq!(dispatch_count.load(Ordering::Relaxed), 0);
+ assert_eq!(DISPATCH_COUNT.load(Ordering::Relaxed), 0);
let _ = runtime.mod_evaluate(mod_a);
- assert_eq!(dispatch_count.load(Ordering::Relaxed), 1);
+ assert_eq!(DISPATCH_COUNT.load(Ordering::Relaxed), 1);
}
#[test]
@@ -1766,7 +1764,6 @@ import "/a.js";
module_loader: Some(loader),
..Default::default()
});
- runtime.sync_ops_cache();
runtime
.execute_script(
"file:///dyn_import3.js",
diff --git a/core/ops.rs b/core/ops.rs
index 50197c9be..42718b8ff 100644
--- a/core/ops.rs
+++ b/core/ops.rs
@@ -1,10 +1,9 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-use crate::error::type_error;
use crate::gotham_state::GothamState;
-use crate::ops_metrics::OpsTracker;
use crate::resources::ResourceTable;
use crate::runtime::GetErrorClassFn;
+use crate::OpsTracker;
use anyhow::Error;
use futures::future::maybe_done;
use futures::future::FusedFuture;
@@ -12,23 +11,19 @@ use futures::future::MaybeDone;
use futures::ready;
use futures::task::noop_waker;
use futures::Future;
-use indexmap::IndexMap;
-use serde::de::DeserializeOwned;
use serde::Serialize;
-use std::cell::RefCell;
use std::cell::UnsafeCell;
-use std::iter::once;
use std::ops::Deref;
use std::ops::DerefMut;
use std::pin::Pin;
-use std::rc::Rc;
use std::task::Context;
use std::task::Poll;
/// Wrapper around a Future, which causes that Future to be polled immediately.
-/// (Background: ops are stored in a `FuturesUnordered` structure which polls
+///
+/// Background: ops are stored in a `FuturesUnordered` structure which polls
/// them, but without the `OpCall` wrapper this doesn't happen until the next
-/// turn of the event loop, which is too late for certain ops.)
+/// turn of the event loop, which is too late for certain ops.
pub struct OpCall<T>(MaybeDone<Pin<Box<dyn Future<Output = T>>>>);
impl<T> OpCall<T> {
@@ -83,32 +78,10 @@ where
pub type PromiseId = i32;
pub type OpAsyncFuture = OpCall<(PromiseId, OpId, OpResult)>;
-pub type OpFn = dyn Fn(Rc<RefCell<OpState>>, OpPayload) -> Op + 'static;
+pub type OpFn =
+ fn(&mut v8::HandleScope, v8::FunctionCallbackArguments, v8::ReturnValue);
pub type OpId = usize;
-pub struct OpPayload<'a, 'b, 'c> {
- pub(crate) scope: &'a mut v8::HandleScope<'b>,
- pub(crate) a: v8::Local<'c, v8::Value>,
- pub(crate) b: v8::Local<'c, v8::Value>,
- pub(crate) op_id: OpId,
- pub(crate) promise_id: PromiseId,
-}
-
-impl<'a, 'b, 'c> OpPayload<'a, 'b, 'c> {
- pub fn deserialize<T: DeserializeOwned, U: DeserializeOwned>(
- self,
- ) -> Result<(T, U), Error> {
- let a: T = serde_v8::from_v8(self.scope, self.a)
- .map_err(Error::from)
- .map_err(|e| type_error(format!("Error parsing args: {}", e)))?;
-
- let b: U = serde_v8::from_v8(self.scope, self.b)
- .map_err(Error::from)
- .map_err(|e| type_error(format!("Error parsing args: {}", e)))?;
- Ok((a, b))
- }
-}
-
pub enum Op {
Sync(OpResult),
Async(OpAsyncFuture),
@@ -141,39 +114,43 @@ pub struct OpError {
code: Option<&'static str>,
}
-pub fn serialize_op_result<R: Serialize + 'static>(
+impl OpError {
+ pub fn new(get_class: GetErrorClassFn, err: Error) -> Self {
+ Self {
+ class_name: (get_class)(&err),
+ message: err.to_string(),
+ code: crate::error_codes::get_error_code(&err),
+ }
+ }
+}
+
+pub fn to_op_result<R: Serialize + 'static>(
+ get_class: GetErrorClassFn,
result: Result<R, Error>,
- state: Rc<RefCell<OpState>>,
) -> OpResult {
match result {
Ok(v) => OpResult::Ok(v.into()),
- Err(err) => OpResult::Err(OpError {
- class_name: (state.borrow().get_error_class_fn)(&err),
- message: err.to_string(),
- code: crate::error_codes::get_error_code(&err),
- }),
+ Err(err) => OpResult::Err(OpError::new(get_class, err)),
}
}
/// Maintains the resources and ops inside a JS runtime.
pub struct OpState {
pub resource_table: ResourceTable,
- pub op_table: OpTable,
pub get_error_class_fn: GetErrorClassFn,
- pub(crate) tracker: OpsTracker,
+ pub tracker: OpsTracker,
gotham_state: GothamState,
}
impl OpState {
- pub(crate) fn new() -> OpState {
+ pub fn new(ops_count: usize) -> OpState {
OpState {
resource_table: Default::default(),
- op_table: OpTable::default(),
get_error_class_fn: &|_| "Error",
+ gotham_state: Default::default(),
tracker: OpsTracker {
- ops: UnsafeCell::new(Vec::with_capacity(256)),
+ ops: UnsafeCell::new(vec![Default::default(); ops_count]),
},
- gotham_state: Default::default(),
}
}
}
@@ -191,81 +168,3 @@ impl DerefMut for OpState {
&mut self.gotham_state
}
}
-
-/// Collection for storing registered ops. The special 'get_op_catalog'
-/// op with OpId `0` is automatically added when the OpTable is created.
-pub struct OpTable(IndexMap<String, Rc<OpFn>>);
-
-impl OpTable {
- pub fn register_op<F>(&mut self, name: &str, op_fn: F) -> OpId
- where
- F: Fn(Rc<RefCell<OpState>>, OpPayload) -> Op + 'static,
- {
- let (op_id, prev) = self.0.insert_full(name.to_owned(), Rc::new(op_fn));
- assert!(prev.is_none());
- op_id
- }
-
- pub fn op_entries(state: Rc<RefCell<OpState>>) -> Vec<(String, OpId)> {
- state.borrow().op_table.0.keys().cloned().zip(0..).collect()
- }
-
- pub fn route_op(
- op_id: OpId,
- state: Rc<RefCell<OpState>>,
- payload: OpPayload,
- ) -> Op {
- let op_fn = state
- .borrow()
- .op_table
- .0
- .get_index(op_id)
- .map(|(_, op_fn)| op_fn.clone());
- match op_fn {
- Some(f) => (f)(state, payload),
- None => Op::NotFound,
- }
- }
-}
-
-impl Default for OpTable {
- fn default() -> Self {
- fn dummy(_state: Rc<RefCell<OpState>>, _p: OpPayload) -> Op {
- unreachable!()
- }
- Self(once(("ops".to_owned(), Rc::new(dummy) as _)).collect())
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn op_table() {
- let state = Rc::new(RefCell::new(OpState::new()));
-
- let foo_id;
- let bar_id;
- {
- let op_table = &mut state.borrow_mut().op_table;
- foo_id =
- op_table.register_op("foo", |_, _| Op::Sync(OpResult::Ok(321.into())));
- assert_eq!(foo_id, 1);
- bar_id =
- op_table.register_op("bar", |_, _| Op::Sync(OpResult::Ok(123.into())));
- assert_eq!(bar_id, 2);
- }
-
- let mut catalog_entries = OpTable::op_entries(state);
- catalog_entries.sort_by(|(_, id1), (_, id2)| id1.partial_cmp(id2).unwrap());
- assert_eq!(
- catalog_entries,
- vec![
- ("ops".to_owned(), 0),
- ("foo".to_owned(), 1),
- ("bar".to_owned(), 2)
- ]
- );
- }
-}
diff --git a/core/ops_builtin.rs b/core/ops_builtin.rs
index d759bc5ba..14d8c6e39 100644
--- a/core/ops_builtin.rs
+++ b/core/ops_builtin.rs
@@ -1,16 +1,13 @@
use crate::error::type_error;
use crate::include_js_files;
-use crate::op_async;
-use crate::op_sync;
use crate::ops_metrics::OpMetrics;
use crate::resources::ResourceId;
-use crate::void_op_async;
-use crate::void_op_sync;
use crate::Extension;
use crate::OpState;
use crate::Resource;
use crate::ZeroCopyBuf;
use anyhow::Error;
+use deno_ops::op;
use std::cell::RefCell;
use std::io::{stderr, stdout, Write};
use std::rc::Rc;
@@ -24,29 +21,40 @@ pub(crate) fn init_builtins() -> Extension {
"02_error.js",
))
.ops(vec![
- ("op_close", op_sync(op_close)),
- ("op_try_close", op_sync(op_try_close)),
- ("op_print", op_sync(op_print)),
- ("op_resources", op_sync(op_resources)),
- ("op_wasm_streaming_feed", op_sync(op_wasm_streaming_feed)),
- ("op_wasm_streaming_abort", op_sync(op_wasm_streaming_abort)),
- (
- "op_wasm_streaming_set_url",
- op_sync(op_wasm_streaming_set_url),
- ),
- ("op_metrics", op_sync(op_metrics)),
- ("op_void_sync", void_op_sync()),
- ("op_void_async", void_op_async()),
- // TODO(@AaronO): track IO metrics for builtin streams
- ("op_read", op_async(op_read)),
- ("op_write", op_async(op_write)),
- ("op_shutdown", op_async(op_shutdown)),
+ op_close::decl(),
+ op_try_close::decl(),
+ op_print::decl(),
+ op_resources::decl(),
+ op_wasm_streaming_feed::decl(),
+ op_wasm_streaming_abort::decl(),
+ op_wasm_streaming_set_url::decl(),
+ op_void_sync::decl(),
+ op_void_async::decl(),
+ // // TODO(@AaronO): track IO metrics for builtin streams
+ op_read::decl(),
+ op_write::decl(),
+ op_shutdown::decl(),
+ op_metrics::decl(),
])
.build()
}
+#[op]
+pub fn void_op_sync(_: &mut OpState, _: (), _: ()) -> Result<(), Error> {
+ Ok(())
+}
+
+pub async fn void_op_async(
+ _state: Rc<RefCell<OpState>>,
+ _: (),
+ _: (),
+) -> Result<(), Error> {
+ Ok(())
+}
+
/// Return map of resources with id as key
/// and string representation as value.
+#[op]
pub fn op_resources(
state: &mut OpState,
_: (),
@@ -60,7 +68,22 @@ pub fn op_resources(
Ok(serialized_resources)
}
+#[op]
+pub fn op_void_sync(_state: &mut OpState, _: (), _: ()) -> Result<(), Error> {
+ Ok(())
+}
+
+#[op]
+pub async fn op_void_async(
+ _state: Rc<RefCell<OpState>>,
+ _: (),
+ _: (),
+) -> Result<(), Error> {
+ Ok(())
+}
+
/// Remove a resource from the resource table.
+#[op]
pub fn op_close(
state: &mut OpState,
rid: Option<ResourceId>,
@@ -75,6 +98,7 @@ pub fn op_close(
/// Try to remove a resource from the resource table. If there is no resource
/// with the specified `rid`, this is a no-op.
+#[op]
pub fn op_try_close(
state: &mut OpState,
rid: Option<ResourceId>,
@@ -87,7 +111,19 @@ pub fn op_try_close(
Ok(())
}
+#[op]
+pub fn op_metrics(
+ state: &mut OpState,
+ _: (),
+ _: (),
+) -> Result<(OpMetrics, Vec<OpMetrics>), Error> {
+ let aggregate = state.tracker.aggregate();
+ let per_op = state.tracker.per_op();
+ Ok((aggregate, per_op))
+}
+
/// Builtin utility to print to stdout/stderr
+#[op]
pub fn op_print(
_state: &mut OpState,
msg: String,
@@ -119,6 +155,7 @@ impl Resource for WasmStreamingResource {
}
/// Feed bytes to WasmStreamingResource.
+#[op]
pub fn op_wasm_streaming_feed(
state: &mut OpState,
rid: ResourceId,
@@ -133,6 +170,7 @@ pub fn op_wasm_streaming_feed(
}
/// Abort a WasmStreamingResource.
+#[op]
pub fn op_wasm_streaming_abort(
state: &mut OpState,
rid: ResourceId,
@@ -153,6 +191,7 @@ pub fn op_wasm_streaming_abort(
Ok(())
}
+#[op]
pub fn op_wasm_streaming_set_url(
state: &mut OpState,
rid: ResourceId,
@@ -166,16 +205,7 @@ pub fn op_wasm_streaming_set_url(
Ok(())
}
-pub fn op_metrics(
- state: &mut OpState,
- _: (),
- _: (),
-) -> Result<(OpMetrics, Vec<OpMetrics>), Error> {
- let aggregate = state.tracker.aggregate();
- let per_op = state.tracker.per_op();
- Ok((aggregate, per_op))
-}
-
+#[op]
async fn op_read(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -185,6 +215,7 @@ async fn op_read(
resource.read(buf).await.map(|n| n as u32)
}
+#[op]
async fn op_write(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -194,6 +225,7 @@ async fn op_write(
resource.write(buf).await.map(|n| n as u32)
}
+#[op]
async fn op_shutdown(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
diff --git a/core/ops_json.rs b/core/ops_json.rs
deleted file mode 100644
index 6d8af602f..000000000
--- a/core/ops_json.rs
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-
-use crate::ops::OpCall;
-use crate::serialize_op_result;
-use crate::Op;
-use crate::OpFn;
-use crate::OpState;
-use anyhow::Error;
-use serde::de::DeserializeOwned;
-use serde::Serialize;
-use std::cell::RefCell;
-use std::future::Future;
-use std::rc::Rc;
-
-/// A helper function that returns a sync NOP OpFn
-///
-/// It's mainly intended for embedders who want to disable ops, see ./examples/disable_ops.rs
-pub fn void_op_sync() -> Box<OpFn> {
- op_sync(|_, _: (), _: ()| Ok(()))
-}
-
-/// A helper function that returns an async NOP OpFn
-///
-/// It's mainly intended for embedders who want to disable ops, see ./examples/disable_ops.rs
-pub fn void_op_async() -> Box<OpFn> {
- op_async(|_, _: (), _: ()| futures::future::ok(()))
-}
-
-/// Creates an op that passes data synchronously using JSON.
-///
-/// The provided function `op_fn` has the following parameters:
-/// * `&mut OpState`: the op state, can be used to read/write resources in the runtime from an op.
-/// * `V`: the deserializable value that is passed to the Rust function.
-/// * `&mut [ZeroCopyBuf]`: raw bytes passed along, usually not needed if the JSON value is used.
-///
-/// `op_fn` returns a serializable value, which is directly returned to JavaScript.
-///
-/// When registering an op like this...
-/// ```ignore
-/// let mut runtime = JsRuntime::new(...);
-/// runtime.register_op("hello", deno_core::op_sync(Self::hello_op));
-/// runtime.sync_ops_cache();
-/// ```
-///
-/// ...it can be invoked from JS using the provided name, for example:
-/// ```js
-/// let result = Deno.core.opSync("hello", args);
-/// ```
-///
-/// `runtime.sync_ops_cache()` must be called after registering new ops
-/// A more complete example is available in the examples directory.
-pub fn op_sync<F, A, B, R>(op_fn: F) -> Box<OpFn>
-where
- F: Fn(&mut OpState, A, B) -> Result<R, Error> + 'static,
- A: DeserializeOwned,
- B: DeserializeOwned,
- R: Serialize + 'static,
-{
- Box::new(move |state, payload| -> Op {
- let result = payload
- .deserialize()
- .and_then(|(a, b)| op_fn(&mut state.borrow_mut(), a, b));
- Op::Sync(serialize_op_result(result, state))
- })
-}
-
-/// Creates an op that passes data asynchronously using JSON.
-///
-/// When this op is dispatched, the runtime doesn't exit while processing it.
-///
-/// The provided function `op_fn` has the following parameters:
-/// * `Rc<RefCell<OpState>`: the op state, can be used to read/write resources in the runtime from an op.
-/// * `V`: the deserializable value that is passed to the Rust function.
-/// * `BufVec`: raw bytes passed along, usually not needed if the JSON value is used.
-///
-/// `op_fn` returns a future, whose output is a serializable value. This value will be asynchronously
-/// returned to JavaScript.
-///
-/// When registering an op like this...
-/// ```ignore
-/// let mut runtime = JsRuntime::new(...);
-/// runtime.register_op("hello", deno_core::op_async(Self::hello_op));
-/// runtime.sync_ops_cache();
-/// ```
-///
-/// ...it can be invoked from JS using the provided name, for example:
-/// ```js
-/// let future = Deno.core.opAsync("hello", args);
-/// ```
-///
-/// `runtime.sync_ops_cache()` must be called after registering new ops
-/// A more complete example is available in the examples directory.
-pub fn op_async<F, A, B, R, RV>(op_fn: F) -> Box<OpFn>
-where
- F: Fn(Rc<RefCell<OpState>>, A, B) -> R + 'static,
- A: DeserializeOwned,
- B: DeserializeOwned,
- R: Future<Output = Result<RV, Error>> + 'static,
- RV: Serialize + 'static,
-{
- Box::new(move |state, payload| -> Op {
- let op_id = payload.op_id;
- let pid = payload.promise_id;
- // Deserialize args, sync error on failure
- let args = match payload.deserialize() {
- Ok(args) => args,
- Err(err) => {
- return Op::Sync(serialize_op_result(Err::<(), Error>(err), state))
- }
- };
- let (a, b) = args;
-
- use crate::futures::FutureExt;
- let fut = op_fn(state.clone(), a, b)
- .map(move |result| (pid, op_id, serialize_op_result(result, state)));
- Op::Async(OpCall::eager(fut))
- })
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[tokio::test]
- async fn op_async_stack_trace() {
- async fn op_throw(
- _state: Rc<RefCell<OpState>>,
- msg: Option<String>,
- _: (),
- ) -> Result<(), Error> {
- assert_eq!(msg.unwrap(), "hello");
- Err(crate::error::generic_error("foo"))
- }
-
- let ext = crate::Extension::builder()
- .ops(vec![("op_throw", op_async(op_throw))])
- .build();
-
- let mut runtime = crate::JsRuntime::new(crate::RuntimeOptions {
- extensions: vec![ext],
- ..Default::default()
- });
-
- runtime
- .execute_script(
- "<init>",
- r#"
- async function f1() {
- await Deno.core.opAsync('op_throw', 'hello');
- }
-
- async function f2() {
- await f1();
- }
-
- f2();
- "#,
- )
- .unwrap();
- let e = runtime.run_event_loop(false).await.unwrap_err().to_string();
- println!("{}", e);
- assert!(e.contains("Error: foo"));
- assert!(e.contains("at async f1 (<init>:"));
- assert!(e.contains("at async f2 (<init>:"));
- }
-}
diff --git a/core/ops_metrics.rs b/core/ops_metrics.rs
index 35c1faf1c..b068aa0ee 100644
--- a/core/ops_metrics.rs
+++ b/core/ops_metrics.rs
@@ -59,20 +59,10 @@ impl OpsTracker {
unsafe { &mut *self.ops.get() }
}
- #[inline]
- fn ensure_capacity(ops: &mut Vec<OpMetrics>, op_id: OpId) {
- if op_id >= ops.len() {
- ops.resize(1 + op_id, OpMetrics::default())
- }
- }
-
#[allow(clippy::mut_from_ref)]
#[inline]
fn metrics_mut(&self, id: OpId) -> &mut OpMetrics {
- let ops = self.ops_mut();
- // TODO(@AaronO): Pre-alloc capacity at runtime init once we forbid post-boot op registrations
- Self::ensure_capacity(ops, id);
- unsafe { ops.get_unchecked_mut(id) }
+ unsafe { self.ops_mut().get_unchecked_mut(id) }
}
#[inline]
diff --git a/core/runtime.rs b/core/runtime.rs
index 7555bc301..a4fa0c51f 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -6,6 +6,7 @@ use crate::error::generic_error;
use crate::error::ErrWithV8Handle;
use crate::error::JsError;
use crate::extensions::OpEventLoopFn;
+use crate::extensions::OpPair;
use crate::inspector::JsRuntimeInspector;
use crate::module_specifier::ModuleSpecifier;
use crate::modules::ModuleId;
@@ -16,13 +17,13 @@ use crate::modules::NoopModuleLoader;
use crate::ops::*;
use crate::Extension;
use crate::OpMiddlewareFn;
-use crate::OpPayload;
use crate::OpResult;
use crate::OpState;
use crate::PromiseId;
use anyhow::Error;
use futures::channel::oneshot;
use futures::future::poll_fn;
+use futures::future::Future;
use futures::future::FutureExt;
use futures::stream::FuturesUnordered;
use futures::stream::StreamExt;
@@ -143,7 +144,6 @@ pub type CompiledWasmModuleStore = CrossIsolateStore<v8::CompiledWasmModule>;
pub(crate) struct JsRuntimeState {
pub global_context: Option<v8::Global<v8::Context>>,
pub(crate) js_recv_cb: Option<v8::Global<v8::Function>>,
- pub(crate) js_sync_cb: Option<v8::Global<v8::Function>>,
pub(crate) js_macrotask_cbs: Vec<v8::Global<v8::Function>>,
pub(crate) js_nexttick_cbs: Vec<v8::Global<v8::Function>>,
pub(crate) js_promise_reject_cb: Option<v8::Global<v8::Function>>,
@@ -279,17 +279,37 @@ impl JsRuntime {
let has_startup_snapshot = options.startup_snapshot.is_some();
+ let js_error_create_fn = options
+ .js_error_create_fn
+ .unwrap_or_else(|| Rc::new(JsError::create));
+
+ // Add builtins extension
+ options
+ .extensions
+ .insert(0, crate::ops_builtin::init_builtins());
+
+ let ops = Self::collect_ops(&mut options.extensions);
+ let mut op_state = OpState::new(ops.len());
+
+ if let Some(get_error_class_fn) = options.get_error_class_fn {
+ op_state.get_error_class_fn = get_error_class_fn;
+ }
+
+ let op_state = Rc::new(RefCell::new(op_state));
+
+ let refs = bindings::external_references(&ops, op_state.clone());
+ let refs: &'static v8::ExternalReferences = Box::leak(Box::new(refs));
let global_context;
let (mut isolate, maybe_snapshot_creator) = if options.will_snapshot {
// TODO(ry) Support loading snapshots before snapshotting.
assert!(options.startup_snapshot.is_none());
- let mut creator =
- v8::SnapshotCreator::new(Some(&bindings::EXTERNAL_REFERENCES));
+ let mut creator = v8::SnapshotCreator::new(Some(refs));
let isolate = unsafe { creator.get_owned_isolate() };
let mut isolate = JsRuntime::setup_isolate(isolate);
{
let scope = &mut v8::HandleScope::new(&mut isolate);
- let context = bindings::initialize_context(scope);
+ let context =
+ bindings::initialize_context(scope, &ops, false, op_state.clone());
global_context = v8::Global::new(scope, context);
creator.set_default_context(context);
}
@@ -299,7 +319,7 @@ impl JsRuntime {
.create_params
.take()
.unwrap_or_else(v8::Isolate::create_params)
- .external_references(&**bindings::EXTERNAL_REFERENCES);
+ .external_references(&**refs);
let snapshot_loaded = if let Some(snapshot) = options.startup_snapshot {
params = match snapshot {
Snapshot::Static(data) => params.snapshot_blob(data),
@@ -315,13 +335,13 @@ impl JsRuntime {
let mut isolate = JsRuntime::setup_isolate(isolate);
{
let scope = &mut v8::HandleScope::new(&mut isolate);
- let context = if snapshot_loaded {
- v8::Context::new(scope)
- } else {
- // If no snapshot is provided, we initialize the context with empty
- // main source code and source maps.
- bindings::initialize_context(scope)
- };
+ let context = bindings::initialize_context(
+ scope,
+ &ops,
+ snapshot_loaded,
+ op_state.clone(),
+ );
+
global_context = v8::Global::new(scope, context);
}
(isolate, None)
@@ -334,17 +354,6 @@ impl JsRuntime {
.module_loader
.unwrap_or_else(|| Rc::new(NoopModuleLoader));
- let js_error_create_fn = options
- .js_error_create_fn
- .unwrap_or_else(|| Rc::new(JsError::create));
- let mut op_state = OpState::new();
-
- if let Some(get_error_class_fn) = options.get_error_class_fn {
- op_state.get_error_class_fn = get_error_class_fn;
- }
-
- let op_state = Rc::new(RefCell::new(op_state));
-
isolate.set_slot(Rc::new(RefCell::new(JsRuntimeState {
global_context: Some(global_context),
pending_promise_exceptions: HashMap::new(),
@@ -352,7 +361,6 @@ impl JsRuntime {
pending_mod_evaluate: None,
dyn_module_evaluate_idle_counter: 0,
js_recv_cb: None,
- js_sync_cb: None,
js_macrotask_cbs: vec![],
js_nexttick_cbs: vec![],
js_promise_reject_cb: None,
@@ -372,11 +380,6 @@ impl JsRuntime {
let module_map = ModuleMap::new(loader, op_state);
isolate.set_slot(Rc::new(RefCell::new(module_map)));
- // Add builtins extension
- options
- .extensions
- .insert(0, crate::ops_builtin::init_builtins());
-
let mut js_runtime = Self {
v8_isolate: Some(isolate),
inspector: Some(inspector),
@@ -394,10 +397,8 @@ impl JsRuntime {
}
// Init extension ops
js_runtime.init_extension_ops().unwrap();
- // Init callbacks (opresolve & syncOpsCache)
+ // Init callbacks (opresolve)
js_runtime.init_cbs();
- // Sync ops cache
- js_runtime.sync_ops_cache();
js_runtime
}
@@ -461,34 +462,44 @@ impl JsRuntime {
Ok(())
}
- /// Initializes ops of provided Extensions
- fn init_extension_ops(&mut self) -> Result<(), Error> {
- let op_state = self.op_state();
- // Take extensions to avoid double-borrow
- let mut extensions: Vec<Extension> = std::mem::take(&mut self.extensions);
-
+ /// Collects ops from extensions & applies middleware
+ fn collect_ops(extensions: &mut [Extension]) -> Vec<OpPair> {
// 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
+ // Flatten ops & apply middlware
+ extensions
+ .iter_mut()
+ .filter_map(|e| e.init_ops())
+ .flatten()
+ .map(|(name, opfn)| (name, macroware(name, opfn)))
+ .collect()
+ }
+
+ /// Initializes ops of provided Extensions
+ fn init_extension_ops(&mut self) -> Result<(), Error> {
+ let op_state = self.op_state();
+ // Take extensions to avoid double-borrow
+ let mut extensions: Vec<Extension> = std::mem::take(&mut self.extensions);
+
+ // Setup state
for e in extensions.iter_mut() {
+ // ops are already registered during in bindings::initialize_context();
e.init_state(&mut op_state.borrow_mut())?;
- // Register each op after middlewaring it
- let ops = e.init_ops().unwrap_or_default();
- for (name, opfn) in ops {
- self.register_op(name, macroware(name, opfn));
- }
+ // Setup event-loop middleware
if let Some(middleware) = e.init_event_loop_middleware() {
self.event_loop_middlewares.push(middleware);
}
}
+
// Restore extensions
self.extensions = extensions;
@@ -511,22 +522,10 @@ impl JsRuntime {
fn init_cbs(&mut self) {
let mut scope = self.handle_scope();
let recv_cb = Self::grab_fn(&mut scope, "Deno.core.opresolve");
- let sync_cb = Self::grab_fn(&mut scope, "Deno.core.syncOpsCache");
// Put global handles in state
let state_rc = JsRuntime::state(&scope);
let mut state = state_rc.borrow_mut();
state.js_recv_cb.replace(recv_cb);
- state.js_sync_cb.replace(sync_cb);
- }
-
- /// Ensures core.js has the latest op-name to op-id mappings
- pub fn sync_ops_cache(&mut self) {
- let scope = &mut self.handle_scope();
- let state_rc = JsRuntime::state(scope);
- let js_sync_cb_handle = state_rc.borrow().js_sync_cb.clone().unwrap();
- let js_sync_cb = js_sync_cb_handle.open(scope);
- let this = v8::undefined(scope).into();
- js_sync_cb.call(scope, this, &[]);
}
/// Returns the runtime's op state, which can be used to maintain ops
@@ -612,7 +611,6 @@ impl JsRuntime {
))));
// Drop other v8::Global handles before snapshotting
std::mem::take(&mut state.borrow_mut().js_recv_cb);
- std::mem::take(&mut state.borrow_mut().js_sync_cb);
let snapshot_creator = self.snapshot_creator.as_mut().unwrap();
let snapshot = snapshot_creator
@@ -623,27 +621,6 @@ impl JsRuntime {
snapshot
}
- /// Registers an op that can be called from JavaScript.
- ///
- /// The _op_ mechanism allows to expose Rust functions to the JS runtime,
- /// which can be called using the provided `name`.
- ///
- /// This function provides byte-level bindings. To pass data via JSON, the
- /// following functions can be passed as an argument for `op_fn`:
- /// * [op_sync()](fn.op_sync.html)
- /// * [op_async()](fn.op_async.html)
- pub fn register_op<F>(&mut self, name: &str, op_fn: F) -> OpId
- where
- F: Fn(Rc<RefCell<OpState>>, OpPayload) -> Op + 'static,
- {
- Self::state(self.v8_isolate())
- .borrow_mut()
- .op_state
- .borrow_mut()
- .op_table
- .register_op(name, op_fn)
- }
-
/// Registers a callback on the isolate when the memory limits are approached.
/// Use this to prevent V8 from crashing the process when reaching the limit.
///
@@ -1552,13 +1529,11 @@ impl JsRuntime {
let mut state = state_rc.borrow_mut();
state.have_unpolled_ops = false;
- let op_state = state.op_state.clone();
-
while let Poll::Ready(Some(item)) = state.pending_ops.poll_next_unpin(cx)
{
let (promise_id, op_id, resp) = item;
- op_state.borrow().tracker.track_async_completed(op_id);
state.unrefed_ops.remove(&promise_id);
+ state.op_state.borrow().tracker.track_async_completed(op_id);
args.push(v8::Integer::new(scope, promise_id as i32).into());
args.push(resp.to_v8(scope).unwrap());
}
@@ -1654,22 +1629,37 @@ impl JsRuntime {
}
}
+#[inline]
+pub fn queue_async_op(
+ scope: &v8::Isolate,
+ op: impl Future<Output = (PromiseId, OpId, OpResult)> + 'static,
+) {
+ let state_rc = JsRuntime::state(scope);
+ let mut state = state_rc.borrow_mut();
+ state.pending_ops.push(OpCall::eager(op));
+ state.have_unpolled_ops = true;
+}
+
#[cfg(test)]
pub mod tests {
use super::*;
use crate::error::custom_error;
+ use crate::error::AnyError;
use crate::modules::ModuleSource;
use crate::modules::ModuleSourceFuture;
use crate::modules::ModuleType;
- use crate::op_async;
- use crate::op_sync;
use crate::ZeroCopyBuf;
+ use deno_ops::op;
use futures::future::lazy;
use std::ops::FnOnce;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
+ // deno_ops macros generate code assuming deno_core in scope.
+ mod deno_core {
+ pub use crate::*;
+ }
pub fn run_in_task<F>(f: F)
where
@@ -1689,26 +1679,26 @@ pub mod tests {
dispatch_count: Arc<AtomicUsize>,
}
- fn op_test(rc_op_state: Rc<RefCell<OpState>>, payload: OpPayload) -> Op {
- let rc_op_state2 = rc_op_state.clone();
- let op_state_ = rc_op_state2.borrow();
+ #[op]
+ async fn op_test(
+ rc_op_state: Rc<RefCell<OpState>>,
+ control: u8,
+ buf: Option<ZeroCopyBuf>,
+ ) -> Result<u8, AnyError> {
+ let op_state_ = rc_op_state.borrow();
let test_state = op_state_.borrow::<TestState>();
test_state.dispatch_count.fetch_add(1, Ordering::Relaxed);
- let (control, buf): (u8, Option<ZeroCopyBuf>) =
- payload.deserialize().unwrap();
match test_state.mode {
Mode::Async => {
assert_eq!(control, 42);
- let resp = (0, 1, serialize_op_result(Ok(43), rc_op_state));
- Op::Async(OpCall::ready(resp))
+ Ok(43)
}
Mode::AsyncZeroCopy(has_buffer) => {
assert_eq!(buf.is_some(), has_buffer);
if let Some(buf) = buf {
assert_eq!(buf.len(), 1);
}
- let resp = (0, 1, serialize_op_result(Ok(43), rc_op_state));
- Op::Async(OpCall::ready(resp))
+ Ok(43)
}
}
}
@@ -1717,7 +1707,7 @@ pub mod tests {
let dispatch_count = Arc::new(AtomicUsize::new(0));
let dispatch_count2 = dispatch_count.clone();
let ext = Extension::builder()
- .ops(vec![("op_test", Box::new(op_test))])
+ .ops(vec![op_test::decl()])
.state(move |state| {
state.put(TestState {
mode,
@@ -2028,30 +2018,6 @@ pub mod tests {
}
#[test]
- fn test_pre_dispatch() {
- run_in_task(|cx| {
- let (mut runtime, _dispatch_count) = setup(Mode::Async);
- runtime
- .execute_script(
- "bad_op_id.js",
- r#"
- let thrown;
- try {
- Deno.core.opcallSync(100, null, null);
- } catch (e) {
- thrown = e;
- }
- assert(String(thrown) === "TypeError: Unknown op id: 100");
- "#,
- )
- .unwrap();
- if let Poll::Ready(Err(_)) = runtime.poll_event_loop(cx, false) {
- unreachable!();
- }
- });
- }
-
- #[test]
fn syntax_error() {
let mut runtime = JsRuntime::new(Default::default());
let src = "hocuspocus(";
@@ -2095,6 +2061,7 @@ pub mod tests {
#[test]
fn test_error_builder() {
+ #[op]
fn op_err(_: &mut OpState, _: (), _: ()) -> Result<(), Error> {
Err(custom_error("DOMExceptionOperationError", "abc"))
}
@@ -2104,9 +2071,7 @@ pub mod tests {
}
run_in_task(|cx| {
- let ext = Extension::builder()
- .ops(vec![("op_err", op_sync(op_err))])
- .build();
+ let ext = Extension::builder().ops(vec![op_err::decl()]).build();
let mut runtime = JsRuntime::new(RuntimeOptions {
extensions: vec![ext],
get_error_class_fn: Some(&get_error_class_name),
@@ -2177,7 +2142,7 @@ pub mod tests {
});
let cb_handle = runtime.v8_isolate().thread_safe_handle();
- let callback_invoke_count = Rc::new(AtomicUsize::default());
+ let callback_invoke_count = Rc::new(AtomicUsize::new(0));
let inner_invoke_count = Rc::clone(&callback_invoke_count);
runtime.add_near_heap_limit_callback(
@@ -2221,7 +2186,7 @@ pub mod tests {
});
let cb_handle = runtime.v8_isolate().thread_safe_handle();
- let callback_invoke_count_first = Rc::new(AtomicUsize::default());
+ let callback_invoke_count_first = Rc::new(AtomicUsize::new(0));
let inner_invoke_count_first = Rc::clone(&callback_invoke_count_first);
runtime.add_near_heap_limit_callback(
move |current_limit, _initial_limit| {
@@ -2230,7 +2195,7 @@ pub mod tests {
},
);
- let callback_invoke_count_second = Rc::new(AtomicUsize::default());
+ let callback_invoke_count_second = Rc::new(AtomicUsize::new(0));
let inner_invoke_count_second = Rc::clone(&callback_invoke_count_second);
runtime.add_near_heap_limit_callback(
move |current_limit, _initial_limit| {
@@ -2500,6 +2465,7 @@ assertEquals(1, notify_return_value);
async fn test_async_opstate_borrow() {
struct InnerState(u64);
+ #[op]
async fn op_async_borrow(
op_state: Rc<RefCell<OpState>>,
_: (),
@@ -2519,7 +2485,7 @@ assertEquals(1, notify_return_value);
}
let extension = Extension::builder()
- .ops(vec![("op_async_borrow", op_async(op_async_borrow))])
+ .ops(vec![op_async_borrow::decl()])
.state(|state| {
state.put(InnerState(42));
Ok(())
@@ -2542,6 +2508,7 @@ assertEquals(1, notify_return_value);
#[tokio::test]
async fn test_set_macrotask_callback_set_next_tick_callback() {
+ #[op]
async fn op_async_sleep(
_op_state: Rc<RefCell<OpState>>,
_: (),
@@ -2553,7 +2520,7 @@ assertEquals(1, notify_return_value);
}
let extension = Extension::builder()
- .ops(vec![("op_async_sleep", op_async(op_async_sleep))])
+ .ops(vec![op_async_sleep::decl()])
.build();
let mut runtime = JsRuntime::new(RuntimeOptions {
@@ -2617,25 +2584,23 @@ assertEquals(1, notify_return_value);
fn test_has_tick_scheduled() {
use futures::task::ArcWake;
- let macrotask = Arc::new(AtomicUsize::default());
- let macrotask_ = Arc::clone(&macrotask);
-
- let next_tick = Arc::new(AtomicUsize::default());
- let next_tick_ = Arc::clone(&next_tick);
+ static MACROTASK: AtomicUsize = AtomicUsize::new(0);
+ static NEXT_TICK: AtomicUsize = AtomicUsize::new(0);
- let op_macrotask = move |_: &mut OpState, _: (), _: ()| {
- macrotask_.fetch_add(1, Ordering::Relaxed);
+ #[op]
+ fn op_macrotask(_: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
+ MACROTASK.fetch_add(1, Ordering::Relaxed);
Ok(())
- };
+ }
- let op_next_tick = move |_: &mut OpState, _: (), _: ()| {
- next_tick_.fetch_add(1, Ordering::Relaxed);
+ #[op]
+ fn op_next_tick(_: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
+ NEXT_TICK.fetch_add(1, Ordering::Relaxed);
Ok(())
- };
+ }
let extension = Extension::builder()
- .ops(vec![("op_macrotask", op_sync(op_macrotask))])
- .ops(vec![("op_next_tick", op_sync(op_next_tick))])
+ .ops(vec![op_macrotask::decl(), op_next_tick::decl()])
.build();
let mut runtime = JsRuntime::new(RuntimeOptions {
@@ -2670,8 +2635,8 @@ assertEquals(1, notify_return_value);
let cx = &mut Context::from_waker(&waker);
assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
- assert_eq!(1, macrotask.load(Ordering::Relaxed));
- assert_eq!(1, next_tick.load(Ordering::Relaxed));
+ assert_eq!(1, MACROTASK.load(Ordering::Relaxed));
+ assert_eq!(1, NEXT_TICK.load(Ordering::Relaxed));
assert_eq!(awoken_times.swap(0, Ordering::Relaxed), 1);
assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
assert_eq!(awoken_times.swap(0, Ordering::Relaxed), 1);
@@ -2756,28 +2721,34 @@ assertEquals(1, notify_return_value);
#[tokio::test]
async fn test_set_promise_reject_callback() {
- let promise_reject = Arc::new(AtomicUsize::default());
- let promise_reject_ = Arc::clone(&promise_reject);
+ static PROMISE_REJECT: AtomicUsize = AtomicUsize::new(0);
+ static UNCAUGHT_EXCEPTION: AtomicUsize = AtomicUsize::new(0);
- let uncaught_exception = Arc::new(AtomicUsize::default());
- let uncaught_exception_ = Arc::clone(&uncaught_exception);
-
- let op_promise_reject = move |_: &mut OpState, _: (), _: ()| {
- promise_reject_.fetch_add(1, Ordering::Relaxed);
+ #[op]
+ fn op_promise_reject(
+ _: &mut OpState,
+ _: (),
+ _: (),
+ ) -> Result<(), AnyError> {
+ PROMISE_REJECT.fetch_add(1, Ordering::Relaxed);
Ok(())
- };
+ }
- let op_uncaught_exception = move |_: &mut OpState, _: (), _: ()| {
- uncaught_exception_.fetch_add(1, Ordering::Relaxed);
+ #[op]
+ fn op_uncaught_exception(
+ _: &mut OpState,
+ _: (),
+ _: (),
+ ) -> Result<(), AnyError> {
+ UNCAUGHT_EXCEPTION.fetch_add(1, Ordering::Relaxed);
Ok(())
- };
+ }
let extension = Extension::builder()
- .ops(vec![("op_promise_reject", op_sync(op_promise_reject))])
- .ops(vec![(
- "op_uncaught_exception",
- op_sync(op_uncaught_exception),
- )])
+ .ops(vec![
+ op_promise_reject::decl(),
+ op_uncaught_exception::decl(),
+ ])
.build();
let mut runtime = JsRuntime::new(RuntimeOptions {
@@ -2812,8 +2783,8 @@ assertEquals(1, notify_return_value);
.unwrap();
runtime.run_event_loop(false).await.unwrap();
- assert_eq!(1, promise_reject.load(Ordering::Relaxed));
- assert_eq!(1, uncaught_exception.load(Ordering::Relaxed));
+ assert_eq!(1, PROMISE_REJECT.load(Ordering::Relaxed));
+ assert_eq!(1, UNCAUGHT_EXCEPTION.load(Ordering::Relaxed));
runtime
.execute_script(
@@ -2840,7 +2811,7 @@ assertEquals(1, notify_return_value);
// printed to stderr.
runtime.run_event_loop(false).await.unwrap();
- assert_eq!(2, promise_reject.load(Ordering::Relaxed));
- assert_eq!(2, uncaught_exception.load(Ordering::Relaxed));
+ assert_eq!(2, PROMISE_REJECT.load(Ordering::Relaxed));
+ assert_eq!(2, UNCAUGHT_EXCEPTION.load(Ordering::Relaxed));
}
}
diff --git a/ext/broadcast_channel/lib.rs b/ext/broadcast_channel/lib.rs
index 91ee67674..eff57c7df 100644
--- a/ext/broadcast_channel/lib.rs
+++ b/ext/broadcast_channel/lib.rs
@@ -8,8 +8,7 @@ pub use in_memory_broadcast_channel::InMemoryBroadcastChannelResource;
use async_trait::async_trait;
use deno_core::error::AnyError;
use deno_core::include_js_files;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::Extension;
use deno_core::OpState;
use deno_core::Resource;
@@ -43,11 +42,15 @@ pub type Message = (String, Vec<u8>);
struct Unstable(bool); // --unstable
-pub fn op_broadcast_subscribe<BC: BroadcastChannel + 'static>(
+#[op]
+pub fn op_broadcast_subscribe<BC>(
state: &mut OpState,
_: (),
_: (),
-) -> Result<ResourceId, AnyError> {
+) -> Result<ResourceId, AnyError>
+where
+ BC: BroadcastChannel + 'static,
+{
let unstable = state.borrow::<Unstable>().0;
if !unstable {
@@ -62,31 +65,43 @@ pub fn op_broadcast_subscribe<BC: BroadcastChannel + 'static>(
Ok(state.resource_table.add(resource))
}
-pub fn op_broadcast_unsubscribe<BC: BroadcastChannel + 'static>(
+#[op]
+pub fn op_broadcast_unsubscribe<BC>(
state: &mut OpState,
rid: ResourceId,
_buf: (),
-) -> Result<(), AnyError> {
+) -> Result<(), AnyError>
+where
+ BC: BroadcastChannel + 'static,
+{
let resource = state.resource_table.get::<BC::Resource>(rid)?;
let bc = state.borrow::<BC>();
bc.unsubscribe(&resource)
}
-pub async fn op_broadcast_send<BC: BroadcastChannel + 'static>(
+#[op]
+pub async fn op_broadcast_send<BC>(
state: Rc<RefCell<OpState>>,
(rid, name): (ResourceId, String),
buf: ZeroCopyBuf,
-) -> Result<(), AnyError> {
+) -> Result<(), AnyError>
+where
+ BC: BroadcastChannel + 'static,
+{
let resource = state.borrow().resource_table.get::<BC::Resource>(rid)?;
let bc = state.borrow().borrow::<BC>().clone();
bc.send(&resource, name, buf.to_vec()).await
}
-pub async fn op_broadcast_recv<BC: BroadcastChannel + 'static>(
+#[op]
+pub async fn op_broadcast_recv<BC>(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
_: (),
-) -> Result<Option<Message>, AnyError> {
+) -> Result<Option<Message>, AnyError>
+where
+ BC: BroadcastChannel + 'static,
+{
let resource = state.borrow().resource_table.get::<BC::Resource>(rid)?;
let bc = state.borrow().borrow::<BC>().clone();
bc.recv(&resource).await
@@ -102,16 +117,10 @@ pub fn init<BC: BroadcastChannel + 'static>(
"01_broadcast_channel.js",
))
.ops(vec![
- (
- "op_broadcast_subscribe",
- op_sync(op_broadcast_subscribe::<BC>),
- ),
- (
- "op_broadcast_unsubscribe",
- op_sync(op_broadcast_unsubscribe::<BC>),
- ),
- ("op_broadcast_send", op_async(op_broadcast_send::<BC>)),
- ("op_broadcast_recv", op_async(op_broadcast_recv::<BC>)),
+ op_broadcast_subscribe::decl::<BC>(),
+ op_broadcast_unsubscribe::decl::<BC>(),
+ op_broadcast_send::decl::<BC>(),
+ op_broadcast_recv::decl::<BC>(),
])
.state(move |state| {
state.put(bc.clone());
diff --git a/ext/crypto/decrypt.rs b/ext/crypto/decrypt.rs
index 801e72ea0..a8666de89 100644
--- a/ext/crypto/decrypt.rs
+++ b/ext/crypto/decrypt.rs
@@ -24,6 +24,7 @@ use ctr::Ctr;
use deno_core::error::custom_error;
use deno_core::error::type_error;
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
use rsa::pkcs1::FromRsaPrivateKey;
@@ -76,6 +77,7 @@ pub enum DecryptAlgorithm {
},
}
+#[op]
pub async fn op_crypto_decrypt(
_state: Rc<RefCell<OpState>>,
opts: DecryptOptions,
diff --git a/ext/crypto/encrypt.rs b/ext/crypto/encrypt.rs
index 63f8af889..b93ca0952 100644
--- a/ext/crypto/encrypt.rs
+++ b/ext/crypto/encrypt.rs
@@ -16,6 +16,7 @@ use aes_gcm::AeadInPlace;
use aes_gcm::NewAead;
use aes_gcm::Nonce;
use ctr::Ctr;
+use deno_core::op;
use block_modes::BlockMode;
use ctr::cipher::StreamCipher;
@@ -79,6 +80,8 @@ pub enum EncryptAlgorithm {
key_length: usize,
},
}
+
+#[op]
pub async fn op_crypto_encrypt(
_state: Rc<RefCell<OpState>>,
opts: EncryptOptions,
diff --git a/ext/crypto/export_key.rs b/ext/crypto/export_key.rs
index 891aea92a..8131f859d 100644
--- a/ext/crypto/export_key.rs
+++ b/ext/crypto/export_key.rs
@@ -1,5 +1,6 @@
use deno_core::error::custom_error;
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
use rsa::pkcs1::UIntBytes;
@@ -84,6 +85,7 @@ pub enum ExportKeyResult {
},
}
+#[op]
pub fn op_crypto_export_key(
_state: &mut OpState,
opts: ExportKeyOptions,
diff --git a/ext/crypto/generate_key.rs b/ext/crypto/generate_key.rs
index 190a8b424..9fe1b62f4 100644
--- a/ext/crypto/generate_key.rs
+++ b/ext/crypto/generate_key.rs
@@ -3,6 +3,7 @@ use std::rc::Rc;
use crate::shared::*;
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
use elliptic_curve::rand_core::OsRng;
@@ -41,6 +42,7 @@ pub enum GenerateKeyOptions {
},
}
+#[op]
pub async fn op_crypto_generate_key(
_state: Rc<RefCell<OpState>>,
opts: GenerateKeyOptions,
diff --git a/ext/crypto/import_key.rs b/ext/crypto/import_key.rs
index b929f38bb..3d29c9947 100644
--- a/ext/crypto/import_key.rs
+++ b/ext/crypto/import_key.rs
@@ -1,4 +1,5 @@
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
use elliptic_curve::pkcs8::der::Decodable as Pkcs8Decodable;
@@ -81,11 +82,13 @@ pub enum ImportKeyResult {
#[serde(rename_all = "camelCase")]
Ec { raw_data: RawKeyData },
#[serde(rename_all = "camelCase")]
+ #[allow(dead_code)]
Aes { raw_data: RawKeyData },
#[serde(rename_all = "camelCase")]
Hmac { raw_data: RawKeyData },
}
+#[op]
pub fn op_crypto_import_key(
_state: &mut OpState,
opts: ImportKeyOptions,
diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs
index 69381e139..3b33830d3 100644
--- a/ext/crypto/lib.rs
+++ b/ext/crypto/lib.rs
@@ -9,8 +9,8 @@ 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_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::Extension;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
@@ -88,22 +88,19 @@ pub fn init(maybe_seed: Option<u64>) -> Extension {
"01_webidl.js",
))
.ops(vec![
- (
- "op_crypto_get_random_values",
- op_sync(op_crypto_get_random_values),
- ),
- ("op_crypto_generate_key", op_async(op_crypto_generate_key)),
- ("op_crypto_sign_key", op_async(op_crypto_sign_key)),
- ("op_crypto_verify_key", op_async(op_crypto_verify_key)),
- ("op_crypto_derive_bits", op_async(op_crypto_derive_bits)),
- ("op_crypto_import_key", op_sync(op_crypto_import_key)),
- ("op_crypto_export_key", op_sync(op_crypto_export_key)),
- ("op_crypto_encrypt", op_async(op_crypto_encrypt)),
- ("op_crypto_decrypt", op_async(op_crypto_decrypt)),
- ("op_crypto_subtle_digest", op_async(op_crypto_subtle_digest)),
- ("op_crypto_random_uuid", op_sync(op_crypto_random_uuid)),
- ("op_crypto_wrap_key", op_sync(op_crypto_wrap_key)),
- ("op_crypto_unwrap_key", op_sync(op_crypto_unwrap_key)),
+ 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(),
])
.state(move |state| {
if let Some(seed) = maybe_seed {
@@ -114,6 +111,7 @@ pub fn init(maybe_seed: Option<u64>) -> Extension {
.build()
}
+#[op]
pub fn op_crypto_get_random_values(
state: &mut OpState,
mut zero_copy: ZeroCopyBuf,
@@ -170,6 +168,7 @@ pub struct SignArg {
named_curve: Option<CryptoNamedCurve>,
}
+#[op]
pub async fn op_crypto_sign_key(
_state: Rc<RefCell<OpState>>,
args: SignArg,
@@ -324,6 +323,7 @@ pub struct VerifyArg {
named_curve: Option<CryptoNamedCurve>,
}
+#[op]
pub async fn op_crypto_verify_key(
_state: Rc<RefCell<OpState>>,
args: VerifyArg,
@@ -484,6 +484,7 @@ pub struct DeriveKeyArg {
info: Option<ZeroCopyBuf>,
}
+#[op]
pub async fn op_crypto_derive_bits(
_state: Rc<RefCell<OpState>>,
args: DeriveKeyArg,
@@ -789,6 +790,7 @@ impl<'a> TryFrom<rsa::pkcs8::der::asn1::Any<'a>>
}
}
+#[op]
pub fn op_crypto_random_uuid(
state: &mut OpState,
_: (),
@@ -808,6 +810,7 @@ pub fn op_crypto_random_uuid(
Ok(uuid.to_string())
}
+#[op]
pub async fn op_crypto_subtle_digest(
_state: Rc<RefCell<OpState>>,
algorithm: CryptoHash,
@@ -831,6 +834,7 @@ pub struct WrapUnwrapKeyArg {
algorithm: Algorithm,
}
+#[op]
pub fn op_crypto_wrap_key(
_state: &mut OpState,
args: WrapUnwrapKeyArg,
@@ -860,6 +864,7 @@ pub fn op_crypto_wrap_key(
}
}
+#[op]
pub fn op_crypto_unwrap_key(
_state: &mut OpState,
args: WrapUnwrapKeyArg,
diff --git a/ext/fetch/lib.rs b/ext/fetch/lib.rs
index e1859e8e3..7a0c9b16f 100644
--- a/ext/fetch/lib.rs
+++ b/ext/fetch/lib.rs
@@ -9,8 +9,8 @@ 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::op;
+
use deno_core::url::Url;
use deno_core::AsyncRefCell;
use deno_core::AsyncResult;
@@ -100,12 +100,9 @@ where
"26_fetch.js",
))
.ops(vec![
- ("op_fetch", op_sync(op_fetch::<FP>)),
- ("op_fetch_send", op_async(op_fetch_send)),
- (
- "op_fetch_custom_client",
- op_sync(op_fetch_custom_client::<FP>),
- ),
+ op_fetch::decl::<FP>(),
+ op_fetch_send::decl(),
+ op_fetch_custom_client::decl::<FP>(),
])
.state(move |state| {
state.put::<Options>(options.clone());
@@ -192,6 +189,7 @@ pub struct FetchReturn {
cancel_handle_rid: Option<ResourceId>,
}
+#[op]
pub fn op_fetch<FP>(
state: &mut OpState,
args: FetchArgs,
@@ -367,6 +365,7 @@ pub struct FetchResponse {
response_rid: ResourceId,
}
+#[op]
pub async fn op_fetch_send(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -525,6 +524,7 @@ pub struct CreateHttpClientOptions {
private_key: Option<String>,
}
+#[op]
pub fn op_fetch_custom_client<FP>(
state: &mut OpState,
args: CreateHttpClientOptions,
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs
index f2e7bb175..b4d8712f4 100644
--- a/ext/ffi/lib.rs
+++ b/ext/ffi/lib.rs
@@ -6,8 +6,8 @@ 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_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
@@ -140,27 +140,24 @@ pub fn init<P: FfiPermissions + 'static>(unstable: bool) -> Extension {
"00_ffi.js",
))
.ops(vec![
- ("op_ffi_load", op_sync(op_ffi_load::<P>)),
- ("op_ffi_get_static", op_sync(op_ffi_get_static)),
- ("op_ffi_call", op_sync(op_ffi_call)),
- ("op_ffi_call_nonblocking", op_async(op_ffi_call_nonblocking)),
- ("op_ffi_call_ptr", op_sync(op_ffi_call_ptr)),
- (
- "op_ffi_call_ptr_nonblocking",
- op_async(op_ffi_call_ptr_nonblocking),
- ),
- ("op_ffi_ptr_of", op_sync(op_ffi_ptr_of::<P>)),
- ("op_ffi_buf_copy_into", op_sync(op_ffi_buf_copy_into::<P>)),
- ("op_ffi_cstr_read", op_sync(op_ffi_cstr_read::<P>)),
- ("op_ffi_read_u8", op_sync(op_ffi_read_u8::<P>)),
- ("op_ffi_read_i8", op_sync(op_ffi_read_i8::<P>)),
- ("op_ffi_read_u16", op_sync(op_ffi_read_u16::<P>)),
- ("op_ffi_read_i16", op_sync(op_ffi_read_i16::<P>)),
- ("op_ffi_read_u32", op_sync(op_ffi_read_u32::<P>)),
- ("op_ffi_read_i32", op_sync(op_ffi_read_i32::<P>)),
- ("op_ffi_read_u64", op_sync(op_ffi_read_u64::<P>)),
- ("op_ffi_read_f32", op_sync(op_ffi_read_f32::<P>)),
- ("op_ffi_read_f64", op_sync(op_ffi_read_f64::<P>)),
+ op_ffi_load::decl::<P>(),
+ op_ffi_get_static::decl(),
+ op_ffi_call::decl(),
+ op_ffi_call_nonblocking::decl(),
+ op_ffi_call_ptr::decl(),
+ op_ffi_call_ptr_nonblocking::decl(),
+ op_ffi_ptr_of::decl::<P>(),
+ op_ffi_buf_copy_into::decl::<P>(),
+ op_ffi_cstr_read::decl::<P>(),
+ op_ffi_read_u8::decl::<P>(),
+ op_ffi_read_i8::decl::<P>(),
+ op_ffi_read_u16::decl::<P>(),
+ op_ffi_read_i16::decl::<P>(),
+ op_ffi_read_u32::decl::<P>(),
+ op_ffi_read_i32::decl::<P>(),
+ op_ffi_read_u64::decl::<P>(),
+ op_ffi_read_f32::decl::<P>(),
+ op_ffi_read_f64::decl::<P>(),
])
.state(move |state| {
// Stolen from deno_webgpu, is there a better option?
@@ -464,6 +461,7 @@ pub(crate) fn format_error(e: dlopen::Error, path: String) -> String {
}
}
+#[op]
fn op_ffi_load<FP>(
state: &mut deno_core::OpState,
args: FfiLoadArgs,
@@ -650,6 +648,7 @@ fn ffi_call(args: FfiCallArgs, symbol: &Symbol) -> Result<Value, AnyError> {
})
}
+#[op]
fn op_ffi_call_ptr(
_state: &mut deno_core::OpState,
args: FfiCallPtrArgs,
@@ -659,6 +658,7 @@ fn op_ffi_call_ptr(
ffi_call(args.into(), &symbol)
}
+#[op]
async fn op_ffi_call_ptr_nonblocking(
_state: Rc<RefCell<deno_core::OpState>>,
args: FfiCallPtrArgs,
@@ -678,6 +678,7 @@ struct FfiGetArgs {
r#type: NativeType,
}
+#[op]
fn op_ffi_get_static(
state: &mut deno_core::OpState,
args: FfiGetArgs,
@@ -735,6 +736,7 @@ fn op_ffi_get_static(
})
}
+#[op]
fn op_ffi_call(
state: &mut deno_core::OpState,
args: FfiCallArgs,
@@ -753,6 +755,7 @@ fn op_ffi_call(
}
/// A non-blocking FFI call.
+#[op]
async fn op_ffi_call_nonblocking(
state: Rc<RefCell<deno_core::OpState>>,
args: FfiCallArgs,
@@ -773,6 +776,7 @@ async fn op_ffi_call_nonblocking(
.unwrap()
}
+#[op]
fn op_ffi_ptr_of<FP>(
state: &mut deno_core::OpState,
buf: ZeroCopyBuf,
@@ -787,6 +791,7 @@ where
Ok(U32x2::from(buf.as_ptr() as u64))
}
+#[op]
fn op_ffi_buf_copy_into<FP>(
state: &mut deno_core::OpState,
(src, mut dst, len): (U32x2, ZeroCopyBuf, usize),
@@ -809,6 +814,7 @@ where
}
}
+#[op]
fn op_ffi_cstr_read<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
@@ -824,6 +830,7 @@ where
Ok(unsafe { CStr::from_ptr(ptr) }.to_str()?.to_string())
}
+#[op]
fn op_ffi_read_u8<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
@@ -838,6 +845,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const u8) })
}
+#[op]
fn op_ffi_read_i8<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
@@ -852,6 +860,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const i8) })
}
+#[op]
fn op_ffi_read_u16<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
@@ -866,6 +875,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const u16) })
}
+#[op]
fn op_ffi_read_i16<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
@@ -880,6 +890,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const i16) })
}
+#[op]
fn op_ffi_read_u32<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
@@ -894,6 +905,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const u32) })
}
+#[op]
fn op_ffi_read_i32<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
@@ -908,6 +920,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const i32) })
}
+#[op]
fn op_ffi_read_u64<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
@@ -924,6 +937,7 @@ where
}))
}
+#[op]
fn op_ffi_read_f32<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
@@ -938,6 +952,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const f32) })
}
+#[op]
fn op_ffi_read_f64<FP>(
state: &mut deno_core::OpState,
ptr: U32x2,
diff --git a/ext/http/lib.rs b/ext/http/lib.rs
index ae5ddb9c3..a89c7a4a1 100644
--- a/ext/http/lib.rs
+++ b/ext/http/lib.rs
@@ -20,8 +20,8 @@ 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_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::AsyncRefCell;
use deno_core::ByteString;
use deno_core::CancelFuture;
@@ -72,19 +72,13 @@ pub fn init() -> Extension {
"01_http.js",
))
.ops(vec![
- ("op_http_accept", op_async(op_http_accept)),
- ("op_http_read", op_async(op_http_read)),
- ("op_http_write_headers", op_async(op_http_write_headers)),
- ("op_http_write", op_async(op_http_write)),
- ("op_http_shutdown", op_async(op_http_shutdown)),
- (
- "op_http_websocket_accept_header",
- op_sync(op_http_websocket_accept_header),
- ),
- (
- "op_http_upgrade_websocket",
- op_async(op_http_upgrade_websocket),
- ),
+ op_http_accept::decl(),
+ op_http_read::decl(),
+ op_http_write_headers::decl(),
+ op_http_write::decl(),
+ op_http_shutdown::decl(),
+ op_http_websocket_accept_header::decl(),
+ op_http_upgrade_websocket::decl(),
])
.build()
}
@@ -371,6 +365,7 @@ struct NextRequestResponse(
String,
);
+#[op]
async fn op_http_accept(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -501,6 +496,7 @@ struct RespondArgs(
Vec<(ByteString, ByteString)>,
);
+#[op]
async fn op_http_write_headers(
state: Rc<RefCell<OpState>>,
args: RespondArgs,
@@ -697,6 +693,7 @@ async fn op_http_write_headers(
}
}
+#[op]
async fn op_http_write(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -737,6 +734,7 @@ async fn op_http_write(
/// Gracefully closes the write half of the HTTP stream. Note that this does not
/// remove the HTTP stream resource from the resource table; it still has to be
/// closed with `Deno.core.close()`.
+#[op]
async fn op_http_shutdown(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -751,6 +749,7 @@ async fn op_http_shutdown(
Ok(())
}
+#[op]
async fn op_http_read(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -799,6 +798,7 @@ async fn op_http_read(
fut.try_or_cancel(cancel_handle).await
}
+#[op]
fn op_http_websocket_accept_header(
_: &mut OpState,
key: String,
@@ -811,6 +811,7 @@ fn op_http_websocket_accept_header(
Ok(base64::encode(digest))
}
+#[op]
async fn op_http_upgrade_websocket(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
diff --git a/ext/net/lib.rs b/ext/net/lib.rs
index c9b888a65..84358210e 100644
--- a/ext/net/lib.rs
+++ b/ext/net/lib.rs
@@ -76,9 +76,6 @@ pub fn init<P: NetPermissions + 'static>(
unstable: bool,
unsafely_ignore_certificate_errors: Option<Vec<String>>,
) -> Extension {
- let mut ops_to_register = vec![];
- ops_to_register.extend(ops::init::<P>());
- ops_to_register.extend(ops_tls::init::<P>());
Extension::builder()
.js(include_js_files!(
prefix "deno:ext/net",
@@ -86,7 +83,7 @@ pub fn init<P: NetPermissions + 'static>(
"02_tls.js",
"04_net_unstable.js",
))
- .ops(ops_to_register)
+ .ops([&ops::init::<P>()[..], &ops_tls::init::<P>()[..]].concat())
.state(move |state| {
state.put(DefaultTlsOptions {
root_cert_store: root_cert_store.clone(),
diff --git a/ext/net/ops.rs b/ext/net/ops.rs
index 682ba0acb..2c9129ebf 100644
--- a/ext/net/ops.rs
+++ b/ext/net/ops.rs
@@ -9,8 +9,8 @@ use deno_core::error::custom_error;
use deno_core::error::generic_error;
use deno_core::error::type_error;
use deno_core::error::AnyError;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::AsyncRefCell;
use deno_core::ByteString;
use deno_core::CancelHandle;
@@ -52,14 +52,14 @@ use std::path::Path;
pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
vec![
- ("op_net_accept", op_async(op_net_accept)),
- ("op_net_connect", op_async(op_net_connect::<P>)),
- ("op_net_listen", op_sync(op_net_listen::<P>)),
- ("op_dgram_recv", op_async(op_dgram_recv)),
- ("op_dgram_send", op_async(op_dgram_send::<P>)),
- ("op_dns_resolve", op_async(op_dns_resolve::<P>)),
- ("op_set_nodelay", op_sync(op_set_nodelay::<P>)),
- ("op_set_keepalive", op_sync(op_set_keepalive::<P>)),
+ op_net_accept::decl(),
+ op_net_connect::decl::<P>(),
+ op_net_listen::decl::<P>(),
+ op_dgram_recv::decl(),
+ op_dgram_send::decl::<P>(),
+ op_dns_resolve::decl::<P>(),
+ op_set_nodelay::decl::<P>(),
+ op_set_keepalive::decl::<P>(),
]
}
@@ -158,6 +158,7 @@ async fn accept_tcp(
})
}
+#[op]
async fn op_net_accept(
state: Rc<RefCell<OpState>>,
args: AcceptArgs,
@@ -210,6 +211,7 @@ async fn receive_udp(
})
}
+#[op]
async fn op_dgram_recv(
state: Rc<RefCell<OpState>>,
args: ReceiveArgs,
@@ -231,6 +233,7 @@ struct SendArgs {
transport_args: ArgsEnum,
}
+#[op]
async fn op_dgram_send<NP>(
state: Rc<RefCell<OpState>>,
args: SendArgs,
@@ -299,6 +302,7 @@ pub struct ConnectArgs {
transport_args: ArgsEnum,
}
+#[op]
pub async fn op_net_connect<NP>(
state: Rc<RefCell<OpState>>,
args: ConnectArgs,
@@ -474,6 +478,7 @@ fn listen_udp(
Ok((rid, local_addr))
}
+#[op]
fn op_net_listen<NP>(
state: &mut OpState,
args: ListenArgs,
@@ -613,6 +618,7 @@ pub struct NameServer {
port: u16,
}
+#[op]
pub async fn op_dns_resolve<NP>(
state: Rc<RefCell<OpState>>,
args: ResolveAddrArgs,
@@ -681,6 +687,7 @@ where
Ok(results)
}
+#[op]
pub fn op_set_nodelay<NP>(
state: &mut OpState,
rid: ResourceId,
@@ -692,6 +699,7 @@ pub fn op_set_nodelay<NP>(
resource.set_nodelay(nodelay)
}
+#[op]
pub fn op_set_keepalive<NP>(
state: &mut OpState,
rid: ResourceId,
@@ -877,7 +885,7 @@ mod tests {
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn tcp_set_no_delay() {
let set_nodelay = Box::new(|state: &mut OpState, rid| {
- op_set_nodelay::<TestPermission>(state, rid, true).unwrap();
+ op_set_nodelay::call::<TestPermission>(state, rid, true).unwrap();
});
let test_fn = Box::new(|socket: SockRef| {
assert!(socket.nodelay().unwrap());
@@ -889,7 +897,7 @@ mod tests {
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn tcp_set_keepalive() {
let set_keepalive = Box::new(|state: &mut OpState, rid| {
- op_set_keepalive::<TestPermission>(state, rid, true).unwrap();
+ op_set_keepalive::call::<TestPermission>(state, rid, true).unwrap();
});
let test_fn = Box::new(|socket: SockRef| {
assert!(!socket.nodelay().unwrap());
@@ -934,7 +942,7 @@ mod tests {
};
let connect_fut =
- op_net_connect::<TestPermission>(conn_state, connect_args, ());
+ op_net_connect::call::<TestPermission>(conn_state, connect_args, ());
let conn = connect_fut.await.unwrap();
let rid = conn.rid;
diff --git a/ext/net/ops_tls.rs b/ext/net/ops_tls.rs
index 01f29b2ad..6289d963f 100644
--- a/ext/net/ops_tls.rs
+++ b/ext/net/ops_tls.rs
@@ -25,8 +25,8 @@ use deno_core::futures::task::Poll;
use deno_core::futures::task::RawWaker;
use deno_core::futures::task::RawWakerVTable;
use deno_core::futures::task::Waker;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::parking_lot::Mutex;
use deno_core::AsyncRefCell;
use deno_core::AsyncResult;
@@ -644,11 +644,11 @@ impl Write for ImplementWriteTrait<'_, TcpStream> {
pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
vec![
- ("op_tls_start", op_async(op_tls_start::<P>)),
- ("op_tls_connect", op_async(op_tls_connect::<P>)),
- ("op_tls_listen", op_sync(op_tls_listen::<P>)),
- ("op_tls_accept", op_async(op_tls_accept)),
- ("op_tls_handshake", op_async(op_tls_handshake)),
+ op_tls_start::decl::<P>(),
+ op_tls_connect::decl::<P>(),
+ op_tls_listen::decl::<P>(),
+ op_tls_accept::decl(),
+ op_tls_handshake::decl(),
]
}
@@ -765,6 +765,7 @@ pub struct StartTlsArgs {
alpn_protocols: Option<Vec<String>>,
}
+#[op]
pub async fn op_tls_start<NP>(
state: Rc<RefCell<OpState>>,
args: StartTlsArgs,
@@ -857,6 +858,7 @@ where
})
}
+#[op]
pub async fn op_tls_connect<NP>(
state: Rc<RefCell<OpState>>,
args: ConnectTlsArgs,
@@ -1016,6 +1018,7 @@ pub struct ListenTlsArgs {
alpn_protocols: Option<Vec<String>>,
}
+#[op]
pub fn op_tls_listen<NP>(
state: &mut OpState,
args: ListenTlsArgs,
@@ -1112,6 +1115,7 @@ where
})
}
+#[op]
pub async fn op_tls_accept(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -1163,6 +1167,7 @@ pub async fn op_tls_accept(
})
}
+#[op]
pub async fn op_tls_handshake(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
diff --git a/ext/url/lib.rs b/ext/url/lib.rs
index f8d659f00..a82b3e702 100644
--- a/ext/url/lib.rs
+++ b/ext/url/lib.rs
@@ -7,7 +7,7 @@ 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::op;
use deno_core::url::form_urlencoded;
use deno_core::url::quirks;
use deno_core::url::Url;
@@ -26,21 +26,12 @@ pub fn init() -> Extension {
"01_urlpattern.js",
))
.ops(vec![
- ("op_url_parse", op_sync(op_url_parse)),
- ("op_url_reparse", op_sync(op_url_reparse)),
- (
- "op_url_parse_search_params",
- op_sync(op_url_parse_search_params),
- ),
- (
- "op_url_stringify_search_params",
- op_sync(op_url_stringify_search_params),
- ),
- ("op_urlpattern_parse", op_sync(op_urlpattern_parse)),
- (
- "op_urlpattern_process_match_input",
- op_sync(op_urlpattern_process_match_input),
- ),
+ op_url_parse::decl(),
+ op_url_reparse::decl(),
+ op_url_parse_search_params::decl(),
+ op_url_stringify_search_params::decl(),
+ op_urlpattern_parse::decl(),
+ op_urlpattern_process_match_input::decl(),
])
.build()
}
@@ -65,6 +56,7 @@ type UrlParts = String;
/// Parse `UrlParseArgs::href` with an optional `UrlParseArgs::base_href`, or an
/// optional part to "set" after parsing. Return `UrlParts`.
+#[op]
pub fn op_url_parse(
_state: &mut deno_core::OpState,
href: String,
@@ -98,6 +90,7 @@ pub enum UrlSetter {
Username = 9,
}
+#[op]
pub fn op_url_reparse(
_state: &mut deno_core::OpState,
href: String,
@@ -167,6 +160,7 @@ fn url_result(
)
}
+#[op]
pub fn op_url_parse_search_params(
_state: &mut deno_core::OpState,
args: Option<String>,
@@ -186,6 +180,7 @@ pub fn op_url_parse_search_params(
Ok(params)
}
+#[op]
pub fn op_url_stringify_search_params(
_state: &mut deno_core::OpState,
args: Vec<(String, String)>,
diff --git a/ext/url/urlpattern.rs b/ext/url/urlpattern.rs
index b9f53665f..4e6b4e4a0 100644
--- a/ext/url/urlpattern.rs
+++ b/ext/url/urlpattern.rs
@@ -1,11 +1,13 @@
use deno_core::error::type_error;
use deno_core::error::AnyError;
+use deno_core::op;
use urlpattern::quirks;
use urlpattern::quirks::MatchInput;
use urlpattern::quirks::StringOrInit;
use urlpattern::quirks::UrlPattern;
+#[op]
pub fn op_urlpattern_parse(
_state: &mut deno_core::OpState,
input: StringOrInit,
@@ -23,6 +25,7 @@ pub fn op_urlpattern_parse(
Ok(pattern)
}
+#[op]
pub fn op_urlpattern_process_match_input(
_state: &mut deno_core::OpState,
input: StringOrInit,
diff --git a/ext/web/blob.rs b/ext/web/blob.rs
index 37e93c853..ad7f6c582 100644
--- a/ext/web/blob.rs
+++ b/ext/web/blob.rs
@@ -1,5 +1,7 @@
use async_trait::async_trait;
use deno_core::error::type_error;
+use deno_core::op;
+
use deno_core::parking_lot::Mutex;
use deno_core::url::Url;
use deno_core::ZeroCopyBuf;
@@ -157,6 +159,7 @@ impl BlobPart for SlicedBlobPart {
}
}
+#[op]
pub fn op_blob_create_part(
state: &mut deno_core::OpState,
data: ZeroCopyBuf,
@@ -175,6 +178,7 @@ pub struct SliceOptions {
len: usize,
}
+#[op]
pub fn op_blob_slice_part(
state: &mut deno_core::OpState,
id: Uuid,
@@ -200,6 +204,7 @@ pub fn op_blob_slice_part(
Ok(id)
}
+#[op]
pub async fn op_blob_read_part(
state: Rc<RefCell<deno_core::OpState>>,
id: Uuid,
@@ -215,6 +220,7 @@ pub async fn op_blob_read_part(
Ok(ZeroCopyBuf::from(buf.to_vec()))
}
+#[op]
pub fn op_blob_remove_part(
state: &mut deno_core::OpState,
id: Uuid,
@@ -225,6 +231,7 @@ pub fn op_blob_remove_part(
Ok(())
}
+#[op]
pub fn op_blob_create_object_url(
state: &mut deno_core::OpState,
media_type: String,
@@ -250,6 +257,7 @@ pub fn op_blob_create_object_url(
Ok(url.to_string())
}
+#[op]
pub fn op_blob_revoke_object_url(
state: &mut deno_core::OpState,
url: String,
@@ -273,6 +281,7 @@ pub struct ReturnBlobPart {
pub size: usize,
}
+#[op]
pub fn op_blob_from_object_url(
state: &mut deno_core::OpState,
url: String,
diff --git a/ext/web/compression.rs b/ext/web/compression.rs
index c84db7550..d38f65d6a 100644
--- a/ext/web/compression.rs
+++ b/ext/web/compression.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
@@ -32,6 +33,7 @@ impl Resource for CompressionResource {
}
}
+#[op]
pub fn op_compression_new(
state: &mut OpState,
format: String,
@@ -53,6 +55,7 @@ pub fn op_compression_new(
Ok(state.resource_table.add(resource))
}
+#[op]
pub fn op_compression_write(
state: &mut OpState,
rid: ResourceId,
@@ -86,6 +89,7 @@ pub fn op_compression_write(
Ok(out.into())
}
+#[op]
pub fn op_compression_finish(
state: &mut OpState,
rid: ResourceId,
diff --git a/ext/web/lib.rs b/ext/web/lib.rs
index f117bfb9d..6c278cbb0 100644
--- a/ext/web/lib.rs
+++ b/ext/web/lib.rs
@@ -9,8 +9,7 @@ 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_async;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::url::Url;
use deno_core::ByteString;
use deno_core::Extension;
@@ -83,58 +82,31 @@ pub fn init<P: TimersPermission + 'static>(
"15_performance.js",
))
.ops(vec![
- ("op_base64_decode", op_sync(op_base64_decode)),
- ("op_base64_encode", op_sync(op_base64_encode)),
- ("op_base64_atob", op_sync(op_base64_atob)),
- ("op_base64_btoa", op_sync(op_base64_btoa)),
- (
- "op_encoding_normalize_label",
- op_sync(op_encoding_normalize_label),
- ),
- ("op_encoding_new_decoder", op_sync(op_encoding_new_decoder)),
- ("op_encoding_decode", op_sync(op_encoding_decode)),
- ("op_encoding_encode_into", op_sync(op_encoding_encode_into)),
- ("op_blob_create_part", op_sync(op_blob_create_part)),
- ("op_blob_slice_part", op_sync(op_blob_slice_part)),
- ("op_blob_read_part", op_async(op_blob_read_part)),
- ("op_blob_remove_part", op_sync(op_blob_remove_part)),
- (
- "op_blob_create_object_url",
- op_sync(op_blob_create_object_url),
- ),
- (
- "op_blob_revoke_object_url",
- op_sync(op_blob_revoke_object_url),
- ),
- ("op_blob_from_object_url", op_sync(op_blob_from_object_url)),
- (
- "op_message_port_create_entangled",
- op_sync(op_message_port_create_entangled),
- ),
- (
- "op_message_port_post_message",
- op_sync(op_message_port_post_message),
- ),
- (
- "op_message_port_recv_message",
- op_async(op_message_port_recv_message),
- ),
- (
- "op_compression_new",
- op_sync(compression::op_compression_new),
- ),
- (
- "op_compression_write",
- op_sync(compression::op_compression_write),
- ),
- (
- "op_compression_finish",
- op_sync(compression::op_compression_finish),
- ),
- ("op_now", op_sync(op_now::<P>)),
- ("op_timer_handle", op_sync(op_timer_handle)),
- ("op_sleep", op_async(op_sleep)),
- ("op_sleep_sync", op_sync(op_sleep_sync::<P>)),
+ op_base64_decode::decl(),
+ op_base64_encode::decl(),
+ op_base64_atob::decl(),
+ op_base64_btoa::decl(),
+ op_encoding_normalize_label::decl(),
+ op_encoding_new_decoder::decl(),
+ op_encoding_decode::decl(),
+ op_encoding_encode_into::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::<P>(),
+ op_timer_handle::decl(),
+ op_sleep::decl(),
+ op_sleep_sync::decl::<P>(),
])
.state(move |state| {
state.put(blob_store.clone());
@@ -147,6 +119,7 @@ pub fn init<P: TimersPermission + 'static>(
.build()
}
+#[op]
fn op_base64_decode(
_: &mut OpState,
input: String,
@@ -157,6 +130,7 @@ fn op_base64_decode(
Ok(b64_decode(&input)?.into())
}
+#[op]
fn op_base64_atob(
_: &mut OpState,
s: ByteString,
@@ -210,6 +184,7 @@ fn b64_decode(input: &[u8]) -> Result<Vec<u8>, AnyError> {
Ok(out)
}
+#[op]
fn op_base64_encode(
_: &mut OpState,
s: ZeroCopyBuf,
@@ -218,6 +193,7 @@ fn op_base64_encode(
Ok(b64_encode(&s))
}
+#[op]
fn op_base64_btoa(
_: &mut OpState,
s: ByteString,
@@ -240,6 +216,7 @@ struct DecoderOptions {
fatal: bool,
}
+#[op]
fn op_encoding_normalize_label(
_state: &mut OpState,
label: String,
@@ -255,6 +232,7 @@ fn op_encoding_normalize_label(
Ok(encoding.name().to_lowercase())
}
+#[op]
fn op_encoding_new_decoder(
state: &mut OpState,
options: DecoderOptions,
@@ -294,6 +272,7 @@ struct DecodeOptions {
stream: bool,
}
+#[op]
fn op_encoding_decode(
state: &mut OpState,
data: ZeroCopyBuf,
@@ -357,6 +336,7 @@ struct EncodeIntoResult {
written: usize,
}
+#[op]
fn op_encoding_encode_into(
_state: &mut OpState,
input: String,
diff --git a/ext/web/message_port.rs b/ext/web/message_port.rs
index 8734f9b65..7f2b18b3c 100644
--- a/ext/web/message_port.rs
+++ b/ext/web/message_port.rs
@@ -4,6 +4,8 @@ use std::rc::Rc;
use deno_core::error::type_error;
use deno_core::error::AnyError;
+use deno_core::op;
+
use deno_core::ZeroCopyBuf;
use deno_core::{CancelFuture, Resource};
use deno_core::{CancelHandle, OpState};
@@ -104,6 +106,7 @@ impl Resource for MessagePortResource {
}
}
+#[op]
pub fn op_message_port_create_entangled(
state: &mut OpState,
_: (),
@@ -185,6 +188,7 @@ pub struct JsMessageData {
transferables: Vec<JsTransferable>,
}
+#[op]
pub fn op_message_port_post_message(
state: &mut OpState,
rid: ResourceId,
@@ -203,6 +207,7 @@ pub fn op_message_port_post_message(
resource.port.send(state, data)
}
+#[op]
pub async fn op_message_port_recv_message(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
diff --git a/ext/web/timers.rs b/ext/web/timers.rs
index 7f17aa969..9a78240f7 100644
--- a/ext/web/timers.rs
+++ b/ext/web/timers.rs
@@ -3,6 +3,8 @@
//! This module helps deno implement timers and performance APIs.
use deno_core::error::AnyError;
+use deno_core::op;
+
use deno_core::CancelFuture;
use deno_core::CancelHandle;
use deno_core::OpState;
@@ -25,6 +27,7 @@ pub type StartTime = Instant;
// since the start time of the deno runtime.
// If the High precision flag is not set, the
// nanoseconds are rounded on 2ms.
+#[op]
pub fn op_now<TP>(
state: &mut OpState,
_argument: (),
@@ -64,6 +67,7 @@ impl Resource for TimerHandle {
/// Creates a [`TimerHandle`] resource that can be used to cancel invocations of
/// [`op_sleep`].
+#[op]
pub fn op_timer_handle(
state: &mut OpState,
_: (),
@@ -77,6 +81,7 @@ pub fn op_timer_handle(
/// Waits asynchronously until either `millis` milliseconds have passed or the
/// [`TimerHandle`] resource given by `rid` has been canceled.
+#[op]
pub async fn op_sleep(
state: Rc<RefCell<OpState>>,
millis: u64,
@@ -89,6 +94,7 @@ pub async fn op_sleep(
Ok(())
}
+#[op]
pub fn op_sleep_sync<TP>(
state: &mut OpState,
millis: u64,
diff --git a/ext/webgpu/src/binding.rs b/ext/webgpu/src/binding.rs
index 9a8fa455f..7370f8034 100644
--- a/ext/webgpu/src/binding.rs
+++ b/ext/webgpu/src/binding.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
@@ -177,6 +178,7 @@ pub struct CreateBindGroupLayoutArgs {
entries: Vec<GpuBindGroupLayoutEntry>,
}
+#[op]
pub fn op_webgpu_create_bind_group_layout(
state: &mut OpState,
args: CreateBindGroupLayoutArgs,
@@ -220,6 +222,7 @@ pub struct CreatePipelineLayoutArgs {
bind_group_layouts: Vec<u32>,
}
+#[op]
pub fn op_webgpu_create_pipeline_layout(
state: &mut OpState,
args: CreatePipelineLayoutArgs,
@@ -271,6 +274,7 @@ pub struct CreateBindGroupArgs {
entries: Vec<GpuBindGroupEntry>,
}
+#[op]
pub fn op_webgpu_create_bind_group(
state: &mut OpState,
args: CreateBindGroupArgs,
diff --git a/ext/webgpu/src/buffer.rs b/ext/webgpu/src/buffer.rs
index 3f2c07883..ce3a78d01 100644
--- a/ext/webgpu/src/buffer.rs
+++ b/ext/webgpu/src/buffer.rs
@@ -3,6 +3,8 @@
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::futures::channel::oneshot;
+use deno_core::op;
+
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
@@ -40,6 +42,7 @@ pub struct CreateBufferArgs {
mapped_at_creation: bool,
}
+#[op]
pub fn op_webgpu_create_buffer(
state: &mut OpState,
args: CreateBufferArgs,
@@ -76,6 +79,7 @@ pub struct BufferGetMapAsyncArgs {
size: u64,
}
+#[op]
pub async fn op_webgpu_buffer_get_map_async(
state: Rc<RefCell<OpState>>,
args: BufferGetMapAsyncArgs,
@@ -167,6 +171,7 @@ pub struct BufferGetMappedRangeArgs {
size: Option<u64>,
}
+#[op]
pub fn op_webgpu_buffer_get_mapped_range(
state: &mut OpState,
args: BufferGetMappedRangeArgs,
@@ -204,6 +209,7 @@ pub struct BufferUnmapArgs {
mapped_rid: ResourceId,
}
+#[op]
pub fn op_webgpu_buffer_unmap(
state: &mut OpState,
args: BufferUnmapArgs,
diff --git a/ext/webgpu/src/bundle.rs b/ext/webgpu/src/bundle.rs
index ea327651a..4a0807302 100644
--- a/ext/webgpu/src/bundle.rs
+++ b/ext/webgpu/src/bundle.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource};
@@ -39,6 +40,7 @@ pub struct CreateRenderBundleEncoderArgs {
stencil_read_only: bool,
}
+#[op]
pub fn op_webgpu_create_render_bundle_encoder(
state: &mut OpState,
args: CreateRenderBundleEncoderArgs,
@@ -99,6 +101,7 @@ pub struct RenderBundleEncoderFinishArgs {
label: Option<String>,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_finish(
state: &mut OpState,
args: RenderBundleEncoderFinishArgs,
@@ -135,6 +138,7 @@ pub struct RenderBundleEncoderSetBindGroupArgs {
dynamic_offsets_data_length: usize,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_set_bind_group(
state: &mut OpState,
args: RenderBundleEncoderSetBindGroupArgs,
@@ -189,6 +193,7 @@ pub struct RenderBundleEncoderPushDebugGroupArgs {
group_label: String,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_push_debug_group(
state: &mut OpState,
args: RenderBundleEncoderPushDebugGroupArgs,
@@ -218,6 +223,7 @@ pub struct RenderBundleEncoderPopDebugGroupArgs {
render_bundle_encoder_rid: ResourceId,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_pop_debug_group(
state: &mut OpState,
args: RenderBundleEncoderPopDebugGroupArgs,
@@ -242,6 +248,7 @@ pub struct RenderBundleEncoderInsertDebugMarkerArgs {
marker_label: String,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_insert_debug_marker(
state: &mut OpState,
args: RenderBundleEncoderInsertDebugMarkerArgs,
@@ -272,6 +279,7 @@ pub struct RenderBundleEncoderSetPipelineArgs {
pipeline: ResourceId,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_set_pipeline(
state: &mut OpState,
args: RenderBundleEncoderSetPipelineArgs,
@@ -304,6 +312,7 @@ pub struct RenderBundleEncoderSetIndexBufferArgs {
size: u64,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_set_index_buffer(
state: &mut OpState,
args: RenderBundleEncoderSetIndexBufferArgs,
@@ -340,6 +349,7 @@ pub struct RenderBundleEncoderSetVertexBufferArgs {
size: u64,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer(
state: &mut OpState,
args: RenderBundleEncoderSetVertexBufferArgs,
@@ -374,6 +384,7 @@ pub struct RenderBundleEncoderDrawArgs {
first_instance: u32,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_draw(
state: &mut OpState,
args: RenderBundleEncoderDrawArgs,
@@ -406,6 +417,7 @@ pub struct RenderBundleEncoderDrawIndexedArgs {
first_instance: u32,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_draw_indexed(
state: &mut OpState,
args: RenderBundleEncoderDrawIndexedArgs,
@@ -436,6 +448,7 @@ pub struct RenderBundleEncoderDrawIndirectArgs {
indirect_offset: u64,
}
+#[op]
pub fn op_webgpu_render_bundle_encoder_draw_indirect(
state: &mut OpState,
args: RenderBundleEncoderDrawIndirectArgs,
diff --git a/ext/webgpu/src/command_encoder.rs b/ext/webgpu/src/command_encoder.rs
index 894b08f27..c81b2abf6 100644
--- a/ext/webgpu/src/command_encoder.rs
+++ b/ext/webgpu/src/command_encoder.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
@@ -36,6 +37,7 @@ pub struct CreateCommandEncoderArgs {
_measure_execution_time: Option<bool>, // not yet implemented
}
+#[op]
pub fn op_webgpu_create_command_encoder(
state: &mut OpState,
args: CreateCommandEncoderArgs,
@@ -96,6 +98,7 @@ pub struct CommandEncoderBeginRenderPassArgs {
_occlusion_query_set: Option<u32>, // not yet implemented
}
+#[op]
pub fn op_webgpu_command_encoder_begin_render_pass(
state: &mut OpState,
args: CommandEncoderBeginRenderPassArgs,
@@ -214,6 +217,7 @@ pub struct CommandEncoderBeginComputePassArgs {
label: Option<String>,
}
+#[op]
pub fn op_webgpu_command_encoder_begin_compute_pass(
state: &mut OpState,
args: CommandEncoderBeginComputePassArgs,
@@ -252,6 +256,7 @@ pub struct CommandEncoderCopyBufferToBufferArgs {
size: u64,
}
+#[op]
pub fn op_webgpu_command_encoder_copy_buffer_to_buffer(
state: &mut OpState,
args: CommandEncoderCopyBufferToBufferArgs,
@@ -310,6 +315,7 @@ pub struct CommandEncoderCopyBufferToTextureArgs {
copy_size: wgpu_types::Extent3d,
}
+#[op]
pub fn op_webgpu_command_encoder_copy_buffer_to_texture(
state: &mut OpState,
args: CommandEncoderCopyBufferToTextureArgs,
@@ -360,6 +366,7 @@ pub struct CommandEncoderCopyTextureToBufferArgs {
copy_size: wgpu_types::Extent3d,
}
+#[op]
pub fn op_webgpu_command_encoder_copy_texture_to_buffer(
state: &mut OpState,
args: CommandEncoderCopyTextureToBufferArgs,
@@ -414,6 +421,7 @@ pub struct CommandEncoderCopyTextureToTextureArgs {
copy_size: wgpu_types::Extent3d,
}
+#[op]
pub fn op_webgpu_command_encoder_copy_texture_to_texture(
state: &mut OpState,
args: CommandEncoderCopyTextureToTextureArgs,
@@ -462,6 +470,7 @@ pub struct CommandEncoderClearBufferArgs {
size: u64,
}
+#[op]
pub fn op_webgpu_command_encoder_clear_buffer(
state: &mut OpState,
args: CommandEncoderClearBufferArgs,
@@ -491,6 +500,7 @@ pub struct CommandEncoderPushDebugGroupArgs {
group_label: String,
}
+#[op]
pub fn op_webgpu_command_encoder_push_debug_group(
state: &mut OpState,
args: CommandEncoderPushDebugGroupArgs,
@@ -512,6 +522,7 @@ pub struct CommandEncoderPopDebugGroupArgs {
command_encoder_rid: ResourceId,
}
+#[op]
pub fn op_webgpu_command_encoder_pop_debug_group(
state: &mut OpState,
args: CommandEncoderPopDebugGroupArgs,
@@ -533,6 +544,7 @@ pub struct CommandEncoderInsertDebugMarkerArgs {
marker_label: String,
}
+#[op]
pub fn op_webgpu_command_encoder_insert_debug_marker(
state: &mut OpState,
args: CommandEncoderInsertDebugMarkerArgs,
@@ -558,6 +570,7 @@ pub struct CommandEncoderWriteTimestampArgs {
query_index: u32,
}
+#[op]
pub fn op_webgpu_command_encoder_write_timestamp(
state: &mut OpState,
args: CommandEncoderWriteTimestampArgs,
@@ -590,6 +603,7 @@ pub struct CommandEncoderResolveQuerySetArgs {
destination_offset: u64,
}
+#[op]
pub fn op_webgpu_command_encoder_resolve_query_set(
state: &mut OpState,
args: CommandEncoderResolveQuerySetArgs,
@@ -624,6 +638,7 @@ pub struct CommandEncoderFinishArgs {
label: Option<String>,
}
+#[op]
pub fn op_webgpu_command_encoder_finish(
state: &mut OpState,
args: CommandEncoderFinishArgs,
diff --git a/ext/webgpu/src/compute_pass.rs b/ext/webgpu/src/compute_pass.rs
index 03d9163cb..e6ebdc098 100644
--- a/ext/webgpu/src/compute_pass.rs
+++ b/ext/webgpu/src/compute_pass.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource};
@@ -26,6 +27,7 @@ pub struct ComputePassSetPipelineArgs {
pipeline: ResourceId,
}
+#[op]
pub fn op_webgpu_compute_pass_set_pipeline(
state: &mut OpState,
args: ComputePassSetPipelineArgs,
@@ -56,6 +58,7 @@ pub struct ComputePassDispatchArgs {
z: u32,
}
+#[op]
pub fn op_webgpu_compute_pass_dispatch(
state: &mut OpState,
args: ComputePassDispatchArgs,
@@ -83,6 +86,7 @@ pub struct ComputePassDispatchIndirectArgs {
indirect_offset: u64,
}
+#[op]
pub fn op_webgpu_compute_pass_dispatch_indirect(
state: &mut OpState,
args: ComputePassDispatchIndirectArgs,
@@ -112,6 +116,7 @@ pub struct ComputePassBeginPipelineStatisticsQueryArgs {
query_index: u32,
}
+#[op]
pub fn op_webgpu_compute_pass_begin_pipeline_statistics_query(
state: &mut OpState,
args: ComputePassBeginPipelineStatisticsQueryArgs,
@@ -139,6 +144,7 @@ pub struct ComputePassEndPipelineStatisticsQueryArgs {
compute_pass_rid: ResourceId,
}
+#[op]
pub fn op_webgpu_compute_pass_end_pipeline_statistics_query(
state: &mut OpState,
args: ComputePassEndPipelineStatisticsQueryArgs,
@@ -163,6 +169,7 @@ pub struct ComputePassWriteTimestampArgs {
query_index: u32,
}
+#[op]
pub fn op_webgpu_compute_pass_write_timestamp(
state: &mut OpState,
args: ComputePassWriteTimestampArgs,
@@ -191,6 +198,7 @@ pub struct ComputePassEndPassArgs {
compute_pass_rid: ResourceId,
}
+#[op]
pub fn op_webgpu_compute_pass_end_pass(
state: &mut OpState,
args: ComputePassEndPassArgs,
@@ -225,6 +233,7 @@ pub struct ComputePassSetBindGroupArgs {
dynamic_offsets_data_length: usize,
}
+#[op]
pub fn op_webgpu_compute_pass_set_bind_group(
state: &mut OpState,
args: ComputePassSetBindGroupArgs,
@@ -278,6 +287,7 @@ pub struct ComputePassPushDebugGroupArgs {
group_label: String,
}
+#[op]
pub fn op_webgpu_compute_pass_push_debug_group(
state: &mut OpState,
args: ComputePassPushDebugGroupArgs,
@@ -307,6 +317,7 @@ pub struct ComputePassPopDebugGroupArgs {
compute_pass_rid: ResourceId,
}
+#[op]
pub fn op_webgpu_compute_pass_pop_debug_group(
state: &mut OpState,
args: ComputePassPopDebugGroupArgs,
@@ -330,6 +341,7 @@ pub struct ComputePassInsertDebugMarkerArgs {
marker_label: String,
}
+#[op]
pub fn op_webgpu_compute_pass_insert_debug_marker(
state: &mut OpState,
args: ComputePassInsertDebugMarkerArgs,
diff --git a/ext/webgpu/src/lib.rs b/ext/webgpu/src/lib.rs
index 9d227a51e..d1eba20ba 100644
--- a/ext/webgpu/src/lib.rs
+++ b/ext/webgpu/src/lib.rs
@@ -2,10 +2,10 @@
use deno_core::error::AnyError;
use deno_core::include_js_files;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::Extension;
-use deno_core::OpFn;
+use deno_core::OpPair;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
@@ -241,6 +241,7 @@ pub struct GpuAdapterDevice {
is_software: bool,
}
+#[op]
pub async fn op_webgpu_request_adapter(
state: Rc<RefCell<OpState>>,
args: RequestAdapterArgs,
@@ -439,6 +440,7 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
}
}
+#[op]
pub async fn op_webgpu_request_device(
state: Rc<RefCell<OpState>>,
args: RequestDeviceArgs,
@@ -539,6 +541,7 @@ impl From<GpuQueryType> for wgpu_types::QueryType {
}
}
+#[op]
pub fn op_webgpu_create_query_set(
state: &mut OpState,
args: CreateQuerySetArgs,
@@ -562,347 +565,102 @@ pub fn op_webgpu_create_query_set(
) => state, WebGpuQuerySet)
}
-fn declare_webgpu_ops() -> Vec<(&'static str, Box<OpFn>)> {
+fn declare_webgpu_ops() -> Vec<OpPair> {
vec![
// Request device/adapter
- (
- "op_webgpu_request_adapter",
- op_async(op_webgpu_request_adapter),
- ),
- (
- "op_webgpu_request_device",
- op_async(op_webgpu_request_device),
- ),
+ op_webgpu_request_adapter::decl(),
+ op_webgpu_request_device::decl(),
// Query Set
- (
- "op_webgpu_create_query_set",
- op_sync(op_webgpu_create_query_set),
- ),
+ op_webgpu_create_query_set::decl(),
// 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::op_webgpu_create_buffer::decl(),
+ buffer::op_webgpu_buffer_get_mapped_range::decl(),
+ buffer::op_webgpu_buffer_unmap::decl(),
// buffer async
- (
- "op_webgpu_buffer_get_map_async",
- op_async(buffer::op_webgpu_buffer_get_map_async),
- ),
+ buffer::op_webgpu_buffer_get_map_async::decl(),
// 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),
- ),
+ texture::op_webgpu_create_texture::decl(),
+ texture::op_webgpu_create_texture_view::decl(),
// sampler
- (
- "op_webgpu_create_sampler",
- op_sync(sampler::op_webgpu_create_sampler),
- ),
+ sampler::op_webgpu_create_sampler::decl(),
// 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),
- ),
+ binding::op_webgpu_create_bind_group_layout::decl(),
+ binding::op_webgpu_create_pipeline_layout::decl(),
+ binding::op_webgpu_create_bind_group::decl(),
// 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),
- ),
+ pipeline::op_webgpu_create_compute_pipeline::decl(),
+ pipeline::op_webgpu_compute_pipeline_get_bind_group_layout::decl(),
+ pipeline::op_webgpu_create_render_pipeline::decl(),
+ pipeline::op_webgpu_render_pipeline_get_bind_group_layout::decl(),
// 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_clear_buffer",
- op_sync(command_encoder::op_webgpu_command_encoder_clear_buffer),
- ),
- (
- "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),
- ),
+ command_encoder::op_webgpu_create_command_encoder::decl(),
+ command_encoder::op_webgpu_command_encoder_begin_render_pass::decl(),
+ command_encoder::op_webgpu_command_encoder_begin_compute_pass::decl(),
+ command_encoder::op_webgpu_command_encoder_copy_buffer_to_buffer::decl(),
+ command_encoder::op_webgpu_command_encoder_copy_buffer_to_texture::decl(),
+ command_encoder::op_webgpu_command_encoder_copy_texture_to_buffer::decl(),
+ command_encoder::op_webgpu_command_encoder_copy_texture_to_texture::decl(),
+ command_encoder::op_webgpu_command_encoder_clear_buffer::decl(),
+ command_encoder::op_webgpu_command_encoder_push_debug_group::decl(),
+ command_encoder::op_webgpu_command_encoder_pop_debug_group::decl(),
+ command_encoder::op_webgpu_command_encoder_insert_debug_marker::decl(),
+ command_encoder::op_webgpu_command_encoder_write_timestamp::decl(),
+ command_encoder::op_webgpu_command_encoder_resolve_query_set::decl(),
+ command_encoder::op_webgpu_command_encoder_finish::decl(),
// 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_constant",
- op_sync(render_pass::op_webgpu_render_pass_set_blend_constant),
- ),
- (
- "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),
- ),
+ render_pass::op_webgpu_render_pass_set_viewport::decl(),
+ render_pass::op_webgpu_render_pass_set_scissor_rect::decl(),
+ render_pass::op_webgpu_render_pass_set_blend_constant::decl(),
+ render_pass::op_webgpu_render_pass_set_stencil_reference::decl(),
+ render_pass::op_webgpu_render_pass_begin_pipeline_statistics_query::decl(),
+ render_pass::op_webgpu_render_pass_end_pipeline_statistics_query::decl(),
+ render_pass::op_webgpu_render_pass_write_timestamp::decl(),
+ render_pass::op_webgpu_render_pass_execute_bundles::decl(),
+ render_pass::op_webgpu_render_pass_end_pass::decl(),
+ render_pass::op_webgpu_render_pass_set_bind_group::decl(),
+ render_pass::op_webgpu_render_pass_push_debug_group::decl(),
+ render_pass::op_webgpu_render_pass_pop_debug_group::decl(),
+ render_pass::op_webgpu_render_pass_insert_debug_marker::decl(),
+ render_pass::op_webgpu_render_pass_set_pipeline::decl(),
+ render_pass::op_webgpu_render_pass_set_index_buffer::decl(),
+ render_pass::op_webgpu_render_pass_set_vertex_buffer::decl(),
+ render_pass::op_webgpu_render_pass_draw::decl(),
+ render_pass::op_webgpu_render_pass_draw_indexed::decl(),
+ render_pass::op_webgpu_render_pass_draw_indirect::decl(),
+ render_pass::op_webgpu_render_pass_draw_indexed_indirect::decl(),
// 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_begin_pipeline_statistics_query",
- op_sync(
- compute_pass::op_webgpu_compute_pass_begin_pipeline_statistics_query,
- ),
- ),
- (
- "op_webgpu_compute_pass_end_pipeline_statistics_query",
- op_sync(
- compute_pass::op_webgpu_compute_pass_end_pipeline_statistics_query,
- ),
- ),
- (
- "op_webgpu_compute_pass_write_timestamp",
- op_sync(compute_pass::op_webgpu_compute_pass_write_timestamp),
- ),
- (
- "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),
- ),
+ compute_pass::op_webgpu_compute_pass_set_pipeline::decl(),
+ compute_pass::op_webgpu_compute_pass_dispatch::decl(),
+ compute_pass::op_webgpu_compute_pass_dispatch_indirect::decl(),
+ compute_pass::op_webgpu_compute_pass_begin_pipeline_statistics_query::decl(
+ ),
+ compute_pass::op_webgpu_compute_pass_end_pipeline_statistics_query::decl(),
+ compute_pass::op_webgpu_compute_pass_write_timestamp::decl(),
+ compute_pass::op_webgpu_compute_pass_end_pass::decl(),
+ compute_pass::op_webgpu_compute_pass_set_bind_group::decl(),
+ compute_pass::op_webgpu_compute_pass_push_debug_group::decl(),
+ compute_pass::op_webgpu_compute_pass_pop_debug_group::decl(),
+ compute_pass::op_webgpu_compute_pass_insert_debug_marker::decl(),
// 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),
- ),
+ bundle::op_webgpu_create_render_bundle_encoder::decl(),
+ bundle::op_webgpu_render_bundle_encoder_finish::decl(),
+ bundle::op_webgpu_render_bundle_encoder_set_bind_group::decl(),
+ bundle::op_webgpu_render_bundle_encoder_push_debug_group::decl(),
+ bundle::op_webgpu_render_bundle_encoder_pop_debug_group::decl(),
+ bundle::op_webgpu_render_bundle_encoder_insert_debug_marker::decl(),
+ bundle::op_webgpu_render_bundle_encoder_set_pipeline::decl(),
+ bundle::op_webgpu_render_bundle_encoder_set_index_buffer::decl(),
+ bundle::op_webgpu_render_bundle_encoder_set_vertex_buffer::decl(),
+ bundle::op_webgpu_render_bundle_encoder_draw::decl(),
+ bundle::op_webgpu_render_bundle_encoder_draw_indexed::decl(),
+ bundle::op_webgpu_render_bundle_encoder_draw_indirect::decl(),
// 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),
- ),
+ queue::op_webgpu_queue_submit::decl(),
+ queue::op_webgpu_write_buffer::decl(),
+ queue::op_webgpu_write_texture::decl(),
// shader
- (
- "op_webgpu_create_shader_module",
- op_sync(shader::op_webgpu_create_shader_module),
- ),
+ shader::op_webgpu_create_shader_module::decl(),
]
}
diff --git a/ext/webgpu/src/pipeline.rs b/ext/webgpu/src/pipeline.rs
index 8327fb946..6ea2a5677 100644
--- a/ext/webgpu/src/pipeline.rs
+++ b/ext/webgpu/src/pipeline.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
@@ -57,6 +58,7 @@ pub struct CreateComputePipelineArgs {
compute: GpuProgrammableStage,
}
+#[op]
pub fn op_webgpu_create_compute_pipeline(
state: &mut OpState,
args: CreateComputePipelineArgs,
@@ -126,6 +128,7 @@ pub struct PipelineLayout {
err: Option<WebGpuError>,
}
+#[op]
pub fn op_webgpu_compute_pipeline_get_bind_group_layout(
state: &mut OpState,
args: ComputePipelineGetBindGroupLayoutArgs,
@@ -303,6 +306,7 @@ pub struct CreateRenderPipelineArgs {
fragment: Option<GpuFragmentState>,
}
+#[op]
pub fn op_webgpu_create_render_pipeline(
state: &mut OpState,
args: CreateRenderPipelineArgs,
@@ -404,6 +408,7 @@ pub struct RenderPipelineGetBindGroupLayoutArgs {
index: u32,
}
+#[op]
pub fn op_webgpu_render_pipeline_get_bind_group_layout(
state: &mut OpState,
args: RenderPipelineGetBindGroupLayoutArgs,
diff --git a/ext/webgpu/src/queue.rs b/ext/webgpu/src/queue.rs
index a662c4ead..3853f0025 100644
--- a/ext/webgpu/src/queue.rs
+++ b/ext/webgpu/src/queue.rs
@@ -3,6 +3,7 @@
use std::num::NonZeroU32;
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::OpState;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
@@ -19,6 +20,7 @@ pub struct QueueSubmitArgs {
command_buffers: Vec<ResourceId>,
}
+#[op]
pub fn op_webgpu_queue_submit(
state: &mut OpState,
args: QueueSubmitArgs,
@@ -73,6 +75,7 @@ pub struct QueueWriteBufferArgs {
size: Option<usize>,
}
+#[op]
pub fn op_webgpu_write_buffer(
state: &mut OpState,
args: QueueWriteBufferArgs,
@@ -111,6 +114,7 @@ pub struct QueueWriteTextureArgs {
size: wgpu_types::Extent3d,
}
+#[op]
pub fn op_webgpu_write_texture(
state: &mut OpState,
args: QueueWriteTextureArgs,
diff --git a/ext/webgpu/src/render_pass.rs b/ext/webgpu/src/render_pass.rs
index 469bf727e..822b4c8c9 100644
--- a/ext/webgpu/src/render_pass.rs
+++ b/ext/webgpu/src/render_pass.rs
@@ -2,6 +2,7 @@
use deno_core::error::type_error;
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource};
@@ -32,6 +33,7 @@ pub struct RenderPassSetViewportArgs {
max_depth: f32,
}
+#[op]
pub fn op_webgpu_render_pass_set_viewport(
state: &mut OpState,
args: RenderPassSetViewportArgs,
@@ -64,6 +66,7 @@ pub struct RenderPassSetScissorRectArgs {
height: u32,
}
+#[op]
pub fn op_webgpu_render_pass_set_scissor_rect(
state: &mut OpState,
args: RenderPassSetScissorRectArgs,
@@ -91,6 +94,7 @@ pub struct RenderPassSetBlendConstantArgs {
color: wgpu_types::Color,
}
+#[op]
pub fn op_webgpu_render_pass_set_blend_constant(
state: &mut OpState,
args: RenderPassSetBlendConstantArgs,
@@ -115,6 +119,7 @@ pub struct RenderPassSetStencilReferenceArgs {
reference: u32,
}
+#[op]
pub fn op_webgpu_render_pass_set_stencil_reference(
state: &mut OpState,
args: RenderPassSetStencilReferenceArgs,
@@ -140,6 +145,7 @@ pub struct RenderPassBeginPipelineStatisticsQueryArgs {
query_index: u32,
}
+#[op]
pub fn op_webgpu_render_pass_begin_pipeline_statistics_query(
state: &mut OpState,
args: RenderPassBeginPipelineStatisticsQueryArgs,
@@ -167,6 +173,7 @@ pub struct RenderPassEndPipelineStatisticsQueryArgs {
render_pass_rid: ResourceId,
}
+#[op]
pub fn op_webgpu_render_pass_end_pipeline_statistics_query(
state: &mut OpState,
args: RenderPassEndPipelineStatisticsQueryArgs,
@@ -191,6 +198,7 @@ pub struct RenderPassWriteTimestampArgs {
query_index: u32,
}
+#[op]
pub fn op_webgpu_render_pass_write_timestamp(
state: &mut OpState,
args: RenderPassWriteTimestampArgs,
@@ -219,6 +227,7 @@ pub struct RenderPassExecuteBundlesArgs {
bundles: Vec<u32>,
}
+#[op]
pub fn op_webgpu_render_pass_execute_bundles(
state: &mut OpState,
args: RenderPassExecuteBundlesArgs,
@@ -258,6 +267,7 @@ pub struct RenderPassEndPassArgs {
render_pass_rid: ResourceId,
}
+#[op]
pub fn op_webgpu_render_pass_end_pass(
state: &mut OpState,
args: RenderPassEndPassArgs,
@@ -289,6 +299,7 @@ pub struct RenderPassSetBindGroupArgs {
dynamic_offsets_data_length: usize,
}
+#[op]
pub fn op_webgpu_render_pass_set_bind_group(
state: &mut OpState,
args: RenderPassSetBindGroupArgs,
@@ -342,6 +353,7 @@ pub struct RenderPassPushDebugGroupArgs {
group_label: String,
}
+#[op]
pub fn op_webgpu_render_pass_push_debug_group(
state: &mut OpState,
args: RenderPassPushDebugGroupArgs,
@@ -371,6 +383,7 @@ pub struct RenderPassPopDebugGroupArgs {
render_pass_rid: ResourceId,
}
+#[op]
pub fn op_webgpu_render_pass_pop_debug_group(
state: &mut OpState,
args: RenderPassPopDebugGroupArgs,
@@ -394,6 +407,7 @@ pub struct RenderPassInsertDebugMarkerArgs {
marker_label: String,
}
+#[op]
pub fn op_webgpu_render_pass_insert_debug_marker(
state: &mut OpState,
args: RenderPassInsertDebugMarkerArgs,
@@ -424,6 +438,7 @@ pub struct RenderPassSetPipelineArgs {
pipeline: u32,
}
+#[op]
pub fn op_webgpu_render_pass_set_pipeline(
state: &mut OpState,
args: RenderPassSetPipelineArgs,
@@ -455,6 +470,7 @@ pub struct RenderPassSetIndexBufferArgs {
size: Option<u64>,
}
+#[op]
pub fn op_webgpu_render_pass_set_index_buffer(
state: &mut OpState,
args: RenderPassSetIndexBufferArgs,
@@ -496,6 +512,7 @@ pub struct RenderPassSetVertexBufferArgs {
size: Option<u64>,
}
+#[op]
pub fn op_webgpu_render_pass_set_vertex_buffer(
state: &mut OpState,
args: RenderPassSetVertexBufferArgs,
@@ -538,6 +555,7 @@ pub struct RenderPassDrawArgs {
first_instance: u32,
}
+#[op]
pub fn op_webgpu_render_pass_draw(
state: &mut OpState,
args: RenderPassDrawArgs,
@@ -569,6 +587,7 @@ pub struct RenderPassDrawIndexedArgs {
first_instance: u32,
}
+#[op]
pub fn op_webgpu_render_pass_draw_indexed(
state: &mut OpState,
args: RenderPassDrawIndexedArgs,
@@ -598,6 +617,7 @@ pub struct RenderPassDrawIndirectArgs {
indirect_offset: u64,
}
+#[op]
pub fn op_webgpu_render_pass_draw_indirect(
state: &mut OpState,
args: RenderPassDrawIndirectArgs,
@@ -627,6 +647,7 @@ pub struct RenderPassDrawIndexedIndirectArgs {
indirect_offset: u64,
}
+#[op]
pub fn op_webgpu_render_pass_draw_indexed_indirect(
state: &mut OpState,
args: RenderPassDrawIndexedIndirectArgs,
diff --git a/ext/webgpu/src/sampler.rs b/ext/webgpu/src/sampler.rs
index c1cb0b411..3c0c43f53 100644
--- a/ext/webgpu/src/sampler.rs
+++ b/ext/webgpu/src/sampler.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
@@ -32,6 +33,7 @@ pub struct CreateSamplerArgs {
max_anisotropy: u8,
}
+#[op]
pub fn op_webgpu_create_sampler(
state: &mut OpState,
args: CreateSamplerArgs,
diff --git a/ext/webgpu/src/shader.rs b/ext/webgpu/src/shader.rs
index 60290de8b..0173fffa2 100644
--- a/ext/webgpu/src/shader.rs
+++ b/ext/webgpu/src/shader.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
@@ -24,6 +25,7 @@ pub struct CreateShaderModuleArgs {
_source_map: Option<()>, // not yet implemented
}
+#[op]
pub fn op_webgpu_create_shader_module(
state: &mut OpState,
args: CreateShaderModuleArgs,
diff --git a/ext/webgpu/src/texture.rs b/ext/webgpu/src/texture.rs
index 30d440e5c..482437478 100644
--- a/ext/webgpu/src/texture.rs
+++ b/ext/webgpu/src/texture.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
@@ -34,6 +35,7 @@ pub struct CreateTextureArgs {
usage: u32,
}
+#[op]
pub fn op_webgpu_create_texture(
state: &mut OpState,
args: CreateTextureArgs,
@@ -76,6 +78,7 @@ pub struct CreateTextureViewArgs {
array_layer_count: Option<u32>,
}
+#[op]
pub fn op_webgpu_create_texture_view(
state: &mut OpState,
args: CreateTextureViewArgs,
diff --git a/ext/websocket/lib.rs b/ext/websocket/lib.rs
index 76ca92136..d712140b5 100644
--- a/ext/websocket/lib.rs
+++ b/ext/websocket/lib.rs
@@ -8,8 +8,8 @@ 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::op;
+
use deno_core::url;
use deno_core::AsyncRefCell;
use deno_core::ByteString;
@@ -190,6 +190,7 @@ impl Resource for WsCancelResource {
// This op is needed because creating a WS instance in JavaScript is a sync
// operation and should throw error when permissions are not fulfilled,
// but actual op that connects WS is async.
+#[op]
pub fn op_ws_check_permission_and_cancel_handle<WP>(
state: &mut OpState,
url: String,
@@ -229,6 +230,7 @@ pub struct CreateResponse {
extensions: String,
}
+#[op]
pub async fn op_ws_create<WP>(
state: Rc<RefCell<OpState>>,
args: CreateArgs,
@@ -378,6 +380,7 @@ pub enum SendValue {
Ping,
}
+#[op]
pub async fn op_ws_send(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -406,6 +409,7 @@ pub struct CloseArgs {
reason: Option<String>,
}
+#[op]
pub async fn op_ws_close(
state: Rc<RefCell<OpState>>,
args: CloseArgs,
@@ -440,6 +444,7 @@ pub enum NextEventResponse {
Closed,
}
+#[op]
pub async fn op_ws_next_event(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -486,14 +491,11 @@ pub fn init<P: WebSocketPermissions + 'static>(
"02_websocketstream.js",
))
.ops(vec![
- (
- "op_ws_check_permission_and_cancel_handle",
- op_sync(op_ws_check_permission_and_cancel_handle::<P>),
- ),
- ("op_ws_create", op_async(op_ws_create::<P>)),
- ("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)),
+ op_ws_check_permission_and_cancel_handle::decl::<P>(),
+ op_ws_create::decl::<P>(),
+ op_ws_send::decl(),
+ op_ws_close::decl(),
+ op_ws_next_event::decl(),
])
.state(move |state| {
state.put::<WsUserAgent>(WsUserAgent(user_agent.clone()));
diff --git a/ext/webstorage/lib.rs b/ext/webstorage/lib.rs
index 0aafefe62..c51301683 100644
--- a/ext/webstorage/lib.rs
+++ b/ext/webstorage/lib.rs
@@ -4,7 +4,7 @@
use deno_core::error::AnyError;
use deno_core::include_js_files;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::Extension;
use deno_core::OpState;
use rusqlite::params;
@@ -26,16 +26,13 @@ pub fn init(origin_storage_dir: Option<PathBuf>) -> Extension {
"01_webstorage.js",
))
.ops(vec![
- ("op_webstorage_length", op_sync(op_webstorage_length)),
- ("op_webstorage_key", op_sync(op_webstorage_key)),
- ("op_webstorage_set", op_sync(op_webstorage_set)),
- ("op_webstorage_get", op_sync(op_webstorage_get)),
- ("op_webstorage_remove", op_sync(op_webstorage_remove)),
- ("op_webstorage_clear", op_sync(op_webstorage_clear)),
- (
- "op_webstorage_iterate_keys",
- op_sync(op_webstorage_iterate_keys),
- ),
+ 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 {
@@ -103,6 +100,7 @@ fn get_webstorage(
Ok(conn)
}
+#[op]
pub fn op_webstorage_length(
state: &mut OpState,
persistent: bool,
@@ -116,6 +114,7 @@ pub fn op_webstorage_length(
Ok(length)
}
+#[op]
pub fn op_webstorage_key(
state: &mut OpState,
index: u32,
@@ -140,6 +139,7 @@ pub struct SetArgs {
key_value: String,
}
+#[op]
pub fn op_webstorage_set(
state: &mut OpState,
args: SetArgs,
@@ -167,6 +167,7 @@ pub fn op_webstorage_set(
Ok(())
}
+#[op]
pub fn op_webstorage_get(
state: &mut OpState,
key_name: String,
@@ -182,6 +183,7 @@ pub fn op_webstorage_get(
Ok(val)
}
+#[op]
pub fn op_webstorage_remove(
state: &mut OpState,
key_name: String,
@@ -195,6 +197,7 @@ pub fn op_webstorage_remove(
Ok(())
}
+#[op]
pub fn op_webstorage_clear(
state: &mut OpState,
persistent: bool,
@@ -208,6 +211,7 @@ pub fn op_webstorage_clear(
Ok(())
}
+#[op]
pub fn op_webstorage_iterate_keys(
state: &mut OpState,
persistent: bool,
diff --git a/ops/Cargo.toml b/ops/Cargo.toml
new file mode 100644
index 000000000..aafa55cbc
--- /dev/null
+++ b/ops/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "deno_ops"
+version = "0.1.1"
+edition = "2021"
+license = "MIT"
+readme = "README.md"
+description = "Proc macro for writing Deno Ops"
+
+[lib]
+path = "./lib.rs"
+proc-macro = true
+
+[dependencies]
+proc-macro-crate = "1.1.3"
+proc-macro2 = "1"
+quote = "1"
+syn = { version = "1", features = ["full", "extra-traits"] }
diff --git a/ops/README.md b/ops/README.md
new file mode 100644
index 000000000..02ee266f7
--- /dev/null
+++ b/ops/README.md
@@ -0,0 +1,16 @@
+# deno_ops
+
+`proc_macro` for generating highly optimized V8 functions from Deno ops.
+
+```rust
+// Declare an op.
+#[op]
+pub fn op_add(_: &mut OpState, a: i32, b: i32) -> Result<i32, AnyError> {
+ Ok(a + b)
+}
+
+// Register with an extension.
+Extension::builder()
+ .ops(vec![op_add::decl()])
+ .build();
+```
diff --git a/ops/lib.rs b/ops/lib.rs
new file mode 100644
index 000000000..d159c6c4b
--- /dev/null
+++ b/ops/lib.rs
@@ -0,0 +1,264 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+use proc_macro::TokenStream;
+use proc_macro2::Span;
+use proc_macro2::TokenStream as TokenStream2;
+use proc_macro_crate::crate_name;
+use proc_macro_crate::FoundCrate;
+use quote::quote;
+use syn::Ident;
+
+// Identifer to the `deno_core` crate.
+//
+// If macro called in deno_core, `crate` is used.
+// If macro called outside deno_core, `deno_core` OR the renamed
+// version from Cargo.toml is used.
+fn core_import() -> TokenStream2 {
+ let found_crate =
+ crate_name("deno_core").expect("deno_core not present in `Cargo.toml`");
+
+ match found_crate {
+ FoundCrate::Itself => {
+ // TODO(@littledivy): This won't work for `deno_core` examples
+ // since `crate` does not refer to `deno_core`.
+ // examples must re-export deno_core to make this work
+ // until Span inspection APIs are stabalized.
+ //
+ // https://github.com/rust-lang/rust/issues/54725
+ quote!(crate)
+ }
+ FoundCrate::Name(name) => {
+ let ident = Ident::new(&name, Span::call_site());
+ quote!(#ident)
+ }
+ }
+}
+
+#[proc_macro_attribute]
+pub fn op(_attr: TokenStream, item: TokenStream) -> TokenStream {
+ let func = syn::parse::<syn::ItemFn>(item).expect("expected a function");
+ let name = &func.sig.ident;
+ let generics = &func.sig.generics;
+ let type_params = &func.sig.generics.params;
+ let where_clause = &func.sig.generics.where_clause;
+
+ // Preserve the original func as op_foo::call()
+ let original_func = {
+ let mut func = func.clone();
+ func.sig.ident = quote::format_ident!("call");
+ func
+ };
+
+ let core = core_import();
+
+ let v8_body = if func.sig.asyncness.is_some() {
+ codegen_v8_async(&core, &func)
+ } else {
+ codegen_v8_sync(&core, &func)
+ };
+
+ // Generate wrapper
+ quote! {
+ #[allow(non_camel_case_types)]
+ pub struct #name;
+
+ impl #name {
+ pub fn name() -> &'static str {
+ stringify!(#name)
+ }
+
+ pub fn v8_cb #generics () -> #core::v8::FunctionCallback #where_clause {
+ use #core::v8::MapFnTo;
+ Self::v8_func::<#type_params>.map_fn_to()
+ }
+
+ pub fn decl #generics () -> (&'static str, #core::v8::FunctionCallback) #where_clause {
+ (Self::name(), Self::v8_cb::<#type_params>())
+ }
+
+ #[inline]
+ #original_func
+
+ pub fn v8_func #generics (
+ scope: &mut #core::v8::HandleScope,
+ args: #core::v8::FunctionCallbackArguments,
+ mut rv: #core::v8::ReturnValue,
+ ) #where_clause {
+ #v8_body
+ }
+ }
+ }.into()
+}
+
+/// Generate the body of a v8 func for an async op
+fn codegen_v8_async(core: &TokenStream2, f: &syn::ItemFn) -> TokenStream2 {
+ let a = codegen_arg(core, &f.sig.inputs[1], "a", 2);
+ let b = codegen_arg(core, &f.sig.inputs[2], "b", 3);
+ let type_params = &f.sig.generics.params;
+
+ quote! {
+ use #core::futures::FutureExt;
+ // SAFETY: Called from Deno.core.opAsync. Which retrieves the index using opId table.
+ let op_id = unsafe {
+ #core::v8::Local::<#core::v8::Integer>::cast(args.get(0))
+ }.value() as usize;
+
+ let promise_id = args.get(1);
+ let promise_id = #core::v8::Local::<#core::v8::Integer>::try_from(promise_id)
+ .map(|l| l.value() as #core::PromiseId)
+ .map_err(#core::anyhow::Error::from);
+ // Fail if promise id invalid (not an int)
+ let promise_id: #core::PromiseId = match promise_id {
+ Ok(promise_id) => promise_id,
+ Err(err) => {
+ #core::_ops::throw_type_error(scope, format!("invalid promise id: {}", err));
+ return;
+ }
+ };
+
+ #a
+ #b
+
+ // SAFETY: Unchecked cast to external since #core guarantees args.data() is a v8 External.
+ let state_refcell_raw = unsafe {
+ #core::v8::Local::<#core::v8::External>::cast(args.data().unwrap_unchecked())
+ }.value();
+
+ // SAFETY: The Rc<RefCell<OpState>> is functionally pinned and is tied to the isolate's lifetime
+ let state = unsafe {
+ let ptr = state_refcell_raw as *const std::cell::RefCell<#core::OpState>;
+ // Increment so it will later be decremented/dropped by the underlaying func it is moved to
+ std::rc::Rc::increment_strong_count(ptr);
+ std::rc::Rc::from_raw(ptr)
+ };
+ // Track async call & get copy of get_error_class_fn
+ let get_class = {
+ let state = state.borrow();
+ state.tracker.track_async(op_id);
+ state.get_error_class_fn
+ };
+
+ #core::_ops::queue_async_op(scope, async move {
+ let result = Self::call::<#type_params>(state, a, b).await;
+ (promise_id, op_id, #core::_ops::to_op_result(get_class, result))
+ });
+ }
+}
+
+/// Generate the body of a v8 func for a sync op
+fn codegen_v8_sync(core: &TokenStream2, f: &syn::ItemFn) -> TokenStream2 {
+ let a = codegen_arg(core, &f.sig.inputs[1], "a", 1);
+ let b = codegen_arg(core, &f.sig.inputs[2], "b", 2);
+ let ret = codegen_sync_ret(core, &f.sig.output);
+ let type_params = &f.sig.generics.params;
+
+ quote! {
+ // SAFETY: Called from Deno.core.opSync. Which retrieves the index using opId table.
+ let op_id = unsafe {
+ #core::v8::Local::<#core::v8::Integer>::cast(args.get(0)).value()
+ } as usize;
+
+ #a
+ #b
+
+ // SAFETY: Unchecked cast to external since #core guarantees args.data() is a v8 External.
+ let state_refcell_raw = unsafe {
+ #core::v8::Local::<#core::v8::External>::cast(args.data().unwrap_unchecked())
+ }.value();
+
+ // SAFETY: The Rc<RefCell<OpState>> is functionally pinned and is tied to the isolate's lifetime
+ let state = unsafe { &*(state_refcell_raw as *const std::cell::RefCell<#core::OpState>) };
+
+ let op_state = &mut state.borrow_mut();
+ let result = Self::call::<#type_params>(op_state, a, b);
+
+ op_state.tracker.track_sync(op_id);
+
+ #ret
+ }
+}
+
+fn codegen_arg(
+ core: &TokenStream2,
+ arg: &syn::FnArg,
+ name: &str,
+ idx: i32,
+) -> TokenStream2 {
+ let ident = quote::format_ident!("{name}");
+ let pat = match arg {
+ syn::FnArg::Typed(pat) => &pat.pat,
+ _ => unreachable!(),
+ };
+ // Fast path if arg should be skipped
+ if matches!(**pat, syn::Pat::Wild(_)) {
+ return quote! { let #ident = (); };
+ }
+ // Otherwise deserialize it via serde_v8
+ quote! {
+ let #ident = args.get(#idx);
+ let #ident = match #core::serde_v8::from_v8(scope, #ident) {
+ Ok(v) => v,
+ Err(err) => {
+ let msg = format!("Error parsing args: {}", #core::anyhow::Error::from(err));
+ return #core::_ops::throw_type_error(scope, msg);
+ }
+ };
+ }
+}
+
+fn codegen_sync_ret(
+ core: &TokenStream2,
+ output: &syn::ReturnType,
+) -> TokenStream2 {
+ let ret_type = match output {
+ // Func with no return no-ops
+ syn::ReturnType::Default => return quote! { let ret = (); },
+ // Func with a return Result<T, E>
+ syn::ReturnType::Type(_, ty) => ty,
+ };
+
+ // Optimize Result<(), Err> to skip serde_v8 when Ok(...)
+ let ok_block = if is_unit_result(&**ret_type) {
+ quote! {}
+ } else {
+ quote! {
+ let ret = #core::serde_v8::to_v8(scope, v).unwrap();
+ rv.set(ret);
+ }
+ };
+
+ quote! {
+ match result {
+ Ok(v) => {
+ #ok_block
+ },
+ Err(err) => {
+ let err = #core::OpError::new(op_state.get_error_class_fn, err);
+ rv.set(#core::serde_v8::to_v8(scope, err).unwrap());
+ },
+ };
+ }
+}
+
+/// Detects if a type is of the form Result<(), Err>
+fn is_unit_result(ty: &syn::Type) -> bool {
+ let path = match ty {
+ syn::Type::Path(ref path) => path,
+ _ => return false,
+ };
+
+ let maybe_result = path.path.segments.first().expect("Invalid return type.");
+ if maybe_result.ident != "Result" {
+ return false;
+ }
+ assert!(!maybe_result.arguments.is_empty());
+
+ let args = match &maybe_result.arguments {
+ syn::PathArguments::AngleBracketed(args) => args,
+ _ => unreachable!(),
+ };
+
+ match args.args.first().unwrap() {
+ syn::GenericArgument::Type(syn::Type::Tuple(ty)) => ty.elems.is_empty(),
+ _ => false,
+ }
+}
diff --git a/runtime/ops/fs.rs b/runtime/ops/fs.rs
index bc84cffb1..f7f0ad33c 100644
--- a/runtime/ops/fs.rs
+++ b/runtime/ops/fs.rs
@@ -8,8 +8,8 @@ use deno_core::error::bad_resource_id;
use deno_core::error::custom_error;
use deno_core::error::type_error;
use deno_core::error::AnyError;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::Extension;
use deno_core::OpState;
use deno_core::RcRef;
@@ -38,59 +38,59 @@ use deno_core::error::not_supported;
pub fn init() -> Extension {
Extension::builder()
.ops(vec![
- ("op_open_sync", op_sync(op_open_sync)),
- ("op_open_async", op_async(op_open_async)),
- ("op_seek_sync", op_sync(op_seek_sync)),
- ("op_seek_async", op_async(op_seek_async)),
- ("op_fdatasync_sync", op_sync(op_fdatasync_sync)),
- ("op_fdatasync_async", op_async(op_fdatasync_async)),
- ("op_fsync_sync", op_sync(op_fsync_sync)),
- ("op_fsync_async", op_async(op_fsync_async)),
- ("op_fstat_sync", op_sync(op_fstat_sync)),
- ("op_fstat_async", op_async(op_fstat_async)),
- ("op_flock_sync", op_sync(op_flock_sync)),
- ("op_flock_async", op_async(op_flock_async)),
- ("op_funlock_sync", op_sync(op_funlock_sync)),
- ("op_funlock_async", op_async(op_funlock_async)),
- ("op_umask", op_sync(op_umask)),
- ("op_chdir", op_sync(op_chdir)),
- ("op_mkdir_sync", op_sync(op_mkdir_sync)),
- ("op_mkdir_async", op_async(op_mkdir_async)),
- ("op_chmod_sync", op_sync(op_chmod_sync)),
- ("op_chmod_async", op_async(op_chmod_async)),
- ("op_chown_sync", op_sync(op_chown_sync)),
- ("op_chown_async", op_async(op_chown_async)),
- ("op_remove_sync", op_sync(op_remove_sync)),
- ("op_remove_async", op_async(op_remove_async)),
- ("op_copy_file_sync", op_sync(op_copy_file_sync)),
- ("op_copy_file_async", op_async(op_copy_file_async)),
- ("op_stat_sync", op_sync(op_stat_sync)),
- ("op_stat_async", op_async(op_stat_async)),
- ("op_realpath_sync", op_sync(op_realpath_sync)),
- ("op_realpath_async", op_async(op_realpath_async)),
- ("op_read_dir_sync", op_sync(op_read_dir_sync)),
- ("op_read_dir_async", op_async(op_read_dir_async)),
- ("op_rename_sync", op_sync(op_rename_sync)),
- ("op_rename_async", op_async(op_rename_async)),
- ("op_link_sync", op_sync(op_link_sync)),
- ("op_link_async", op_async(op_link_async)),
- ("op_symlink_sync", op_sync(op_symlink_sync)),
- ("op_symlink_async", op_async(op_symlink_async)),
- ("op_read_link_sync", op_sync(op_read_link_sync)),
- ("op_read_link_async", op_async(op_read_link_async)),
- ("op_ftruncate_sync", op_sync(op_ftruncate_sync)),
- ("op_ftruncate_async", op_async(op_ftruncate_async)),
- ("op_truncate_sync", op_sync(op_truncate_sync)),
- ("op_truncate_async", op_async(op_truncate_async)),
- ("op_make_temp_dir_sync", op_sync(op_make_temp_dir_sync)),
- ("op_make_temp_dir_async", op_async(op_make_temp_dir_async)),
- ("op_make_temp_file_sync", op_sync(op_make_temp_file_sync)),
- ("op_make_temp_file_async", op_async(op_make_temp_file_async)),
- ("op_cwd", op_sync(op_cwd)),
- ("op_futime_sync", op_sync(op_futime_sync)),
- ("op_futime_async", op_async(op_futime_async)),
- ("op_utime_sync", op_sync(op_utime_sync)),
- ("op_utime_async", op_async(op_utime_async)),
+ op_open_sync::decl(),
+ op_open_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(),
])
.build()
}
@@ -157,6 +157,7 @@ fn open_helper(
Ok((path, open_options))
}
+#[op]
fn op_open_sync(
state: &mut OpState,
args: OpenArgs,
@@ -172,6 +173,7 @@ fn op_open_sync(
Ok(rid)
}
+#[op]
async fn op_open_async(
state: Rc<RefCell<OpState>>,
args: OpenArgs,
@@ -214,6 +216,7 @@ fn seek_helper(args: SeekArgs) -> Result<(u32, SeekFrom), AnyError> {
Ok((rid, seek_from))
}
+#[op]
fn op_seek_sync(
state: &mut OpState,
args: SeekArgs,
@@ -229,6 +232,7 @@ fn op_seek_sync(
Ok(pos)
}
+#[op]
async fn op_seek_async(
state: Rc<RefCell<OpState>>,
args: SeekArgs,
@@ -253,6 +257,7 @@ async fn op_seek_async(
Ok(pos)
}
+#[op]
fn op_fdatasync_sync(
state: &mut OpState,
rid: ResourceId,
@@ -265,6 +270,7 @@ fn op_fdatasync_sync(
Ok(())
}
+#[op]
async fn op_fdatasync_async(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -287,6 +293,7 @@ async fn op_fdatasync_async(
Ok(())
}
+#[op]
fn op_fsync_sync(
state: &mut OpState,
rid: ResourceId,
@@ -299,6 +306,7 @@ fn op_fsync_sync(
Ok(())
}
+#[op]
async fn op_fsync_async(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -321,6 +329,7 @@ async fn op_fsync_async(
Ok(())
}
+#[op]
fn op_fstat_sync(
state: &mut OpState,
rid: ResourceId,
@@ -333,6 +342,7 @@ fn op_fstat_sync(
Ok(get_stat(metadata))
}
+#[op]
async fn op_fstat_async(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -355,6 +365,7 @@ async fn op_fstat_async(
Ok(get_stat(metadata))
}
+#[op]
fn op_flock_sync(
state: &mut OpState,
rid: ResourceId,
@@ -376,6 +387,7 @@ fn op_flock_sync(
})
}
+#[op]
async fn op_flock_async(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -416,6 +428,7 @@ async fn op_flock_async(
.await?
}
+#[op]
fn op_funlock_sync(
state: &mut OpState,
rid: ResourceId,
@@ -433,6 +446,7 @@ fn op_funlock_sync(
})
}
+#[op]
async fn op_funlock_async(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -469,6 +483,7 @@ async fn op_funlock_async(
.await?
}
+#[op]
fn op_umask(
state: &mut OpState,
mask: Option<u32>,
@@ -501,6 +516,7 @@ fn op_umask(
}
}
+#[op]
fn op_chdir(
state: &mut OpState,
directory: String,
@@ -522,6 +538,7 @@ pub struct MkdirArgs {
mode: Option<u32>,
}
+#[op]
fn op_mkdir_sync(
state: &mut OpState,
args: MkdirArgs,
@@ -544,6 +561,7 @@ fn op_mkdir_sync(
Ok(())
}
+#[op]
async fn op_mkdir_async(
state: Rc<RefCell<OpState>>,
args: MkdirArgs,
@@ -582,6 +600,7 @@ pub struct ChmodArgs {
mode: u32,
}
+#[op]
fn op_chmod_sync(
state: &mut OpState,
args: ChmodArgs,
@@ -611,6 +630,7 @@ fn op_chmod_sync(
}
}
+#[op]
async fn op_chmod_async(
state: Rc<RefCell<OpState>>,
args: ChmodArgs,
@@ -656,6 +676,7 @@ pub struct ChownArgs {
gid: Option<u32>,
}
+#[op]
fn op_chown_sync(
state: &mut OpState,
args: ChownArgs,
@@ -690,6 +711,7 @@ fn op_chown_sync(
}
}
+#[op]
async fn op_chown_async(
state: Rc<RefCell<OpState>>,
args: ChownArgs,
@@ -738,6 +760,7 @@ pub struct RemoveArgs {
recursive: bool,
}
+#[op]
fn op_remove_sync(
state: &mut OpState,
args: RemoveArgs,
@@ -783,6 +806,7 @@ fn op_remove_sync(
Ok(())
}
+#[op]
async fn op_remove_async(
state: Rc<RefCell<OpState>>,
args: RemoveArgs,
@@ -841,6 +865,7 @@ pub struct CopyFileArgs {
to: String,
}
+#[op]
fn op_copy_file_sync(
state: &mut OpState,
args: CopyFileArgs,
@@ -879,6 +904,7 @@ fn op_copy_file_sync(
Ok(())
}
+#[op]
async fn op_copy_file_async(
state: Rc<RefCell<OpState>>,
args: CopyFileArgs,
@@ -1007,6 +1033,7 @@ pub struct StatArgs {
lstat: bool,
}
+#[op]
fn op_stat_sync(
state: &mut OpState,
args: StatArgs,
@@ -1027,6 +1054,7 @@ fn op_stat_sync(
Ok(get_stat(metadata))
}
+#[op]
async fn op_stat_async(
state: Rc<RefCell<OpState>>,
args: StatArgs,
@@ -1056,6 +1084,7 @@ async fn op_stat_async(
.unwrap()
}
+#[op]
fn op_realpath_sync(
state: &mut OpState,
path: String,
@@ -1077,6 +1106,7 @@ fn op_realpath_sync(
Ok(realpath_str)
}
+#[op]
async fn op_realpath_async(
state: Rc<RefCell<OpState>>,
path: String,
@@ -1114,6 +1144,7 @@ pub struct DirEntry {
is_symlink: bool,
}
+#[op]
fn op_read_dir_sync(
state: &mut OpState,
path: String,
@@ -1154,6 +1185,7 @@ fn op_read_dir_sync(
Ok(entries)
}
+#[op]
async fn op_read_dir_async(
state: Rc<RefCell<OpState>>,
path: String,
@@ -1206,6 +1238,7 @@ pub struct RenameArgs {
newpath: String,
}
+#[op]
fn op_rename_sync(
state: &mut OpState,
args: RenameArgs,
@@ -1234,6 +1267,7 @@ fn op_rename_sync(
Ok(())
}
+#[op]
async fn op_rename_async(
state: Rc<RefCell<OpState>>,
args: RenameArgs,
@@ -1279,6 +1313,7 @@ pub struct LinkArgs {
newpath: String,
}
+#[op]
fn op_link_sync(
state: &mut OpState,
args: LinkArgs,
@@ -1309,6 +1344,7 @@ fn op_link_sync(
Ok(())
}
+#[op]
async fn op_link_async(
state: Rc<RefCell<OpState>>,
args: LinkArgs,
@@ -1362,6 +1398,7 @@ pub struct SymlinkOptions {
_type: String,
}
+#[op]
fn op_symlink_sync(
state: &mut OpState,
args: SymlinkArgs,
@@ -1423,6 +1460,7 @@ fn op_symlink_sync(
}
}
+#[op]
async fn op_symlink_async(
state: Rc<RefCell<OpState>>,
args: SymlinkArgs,
@@ -1487,6 +1525,7 @@ async fn op_symlink_async(
.unwrap()
}
+#[op]
fn op_read_link_sync(
state: &mut OpState,
path: String,
@@ -1510,6 +1549,7 @@ fn op_read_link_sync(
Ok(targetstr)
}
+#[op]
async fn op_read_link_async(
state: Rc<RefCell<OpState>>,
path: String,
@@ -1545,6 +1585,7 @@ pub struct FtruncateArgs {
len: i32,
}
+#[op]
fn op_ftruncate_sync(
state: &mut OpState,
args: FtruncateArgs,
@@ -1559,6 +1600,7 @@ fn op_ftruncate_sync(
Ok(())
}
+#[op]
async fn op_ftruncate_async(
state: Rc<RefCell<OpState>>,
args: FtruncateArgs,
@@ -1591,6 +1633,7 @@ pub struct TruncateArgs {
len: u64,
}
+#[op]
fn op_truncate_sync(
state: &mut OpState,
args: TruncateArgs,
@@ -1616,6 +1659,7 @@ fn op_truncate_sync(
Ok(())
}
+#[op]
async fn op_truncate_async(
state: Rc<RefCell<OpState>>,
args: TruncateArgs,
@@ -1699,6 +1743,7 @@ pub struct MakeTempArgs {
suffix: Option<String>,
}
+#[op]
fn op_make_temp_dir_sync(
state: &mut OpState,
args: MakeTempArgs,
@@ -1728,6 +1773,7 @@ fn op_make_temp_dir_sync(
Ok(path_str)
}
+#[op]
async fn op_make_temp_dir_async(
state: Rc<RefCell<OpState>>,
args: MakeTempArgs,
@@ -1762,6 +1808,7 @@ async fn op_make_temp_dir_async(
.unwrap()
}
+#[op]
fn op_make_temp_file_sync(
state: &mut OpState,
args: MakeTempArgs,
@@ -1791,6 +1838,7 @@ fn op_make_temp_file_sync(
Ok(path_str)
}
+#[op]
async fn op_make_temp_file_async(
state: Rc<RefCell<OpState>>,
args: MakeTempArgs,
@@ -1833,6 +1881,7 @@ pub struct FutimeArgs {
mtime: (i64, u32),
}
+#[op]
fn op_futime_sync(
state: &mut OpState,
args: FutimeArgs,
@@ -1856,6 +1905,7 @@ fn op_futime_sync(
Ok(())
}
+#[op]
async fn op_futime_async(
state: Rc<RefCell<OpState>>,
args: FutimeArgs,
@@ -1904,6 +1954,7 @@ pub struct UtimeArgs {
mtime: (i64, u32),
}
+#[op]
fn op_utime_sync(
state: &mut OpState,
args: UtimeArgs,
@@ -1922,6 +1973,7 @@ fn op_utime_sync(
Ok(())
}
+#[op]
async fn op_utime_async(
state: Rc<RefCell<OpState>>,
args: UtimeArgs,
@@ -1949,6 +2001,7 @@ async fn op_utime_async(
.unwrap()
}
+#[op]
fn op_cwd(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
let path = current_dir()?;
state
diff --git a/runtime/ops/fs_events.rs b/runtime/ops/fs_events.rs
index 89ded2731..8909b2636 100644
--- a/runtime/ops/fs_events.rs
+++ b/runtime/ops/fs_events.rs
@@ -11,8 +11,8 @@ use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ResourceId;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::Extension;
use notify::event::Event as NotifyEvent;
use notify::Error as NotifyError;
@@ -31,10 +31,7 @@ use tokio::sync::mpsc;
pub fn init() -> Extension {
Extension::builder()
- .ops(vec![
- ("op_fs_events_open", op_sync(op_fs_events_open)),
- ("op_fs_events_poll", op_async(op_fs_events_poll)),
- ])
+ .ops(vec![op_fs_events_open::decl(), op_fs_events_poll::decl()])
.build()
}
@@ -97,6 +94,7 @@ pub struct OpenArgs {
paths: Vec<String>,
}
+#[op]
fn op_fs_events_open(
state: &mut OpState,
args: OpenArgs,
@@ -131,6 +129,7 @@ fn op_fs_events_open(
Ok(rid)
}
+#[op]
async fn op_fs_events_poll(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
diff --git a/runtime/ops/http.rs b/runtime/ops/http.rs
index 5b8acb881..25f123b32 100644
--- a/runtime/ops/http.rs
+++ b/runtime/ops/http.rs
@@ -2,7 +2,7 @@ use std::rc::Rc;
use deno_core::error::bad_resource_id;
use deno_core::error::AnyError;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::Extension;
use deno_core::OpState;
use deno_core::ResourceId;
@@ -12,10 +12,11 @@ use deno_net::ops_tls::TlsStreamResource;
pub fn init() -> Extension {
Extension::builder()
- .ops(vec![("op_http_start", op_sync(op_http_start))])
+ .ops(vec![op_http_start::decl()])
.build()
}
+#[op]
fn op_http_start(
state: &mut OpState,
tcp_stream_rid: ResourceId,
diff --git a/runtime/ops/io.rs b/runtime/ops/io.rs
index 61f1a2578..35dddaac2 100644
--- a/runtime/ops/io.rs
+++ b/runtime/ops/io.rs
@@ -3,7 +3,7 @@
use deno_core::error::not_supported;
use deno_core::error::resource_unavailable;
use deno_core::error::AnyError;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::AsyncMutFuture;
use deno_core::AsyncRefCell;
use deno_core::AsyncResult;
@@ -69,10 +69,7 @@ static STDERR_HANDLE: Lazy<StdFile> = Lazy::new(|| unsafe {
pub fn init() -> Extension {
Extension::builder()
- .ops(vec![
- ("op_read_sync", op_sync(op_read_sync)),
- ("op_write_sync", op_sync(op_write_sync)),
- ])
+ .ops(vec![op_read_sync::decl(), op_write_sync::decl()])
.build()
}
@@ -354,6 +351,7 @@ impl Resource for StdFileResource {
}
}
+#[op]
fn op_read_sync(
state: &mut OpState,
rid: ResourceId,
@@ -368,6 +366,7 @@ fn op_read_sync(
})
}
+#[op]
fn op_write_sync(
state: &mut OpState,
rid: ResourceId,
diff --git a/runtime/ops/os.rs b/runtime/ops/os.rs
index 405faf45a..d9abbb221 100644
--- a/runtime/ops/os.rs
+++ b/runtime/ops/os.rs
@@ -3,7 +3,7 @@
use super::utils::into_string;
use crate::permissions::Permissions;
use deno_core::error::{type_error, AnyError};
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::url::Url;
use deno_core::Extension;
use deno_core::OpState;
@@ -17,19 +17,19 @@ use std::sync::Arc;
pub fn init(maybe_exit_code: Option<Arc<AtomicI32>>) -> Extension {
Extension::builder()
.ops(vec![
- ("op_env", op_sync(op_env)),
- ("op_exec_path", op_sync(op_exec_path)),
- ("op_exit", op_sync(op_exit)),
- ("op_delete_env", op_sync(op_delete_env)),
- ("op_get_env", op_sync(op_get_env)),
- ("op_getuid", op_sync(op_getuid)),
- ("op_hostname", op_sync(op_hostname)),
- ("op_loadavg", op_sync(op_loadavg)),
- ("op_network_interfaces", op_sync(op_network_interfaces)),
- ("op_os_release", op_sync(op_os_release)),
- ("op_set_env", op_sync(op_set_env)),
- ("op_set_exit_code", op_sync(op_set_exit_code)),
- ("op_system_memory_info", op_sync(op_system_memory_info)),
+ op_env::decl(),
+ op_exec_path::decl(),
+ op_exit::decl(),
+ op_delete_env::decl(),
+ op_get_env::decl(),
+ op_getuid::decl(),
+ op_hostname::decl(),
+ op_loadavg::decl(),
+ op_network_interfaces::decl(),
+ op_os_release::decl(),
+ op_set_env::decl(),
+ op_set_exit_code::decl(),
+ op_system_memory_info::decl(),
])
.state(move |state| {
let exit_code = maybe_exit_code.clone().unwrap_or_default();
@@ -39,6 +39,7 @@ pub fn init(maybe_exit_code: Option<Arc<AtomicI32>>) -> Extension {
.build()
}
+#[op]
fn op_exec_path(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
let current_exe = env::current_exe().unwrap();
state
@@ -53,6 +54,7 @@ fn op_exec_path(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
into_string(path.into_os_string())
}
+#[op]
fn op_set_env(
state: &mut OpState,
key: String,
@@ -68,6 +70,7 @@ fn op_set_env(
Ok(())
}
+#[op]
fn op_env(
state: &mut OpState,
_: (),
@@ -77,6 +80,7 @@ fn op_env(
Ok(env::vars().collect())
}
+#[op]
fn op_get_env(
state: &mut OpState,
key: String,
@@ -93,6 +97,7 @@ fn op_get_env(
Ok(r)
}
+#[op]
fn op_delete_env(
state: &mut OpState,
key: String,
@@ -106,6 +111,7 @@ fn op_delete_env(
Ok(())
}
+#[op]
fn op_set_exit_code(
state: &mut OpState,
code: i32,
@@ -115,11 +121,13 @@ fn op_set_exit_code(
Ok(())
}
+#[op]
fn op_exit(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
let code = state.borrow::<Arc<AtomicI32>>().load(Relaxed);
std::process::exit(code)
}
+#[op]
fn op_loadavg(
state: &mut OpState,
_: (),
@@ -133,6 +141,7 @@ fn op_loadavg(
}
}
+#[op]
fn op_hostname(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
super::check_unstable(state, "Deno.hostname");
state.borrow_mut::<Permissions>().env.check_all()?;
@@ -140,6 +149,7 @@ fn op_hostname(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
Ok(hostname)
}
+#[op]
fn op_os_release(
state: &mut OpState,
_: (),
@@ -151,6 +161,7 @@ fn op_os_release(
Ok(release)
}
+#[op]
fn op_network_interfaces(
state: &mut OpState,
_: (),
@@ -218,6 +229,7 @@ struct MemInfo {
pub swap_free: u64,
}
+#[op]
fn op_system_memory_info(
state: &mut OpState,
_: (),
@@ -240,6 +252,7 @@ fn op_system_memory_info(
}
#[cfg(not(windows))]
+#[op]
fn op_getuid(
state: &mut OpState,
_: (),
@@ -251,6 +264,7 @@ fn op_getuid(
}
#[cfg(windows)]
+#[op]
fn op_getuid(
state: &mut OpState,
_: (),
diff --git a/runtime/ops/permissions.rs b/runtime/ops/permissions.rs
index da82f1fd0..401562439 100644
--- a/runtime/ops/permissions.rs
+++ b/runtime/ops/permissions.rs
@@ -4,7 +4,7 @@ use crate::permissions::Permissions;
use deno_core::error::custom_error;
use deno_core::error::uri_error;
use deno_core::error::AnyError;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::url;
use deno_core::Extension;
use deno_core::OpState;
@@ -14,9 +14,9 @@ use std::path::Path;
pub fn init() -> Extension {
Extension::builder()
.ops(vec![
- ("op_query_permission", op_sync(op_query_permission)),
- ("op_revoke_permission", op_sync(op_revoke_permission)),
- ("op_request_permission", op_sync(op_request_permission)),
+ op_query_permission::decl(),
+ op_revoke_permission::decl(),
+ op_request_permission::decl(),
])
.build()
}
@@ -30,6 +30,7 @@ pub struct PermissionArgs {
command: Option<String>,
}
+#[op]
pub fn op_query_permission(
state: &mut OpState,
args: PermissionArgs,
@@ -61,6 +62,7 @@ pub fn op_query_permission(
Ok(perm.to_string())
}
+#[op]
pub fn op_revoke_permission(
state: &mut OpState,
args: PermissionArgs,
@@ -92,6 +94,7 @@ pub fn op_revoke_permission(
Ok(perm.to_string())
}
+#[op]
pub fn op_request_permission(
state: &mut OpState,
args: PermissionArgs,
diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs
index eee266986..7c45c47fc 100644
--- a/runtime/ops/process.rs
+++ b/runtime/ops/process.rs
@@ -8,8 +8,8 @@ use crate::permissions::Permissions;
use deno_core::error::bad_resource_id;
use deno_core::error::type_error;
use deno_core::error::AnyError;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::AsyncMutFuture;
use deno_core::AsyncRefCell;
use deno_core::Extension;
@@ -29,11 +29,7 @@ use std::os::unix::process::ExitStatusExt;
pub fn init() -> Extension {
Extension::builder()
- .ops(vec![
- ("op_run", op_sync(op_run)),
- ("op_run_status", op_async(op_run_status)),
- ("op_kill", op_sync(op_kill)),
- ])
+ .ops(vec![op_run::decl(), op_run_status::decl(), op_kill::decl()])
.build()
}
@@ -102,6 +98,7 @@ struct RunInfo {
stderr_rid: Option<ResourceId>,
}
+#[op]
fn op_run(
state: &mut OpState,
run_args: RunArgs,
@@ -226,6 +223,7 @@ struct ProcessStatus {
exit_signal: i32,
}
+#[op]
async fn op_run_status(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -303,6 +301,7 @@ pub fn kill(pid: i32, signal: &str) -> Result<(), AnyError> {
}
}
+#[op]
fn op_kill(
state: &mut OpState,
pid: i32,
diff --git a/runtime/ops/runtime.rs b/runtime/ops/runtime.rs
index 19228af78..4f951383e 100644
--- a/runtime/ops/runtime.rs
+++ b/runtime/ops/runtime.rs
@@ -3,14 +3,14 @@
use crate::permissions::Permissions;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
-use deno_core::op_sync;
+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()
- .ops(vec![("op_main_module", op_sync(op_main_module))])
+ .ops(vec![op_main_module::decl()])
.state(move |state| {
state.put::<ModuleSpecifier>(main_module.clone());
Ok(())
@@ -18,6 +18,7 @@ pub fn init(main_module: ModuleSpecifier) -> Extension {
.build()
}
+#[op]
fn op_main_module(
state: &mut OpState,
_: (),
diff --git a/runtime/ops/signal.rs b/runtime/ops/signal.rs
index 9511b83e2..d9f05a777 100644
--- a/runtime/ops/signal.rs
+++ b/runtime/ops/signal.rs
@@ -4,8 +4,8 @@ use deno_core::error::generic_error;
#[cfg(not(target_os = "windows"))]
use deno_core::error::type_error;
use deno_core::error::AnyError;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::Extension;
use deno_core::OpState;
use std::cell::RefCell;
@@ -31,9 +31,9 @@ use tokio::signal::unix::{signal, Signal, SignalKind};
pub fn init() -> Extension {
Extension::builder()
.ops(vec![
- ("op_signal_bind", op_sync(op_signal_bind)),
- ("op_signal_unbind", op_sync(op_signal_unbind)),
- ("op_signal_poll", op_async(op_signal_poll)),
+ op_signal_bind::decl(),
+ op_signal_unbind::decl(),
+ op_signal_poll::decl(),
])
.build()
}
@@ -174,6 +174,7 @@ pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
}
#[cfg(unix)]
+#[op]
fn op_signal_bind(
state: &mut OpState,
sig: String,
@@ -195,6 +196,7 @@ fn op_signal_bind(
}
#[cfg(unix)]
+#[op]
async fn op_signal_poll(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
@@ -214,6 +216,7 @@ async fn op_signal_poll(
}
#[cfg(unix)]
+#[op]
pub fn op_signal_unbind(
state: &mut OpState,
rid: ResourceId,
@@ -224,6 +227,7 @@ pub fn op_signal_unbind(
}
#[cfg(not(unix))]
+#[op]
pub fn op_signal_bind(
_state: &mut OpState,
_: (),
@@ -233,6 +237,7 @@ pub fn op_signal_bind(
}
#[cfg(not(unix))]
+#[op]
fn op_signal_unbind(
_state: &mut OpState,
_: (),
@@ -242,6 +247,7 @@ fn op_signal_unbind(
}
#[cfg(not(unix))]
+#[op]
async fn op_signal_poll(
_state: Rc<RefCell<OpState>>,
_: (),
diff --git a/runtime/ops/tty.rs b/runtime/ops/tty.rs
index ee6b112bc..bbf6bd412 100644
--- a/runtime/ops/tty.rs
+++ b/runtime/ops/tty.rs
@@ -5,7 +5,7 @@ use deno_core::error::bad_resource_id;
use deno_core::error::not_supported;
use deno_core::error::resource_unavailable;
use deno_core::error::AnyError;
-use deno_core::op_sync;
+use deno_core::op;
use deno_core::Extension;
use deno_core::OpState;
use deno_core::RcRef;
@@ -47,9 +47,9 @@ fn get_windows_handle(
pub fn init() -> Extension {
Extension::builder()
.ops(vec![
- ("op_set_raw", op_sync(op_set_raw)),
- ("op_isatty", op_sync(op_isatty)),
- ("op_console_size", op_sync(op_console_size)),
+ op_set_raw::decl(),
+ op_isatty::decl(),
+ op_console_size::decl(),
])
.build()
}
@@ -67,6 +67,7 @@ pub struct SetRawArgs {
options: SetRawOptions,
}
+#[op]
fn op_set_raw(
state: &mut OpState,
args: SetRawArgs,
@@ -211,6 +212,7 @@ fn op_set_raw(
}
}
+#[op]
fn op_isatty(
state: &mut OpState,
rid: ResourceId,
@@ -245,6 +247,7 @@ struct ConsoleSize {
rows: u32,
}
+#[op]
fn op_console_size(
state: &mut OpState,
rid: ResourceId,
diff --git a/runtime/ops/web_worker.rs b/runtime/ops/web_worker.rs
index e32f2371d..3c64cf1f6 100644
--- a/runtime/ops/web_worker.rs
+++ b/runtime/ops/web_worker.rs
@@ -5,8 +5,8 @@ mod sync_fetch;
use crate::web_worker::WebWorkerInternalHandle;
use crate::web_worker::WebWorkerType;
use deno_core::error::AnyError;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::CancelFuture;
use deno_core::Extension;
use deno_core::OpState;
@@ -19,16 +19,17 @@ use self::sync_fetch::op_worker_sync_fetch;
pub fn init() -> Extension {
Extension::builder()
.ops(vec![
- ("op_worker_post_message", op_sync(op_worker_post_message)),
- ("op_worker_recv_message", op_async(op_worker_recv_message)),
+ op_worker_post_message::decl(),
+ op_worker_recv_message::decl(),
// Notify host that guest worker closes.
- ("op_worker_close", op_sync(op_worker_close)),
- ("op_worker_get_type", op_sync(op_worker_get_type)),
- ("op_worker_sync_fetch", op_sync(op_worker_sync_fetch)),
+ op_worker_close::decl(),
+ op_worker_get_type::decl(),
+ op_worker_sync_fetch::decl(),
])
.build()
}
+#[op]
fn op_worker_post_message(
state: &mut OpState,
data: JsMessageData,
@@ -39,6 +40,7 @@ fn op_worker_post_message(
Ok(())
}
+#[op]
async fn op_worker_recv_message(
state: Rc<RefCell<OpState>>,
_: (),
@@ -55,6 +57,7 @@ async fn op_worker_recv_message(
.await?
}
+#[op]
fn op_worker_close(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
// Notify parent that we're finished
let mut handle = state.borrow_mut::<WebWorkerInternalHandle>().clone();
@@ -63,6 +66,7 @@ fn op_worker_close(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
Ok(())
}
+#[op]
fn op_worker_get_type(
state: &mut OpState,
_: (),
diff --git a/runtime/ops/web_worker/sync_fetch.rs b/runtime/ops/web_worker/sync_fetch.rs
index 76791ded5..464697f94 100644
--- a/runtime/ops/web_worker/sync_fetch.rs
+++ b/runtime/ops/web_worker/sync_fetch.rs
@@ -4,6 +4,7 @@ use crate::web_worker::WebWorkerInternalHandle;
use crate::web_worker::WebWorkerType;
use deno_core::error::type_error;
use deno_core::error::AnyError;
+use deno_core::op;
use deno_core::url::Url;
use deno_core::OpState;
use deno_fetch::data_url::DataUrl;
@@ -30,6 +31,7 @@ pub struct SyncFetchScript {
script: String,
}
+#[op]
pub fn op_worker_sync_fetch(
state: &mut OpState,
scripts: Vec<String>,
diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs
index 1213da6d2..cebce81a4 100644
--- a/runtime/ops/worker_host.rs
+++ b/runtime/ops/worker_host.rs
@@ -13,8 +13,8 @@ use crate::web_worker::WorkerControlEvent;
use crate::web_worker::WorkerId;
use deno_core::error::AnyError;
use deno_core::futures::future::LocalFutureObj;
-use deno_core::op_async;
-use deno_core::op_sync;
+use deno_core::op;
+
use deno_core::serde::Deserialize;
use deno_core::Extension;
use deno_core::ModuleSpecifier;
@@ -122,14 +122,11 @@ pub fn init(
Ok(())
})
.ops(vec![
- ("op_create_worker", op_sync(op_create_worker)),
- (
- "op_host_terminate_worker",
- op_sync(op_host_terminate_worker),
- ),
- ("op_host_post_message", op_sync(op_host_post_message)),
- ("op_host_recv_ctrl", op_async(op_host_recv_ctrl)),
- ("op_host_recv_message", op_async(op_host_recv_message)),
+ 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()
}
@@ -147,6 +144,7 @@ pub struct CreateWorkerArgs {
}
/// Create worker as the host
+#[op]
fn op_create_worker(
state: &mut OpState,
args: CreateWorkerArgs,
@@ -263,6 +261,7 @@ fn op_create_worker(
Ok(worker_id)
}
+#[op]
fn op_host_terminate_worker(
state: &mut OpState,
id: WorkerId,
@@ -317,6 +316,7 @@ fn close_channel(
}
/// Get control event from guest worker as host
+#[op]
async fn op_host_recv_ctrl(
state: Rc<RefCell<OpState>>,
id: WorkerId,
@@ -348,6 +348,7 @@ async fn op_host_recv_ctrl(
Ok(WorkerControlEvent::Close)
}
+#[op]
async fn op_host_recv_message(
state: Rc<RefCell<OpState>>,
id: WorkerId,
@@ -373,6 +374,7 @@ async fn op_host_recv_message(
}
/// Post message to guest worker as host
+#[op]
fn op_host_post_message(
state: &mut OpState,
id: WorkerId,