1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 13:00:36 -05:00

feat(core): codegen ops (#13861)

Co-authored-by: Aaron O'Mullan <aaron.omullan@gmail.com>
This commit is contained in:
Divy Srivastava 2022-03-14 23:14:15 +05:30 committed by GitHub
parent 4e3ed37037
commit b4e42953e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
78 changed files with 1754 additions and 1664 deletions

21
Cargo.lock generated
View file

@ -856,6 +856,7 @@ version = "0.122.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"deno_ast", "deno_ast",
"deno_ops",
"futures", "futures",
"indexmap", "indexmap",
"libc", "libc",
@ -1019,6 +1020,16 @@ dependencies = [
"trust-dns-resolver", "trust-dns-resolver",
] ]
[[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]] [[package]]
name = "deno_runtime" name = "deno_runtime"
version = "0.48.0" version = "0.48.0"
@ -2925,6 +2936,16 @@ dependencies = [
"output_vt100", "output_vt100",
] ]
[[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]] [[package]]
name = "proc-macro-error" name = "proc-macro-error"
version = "1.0.4" version = "1.0.4"

View file

@ -6,6 +6,7 @@ members = [
"bench_util", "bench_util",
"cli", "cli",
"core", "core",
"ops",
"runtime", "runtime",
"serde_v8", "serde_v8",
"test_ffi", "test_ffi",

View file

@ -3,11 +3,9 @@ use deno_bench_util::bencher::{benchmark_group, Bencher};
use deno_bench_util::{bench_js_async, bench_js_sync}; use deno_bench_util::{bench_js_async, bench_js_sync};
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::serialize_op_result;
use deno_core::Extension; use deno_core::Extension;
use deno_core::Op;
use deno_core::OpState; use deno_core::OpState;
use std::cell::RefCell; use std::cell::RefCell;
@ -16,17 +14,25 @@ use std::rc::Rc;
fn setup() -> Vec<Extension> { fn setup() -> Vec<Extension> {
vec![Extension::builder() vec![Extension::builder()
.ops(vec![ .ops(vec![
("pi_json", op_sync(|_, _: (), _: ()| Ok(314159))), op_pi_json::decl(),
("pi_async", op_async(op_pi_async)), op_pi_async::decl(),
( op_nop::decl(),
"nop",
Box::new(|state, _| Op::Sync(serialize_op_result(Ok(9), state))),
),
]) ])
.build()] .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 // this is a function since async closures aren't stable
#[op]
async fn op_pi_async( async fn op_pi_async(
_: Rc<RefCell<OpState>>, _: Rc<RefCell<OpState>>,
_: (), _: (),
@ -36,15 +42,15 @@ async fn op_pi_async(
} }
fn bench_op_pi_json(b: &mut Bencher) { 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) { 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) { 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) { fn bench_is_proxy(b: &mut Bencher) {
@ -58,4 +64,5 @@ benchmark_group!(
bench_op_async, bench_op_async,
bench_is_proxy bench_is_proxy
); );
bench_or_profile!(benches); bench_or_profile!(benches);

View file

@ -1,11 +1,14 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::custom_error; 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::Deserialize;
use deno_core::serde_json::json; use deno_core::serde_json::json;
use deno_core::serde_json::Value; use deno_core::serde_json::Value;
use deno_core::Extension;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::OpState;
use deno_core::RuntimeOptions; use deno_core::RuntimeOptions;
use regex::Regex; use regex::Regex;
use std::collections::HashMap; use std::collections::HashMap;
@ -185,79 +188,112 @@ fn create_compiler_snapshot(
build_libs.push(op_lib.to_owned()); build_libs.push(op_lib.to_owned());
} }
let re_asset = Regex::new(r"asset:/{3}lib\.(\S+)\.d\.ts").expect("bad regex"); #[op]
let build_specifier = "asset:///bootstrap.ts"; 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 { #[op]
will_snapshot: true, fn op_cwd(
..Default::default() _state: &mut OpState,
}); _args: Value,
js_runtime.register_op( _: (),
"op_build_info", ) -> Result<Value, AnyError> {
op_sync(move |_state, _args: Value, _: ()| { Ok(json!("cache:///"))
Ok(json!({ }
"buildSpecifier": build_specifier,
"libs": build_libs, #[op]
})) fn op_exists(
}), _state: &mut OpState,
); _args: Value,
js_runtime.register_op( _: (),
"op_cwd", ) -> Result<Value, AnyError> {
op_sync(move |_state, _args: Value, _: ()| Ok(json!("cache:///"))), Ok(json!(false))
); }
// 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. #[op]
js_runtime.register_op(
"op_exists",
op_sync(move |_state, _args: LoadArgs, _: ()| Ok(json!(false))),
);
// using the same op that is used in `tsc.rs` for loading modules and reading // using the same op that is used in `tsc.rs` for loading modules and reading
// files, but a slightly different implementation at build time. // files, but a slightly different implementation at build time.
js_runtime.register_op( fn op_load(
"op_load", state: &mut OpState,
op_sync(move |_state, args: LoadArgs, _: ()| { args: LoadArgs,
// we need a basic file to send to tsc to warm it up. _: (),
if args.specifier == build_specifier { ) -> 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!({ Ok(json!({
"data": r#"console.log("hello deno!");"#, "data": data,
"hash": "1", "hash": "1",
// this corresponds to `ts.ScriptKind.TypeScript` // this corresponds to `ts.ScriptKind.TypeScript`
"scriptKind": 3 "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 { } else {
Err(custom_error( Err(custom_error(
"InvalidSpecifier", "InvalidSpecifier",
format!("An invalid specifier was requested: {}", args.specifier), format!("An invalid specifier was requested: {}", args.specifier),
)) ))
} }
}), } else {
); Err(custom_error(
js_runtime.sync_ops_cache(); "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); create_snapshot(js_runtime, snapshot_path, files);
} }

View file

@ -27,7 +27,7 @@ use deno_core::anyhow::anyhow;
use deno_core::error::custom_error; use deno_core::error::custom_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::located_script_name; use deno_core::located_script_name;
use deno_core::op_sync; use deno_core::op;
use deno_core::parking_lot::Mutex; use deno_core::parking_lot::Mutex;
use deno_core::resolve_url; use deno_core::resolve_url;
use deno_core::serde::de; use deno_core::serde::de;
@ -40,7 +40,7 @@ use deno_core::url::Url;
use deno_core::Extension; use deno_core::Extension;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::OpFn; use deno_core::OpState;
use deno_core::RuntimeOptions; use deno_core::RuntimeOptions;
use deno_runtime::tokio_util::create_basic_runtime; use deno_runtime::tokio_util::create_basic_runtime;
use log::error; use log::error;
@ -2502,19 +2502,6 @@ fn normalize_specifier<S: AsRef<str>>(
.map_err(|err| err.into()) .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)] #[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct SourceSnapshotArgs { struct SourceSnapshotArgs {
@ -2524,10 +2511,13 @@ struct SourceSnapshotArgs {
/// The language service is dropping a reference to a source file snapshot, and /// The language service is dropping a reference to a source file snapshot, and
/// we can drop our version of that document. /// we can drop our version of that document.
#[op]
fn op_dispose( fn op_dispose(
state: &mut State, state: &mut OpState,
args: SourceSnapshotArgs, args: SourceSnapshotArgs,
_: (),
) -> Result<bool, AnyError> { ) -> Result<bool, AnyError> {
let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_dispose", Some(&args)); let mark = state.performance.mark("op_dispose", Some(&args));
let specifier = state.normalize_specifier(&args.specifier)?; let specifier = state.normalize_specifier(&args.specifier)?;
state.snapshots.remove(&(specifier, args.version.into())); state.snapshots.remove(&(specifier, args.version.into()));
@ -2541,7 +2531,13 @@ struct SpecifierArgs {
specifier: String, 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 // 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 // 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 // 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 /// The language service wants to compare an old snapshot with a new snapshot to
/// determine what source has changed. /// determine what source has changed.
#[op]
fn op_get_change_range( fn op_get_change_range(
state: &mut State, state: &mut OpState,
args: GetChangeRangeArgs, args: GetChangeRangeArgs,
_: (),
) -> Result<Value, AnyError> { ) -> Result<Value, AnyError> {
let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_get_change_range", Some(&args)); let mark = state.performance.mark("op_get_change_range", Some(&args));
let specifier = state.normalize_specifier(&args.specifier)?; let specifier = state.normalize_specifier(&args.specifier)?;
cache_snapshot(state, &specifier, args.version.clone())?; cache_snapshot(state, &specifier, args.version.clone())?;
@ -2613,10 +2612,13 @@ fn op_get_change_range(
r r
} }
#[op]
fn op_get_length( fn op_get_length(
state: &mut State, state: &mut OpState,
args: SourceSnapshotArgs, args: SourceSnapshotArgs,
_: (),
) -> Result<usize, AnyError> { ) -> Result<usize, AnyError> {
let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_get_length", Some(&args)); let mark = state.performance.mark("op_get_length", Some(&args));
let specifier = state.normalize_specifier(args.specifier)?; let specifier = state.normalize_specifier(args.specifier)?;
let r = if let Some(Some(asset)) = let r = if let Some(Some(asset)) =
@ -2644,10 +2646,13 @@ struct GetTextArgs {
end: usize, end: usize,
} }
#[op]
fn op_get_text( fn op_get_text(
state: &mut State, state: &mut OpState,
args: GetTextArgs, args: GetTextArgs,
_: (),
) -> Result<String, AnyError> { ) -> Result<String, AnyError> {
let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_get_text", Some(&args)); let mark = state.performance.mark("op_get_text", Some(&args));
let specifier = state.normalize_specifier(args.specifier)?; let specifier = state.normalize_specifier(args.specifier)?;
let maybe_asset = state.state_snapshot.assets.get_cached(&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()) 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()) Ok(state.token.is_cancelled())
} }
#[op]
fn op_load( fn op_load(
state: &mut State, state: &mut OpState,
args: SpecifierArgs, args: SpecifierArgs,
_: (),
) -> Result<Option<String>, AnyError> { ) -> Result<Option<String>, AnyError> {
let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_load", Some(&args)); let mark = state.performance.mark("op_load", Some(&args));
let specifier = state.normalize_specifier(args.specifier)?; let specifier = state.normalize_specifier(args.specifier)?;
let document = state.state_snapshot.documents.get(&specifier); let document = state.state_snapshot.documents.get(&specifier);
@ -2679,10 +2693,13 @@ fn op_load(
Ok(document.map(|d| d.content().to_string())) Ok(document.map(|d| d.content().to_string()))
} }
#[op]
fn op_resolve( fn op_resolve(
state: &mut State, state: &mut OpState,
args: ResolveArgs, args: ResolveArgs,
_: (),
) -> Result<Vec<Option<(String, String)>>, AnyError> { ) -> Result<Vec<Option<(String, String)>>, AnyError> {
let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_resolve", Some(&args)); let mark = state.performance.mark("op_resolve", Some(&args));
let referrer = state.normalize_specifier(&args.base)?; let referrer = state.normalize_specifier(&args.base)?;
@ -2713,15 +2730,24 @@ fn op_resolve(
result 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); state.response = Some(args);
Ok(true) Ok(true)
} }
#[op]
fn op_script_names( fn op_script_names(
state: &mut State, state: &mut OpState,
_args: Value, _args: Value,
_: (),
) -> Result<Vec<ModuleSpecifier>, AnyError> { ) -> Result<Vec<ModuleSpecifier>, AnyError> {
let state = state.borrow_mut::<State>();
Ok( Ok(
state state
.state_snapshot .state_snapshot
@ -2739,10 +2765,13 @@ struct ScriptVersionArgs {
specifier: String, specifier: String,
} }
#[op]
fn op_script_version( fn op_script_version(
state: &mut State, state: &mut OpState,
args: ScriptVersionArgs, args: ScriptVersionArgs,
_: (),
) -> Result<Option<String>, AnyError> { ) -> Result<Option<String>, AnyError> {
let state = state.borrow_mut::<State>();
// this op is very "noisy" and measuring its performance is not useful, so we // this op is very "noisy" and measuring its performance is not useful, so we
// don't measure it uniquely anymore. // don't measure it uniquely anymore.
let specifier = state.normalize_specifier(args.specifier)?; 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 { fn init_extension(performance: Arc<Performance>) -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
("op_dispose", op_lsp(op_dispose)), op_dispose::decl(),
("op_exists", op_lsp(op_exists)), op_exists::decl(),
("op_get_change_range", op_lsp(op_get_change_range)), op_get_change_range::decl(),
("op_get_length", op_lsp(op_get_length)), op_get_length::decl(),
("op_get_text", op_lsp(op_get_text)), op_get_text::decl(),
("op_is_cancelled", op_lsp(op_is_cancelled)), op_is_cancelled::decl(),
("op_load", op_lsp(op_load)), op_load::decl(),
("op_resolve", op_lsp(op_resolve)), op_resolve::decl(),
("op_respond", op_lsp(op_respond)), op_respond::decl(),
("op_script_names", op_lsp(op_script_names)), op_script_names::decl(),
("op_script_version", op_lsp(op_script_version)), op_script_version::decl(),
]) ])
.state(move |state| { .state(move |state| {
state.put(State::new( state.put(State::new(
@ -3832,7 +3861,7 @@ mod tests {
#[test] #[test]
fn test_op_exists() { fn test_op_exists() {
let (_, state_snapshot, _) = setup( let (mut rt, state_snapshot, _) = setup(
false, false,
json!({ json!({
"target": "esnext", "target": "esnext",
@ -3843,12 +3872,16 @@ mod tests {
&[], &[],
); );
let performance = Arc::new(Performance::default()); let performance = Arc::new(Performance::default());
let mut state = State::new(state_snapshot, performance); let state = State::new(state_snapshot, performance);
let actual = op_exists( let op_state = rt.op_state();
&mut state, let mut op_state = op_state.borrow_mut();
op_state.put(state);
let actual = op_exists::call(
&mut op_state,
SpecifierArgs { SpecifierArgs {
specifier: "/error/unknown:something/index.d.ts".to_string(), specifier: "/error/unknown:something/index.d.ts".to_string(),
}, },
(),
); );
assert!(actual.is_ok()); assert!(actual.is_ok());
let actual = actual.unwrap(); let actual = actual.unwrap();

View file

@ -1,7 +1,7 @@
use crate::tools::bench::BenchEvent; use crate::tools::bench::BenchEvent;
use deno_core::error::generic_error; use deno_core::error::generic_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_sync; use deno_core::op;
use deno_core::Extension; use deno_core::Extension;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::OpState; use deno_core::OpState;
@ -15,17 +15,11 @@ use uuid::Uuid;
pub fn init(sender: UnboundedSender<BenchEvent>) -> Extension { pub fn init(sender: UnboundedSender<BenchEvent>) -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
( op_pledge_test_permissions::decl(),
"op_pledge_test_permissions", op_restore_test_permissions::decl(),
op_sync(op_pledge_test_permissions), op_get_bench_origin::decl(),
), op_dispatch_bench_event::decl(),
( op_bench_now::decl(),
"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)),
]) ])
.state(move |state| { .state(move |state| {
state.put(sender.clone()); state.put(sender.clone());
@ -37,6 +31,7 @@ pub fn init(sender: UnboundedSender<BenchEvent>) -> Extension {
#[derive(Clone)] #[derive(Clone)]
struct PermissionsHolder(Uuid, Permissions); struct PermissionsHolder(Uuid, Permissions);
#[op]
pub fn op_pledge_test_permissions( pub fn op_pledge_test_permissions(
state: &mut OpState, state: &mut OpState,
args: ChildPermissionsArg, args: ChildPermissionsArg,
@ -55,6 +50,7 @@ pub fn op_pledge_test_permissions(
Ok(token) Ok(token)
} }
#[op]
pub fn op_restore_test_permissions( pub fn op_restore_test_permissions(
state: &mut OpState, state: &mut OpState,
token: Uuid, token: Uuid,
@ -73,6 +69,7 @@ pub fn op_restore_test_permissions(
} }
} }
#[op]
fn op_get_bench_origin( fn op_get_bench_origin(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -81,6 +78,7 @@ fn op_get_bench_origin(
Ok(state.borrow::<ModuleSpecifier>().to_string()) Ok(state.borrow::<ModuleSpecifier>().to_string())
} }
#[op]
fn op_dispatch_bench_event( fn op_dispatch_bench_event(
state: &mut OpState, state: &mut OpState,
event: BenchEvent, event: BenchEvent,
@ -92,6 +90,7 @@ fn op_dispatch_bench_event(
Ok(()) Ok(())
} }
#[op]
fn op_bench_now(state: &mut OpState, _: (), _: ()) -> Result<u64, AnyError> { fn op_bench_now(state: &mut OpState, _: (), _: ()) -> Result<u64, AnyError> {
let ns = state.borrow::<time::Instant>().elapsed().as_nanos(); let ns = state.borrow::<time::Instant>().elapsed().as_nanos();
let ns_u64 = u64::try_from(ns)?; let ns_u64 = u64::try_from(ns)?;

View file

@ -6,7 +6,7 @@ use crate::proc_state::ProcState;
use crate::source_maps::get_orig_position; use crate::source_maps::get_orig_position;
use crate::source_maps::CachedMaps; use crate::source_maps::CachedMaps;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_sync; use deno_core::op;
use deno_core::serde_json; use deno_core::serde_json;
use deno_core::serde_json::json; use deno_core::serde_json::json;
use deno_core::serde_json::Value; use deno_core::serde_json::Value;
@ -19,9 +19,9 @@ use std::collections::HashMap;
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
("op_apply_source_map", op_sync(op_apply_source_map)), op_apply_source_map::decl(),
("op_format_diagnostic", op_sync(op_format_diagnostic)), op_format_diagnostic::decl(),
("op_format_file_name", op_sync(op_format_file_name)), op_format_file_name::decl(),
]) ])
.build() .build()
} }
@ -42,6 +42,7 @@ struct AppliedSourceMap {
column_number: u32, column_number: u32,
} }
#[op]
fn op_apply_source_map( fn op_apply_source_map(
state: &mut OpState, state: &mut OpState,
args: ApplySourceMap, args: ApplySourceMap,
@ -66,6 +67,7 @@ fn op_apply_source_map(
}) })
} }
#[op]
fn op_format_diagnostic( fn op_format_diagnostic(
_state: &mut OpState, _state: &mut OpState,
args: Value, args: Value,
@ -75,6 +77,7 @@ fn op_format_diagnostic(
Ok(json!(diagnostic.to_string())) Ok(json!(diagnostic.to_string()))
} }
#[op]
fn op_format_file_name( fn op_format_file_name(
_state: &mut OpState, _state: &mut OpState,
file_name: String, file_name: String,

View file

@ -16,7 +16,8 @@ use deno_core::anyhow::Context;
use deno_core::error::custom_error; use deno_core::error::custom_error;
use deno_core::error::generic_error; use deno_core::error::generic_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_async;
use deno_core::op;
use deno_core::parking_lot::RwLock; use deno_core::parking_lot::RwLock;
use deno_core::resolve_url_or_path; use deno_core::resolve_url_or_path;
use deno_core::serde_json; use deno_core::serde_json;
@ -35,9 +36,7 @@ use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder().ops(vec![op_emit::decl()]).build()
.ops(vec![("op_emit", op_async(op_emit))])
.build()
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -141,6 +140,7 @@ fn to_maybe_jsx_import_source_module(
} }
} }
#[op]
async fn op_emit( async fn op_emit(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: EmitArgs, args: EmitArgs,

View file

@ -1,7 +1,7 @@
use crate::tools::test::TestEvent; use crate::tools::test::TestEvent;
use deno_core::error::generic_error; use deno_core::error::generic_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_sync; use deno_core::op;
use deno_core::Extension; use deno_core::Extension;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::OpState; use deno_core::OpState;
@ -14,16 +14,10 @@ use uuid::Uuid;
pub fn init(sender: UnboundedSender<TestEvent>) -> Extension { pub fn init(sender: UnboundedSender<TestEvent>) -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
( op_pledge_test_permissions::decl(),
"op_pledge_test_permissions", op_restore_test_permissions::decl(),
op_sync(op_pledge_test_permissions), op_get_test_origin::decl(),
), op_dispatch_test_event::decl(),
(
"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)),
]) ])
.state(move |state| { .state(move |state| {
state.put(sender.clone()); state.put(sender.clone());
@ -35,6 +29,7 @@ pub fn init(sender: UnboundedSender<TestEvent>) -> Extension {
#[derive(Clone)] #[derive(Clone)]
struct PermissionsHolder(Uuid, Permissions); struct PermissionsHolder(Uuid, Permissions);
#[op]
pub fn op_pledge_test_permissions( pub fn op_pledge_test_permissions(
state: &mut OpState, state: &mut OpState,
args: ChildPermissionsArg, args: ChildPermissionsArg,
@ -53,6 +48,7 @@ pub fn op_pledge_test_permissions(
Ok(token) Ok(token)
} }
#[op]
pub fn op_restore_test_permissions( pub fn op_restore_test_permissions(
state: &mut OpState, state: &mut OpState,
token: Uuid, token: Uuid,
@ -71,6 +67,7 @@ pub fn op_restore_test_permissions(
} }
} }
#[op]
fn op_get_test_origin( fn op_get_test_origin(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -79,6 +76,7 @@ fn op_get_test_origin(
Ok(state.borrow::<ModuleSpecifier>().to_string()) Ok(state.borrow::<ModuleSpecifier>().to_string())
} }
#[op]
fn op_dispatch_test_event( fn op_dispatch_test_event(
state: &mut OpState, state: &mut OpState,
event: TestEvent, event: TestEvent,

View file

@ -11,18 +11,18 @@ use deno_core::anyhow::anyhow;
use deno_core::anyhow::Context; use deno_core::anyhow::Context;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::located_script_name; use deno_core::located_script_name;
use deno_core::op_sync; use deno_core::op;
use deno_core::parking_lot::RwLock; use deno_core::parking_lot::RwLock;
use deno_core::resolve_url_or_path; use deno_core::resolve_url_or_path;
use deno_core::serde::de;
use deno_core::serde::Deserialize; use deno_core::serde::Deserialize;
use deno_core::serde::Serialize; use deno_core::serde::Serialize;
use deno_core::serde_json; use deno_core::serde_json;
use deno_core::serde_json::json; use deno_core::serde_json::json;
use deno_core::serde_json::Value; use deno_core::serde_json::Value;
use deno_core::Extension;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::OpFn; use deno_core::OpState;
use deno_core::RuntimeOptions; use deno_core::RuntimeOptions;
use deno_core::Snapshot; use deno_core::Snapshot;
use deno_graph::Resolved; use deno_graph::Resolved;
@ -298,18 +298,6 @@ fn normalize_specifier(specifier: &str) -> Result<ModuleSpecifier, AnyError> {
.map_err(|err| err.into()) .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)] #[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct CreateHashArgs { struct CreateHashArgs {
@ -318,7 +306,13 @@ struct CreateHashArgs {
data: String, 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) let v: CreateHashArgs = serde_json::from_value(args)
.context("Invalid request from JavaScript for \"op_create_hash\".")?; .context("Invalid request from JavaScript for \"op_create_hash\".")?;
let mut data = vec![v.data.as_bytes().to_owned()]; 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 })) 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 { if let Some(config_specifier) = &state.maybe_config_specifier {
let cwd = config_specifier.join("./")?; let cwd = config_specifier.join("./")?;
Ok(cwd.to_string()) Ok(cwd.to_string())
@ -350,7 +346,13 @@ struct EmitArgs {
maybe_specifiers: Option<Vec<String>>, 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() { match args.file_name.as_ref() {
"deno:///.tsbuildinfo" => state.maybe_tsbuildinfo = Some(args.data), "deno:///.tsbuildinfo" => state.maybe_tsbuildinfo = Some(args.data),
_ => { _ => {
@ -403,7 +405,13 @@ struct ExistsArgs {
specifier: String, 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(); let graph_data = state.graph_data.read();
if let Ok(specifier) = normalize_specifier(&args.specifier) { if let Ok(specifier) = normalize_specifier(&args.specifier) {
if specifier.scheme() == "asset" || specifier.scheme() == "data" { 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) let v: LoadArgs = serde_json::from_value(args)
.context("Invalid request from JavaScript for \"op_load\".")?; .context("Invalid request from JavaScript for \"op_load\".")?;
let specifier = normalize_specifier(&v.specifier) let specifier = normalize_specifier(&v.specifier)
@ -507,7 +517,13 @@ pub struct ResolveArgs {
pub specifiers: Vec<String>, 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 mut resolved: Vec<(String, String)> = Vec::new();
let referrer = if let Some(remapped_specifier) = let referrer = if let Some(remapped_specifier) =
state.remapped_specifiers.get(&args.base) state.remapped_specifiers.get(&args.base)
@ -612,7 +628,13 @@ struct RespondArgs {
pub stats: emit::Stats, 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) let v: RespondArgs = serde_json::from_value(args)
.context("Error converting the result for \"op_respond\".")?; .context("Error converting the result for \"op_respond\".")?;
state.maybe_response = Some(v); 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 /// contains information, like any emitted files, diagnostics, statistics and
/// optionally an updated TypeScript build info. /// optionally an updated TypeScript build info.
pub(crate) fn exec(request: Request) -> Result<Response, AnyError> { 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" // 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. Therefore, we have to check the root modules against their
// extensions and remap any that are unacceptable to tsc and add them to the // 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(); .collect();
let mut runtime = JsRuntime::new(RuntimeOptions {
{ startup_snapshot: Some(compiler_snapshot()),
let op_state = runtime.op_state(); extensions: vec![Extension::builder()
let mut op_state = op_state.borrow_mut(); .ops(vec![
op_state.put(State::new( op_cwd::decl(),
request.graph_data, op_create_hash::decl(),
request.hash_data.clone(), op_emit::decl(),
request.maybe_config_specifier.clone(), op_exists::decl(),
request.maybe_tsbuildinfo.clone(), op_load::decl(),
root_map, op_resolve::decl(),
remapped_specifiers, op_respond::decl(),
)); ])
} .state(move |state| {
state.put(State::new(
runtime.register_op("op_cwd", op(op_cwd)); request.graph_data.clone(),
runtime.register_op("op_create_hash", op(op_create_hash)); request.hash_data.clone(),
runtime.register_op("op_emit", op(op_emit)); request.maybe_config_specifier.clone(),
runtime.register_op("op_exists", op(op_exists)); request.maybe_tsbuildinfo.clone(),
runtime.register_op("op_load", op(op_load)); root_map.clone(),
runtime.register_op("op_resolve", op(op_resolve)); remapped_specifiers.clone(),
runtime.register_op("op_respond", op(op_respond)); ));
runtime.sync_ops_cache(); Ok(())
})
.build()],
..Default::default()
});
let startup_source = "globalThis.startup({ legacyFlag: false })"; let startup_source = "globalThis.startup({ legacyFlag: false })";
let request_value = json!({ let request_value = json!({
@ -720,6 +742,7 @@ mod tests {
use crate::diagnostics::DiagnosticCategory; use crate::diagnostics::DiagnosticCategory;
use crate::emit::Stats; use crate::emit::Stats;
use deno_core::futures::future; use deno_core::futures::future;
use deno_core::OpState;
use deno_graph::ModuleKind; use deno_graph::ModuleKind;
use std::fs; use std::fs;
@ -757,7 +780,7 @@ mod tests {
maybe_specifier: Option<ModuleSpecifier>, maybe_specifier: Option<ModuleSpecifier>,
maybe_hash_data: Option<Vec<Vec<u8>>>, maybe_hash_data: Option<Vec<Vec<u8>>>,
maybe_tsbuildinfo: Option<String>, maybe_tsbuildinfo: Option<String>,
) -> State { ) -> OpState {
let specifier = maybe_specifier let specifier = maybe_specifier
.unwrap_or_else(|| resolve_url_or_path("file:///main.ts").unwrap()); .unwrap_or_else(|| resolve_url_or_path("file:///main.ts").unwrap());
let hash_data = maybe_hash_data.unwrap_or_else(|| vec![b"".to_vec()]); let hash_data = maybe_hash_data.unwrap_or_else(|| vec![b"".to_vec()]);
@ -774,14 +797,17 @@ mod tests {
None, None,
) )
.await; .await;
State::new( let state = State::new(
Arc::new(RwLock::new((&graph).into())), Arc::new(RwLock::new((&graph).into())),
hash_data, hash_data,
None, None,
maybe_tsbuildinfo, maybe_tsbuildinfo,
HashMap::new(), HashMap::new(),
HashMap::new(), HashMap::new(),
) );
let mut op_state = OpState::new(1);
op_state.put(state);
op_state
} }
async fn test_exec( async fn test_exec(
@ -852,9 +878,12 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_create_hash() { async fn test_create_hash() {
let mut state = setup(None, Some(vec![b"something".to_vec()]), None).await; let mut state = setup(None, Some(vec![b"something".to_vec()]), None).await;
let actual = let actual = op_create_hash::call(
op_create_hash(&mut state, json!({ "data": "some sort of content" })) &mut state,
.expect("could not invoke op"); json!({ "data": "some sort of content" }),
(),
)
.expect("could not invoke op");
assert_eq!( assert_eq!(
actual, actual,
json!({"hash": "ae92df8f104748768838916857a1623b6a3c593110131b0a00f81ad9dac16511"}) json!({"hash": "ae92df8f104748768838916857a1623b6a3c593110131b0a00f81ad9dac16511"})
@ -898,16 +927,18 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_emit() { async fn test_emit() {
let mut state = setup(None, None, None).await; let mut state = setup(None, None, None).await;
let actual = op_emit( let actual = op_emit::call(
&mut state, &mut state,
EmitArgs { EmitArgs {
data: "some file content".to_string(), data: "some file content".to_string(),
file_name: "cache:///some/file.js".to_string(), file_name: "cache:///some/file.js".to_string(),
maybe_specifiers: Some(vec!["file:///some/file.ts".to_string()]), maybe_specifiers: Some(vec!["file:///some/file.ts".to_string()]),
}, },
(),
) )
.expect("should have invoked op"); .expect("should have invoked op");
assert_eq!(actual, json!(true)); assert_eq!(actual, json!(true));
let state = state.borrow::<State>();
assert_eq!(state.emitted_files.len(), 1); assert_eq!(state.emitted_files.len(), 1);
assert!(state.maybe_tsbuildinfo.is_none()); assert!(state.maybe_tsbuildinfo.is_none());
assert_eq!( assert_eq!(
@ -926,7 +957,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_emit_strange_specifier() { async fn test_emit_strange_specifier() {
let mut state = setup(None, None, None).await; let mut state = setup(None, None, None).await;
let actual = op_emit( let actual = op_emit::call(
&mut state, &mut state,
EmitArgs { EmitArgs {
data: "some file content".to_string(), data: "some file content".to_string(),
@ -935,9 +966,11 @@ mod tests {
vec!["file:///some/file.ts?q=.json".to_string()], vec!["file:///some/file.ts?q=.json".to_string()],
), ),
}, },
(),
) )
.expect("should have invoked op"); .expect("should have invoked op");
assert_eq!(actual, json!(true)); assert_eq!(actual, json!(true));
let state = state.borrow::<State>();
assert_eq!(state.emitted_files.len(), 1); assert_eq!(state.emitted_files.len(), 1);
assert!(state.maybe_tsbuildinfo.is_none()); assert!(state.maybe_tsbuildinfo.is_none());
assert_eq!( assert_eq!(
@ -956,16 +989,18 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_emit_tsbuildinfo() { async fn test_emit_tsbuildinfo() {
let mut state = setup(None, None, None).await; let mut state = setup(None, None, None).await;
let actual = op_emit( let actual = op_emit::call(
&mut state, &mut state,
EmitArgs { EmitArgs {
data: "some file content".to_string(), data: "some file content".to_string(),
file_name: "deno:///.tsbuildinfo".to_string(), file_name: "deno:///.tsbuildinfo".to_string(),
maybe_specifiers: None, maybe_specifiers: None,
}, },
(),
) )
.expect("should have invoked op"); .expect("should have invoked op");
assert_eq!(actual, json!(true)); assert_eq!(actual, json!(true));
let state = state.borrow::<State>();
assert_eq!(state.emitted_files.len(), 0); assert_eq!(state.emitted_files.len(), 0);
assert_eq!( assert_eq!(
state.maybe_tsbuildinfo, state.maybe_tsbuildinfo,
@ -981,9 +1016,10 @@ mod tests {
Some("some content".to_string()), Some("some content".to_string()),
) )
.await; .await;
let actual = op_load( let actual = op_load::call(
&mut state, &mut state,
json!({ "specifier": "https://deno.land/x/mod.ts"}), json!({ "specifier": "https://deno.land/x/mod.ts"}),
(),
) )
.expect("should have invoked op"); .expect("should have invoked op");
assert_eq!( assert_eq!(
@ -1012,9 +1048,12 @@ mod tests {
Some("some content".to_string()), Some("some content".to_string()),
) )
.await; .await;
let value = let value = op_load::call(
op_load(&mut state, json!({ "specifier": "asset:///lib.dom.d.ts" })) &mut state,
.expect("should have invoked op"); json!({ "specifier": "asset:///lib.dom.d.ts" }),
(),
)
.expect("should have invoked op");
let actual: LoadResponse = let actual: LoadResponse =
serde_json::from_value(value).expect("failed to deserialize"); serde_json::from_value(value).expect("failed to deserialize");
let expected = get_asset("lib.dom.d.ts").unwrap(); let expected = get_asset("lib.dom.d.ts").unwrap();
@ -1031,9 +1070,12 @@ mod tests {
Some("some content".to_string()), Some("some content".to_string()),
) )
.await; .await;
let actual = let actual = op_load::call(
op_load(&mut state, json!({ "specifier": "deno:///.tsbuildinfo"})) &mut state,
.expect("should have invoked op"); json!({ "specifier": "deno:///.tsbuildinfo"}),
(),
)
.expect("should have invoked op");
assert_eq!( assert_eq!(
actual, actual,
json!({ json!({
@ -1047,9 +1089,10 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_load_missing_specifier() { async fn test_load_missing_specifier() {
let mut state = setup(None, None, None).await; let mut state = setup(None, None, None).await;
let actual = op_load( let actual = op_load::call(
&mut state, &mut state,
json!({ "specifier": "https://deno.land/x/mod.ts"}), json!({ "specifier": "https://deno.land/x/mod.ts"}),
(),
) )
.expect("should have invoked op"); .expect("should have invoked op");
assert_eq!( assert_eq!(
@ -1070,12 +1113,13 @@ mod tests {
None, None,
) )
.await; .await;
let actual = op_resolve( let actual = op_resolve::call(
&mut state, &mut state,
ResolveArgs { ResolveArgs {
base: "https://deno.land/x/a.ts".to_string(), base: "https://deno.land/x/a.ts".to_string(),
specifiers: vec!["./b.ts".to_string()], specifiers: vec!["./b.ts".to_string()],
}, },
(),
) )
.expect("should have invoked op"); .expect("should have invoked op");
assert_eq!(actual, json!([["https://deno.land/x/b.ts", ".ts"]])); assert_eq!(actual, json!([["https://deno.land/x/b.ts", ".ts"]]));
@ -1089,12 +1133,13 @@ mod tests {
None, None,
) )
.await; .await;
let actual = op_resolve( let actual = op_resolve::call(
&mut state, &mut state,
ResolveArgs { ResolveArgs {
base: "https://deno.land/x/a.ts".to_string(), base: "https://deno.land/x/a.ts".to_string(),
specifiers: vec!["./bad.ts".to_string()], specifiers: vec!["./bad.ts".to_string()],
}, },
(),
) )
.expect("should have not errored"); .expect("should have not errored");
assert_eq!( assert_eq!(
@ -1106,7 +1151,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_respond() { async fn test_respond() {
let mut state = setup(None, None, None).await; let mut state = setup(None, None, None).await;
let actual = op_respond( let actual = op_respond::call(
&mut state, &mut state,
json!({ json!({
"diagnostics": [ "diagnostics": [
@ -1118,9 +1163,11 @@ mod tests {
], ],
"stats": [["a", 12]] "stats": [["a", 12]]
}), }),
(),
) )
.expect("should have invoked op"); .expect("should have invoked op");
assert_eq!(actual, json!(true)); assert_eq!(actual, json!(true));
let state = state.borrow::<State>();
assert_eq!( assert_eq!(
state.maybe_response, state.maybe_response,
Some(RespondArgs { Some(RespondArgs {

View file

@ -921,6 +921,7 @@ delete Object.prototype.__proto__;
// A build time only op that provides some setup information that is used to // A build time only op that provides some setup information that is used to
// ensure the snapshot is setup properly. // ensure the snapshot is setup properly.
/** @type {{ buildSpecifier: string; libs: string[] }} */ /** @type {{ buildSpecifier: string; libs: string[] }} */
const { buildSpecifier, libs } = core.opSync("op_build_info", {}); const { buildSpecifier, libs } = core.opSync("op_build_info", {});
for (const lib of libs) { for (const lib of libs) {
const specifier = `lib.${lib}.d.ts`; const specifier = `lib.${lib}.d.ts`;

View file

@ -16,7 +16,6 @@
ErrorCaptureStackTrace, ErrorCaptureStackTrace,
Promise, Promise,
ObjectEntries, ObjectEntries,
ObjectFreeze,
ObjectFromEntries, ObjectFromEntries,
MapPrototypeGet, MapPrototypeGet,
MapPrototypeDelete, MapPrototypeDelete,
@ -27,11 +26,12 @@
ObjectAssign, ObjectAssign,
SymbolFor, SymbolFor,
} = window.__bootstrap.primordials; } = 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. // Available on start due to bindings.
const { opcallSync, opcallAsync, refOp_, unrefOp_ } = window.Deno.core; const { refOp_, unrefOp_ } = window.Deno.core;
let opsCache = {};
const errorMap = {}; const errorMap = {};
// Builtin v8 / JS errors // Builtin v8 / JS errors
registerErrorClass("Error", Error); registerErrorClass("Error", Error);
@ -110,15 +110,6 @@
return promiseRing[idx] != NO_PROMISE; 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() { function opresolve() {
for (let i = 0; i < arguments.length; i += 2) { for (let i = 0; i < arguments.length; i += 2) {
const promiseId = arguments[i]; const promiseId = arguments[i];
@ -160,7 +151,7 @@
function opAsync(opName, arg1 = null, arg2 = null) { function opAsync(opName, arg1 = null, arg2 = null) {
const promiseId = nextPromiseId++; 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) // Handle sync error (e.g: error parsing args)
if (maybeError) return unwrapOpResult(maybeError); if (maybeError) return unwrapOpResult(maybeError);
let p = PromisePrototypeThen(setPromise(promiseId), unwrapOpResult); let p = PromisePrototypeThen(setPromise(promiseId), unwrapOpResult);
@ -179,8 +170,8 @@
return p; return p;
} }
function opSync(opName, arg1 = null, arg2 = null) { function opSync(opName, arg1, arg2) {
return unwrapOpResult(opcallSync(opsCache[opName], arg1, arg2)); return unwrapOpResult(ops[opName](opIds[opName], arg1, arg2));
} }
function refOp(promiseId) { function refOp(promiseId) {
@ -228,7 +219,7 @@
function metrics() { function metrics() {
const [aggregate, perOps] = opSync("op_metrics"); const [aggregate, perOps] = opSync("op_metrics");
aggregate.ops = ObjectFromEntries(ArrayPrototypeMap( aggregate.ops = ObjectFromEntries(ArrayPrototypeMap(
ObjectEntries(opsCache), ObjectEntries(opIds),
([opName, opId]) => [opName, perOps[opId]], ([opName, opId]) => [opName, perOps[opId]],
)); ));
return aggregate; return aggregate;
@ -257,7 +248,6 @@
const core = ObjectAssign(globalThis.Deno.core, { const core = ObjectAssign(globalThis.Deno.core, {
opAsync, opAsync,
opSync, opSync,
ops,
close, close,
tryClose, tryClose,
read, read,
@ -269,7 +259,6 @@
registerErrorBuilder, registerErrorBuilder,
registerErrorClass, registerErrorClass,
opresolve, opresolve,
syncOpsCache,
BadResource, BadResource,
BadResourcePrototype, BadResourcePrototype,
Interrupted, Interrupted,

View file

@ -14,6 +14,7 @@ path = "lib.rs"
[dependencies] [dependencies]
anyhow = "1.0.55" anyhow = "1.0.55"
deno_ops = { path = "../ops", version = "0.1.0" }
futures = "0.3.21" futures = "0.3.21"
indexmap = "1.7.0" indexmap = "1.7.0"
libc = "0.2.106" libc = "0.2.106"

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::error::is_instance_of_error; use crate::error::is_instance_of_error;
use crate::extensions::OpPair;
use crate::modules::get_module_type_from_assertions; use crate::modules::get_module_type_from_assertions;
use crate::modules::parse_import_assertions; use crate::modules::parse_import_assertions;
use crate::modules::validate_import_assertions; use crate::modules::validate_import_assertions;
@ -8,21 +9,18 @@ use crate::modules::ImportAssertionsKind;
use crate::modules::ModuleMap; use crate::modules::ModuleMap;
use crate::resolve_url_or_path; use crate::resolve_url_or_path;
use crate::JsRuntime; use crate::JsRuntime;
use crate::Op; use crate::OpState;
use crate::OpId;
use crate::OpPayload;
use crate::OpResult;
use crate::OpTable;
use crate::PromiseId; use crate::PromiseId;
use crate::ZeroCopyBuf; use crate::ZeroCopyBuf;
use anyhow::Error; use anyhow::Error;
use log::debug; use log::debug;
use once_cell::sync::Lazy;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use serde_v8::to_v8; use serde_v8::to_v8;
use std::cell::RefCell; use std::cell::RefCell;
use std::option::Option; use std::option::Option;
use std::os::raw::c_void;
use std::rc::Rc;
use url::Url; use url::Url;
use v8::HandleScope; use v8::HandleScope;
use v8::Local; use v8::Local;
@ -31,88 +29,88 @@ use v8::SharedArrayBuffer;
use v8::ValueDeserializerHelper; use v8::ValueDeserializerHelper;
use v8::ValueSerializerHelper; use v8::ValueSerializerHelper;
const UNDEFINED_OP_ID_MSG: &str = pub fn external_references(
"invalid op id: received `undefined` instead of an integer. ops: &[OpPair],
This error is often caused by a typo in an op name, or not calling op_state: Rc<RefCell<OpState>>,
JsRuntime::sync_ops_cache() after JsRuntime initialization."; ) -> v8::ExternalReferences {
let mut refs = vec![
pub static EXTERNAL_REFERENCES: Lazy<v8::ExternalReferences> = v8::ExternalReference {
Lazy::new(|| { function: ref_op.map_fn_to(),
v8::ExternalReferences::new(&[ },
v8::ExternalReference { v8::ExternalReference {
function: opcall_async.map_fn_to(), function: unref_op.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: opcall_sync.map_fn_to(), function: set_macrotask_callback.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: ref_op.map_fn_to(), function: set_nexttick_callback.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: unref_op.map_fn_to(), function: set_promise_reject_callback.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: set_macrotask_callback.map_fn_to(), function: set_uncaught_exception_callback.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: set_nexttick_callback.map_fn_to(), function: run_microtasks.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: set_promise_reject_callback.map_fn_to(), function: has_tick_scheduled.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: set_uncaught_exception_callback.map_fn_to(), function: set_has_tick_scheduled.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: run_microtasks.map_fn_to(), function: eval_context.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: has_tick_scheduled.map_fn_to(), function: queue_microtask.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: set_has_tick_scheduled.map_fn_to(), function: create_host_object.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: eval_context.map_fn_to(), function: encode.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: queue_microtask.map_fn_to(), function: decode.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: create_host_object.map_fn_to(), function: serialize.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: encode.map_fn_to(), function: deserialize.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: decode.map_fn_to(), function: get_promise_details.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: serialize.map_fn_to(), function: get_proxy_details.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: deserialize.map_fn_to(), function: is_proxy.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: get_promise_details.map_fn_to(), function: memory_usage.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: get_proxy_details.map_fn_to(), function: call_console.map_fn_to(),
}, },
v8::ExternalReference { v8::ExternalReference {
function: is_proxy.map_fn_to(), function: set_wasm_streaming_callback.map_fn_to(),
}, },
v8::ExternalReference { ];
function: memory_usage.map_fn_to(), let op_refs = ops
}, .iter()
v8::ExternalReference { .map(|(_, opref)| v8::ExternalReference { function: *opref });
function: call_console.map_fn_to(), refs.extend(op_refs);
}, let raw_op_state = Rc::as_ptr(&op_state) as *mut c_void;
v8::ExternalReference { refs.push(v8::ExternalReference {
function: set_wasm_streaming_callback.map_fn_to(), pointer: raw_op_state,
},
])
}); });
v8::ExternalReferences::new(&refs)
}
pub fn script_origin<'a>( pub fn script_origin<'a>(
s: &mut v8::HandleScope<'a>, s: &mut v8::HandleScope<'a>,
@ -154,6 +152,9 @@ pub fn module_origin<'a>(
pub fn initialize_context<'s>( pub fn initialize_context<'s>(
scope: &mut v8::HandleScope<'s, ()>, scope: &mut v8::HandleScope<'s, ()>,
ops: &[OpPair],
snapshot_loaded: bool,
op_state: Rc<RefCell<OpState>>,
) -> v8::Local<'s, v8::Context> { ) -> v8::Local<'s, v8::Context> {
let scope = &mut v8::EscapableHandleScope::new(scope); let scope = &mut v8::EscapableHandleScope::new(scope);
@ -162,17 +163,43 @@ pub fn initialize_context<'s>(
let scope = &mut v8::ContextScope::new(scope, context); let scope = &mut v8::ContextScope::new(scope, context);
// global.Deno = { core: {} };
let deno_key = v8::String::new(scope, "Deno").unwrap(); 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); let deno_val = v8::Object::new(scope);
global.set(scope, deno_key.into(), deno_val.into()); 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); let core_val = v8::Object::new(scope);
deno_val.set(scope, core_key.into(), core_val.into()); 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.* // 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, "refOp_", ref_op);
set_func(scope, core_val, "unrefOp_", unref_op); set_func(scope, core_val, "unrefOp_", unref_op);
set_func( set_func(
@ -227,10 +254,14 @@ pub fn initialize_context<'s>(
// Direct bindings on `window`. // Direct bindings on `window`.
set_func(scope, global, "queueMicrotask", queue_microtask); 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) scope.escape(context)
} }
#[inline(always)]
pub fn set_func( pub fn set_func(
scope: &mut v8::HandleScope<'_>, scope: &mut v8::HandleScope<'_>,
obj: v8::Local<v8::Object>, obj: v8::Local<v8::Object>,
@ -238,8 +269,26 @@ pub fn set_func(
callback: impl v8::MapFnTo<v8::FunctionCallback>, callback: impl v8::MapFnTo<v8::FunctionCallback>,
) { ) {
let key = v8::String::new(scope, name).unwrap(); let key = v8::String::new(scope, name).unwrap();
let tmpl = v8::FunctionTemplate::new(scope, callback); let val = v8::Function::new(scope, callback).unwrap();
let val = tmpl.get_function(scope).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); val.set_name(key);
obj.set(scope, key.into(), val.into()); 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>( fn ref_op<'s>(
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
args: v8::FunctionCallbackArguments, args: v8::FunctionCallbackArguments,
@ -1471,7 +1389,7 @@ fn is_proxy(
rv.set(v8::Boolean::new(scope, args.get(0).is_proxy()).into()) 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 message = v8::String::new(scope, message.as_ref()).unwrap();
let exception = v8::Exception::type_error(scope, message); let exception = v8::Exception::type_error(scope, message);
scope.throw_exception(exception); scope.throw_exception(exception);

View file

@ -1,6 +1,6 @@
use anyhow::Error; 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 err
.downcast_ref::<std::io::Error>() .downcast_ref::<std::io::Error>()
.map(|e| match e.raw_os_error() { .map(|e| match e.raw_os_error() {

View file

@ -9,7 +9,7 @@ use deno_core::RuntimeOptions;
fn main() { fn main() {
let my_ext = Extension::builder() let my_ext = Extension::builder()
.middleware(|name, opfn| match name { .middleware(|name, opfn| match name {
"op_print" => deno_core::void_op_sync(), "op_print" => deno_core::void_op_sync::v8_cb(),
_ => opfn, _ => opfn,
}) })
.build(); .build();

View file

@ -2,27 +2,37 @@
//! This example shows you how to define ops in Rust and then call them from //! This example shows you how to define ops in Rust and then call them from
//! JavaScript. //! JavaScript.
use deno_core::op_sync; use deno_core::op;
use deno_core::Extension; use deno_core::Extension;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::OpState;
use deno_core::RuntimeOptions; 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() { fn main() {
// Build a deno_core::Extension providing custom ops // Build a deno_core::Extension providing custom ops
let ext = Extension::builder() let ext = Extension::builder()
.ops(vec![ .ops(vec![
// An op for summing an array of numbers // An op for summing an array of numbers
( // The op-layer automatically deserializes inputs
"op_sum", // and serializes the returned Result & value
// The op-layer automatically deserializes inputs op_sum::decl(),
// 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)
}),
),
]) ])
.build(); .build();

View file

@ -11,12 +11,12 @@ const responseBuf = new Uint8Array(
/** Listens on 0.0.0.0:4500, returns rid. */ /** Listens on 0.0.0.0:4500, returns rid. */
function listen() { function listen() {
return Deno.core.opSync("listen"); return Deno.core.opSync("op_listen");
} }
/** Accepts a connection, returns rid. */ /** Accepts a connection, returns rid. */
function accept(serverRid) { function accept(serverRid) {
return Deno.core.opAsync("accept", serverRid); return Deno.core.opAsync("op_accept", serverRid);
} }
async function serve(rid) { async function serve(rid) {

View file

@ -1,5 +1,6 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::anyhow::Error; use deno_core::anyhow::Error;
use deno_core::op;
use deno_core::AsyncRefCell; use deno_core::AsyncRefCell;
use deno_core::AsyncResult; use deno_core::AsyncResult;
use deno_core::CancelHandle; use deno_core::CancelHandle;
@ -17,6 +18,11 @@ use std::rc::Rc;
use tokio::io::AsyncReadExt; use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt; 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; struct Logger;
impl log::Log for Logger { impl log::Log for Logger {
@ -119,10 +125,7 @@ impl From<tokio::net::TcpStream> for TcpStream {
fn create_js_runtime() -> JsRuntime { fn create_js_runtime() -> JsRuntime {
let ext = deno_core::Extension::builder() let ext = deno_core::Extension::builder()
.ops(vec![ .ops(vec![op_listen::decl(), op_accept::decl()])
("listen", deno_core::op_sync(op_listen)),
("accept", deno_core::op_async(op_accept)),
])
.build(); .build();
JsRuntime::new(deno_core::RuntimeOptions { JsRuntime::new(deno_core::RuntimeOptions {
@ -131,6 +134,7 @@ fn create_js_runtime() -> JsRuntime {
}) })
} }
#[op]
fn op_listen(state: &mut OpState, _: (), _: ()) -> Result<ResourceId, Error> { fn op_listen(state: &mut OpState, _: (), _: ()) -> Result<ResourceId, Error> {
log::debug!("listen"); log::debug!("listen");
let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap(); 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) Ok(rid)
} }
#[op]
async fn op_accept( async fn op_accept(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::anyhow::Error; use deno_core::anyhow::Error;
use deno_core::op;
use deno_core::Extension; use deno_core::Extension;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::OpState; use deno_core::OpState;
@ -9,14 +10,16 @@ use futures::channel::mpsc;
use futures::stream::StreamExt; use futures::stream::StreamExt;
use std::task::Poll; 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()>; type Task = Box<dyn FnOnce()>;
fn main() { fn main() {
let my_ext = Extension::builder() let my_ext = Extension::builder()
.ops(vec![( .ops(vec![op_schedule_task::decl()])
"op_schedule_task",
deno_core::op_sync(op_schedule_task),
)])
.event_loop_middleware(|state, cx| { .event_loop_middleware(|state, cx| {
let recv = state.borrow_mut::<mpsc::UnboundedReceiver<Task>>(); let recv = state.borrow_mut::<mpsc::UnboundedReceiver<Task>>();
let mut ref_loop = false; let mut ref_loop = false;
@ -58,6 +61,7 @@ fn main() {
runtime.block_on(future).unwrap(); runtime.block_on(future).unwrap();
} }
#[op]
fn op_schedule_task(state: &mut OpState, i: u8, _: ()) -> Result<(), Error> { fn op_schedule_task(state: &mut OpState, i: u8, _: ()) -> Result<(), Error> {
let tx = state.borrow_mut::<mpsc::UnboundedSender<Task>>(); let tx = state.borrow_mut::<mpsc::UnboundedSender<Task>>();
tx.unbounded_send(Box::new(move || println!("Hello, world! x{}", i))) tx.unbounded_send(Box::new(move || println!("Hello, world! x{}", i)))

View file

@ -1,12 +1,13 @@
use crate::OpFn; // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::OpState; use crate::OpState;
use anyhow::Error; use anyhow::Error;
use std::task::Context; use std::task::Context;
pub type SourcePair = (&'static str, Box<SourceLoadFn>); pub type SourcePair = (&'static str, Box<SourceLoadFn>);
pub type SourceLoadFn = dyn Fn() -> Result<String, Error>; pub type SourceLoadFn = dyn Fn() -> Result<String, Error>;
pub type OpPair = (&'static str, Box<OpFn>); pub type OpFnRef = v8::FunctionCallback;
pub type OpMiddlewareFn = dyn Fn(&'static str, Box<OpFn>) -> Box<OpFn>; 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 OpStateFn = dyn Fn(&mut OpState) -> Result<(), Error>;
pub type OpEventLoopFn = dyn Fn(&mut OpState, &mut Context) -> bool; 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 pub fn middleware<F>(&mut self, middleware_fn: F) -> &mut Self
where 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.middleware = Some(Box::new(middleware_fn));
self self

View file

@ -13,7 +13,6 @@ mod modules;
mod normalize_path; mod normalize_path;
mod ops; mod ops;
mod ops_builtin; mod ops_builtin;
mod ops_json;
mod ops_metrics; mod ops_metrics;
mod resources; mod resources;
mod runtime; mod runtime;
@ -44,6 +43,10 @@ pub use crate::async_cell::AsyncRefCell;
pub use crate::async_cell::AsyncRefFuture; pub use crate::async_cell::AsyncRefFuture;
pub use crate::async_cell::RcLike; pub use crate::async_cell::RcLike;
pub use crate::async_cell::RcRef; 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::flags::v8_set_flags;
pub use crate::inspector::InspectorMsg; pub use crate::inspector::InspectorMsg;
pub use crate::inspector::InspectorMsgKind; pub use crate::inspector::InspectorMsgKind;
@ -65,24 +68,21 @@ pub use crate::modules::ModuleSourceFuture;
pub use crate::modules::ModuleType; pub use crate::modules::ModuleType;
pub use crate::modules::NoopModuleLoader; pub use crate::modules::NoopModuleLoader;
pub use crate::normalize_path::normalize_path; pub use crate::normalize_path::normalize_path;
pub use crate::ops::serialize_op_result;
pub use crate::ops::Op; pub use crate::ops::Op;
pub use crate::ops::OpAsyncFuture; pub use crate::ops::OpAsyncFuture;
pub use crate::ops::OpCall; pub use crate::ops::OpCall;
pub use crate::ops::OpError;
pub use crate::ops::OpFn; pub use crate::ops::OpFn;
pub use crate::ops::OpId; pub use crate::ops::OpId;
pub use crate::ops::OpPayload;
pub use crate::ops::OpResult; pub use crate::ops::OpResult;
pub use crate::ops::OpState; pub use crate::ops::OpState;
pub use crate::ops::OpTable;
pub use crate::ops::PromiseId; pub use crate::ops::PromiseId;
pub use crate::ops_builtin::op_close; pub use crate::ops_builtin::op_close;
pub use crate::ops_builtin::op_print; pub use crate::ops_builtin::op_print;
pub use crate::ops_builtin::op_resources; pub use crate::ops_builtin::op_resources;
pub use crate::ops_json::op_async; pub use crate::ops_builtin::void_op_async;
pub use crate::ops_json::op_sync; pub use crate::ops_builtin::void_op_sync;
pub use crate::ops_json::void_op_async; pub use crate::ops_metrics::OpsTracker;
pub use crate::ops_json::void_op_sync;
pub use crate::resources::AsyncResult; pub use crate::resources::AsyncResult;
pub use crate::resources::Resource; pub use crate::resources::Resource;
pub use crate::resources::ResourceId; pub use crate::resources::ResourceId;
@ -95,16 +95,21 @@ pub use crate::runtime::JsRuntime;
pub use crate::runtime::RuntimeOptions; pub use crate::runtime::RuntimeOptions;
pub use crate::runtime::SharedArrayBufferStore; pub use crate::runtime::SharedArrayBufferStore;
pub use crate::runtime::Snapshot; pub use crate::runtime::Snapshot;
// pub use crate::runtime_modules::include_js_files!; pub use deno_ops::op;
pub use crate::extensions::Extension;
pub use crate::extensions::ExtensionBuilder;
pub use crate::extensions::OpMiddlewareFn;
pub use crate::extensions::OpPair;
pub fn v8_version() -> &'static str { pub fn v8_version() -> &'static str {
v8::V8::get_version() 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 /// A helper macro that will return a call site in Rust code. Should be
/// used when executing internal one-line scripts for JsRuntime lifecycle. /// used when executing internal one-line scripts for JsRuntime lifecycle.
/// ///

View file

@ -1073,13 +1073,11 @@ impl ModuleMap {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::ops::OpCall; use crate::error::AnyError;
use crate::serialize_op_result;
use crate::Extension; use crate::Extension;
use crate::JsRuntime; use crate::JsRuntime;
use crate::Op;
use crate::OpPayload;
use crate::RuntimeOptions; use crate::RuntimeOptions;
use deno_ops::op;
use futures::future::FutureExt; use futures::future::FutureExt;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::fmt; use std::fmt;
@ -1088,6 +1086,10 @@ mod tests {
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc; 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 // 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 // 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 loader = Rc::new(ModsLoader::default());
let resolve_count = loader.count.clone(); let resolve_count = loader.count.clone();
let dispatch_count = Arc::new(AtomicUsize::new(0)); static DISPATCH_COUNT: AtomicUsize = AtomicUsize::new(0);
let dispatch_count_ = dispatch_count.clone();
let op_test = move |state, payload: OpPayload| -> Op { #[op]
dispatch_count_.fetch_add(1, Ordering::Relaxed); fn op_test(_: &mut OpState, control: u8, _: ()) -> Result<u8, AnyError> {
let (control, _): (u8, ()) = payload.deserialize().unwrap(); DISPATCH_COUNT.fetch_add(1, Ordering::Relaxed);
assert_eq!(control, 42); assert_eq!(control, 42);
let resp = (0, 1, serialize_op_result(Ok(43), state)); Ok(43)
Op::Async(OpCall::ready(resp)) }
};
let ext = Extension::builder() let ext = Extension::builder().ops(vec![op_test::decl()]).build();
.ops(vec![("op_test", Box::new(op_test))])
.build();
let mut runtime = JsRuntime::new(RuntimeOptions { let mut runtime = JsRuntime::new(RuntimeOptions {
extensions: vec![ext], extensions: vec![ext],
@ -1435,7 +1433,7 @@ import "/a.js";
) )
.unwrap(); .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()); let module_map_rc = JsRuntime::module_map(runtime.v8_isolate());
@ -1452,12 +1450,12 @@ import "/a.js";
import { b } from './b.js' import { b } from './b.js'
if (b() != 'b') throw Error(); if (b() != 'b') throw Error();
let control = 42; let control = 42;
Deno.core.opAsync("op_test", control); Deno.core.opSync("op_test", control);
"#, "#,
) )
.unwrap(); .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); let imports = module_map.get_requested_modules(mod_a);
assert_eq!( assert_eq!(
imports, imports,
@ -1481,14 +1479,14 @@ import "/a.js";
}; };
runtime.instantiate_module(mod_b).unwrap(); 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); assert_eq!(resolve_count.load(Ordering::SeqCst), 1);
runtime.instantiate_module(mod_a).unwrap(); 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); let _ = runtime.mod_evaluate(mod_a);
assert_eq!(dispatch_count.load(Ordering::Relaxed), 1); assert_eq!(DISPATCH_COUNT.load(Ordering::Relaxed), 1);
} }
#[test] #[test]
@ -1766,7 +1764,6 @@ import "/a.js";
module_loader: Some(loader), module_loader: Some(loader),
..Default::default() ..Default::default()
}); });
runtime.sync_ops_cache();
runtime runtime
.execute_script( .execute_script(
"file:///dyn_import3.js", "file:///dyn_import3.js",

View file

@ -1,10 +1,9 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::error::type_error;
use crate::gotham_state::GothamState; use crate::gotham_state::GothamState;
use crate::ops_metrics::OpsTracker;
use crate::resources::ResourceTable; use crate::resources::ResourceTable;
use crate::runtime::GetErrorClassFn; use crate::runtime::GetErrorClassFn;
use crate::OpsTracker;
use anyhow::Error; use anyhow::Error;
use futures::future::maybe_done; use futures::future::maybe_done;
use futures::future::FusedFuture; use futures::future::FusedFuture;
@ -12,23 +11,19 @@ use futures::future::MaybeDone;
use futures::ready; use futures::ready;
use futures::task::noop_waker; use futures::task::noop_waker;
use futures::Future; use futures::Future;
use indexmap::IndexMap;
use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
use std::cell::RefCell;
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::iter::once;
use std::ops::Deref; use std::ops::Deref;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc;
use std::task::Context; use std::task::Context;
use std::task::Poll; use std::task::Poll;
/// Wrapper around a Future, which causes that Future to be polled immediately. /// 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 /// 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>>>>); pub struct OpCall<T>(MaybeDone<Pin<Box<dyn Future<Output = T>>>>);
impl<T> OpCall<T> { impl<T> OpCall<T> {
@ -83,32 +78,10 @@ where
pub type PromiseId = i32; pub type PromiseId = i32;
pub type OpAsyncFuture = OpCall<(PromiseId, OpId, OpResult)>; 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 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 { pub enum Op {
Sync(OpResult), Sync(OpResult),
Async(OpAsyncFuture), Async(OpAsyncFuture),
@ -141,39 +114,43 @@ pub struct OpError {
code: Option<&'static str>, 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>, result: Result<R, Error>,
state: Rc<RefCell<OpState>>,
) -> OpResult { ) -> OpResult {
match result { match result {
Ok(v) => OpResult::Ok(v.into()), Ok(v) => OpResult::Ok(v.into()),
Err(err) => OpResult::Err(OpError { Err(err) => OpResult::Err(OpError::new(get_class, err)),
class_name: (state.borrow().get_error_class_fn)(&err),
message: err.to_string(),
code: crate::error_codes::get_error_code(&err),
}),
} }
} }
/// Maintains the resources and ops inside a JS runtime. /// Maintains the resources and ops inside a JS runtime.
pub struct OpState { pub struct OpState {
pub resource_table: ResourceTable, pub resource_table: ResourceTable,
pub op_table: OpTable,
pub get_error_class_fn: GetErrorClassFn, pub get_error_class_fn: GetErrorClassFn,
pub(crate) tracker: OpsTracker, pub tracker: OpsTracker,
gotham_state: GothamState, gotham_state: GothamState,
} }
impl OpState { impl OpState {
pub(crate) fn new() -> OpState { pub fn new(ops_count: usize) -> OpState {
OpState { OpState {
resource_table: Default::default(), resource_table: Default::default(),
op_table: OpTable::default(),
get_error_class_fn: &|_| "Error", get_error_class_fn: &|_| "Error",
tracker: OpsTracker {
ops: UnsafeCell::new(Vec::with_capacity(256)),
},
gotham_state: Default::default(), gotham_state: Default::default(),
tracker: OpsTracker {
ops: UnsafeCell::new(vec![Default::default(); ops_count]),
},
} }
} }
} }
@ -191,81 +168,3 @@ impl DerefMut for OpState {
&mut self.gotham_state &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)
]
);
}
}

View file

@ -1,16 +1,13 @@
use crate::error::type_error; use crate::error::type_error;
use crate::include_js_files; use crate::include_js_files;
use crate::op_async;
use crate::op_sync;
use crate::ops_metrics::OpMetrics; use crate::ops_metrics::OpMetrics;
use crate::resources::ResourceId; use crate::resources::ResourceId;
use crate::void_op_async;
use crate::void_op_sync;
use crate::Extension; use crate::Extension;
use crate::OpState; use crate::OpState;
use crate::Resource; use crate::Resource;
use crate::ZeroCopyBuf; use crate::ZeroCopyBuf;
use anyhow::Error; use anyhow::Error;
use deno_ops::op;
use std::cell::RefCell; use std::cell::RefCell;
use std::io::{stderr, stdout, Write}; use std::io::{stderr, stdout, Write};
use std::rc::Rc; use std::rc::Rc;
@ -24,29 +21,40 @@ pub(crate) fn init_builtins() -> Extension {
"02_error.js", "02_error.js",
)) ))
.ops(vec![ .ops(vec![
("op_close", op_sync(op_close)), op_close::decl(),
("op_try_close", op_sync(op_try_close)), op_try_close::decl(),
("op_print", op_sync(op_print)), op_print::decl(),
("op_resources", op_sync(op_resources)), op_resources::decl(),
("op_wasm_streaming_feed", op_sync(op_wasm_streaming_feed)), op_wasm_streaming_feed::decl(),
("op_wasm_streaming_abort", op_sync(op_wasm_streaming_abort)), op_wasm_streaming_abort::decl(),
( op_wasm_streaming_set_url::decl(),
"op_wasm_streaming_set_url", op_void_sync::decl(),
op_sync(op_wasm_streaming_set_url), op_void_async::decl(),
), // // TODO(@AaronO): track IO metrics for builtin streams
("op_metrics", op_sync(op_metrics)), op_read::decl(),
("op_void_sync", void_op_sync()), op_write::decl(),
("op_void_async", void_op_async()), op_shutdown::decl(),
// TODO(@AaronO): track IO metrics for builtin streams op_metrics::decl(),
("op_read", op_async(op_read)),
("op_write", op_async(op_write)),
("op_shutdown", op_async(op_shutdown)),
]) ])
.build() .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 /// Return map of resources with id as key
/// and string representation as value. /// and string representation as value.
#[op]
pub fn op_resources( pub fn op_resources(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -60,7 +68,22 @@ pub fn op_resources(
Ok(serialized_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. /// Remove a resource from the resource table.
#[op]
pub fn op_close( pub fn op_close(
state: &mut OpState, state: &mut OpState,
rid: Option<ResourceId>, 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 /// Try to remove a resource from the resource table. If there is no resource
/// with the specified `rid`, this is a no-op. /// with the specified `rid`, this is a no-op.
#[op]
pub fn op_try_close( pub fn op_try_close(
state: &mut OpState, state: &mut OpState,
rid: Option<ResourceId>, rid: Option<ResourceId>,
@ -87,7 +111,19 @@ pub fn op_try_close(
Ok(()) 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 /// Builtin utility to print to stdout/stderr
#[op]
pub fn op_print( pub fn op_print(
_state: &mut OpState, _state: &mut OpState,
msg: String, msg: String,
@ -119,6 +155,7 @@ impl Resource for WasmStreamingResource {
} }
/// Feed bytes to WasmStreamingResource. /// Feed bytes to WasmStreamingResource.
#[op]
pub fn op_wasm_streaming_feed( pub fn op_wasm_streaming_feed(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -133,6 +170,7 @@ pub fn op_wasm_streaming_feed(
} }
/// Abort a WasmStreamingResource. /// Abort a WasmStreamingResource.
#[op]
pub fn op_wasm_streaming_abort( pub fn op_wasm_streaming_abort(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -153,6 +191,7 @@ pub fn op_wasm_streaming_abort(
Ok(()) Ok(())
} }
#[op]
pub fn op_wasm_streaming_set_url( pub fn op_wasm_streaming_set_url(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -166,16 +205,7 @@ pub fn op_wasm_streaming_set_url(
Ok(()) Ok(())
} }
pub fn op_metrics( #[op]
state: &mut OpState,
_: (),
_: (),
) -> Result<(OpMetrics, Vec<OpMetrics>), Error> {
let aggregate = state.tracker.aggregate();
let per_op = state.tracker.per_op();
Ok((aggregate, per_op))
}
async fn op_read( async fn op_read(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -185,6 +215,7 @@ async fn op_read(
resource.read(buf).await.map(|n| n as u32) resource.read(buf).await.map(|n| n as u32)
} }
#[op]
async fn op_write( async fn op_write(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -194,6 +225,7 @@ async fn op_write(
resource.write(buf).await.map(|n| n as u32) resource.write(buf).await.map(|n| n as u32)
} }
#[op]
async fn op_shutdown( async fn op_shutdown(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,

View file

@ -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>:"));
}
}

View file

@ -59,20 +59,10 @@ impl OpsTracker {
unsafe { &mut *self.ops.get() } 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)] #[allow(clippy::mut_from_ref)]
#[inline] #[inline]
fn metrics_mut(&self, id: OpId) -> &mut OpMetrics { fn metrics_mut(&self, id: OpId) -> &mut OpMetrics {
let ops = self.ops_mut(); unsafe { self.ops_mut().get_unchecked_mut(id) }
// 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) }
} }
#[inline] #[inline]

View file

@ -6,6 +6,7 @@ use crate::error::generic_error;
use crate::error::ErrWithV8Handle; use crate::error::ErrWithV8Handle;
use crate::error::JsError; use crate::error::JsError;
use crate::extensions::OpEventLoopFn; use crate::extensions::OpEventLoopFn;
use crate::extensions::OpPair;
use crate::inspector::JsRuntimeInspector; use crate::inspector::JsRuntimeInspector;
use crate::module_specifier::ModuleSpecifier; use crate::module_specifier::ModuleSpecifier;
use crate::modules::ModuleId; use crate::modules::ModuleId;
@ -16,13 +17,13 @@ use crate::modules::NoopModuleLoader;
use crate::ops::*; use crate::ops::*;
use crate::Extension; use crate::Extension;
use crate::OpMiddlewareFn; use crate::OpMiddlewareFn;
use crate::OpPayload;
use crate::OpResult; use crate::OpResult;
use crate::OpState; use crate::OpState;
use crate::PromiseId; use crate::PromiseId;
use anyhow::Error; use anyhow::Error;
use futures::channel::oneshot; use futures::channel::oneshot;
use futures::future::poll_fn; use futures::future::poll_fn;
use futures::future::Future;
use futures::future::FutureExt; use futures::future::FutureExt;
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use futures::stream::StreamExt; use futures::stream::StreamExt;
@ -143,7 +144,6 @@ pub type CompiledWasmModuleStore = CrossIsolateStore<v8::CompiledWasmModule>;
pub(crate) struct JsRuntimeState { pub(crate) struct JsRuntimeState {
pub global_context: Option<v8::Global<v8::Context>>, pub global_context: Option<v8::Global<v8::Context>>,
pub(crate) js_recv_cb: Option<v8::Global<v8::Function>>, 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_macrotask_cbs: Vec<v8::Global<v8::Function>>,
pub(crate) js_nexttick_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>>, 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 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 global_context;
let (mut isolate, maybe_snapshot_creator) = if options.will_snapshot { let (mut isolate, maybe_snapshot_creator) = if options.will_snapshot {
// TODO(ry) Support loading snapshots before snapshotting. // TODO(ry) Support loading snapshots before snapshotting.
assert!(options.startup_snapshot.is_none()); assert!(options.startup_snapshot.is_none());
let mut creator = let mut creator = v8::SnapshotCreator::new(Some(refs));
v8::SnapshotCreator::new(Some(&bindings::EXTERNAL_REFERENCES));
let isolate = unsafe { creator.get_owned_isolate() }; let isolate = unsafe { creator.get_owned_isolate() };
let mut isolate = JsRuntime::setup_isolate(isolate); let mut isolate = JsRuntime::setup_isolate(isolate);
{ {
let scope = &mut v8::HandleScope::new(&mut 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); global_context = v8::Global::new(scope, context);
creator.set_default_context(context); creator.set_default_context(context);
} }
@ -299,7 +319,7 @@ impl JsRuntime {
.create_params .create_params
.take() .take()
.unwrap_or_else(v8::Isolate::create_params) .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 { let snapshot_loaded = if let Some(snapshot) = options.startup_snapshot {
params = match snapshot { params = match snapshot {
Snapshot::Static(data) => params.snapshot_blob(data), Snapshot::Static(data) => params.snapshot_blob(data),
@ -315,13 +335,13 @@ impl JsRuntime {
let mut isolate = JsRuntime::setup_isolate(isolate); let mut isolate = JsRuntime::setup_isolate(isolate);
{ {
let scope = &mut v8::HandleScope::new(&mut isolate); let scope = &mut v8::HandleScope::new(&mut isolate);
let context = if snapshot_loaded { let context = bindings::initialize_context(
v8::Context::new(scope) scope,
} else { &ops,
// If no snapshot is provided, we initialize the context with empty snapshot_loaded,
// main source code and source maps. op_state.clone(),
bindings::initialize_context(scope) );
};
global_context = v8::Global::new(scope, context); global_context = v8::Global::new(scope, context);
} }
(isolate, None) (isolate, None)
@ -334,17 +354,6 @@ impl JsRuntime {
.module_loader .module_loader
.unwrap_or_else(|| Rc::new(NoopModuleLoader)); .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 { isolate.set_slot(Rc::new(RefCell::new(JsRuntimeState {
global_context: Some(global_context), global_context: Some(global_context),
pending_promise_exceptions: HashMap::new(), pending_promise_exceptions: HashMap::new(),
@ -352,7 +361,6 @@ impl JsRuntime {
pending_mod_evaluate: None, pending_mod_evaluate: None,
dyn_module_evaluate_idle_counter: 0, dyn_module_evaluate_idle_counter: 0,
js_recv_cb: None, js_recv_cb: None,
js_sync_cb: None,
js_macrotask_cbs: vec![], js_macrotask_cbs: vec![],
js_nexttick_cbs: vec![], js_nexttick_cbs: vec![],
js_promise_reject_cb: None, js_promise_reject_cb: None,
@ -372,11 +380,6 @@ impl JsRuntime {
let module_map = ModuleMap::new(loader, op_state); let module_map = ModuleMap::new(loader, op_state);
isolate.set_slot(Rc::new(RefCell::new(module_map))); 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 { let mut js_runtime = Self {
v8_isolate: Some(isolate), v8_isolate: Some(isolate),
inspector: Some(inspector), inspector: Some(inspector),
@ -394,10 +397,8 @@ impl JsRuntime {
} }
// Init extension ops // Init extension ops
js_runtime.init_extension_ops().unwrap(); js_runtime.init_extension_ops().unwrap();
// Init callbacks (opresolve & syncOpsCache) // Init callbacks (opresolve)
js_runtime.init_cbs(); js_runtime.init_cbs();
// Sync ops cache
js_runtime.sync_ops_cache();
js_runtime js_runtime
} }
@ -461,34 +462,44 @@ impl JsRuntime {
Ok(()) Ok(())
} }
/// 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));
// 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 /// Initializes ops of provided Extensions
fn init_extension_ops(&mut self) -> Result<(), Error> { fn init_extension_ops(&mut self) -> Result<(), Error> {
let op_state = self.op_state(); let op_state = self.op_state();
// Take extensions to avoid double-borrow // Take extensions to avoid double-borrow
let mut extensions: Vec<Extension> = std::mem::take(&mut self.extensions); let mut extensions: Vec<Extension> = std::mem::take(&mut self.extensions);
// Middleware // Setup state
let middleware: Vec<Box<OpMiddlewareFn>> = extensions
.iter_mut()
.filter_map(|e| e.init_middleware())
.collect();
// macroware wraps an opfn in all the middleware
let macroware =
move |name, opfn| middleware.iter().fold(opfn, |opfn, m| m(name, opfn));
// Register ops
for e in extensions.iter_mut() { for e in extensions.iter_mut() {
// ops are already registered during in bindings::initialize_context();
e.init_state(&mut op_state.borrow_mut())?; 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() { if let Some(middleware) = e.init_event_loop_middleware() {
self.event_loop_middlewares.push(middleware); self.event_loop_middlewares.push(middleware);
} }
} }
// Restore extensions // Restore extensions
self.extensions = extensions; self.extensions = extensions;
@ -511,22 +522,10 @@ impl JsRuntime {
fn init_cbs(&mut self) { fn init_cbs(&mut self) {
let mut scope = self.handle_scope(); let mut scope = self.handle_scope();
let recv_cb = Self::grab_fn(&mut scope, "Deno.core.opresolve"); 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 // Put global handles in state
let state_rc = JsRuntime::state(&scope); let state_rc = JsRuntime::state(&scope);
let mut state = state_rc.borrow_mut(); let mut state = state_rc.borrow_mut();
state.js_recv_cb.replace(recv_cb); 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 /// 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 // 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_recv_cb);
std::mem::take(&mut state.borrow_mut().js_sync_cb);
let snapshot_creator = self.snapshot_creator.as_mut().unwrap(); let snapshot_creator = self.snapshot_creator.as_mut().unwrap();
let snapshot = snapshot_creator let snapshot = snapshot_creator
@ -623,27 +621,6 @@ impl JsRuntime {
snapshot 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. /// 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. /// 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(); let mut state = state_rc.borrow_mut();
state.have_unpolled_ops = false; 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) while let Poll::Ready(Some(item)) = state.pending_ops.poll_next_unpin(cx)
{ {
let (promise_id, op_id, resp) = item; let (promise_id, op_id, resp) = item;
op_state.borrow().tracker.track_async_completed(op_id);
state.unrefed_ops.remove(&promise_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(v8::Integer::new(scope, promise_id as i32).into());
args.push(resp.to_v8(scope).unwrap()); 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)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::error::custom_error; use crate::error::custom_error;
use crate::error::AnyError;
use crate::modules::ModuleSource; use crate::modules::ModuleSource;
use crate::modules::ModuleSourceFuture; use crate::modules::ModuleSourceFuture;
use crate::modules::ModuleType; use crate::modules::ModuleType;
use crate::op_async;
use crate::op_sync;
use crate::ZeroCopyBuf; use crate::ZeroCopyBuf;
use deno_ops::op;
use futures::future::lazy; use futures::future::lazy;
use std::ops::FnOnce; use std::ops::FnOnce;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc; 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) pub fn run_in_task<F>(f: F)
where where
@ -1689,26 +1679,26 @@ pub mod tests {
dispatch_count: Arc<AtomicUsize>, dispatch_count: Arc<AtomicUsize>,
} }
fn op_test(rc_op_state: Rc<RefCell<OpState>>, payload: OpPayload) -> Op { #[op]
let rc_op_state2 = rc_op_state.clone(); async fn op_test(
let op_state_ = rc_op_state2.borrow(); 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>(); let test_state = op_state_.borrow::<TestState>();
test_state.dispatch_count.fetch_add(1, Ordering::Relaxed); test_state.dispatch_count.fetch_add(1, Ordering::Relaxed);
let (control, buf): (u8, Option<ZeroCopyBuf>) =
payload.deserialize().unwrap();
match test_state.mode { match test_state.mode {
Mode::Async => { Mode::Async => {
assert_eq!(control, 42); assert_eq!(control, 42);
let resp = (0, 1, serialize_op_result(Ok(43), rc_op_state)); Ok(43)
Op::Async(OpCall::ready(resp))
} }
Mode::AsyncZeroCopy(has_buffer) => { Mode::AsyncZeroCopy(has_buffer) => {
assert_eq!(buf.is_some(), has_buffer); assert_eq!(buf.is_some(), has_buffer);
if let Some(buf) = buf { if let Some(buf) = buf {
assert_eq!(buf.len(), 1); assert_eq!(buf.len(), 1);
} }
let resp = (0, 1, serialize_op_result(Ok(43), rc_op_state)); Ok(43)
Op::Async(OpCall::ready(resp))
} }
} }
} }
@ -1717,7 +1707,7 @@ pub mod tests {
let dispatch_count = Arc::new(AtomicUsize::new(0)); let dispatch_count = Arc::new(AtomicUsize::new(0));
let dispatch_count2 = dispatch_count.clone(); let dispatch_count2 = dispatch_count.clone();
let ext = Extension::builder() let ext = Extension::builder()
.ops(vec![("op_test", Box::new(op_test))]) .ops(vec![op_test::decl()])
.state(move |state| { .state(move |state| {
state.put(TestState { state.put(TestState {
mode, mode,
@ -2027,30 +2017,6 @@ pub mod tests {
v8_isolate_handle.terminate_execution(); v8_isolate_handle.terminate_execution();
} }
#[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] #[test]
fn syntax_error() { fn syntax_error() {
let mut runtime = JsRuntime::new(Default::default()); let mut runtime = JsRuntime::new(Default::default());
@ -2095,6 +2061,7 @@ pub mod tests {
#[test] #[test]
fn test_error_builder() { fn test_error_builder() {
#[op]
fn op_err(_: &mut OpState, _: (), _: ()) -> Result<(), Error> { fn op_err(_: &mut OpState, _: (), _: ()) -> Result<(), Error> {
Err(custom_error("DOMExceptionOperationError", "abc")) Err(custom_error("DOMExceptionOperationError", "abc"))
} }
@ -2104,9 +2071,7 @@ pub mod tests {
} }
run_in_task(|cx| { run_in_task(|cx| {
let ext = Extension::builder() let ext = Extension::builder().ops(vec![op_err::decl()]).build();
.ops(vec![("op_err", op_sync(op_err))])
.build();
let mut runtime = JsRuntime::new(RuntimeOptions { let mut runtime = JsRuntime::new(RuntimeOptions {
extensions: vec![ext], extensions: vec![ext],
get_error_class_fn: Some(&get_error_class_name), 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 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); let inner_invoke_count = Rc::clone(&callback_invoke_count);
runtime.add_near_heap_limit_callback( runtime.add_near_heap_limit_callback(
@ -2221,7 +2186,7 @@ pub mod tests {
}); });
let cb_handle = runtime.v8_isolate().thread_safe_handle(); 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); let inner_invoke_count_first = Rc::clone(&callback_invoke_count_first);
runtime.add_near_heap_limit_callback( runtime.add_near_heap_limit_callback(
move |current_limit, _initial_limit| { 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); let inner_invoke_count_second = Rc::clone(&callback_invoke_count_second);
runtime.add_near_heap_limit_callback( runtime.add_near_heap_limit_callback(
move |current_limit, _initial_limit| { move |current_limit, _initial_limit| {
@ -2500,6 +2465,7 @@ assertEquals(1, notify_return_value);
async fn test_async_opstate_borrow() { async fn test_async_opstate_borrow() {
struct InnerState(u64); struct InnerState(u64);
#[op]
async fn op_async_borrow( async fn op_async_borrow(
op_state: Rc<RefCell<OpState>>, op_state: Rc<RefCell<OpState>>,
_: (), _: (),
@ -2519,7 +2485,7 @@ assertEquals(1, notify_return_value);
} }
let extension = Extension::builder() let extension = Extension::builder()
.ops(vec![("op_async_borrow", op_async(op_async_borrow))]) .ops(vec![op_async_borrow::decl()])
.state(|state| { .state(|state| {
state.put(InnerState(42)); state.put(InnerState(42));
Ok(()) Ok(())
@ -2542,6 +2508,7 @@ assertEquals(1, notify_return_value);
#[tokio::test] #[tokio::test]
async fn test_set_macrotask_callback_set_next_tick_callback() { async fn test_set_macrotask_callback_set_next_tick_callback() {
#[op]
async fn op_async_sleep( async fn op_async_sleep(
_op_state: Rc<RefCell<OpState>>, _op_state: Rc<RefCell<OpState>>,
_: (), _: (),
@ -2553,7 +2520,7 @@ assertEquals(1, notify_return_value);
} }
let extension = Extension::builder() let extension = Extension::builder()
.ops(vec![("op_async_sleep", op_async(op_async_sleep))]) .ops(vec![op_async_sleep::decl()])
.build(); .build();
let mut runtime = JsRuntime::new(RuntimeOptions { let mut runtime = JsRuntime::new(RuntimeOptions {
@ -2617,25 +2584,23 @@ assertEquals(1, notify_return_value);
fn test_has_tick_scheduled() { fn test_has_tick_scheduled() {
use futures::task::ArcWake; use futures::task::ArcWake;
let macrotask = Arc::new(AtomicUsize::default()); static MACROTASK: AtomicUsize = AtomicUsize::new(0);
let macrotask_ = Arc::clone(&macrotask); static NEXT_TICK: AtomicUsize = AtomicUsize::new(0);
let next_tick = Arc::new(AtomicUsize::default()); #[op]
let next_tick_ = Arc::clone(&next_tick); fn op_macrotask(_: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
MACROTASK.fetch_add(1, Ordering::Relaxed);
let op_macrotask = move |_: &mut OpState, _: (), _: ()| {
macrotask_.fetch_add(1, Ordering::Relaxed);
Ok(()) Ok(())
}; }
let op_next_tick = move |_: &mut OpState, _: (), _: ()| { #[op]
next_tick_.fetch_add(1, Ordering::Relaxed); fn op_next_tick(_: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
NEXT_TICK.fetch_add(1, Ordering::Relaxed);
Ok(()) Ok(())
}; }
let extension = Extension::builder() let extension = Extension::builder()
.ops(vec![("op_macrotask", op_sync(op_macrotask))]) .ops(vec![op_macrotask::decl(), op_next_tick::decl()])
.ops(vec![("op_next_tick", op_sync(op_next_tick))])
.build(); .build();
let mut runtime = JsRuntime::new(RuntimeOptions { let mut runtime = JsRuntime::new(RuntimeOptions {
@ -2670,8 +2635,8 @@ assertEquals(1, notify_return_value);
let cx = &mut Context::from_waker(&waker); let cx = &mut Context::from_waker(&waker);
assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending)); assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
assert_eq!(1, macrotask.load(Ordering::Relaxed)); assert_eq!(1, MACROTASK.load(Ordering::Relaxed));
assert_eq!(1, next_tick.load(Ordering::Relaxed)); assert_eq!(1, NEXT_TICK.load(Ordering::Relaxed));
assert_eq!(awoken_times.swap(0, Ordering::Relaxed), 1); assert_eq!(awoken_times.swap(0, Ordering::Relaxed), 1);
assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending)); assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
assert_eq!(awoken_times.swap(0, Ordering::Relaxed), 1); assert_eq!(awoken_times.swap(0, Ordering::Relaxed), 1);
@ -2756,28 +2721,34 @@ assertEquals(1, notify_return_value);
#[tokio::test] #[tokio::test]
async fn test_set_promise_reject_callback() { async fn test_set_promise_reject_callback() {
let promise_reject = Arc::new(AtomicUsize::default()); static PROMISE_REJECT: AtomicUsize = AtomicUsize::new(0);
let promise_reject_ = Arc::clone(&promise_reject); static UNCAUGHT_EXCEPTION: AtomicUsize = AtomicUsize::new(0);
let uncaught_exception = Arc::new(AtomicUsize::default()); #[op]
let uncaught_exception_ = Arc::clone(&uncaught_exception); fn op_promise_reject(
_: &mut OpState,
let op_promise_reject = move |_: &mut OpState, _: (), _: ()| { _: (),
promise_reject_.fetch_add(1, Ordering::Relaxed); _: (),
) -> Result<(), AnyError> {
PROMISE_REJECT.fetch_add(1, Ordering::Relaxed);
Ok(()) Ok(())
}; }
let op_uncaught_exception = move |_: &mut OpState, _: (), _: ()| { #[op]
uncaught_exception_.fetch_add(1, Ordering::Relaxed); fn op_uncaught_exception(
_: &mut OpState,
_: (),
_: (),
) -> Result<(), AnyError> {
UNCAUGHT_EXCEPTION.fetch_add(1, Ordering::Relaxed);
Ok(()) Ok(())
}; }
let extension = Extension::builder() let extension = Extension::builder()
.ops(vec![("op_promise_reject", op_sync(op_promise_reject))]) .ops(vec![
.ops(vec![( op_promise_reject::decl(),
"op_uncaught_exception", op_uncaught_exception::decl(),
op_sync(op_uncaught_exception), ])
)])
.build(); .build();
let mut runtime = JsRuntime::new(RuntimeOptions { let mut runtime = JsRuntime::new(RuntimeOptions {
@ -2812,8 +2783,8 @@ assertEquals(1, notify_return_value);
.unwrap(); .unwrap();
runtime.run_event_loop(false).await.unwrap(); runtime.run_event_loop(false).await.unwrap();
assert_eq!(1, promise_reject.load(Ordering::Relaxed)); assert_eq!(1, PROMISE_REJECT.load(Ordering::Relaxed));
assert_eq!(1, uncaught_exception.load(Ordering::Relaxed)); assert_eq!(1, UNCAUGHT_EXCEPTION.load(Ordering::Relaxed));
runtime runtime
.execute_script( .execute_script(
@ -2840,7 +2811,7 @@ assertEquals(1, notify_return_value);
// printed to stderr. // printed to stderr.
runtime.run_event_loop(false).await.unwrap(); runtime.run_event_loop(false).await.unwrap();
assert_eq!(2, promise_reject.load(Ordering::Relaxed)); assert_eq!(2, PROMISE_REJECT.load(Ordering::Relaxed));
assert_eq!(2, uncaught_exception.load(Ordering::Relaxed)); assert_eq!(2, UNCAUGHT_EXCEPTION.load(Ordering::Relaxed));
} }
} }

View file

@ -8,8 +8,7 @@ pub use in_memory_broadcast_channel::InMemoryBroadcastChannelResource;
use async_trait::async_trait; use async_trait::async_trait;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
use deno_core::Resource; use deno_core::Resource;
@ -43,11 +42,15 @@ pub type Message = (String, Vec<u8>);
struct Unstable(bool); // --unstable struct Unstable(bool); // --unstable
pub fn op_broadcast_subscribe<BC: BroadcastChannel + 'static>( #[op]
pub fn op_broadcast_subscribe<BC>(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
_: (), _: (),
) -> Result<ResourceId, AnyError> { ) -> Result<ResourceId, AnyError>
where
BC: BroadcastChannel + 'static,
{
let unstable = state.borrow::<Unstable>().0; let unstable = state.borrow::<Unstable>().0;
if !unstable { if !unstable {
@ -62,31 +65,43 @@ pub fn op_broadcast_subscribe<BC: BroadcastChannel + 'static>(
Ok(state.resource_table.add(resource)) Ok(state.resource_table.add(resource))
} }
pub fn op_broadcast_unsubscribe<BC: BroadcastChannel + 'static>( #[op]
pub fn op_broadcast_unsubscribe<BC>(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
_buf: (), _buf: (),
) -> Result<(), AnyError> { ) -> Result<(), AnyError>
where
BC: BroadcastChannel + 'static,
{
let resource = state.resource_table.get::<BC::Resource>(rid)?; let resource = state.resource_table.get::<BC::Resource>(rid)?;
let bc = state.borrow::<BC>(); let bc = state.borrow::<BC>();
bc.unsubscribe(&resource) bc.unsubscribe(&resource)
} }
pub async fn op_broadcast_send<BC: BroadcastChannel + 'static>( #[op]
pub async fn op_broadcast_send<BC>(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
(rid, name): (ResourceId, String), (rid, name): (ResourceId, String),
buf: ZeroCopyBuf, buf: ZeroCopyBuf,
) -> Result<(), AnyError> { ) -> Result<(), AnyError>
where
BC: BroadcastChannel + 'static,
{
let resource = state.borrow().resource_table.get::<BC::Resource>(rid)?; let resource = state.borrow().resource_table.get::<BC::Resource>(rid)?;
let bc = state.borrow().borrow::<BC>().clone(); let bc = state.borrow().borrow::<BC>().clone();
bc.send(&resource, name, buf.to_vec()).await 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>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, 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 resource = state.borrow().resource_table.get::<BC::Resource>(rid)?;
let bc = state.borrow().borrow::<BC>().clone(); let bc = state.borrow().borrow::<BC>().clone();
bc.recv(&resource).await bc.recv(&resource).await
@ -102,16 +117,10 @@ pub fn init<BC: BroadcastChannel + 'static>(
"01_broadcast_channel.js", "01_broadcast_channel.js",
)) ))
.ops(vec![ .ops(vec![
( op_broadcast_subscribe::decl::<BC>(),
"op_broadcast_subscribe", op_broadcast_unsubscribe::decl::<BC>(),
op_sync(op_broadcast_subscribe::<BC>), op_broadcast_send::decl::<BC>(),
), op_broadcast_recv::decl::<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>)),
]) ])
.state(move |state| { .state(move |state| {
state.put(bc.clone()); state.put(bc.clone());

View file

@ -24,6 +24,7 @@ use ctr::Ctr;
use deno_core::error::custom_error; use deno_core::error::custom_error;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::OpState; use deno_core::OpState;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use rsa::pkcs1::FromRsaPrivateKey; use rsa::pkcs1::FromRsaPrivateKey;
@ -76,6 +77,7 @@ pub enum DecryptAlgorithm {
}, },
} }
#[op]
pub async fn op_crypto_decrypt( pub async fn op_crypto_decrypt(
_state: Rc<RefCell<OpState>>, _state: Rc<RefCell<OpState>>,
opts: DecryptOptions, opts: DecryptOptions,

View file

@ -16,6 +16,7 @@ use aes_gcm::AeadInPlace;
use aes_gcm::NewAead; use aes_gcm::NewAead;
use aes_gcm::Nonce; use aes_gcm::Nonce;
use ctr::Ctr; use ctr::Ctr;
use deno_core::op;
use block_modes::BlockMode; use block_modes::BlockMode;
use ctr::cipher::StreamCipher; use ctr::cipher::StreamCipher;
@ -79,6 +80,8 @@ pub enum EncryptAlgorithm {
key_length: usize, key_length: usize,
}, },
} }
#[op]
pub async fn op_crypto_encrypt( pub async fn op_crypto_encrypt(
_state: Rc<RefCell<OpState>>, _state: Rc<RefCell<OpState>>,
opts: EncryptOptions, opts: EncryptOptions,

View file

@ -1,5 +1,6 @@
use deno_core::error::custom_error; use deno_core::error::custom_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::OpState; use deno_core::OpState;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use rsa::pkcs1::UIntBytes; use rsa::pkcs1::UIntBytes;
@ -84,6 +85,7 @@ pub enum ExportKeyResult {
}, },
} }
#[op]
pub fn op_crypto_export_key( pub fn op_crypto_export_key(
_state: &mut OpState, _state: &mut OpState,
opts: ExportKeyOptions, opts: ExportKeyOptions,

View file

@ -3,6 +3,7 @@ use std::rc::Rc;
use crate::shared::*; use crate::shared::*;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::OpState; use deno_core::OpState;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use elliptic_curve::rand_core::OsRng; use elliptic_curve::rand_core::OsRng;
@ -41,6 +42,7 @@ pub enum GenerateKeyOptions {
}, },
} }
#[op]
pub async fn op_crypto_generate_key( pub async fn op_crypto_generate_key(
_state: Rc<RefCell<OpState>>, _state: Rc<RefCell<OpState>>,
opts: GenerateKeyOptions, opts: GenerateKeyOptions,

View file

@ -1,4 +1,5 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::OpState; use deno_core::OpState;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use elliptic_curve::pkcs8::der::Decodable as Pkcs8Decodable; use elliptic_curve::pkcs8::der::Decodable as Pkcs8Decodable;
@ -81,11 +82,13 @@ pub enum ImportKeyResult {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
Ec { raw_data: RawKeyData }, Ec { raw_data: RawKeyData },
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[allow(dead_code)]
Aes { raw_data: RawKeyData }, Aes { raw_data: RawKeyData },
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
Hmac { raw_data: RawKeyData }, Hmac { raw_data: RawKeyData },
} }
#[op]
pub fn op_crypto_import_key( pub fn op_crypto_import_key(
_state: &mut OpState, _state: &mut OpState,
opts: ImportKeyOptions, opts: ImportKeyOptions,

View file

@ -9,8 +9,8 @@ use deno_core::error::not_supported;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
@ -88,22 +88,19 @@ pub fn init(maybe_seed: Option<u64>) -> Extension {
"01_webidl.js", "01_webidl.js",
)) ))
.ops(vec![ .ops(vec![
( op_crypto_get_random_values::decl(),
"op_crypto_get_random_values", op_crypto_generate_key::decl(),
op_sync(op_crypto_get_random_values), op_crypto_sign_key::decl(),
), op_crypto_verify_key::decl(),
("op_crypto_generate_key", op_async(op_crypto_generate_key)), op_crypto_derive_bits::decl(),
("op_crypto_sign_key", op_async(op_crypto_sign_key)), op_crypto_import_key::decl(),
("op_crypto_verify_key", op_async(op_crypto_verify_key)), op_crypto_export_key::decl(),
("op_crypto_derive_bits", op_async(op_crypto_derive_bits)), op_crypto_encrypt::decl(),
("op_crypto_import_key", op_sync(op_crypto_import_key)), op_crypto_decrypt::decl(),
("op_crypto_export_key", op_sync(op_crypto_export_key)), op_crypto_subtle_digest::decl(),
("op_crypto_encrypt", op_async(op_crypto_encrypt)), op_crypto_random_uuid::decl(),
("op_crypto_decrypt", op_async(op_crypto_decrypt)), op_crypto_wrap_key::decl(),
("op_crypto_subtle_digest", op_async(op_crypto_subtle_digest)), op_crypto_unwrap_key::decl(),
("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)),
]) ])
.state(move |state| { .state(move |state| {
if let Some(seed) = maybe_seed { if let Some(seed) = maybe_seed {
@ -114,6 +111,7 @@ pub fn init(maybe_seed: Option<u64>) -> Extension {
.build() .build()
} }
#[op]
pub fn op_crypto_get_random_values( pub fn op_crypto_get_random_values(
state: &mut OpState, state: &mut OpState,
mut zero_copy: ZeroCopyBuf, mut zero_copy: ZeroCopyBuf,
@ -170,6 +168,7 @@ pub struct SignArg {
named_curve: Option<CryptoNamedCurve>, named_curve: Option<CryptoNamedCurve>,
} }
#[op]
pub async fn op_crypto_sign_key( pub async fn op_crypto_sign_key(
_state: Rc<RefCell<OpState>>, _state: Rc<RefCell<OpState>>,
args: SignArg, args: SignArg,
@ -324,6 +323,7 @@ pub struct VerifyArg {
named_curve: Option<CryptoNamedCurve>, named_curve: Option<CryptoNamedCurve>,
} }
#[op]
pub async fn op_crypto_verify_key( pub async fn op_crypto_verify_key(
_state: Rc<RefCell<OpState>>, _state: Rc<RefCell<OpState>>,
args: VerifyArg, args: VerifyArg,
@ -484,6 +484,7 @@ pub struct DeriveKeyArg {
info: Option<ZeroCopyBuf>, info: Option<ZeroCopyBuf>,
} }
#[op]
pub async fn op_crypto_derive_bits( pub async fn op_crypto_derive_bits(
_state: Rc<RefCell<OpState>>, _state: Rc<RefCell<OpState>>,
args: DeriveKeyArg, args: DeriveKeyArg,
@ -789,6 +790,7 @@ impl<'a> TryFrom<rsa::pkcs8::der::asn1::Any<'a>>
} }
} }
#[op]
pub fn op_crypto_random_uuid( pub fn op_crypto_random_uuid(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -808,6 +810,7 @@ pub fn op_crypto_random_uuid(
Ok(uuid.to_string()) Ok(uuid.to_string())
} }
#[op]
pub async fn op_crypto_subtle_digest( pub async fn op_crypto_subtle_digest(
_state: Rc<RefCell<OpState>>, _state: Rc<RefCell<OpState>>,
algorithm: CryptoHash, algorithm: CryptoHash,
@ -831,6 +834,7 @@ pub struct WrapUnwrapKeyArg {
algorithm: Algorithm, algorithm: Algorithm,
} }
#[op]
pub fn op_crypto_wrap_key( pub fn op_crypto_wrap_key(
_state: &mut OpState, _state: &mut OpState,
args: WrapUnwrapKeyArg, args: WrapUnwrapKeyArg,
@ -860,6 +864,7 @@ pub fn op_crypto_wrap_key(
} }
} }
#[op]
pub fn op_crypto_unwrap_key( pub fn op_crypto_unwrap_key(
_state: &mut OpState, _state: &mut OpState,
args: WrapUnwrapKeyArg, args: WrapUnwrapKeyArg,

View file

@ -9,8 +9,8 @@ use deno_core::futures::Future;
use deno_core::futures::Stream; use deno_core::futures::Stream;
use deno_core::futures::StreamExt; use deno_core::futures::StreamExt;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::AsyncRefCell; use deno_core::AsyncRefCell;
use deno_core::AsyncResult; use deno_core::AsyncResult;
@ -100,12 +100,9 @@ where
"26_fetch.js", "26_fetch.js",
)) ))
.ops(vec![ .ops(vec![
("op_fetch", op_sync(op_fetch::<FP>)), op_fetch::decl::<FP>(),
("op_fetch_send", op_async(op_fetch_send)), op_fetch_send::decl(),
( op_fetch_custom_client::decl::<FP>(),
"op_fetch_custom_client",
op_sync(op_fetch_custom_client::<FP>),
),
]) ])
.state(move |state| { .state(move |state| {
state.put::<Options>(options.clone()); state.put::<Options>(options.clone());
@ -192,6 +189,7 @@ pub struct FetchReturn {
cancel_handle_rid: Option<ResourceId>, cancel_handle_rid: Option<ResourceId>,
} }
#[op]
pub fn op_fetch<FP>( pub fn op_fetch<FP>(
state: &mut OpState, state: &mut OpState,
args: FetchArgs, args: FetchArgs,
@ -367,6 +365,7 @@ pub struct FetchResponse {
response_rid: ResourceId, response_rid: ResourceId,
} }
#[op]
pub async fn op_fetch_send( pub async fn op_fetch_send(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -525,6 +524,7 @@ pub struct CreateHttpClientOptions {
private_key: Option<String>, private_key: Option<String>,
} }
#[op]
pub fn op_fetch_custom_client<FP>( pub fn op_fetch_custom_client<FP>(
state: &mut OpState, state: &mut OpState,
args: CreateHttpClientOptions, args: CreateHttpClientOptions,

View file

@ -6,8 +6,8 @@ use deno_core::error::range_error;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::serde_json; use deno_core::serde_json;
use deno_core::serde_json::json; use deno_core::serde_json::json;
use deno_core::serde_json::Value; use deno_core::serde_json::Value;
@ -140,27 +140,24 @@ pub fn init<P: FfiPermissions + 'static>(unstable: bool) -> Extension {
"00_ffi.js", "00_ffi.js",
)) ))
.ops(vec![ .ops(vec![
("op_ffi_load", op_sync(op_ffi_load::<P>)), op_ffi_load::decl::<P>(),
("op_ffi_get_static", op_sync(op_ffi_get_static)), op_ffi_get_static::decl(),
("op_ffi_call", op_sync(op_ffi_call)), op_ffi_call::decl(),
("op_ffi_call_nonblocking", op_async(op_ffi_call_nonblocking)), op_ffi_call_nonblocking::decl(),
("op_ffi_call_ptr", op_sync(op_ffi_call_ptr)), op_ffi_call_ptr::decl(),
( op_ffi_call_ptr_nonblocking::decl(),
"op_ffi_call_ptr_nonblocking", op_ffi_ptr_of::decl::<P>(),
op_async(op_ffi_call_ptr_nonblocking), op_ffi_buf_copy_into::decl::<P>(),
), op_ffi_cstr_read::decl::<P>(),
("op_ffi_ptr_of", op_sync(op_ffi_ptr_of::<P>)), op_ffi_read_u8::decl::<P>(),
("op_ffi_buf_copy_into", op_sync(op_ffi_buf_copy_into::<P>)), op_ffi_read_i8::decl::<P>(),
("op_ffi_cstr_read", op_sync(op_ffi_cstr_read::<P>)), op_ffi_read_u16::decl::<P>(),
("op_ffi_read_u8", op_sync(op_ffi_read_u8::<P>)), op_ffi_read_i16::decl::<P>(),
("op_ffi_read_i8", op_sync(op_ffi_read_i8::<P>)), op_ffi_read_u32::decl::<P>(),
("op_ffi_read_u16", op_sync(op_ffi_read_u16::<P>)), op_ffi_read_i32::decl::<P>(),
("op_ffi_read_i16", op_sync(op_ffi_read_i16::<P>)), op_ffi_read_u64::decl::<P>(),
("op_ffi_read_u32", op_sync(op_ffi_read_u32::<P>)), op_ffi_read_f32::decl::<P>(),
("op_ffi_read_i32", op_sync(op_ffi_read_i32::<P>)), op_ffi_read_f64::decl::<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>)),
]) ])
.state(move |state| { .state(move |state| {
// Stolen from deno_webgpu, is there a better option? // 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>( fn op_ffi_load<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
args: FfiLoadArgs, args: FfiLoadArgs,
@ -650,6 +648,7 @@ fn ffi_call(args: FfiCallArgs, symbol: &Symbol) -> Result<Value, AnyError> {
}) })
} }
#[op]
fn op_ffi_call_ptr( fn op_ffi_call_ptr(
_state: &mut deno_core::OpState, _state: &mut deno_core::OpState,
args: FfiCallPtrArgs, args: FfiCallPtrArgs,
@ -659,6 +658,7 @@ fn op_ffi_call_ptr(
ffi_call(args.into(), &symbol) ffi_call(args.into(), &symbol)
} }
#[op]
async fn op_ffi_call_ptr_nonblocking( async fn op_ffi_call_ptr_nonblocking(
_state: Rc<RefCell<deno_core::OpState>>, _state: Rc<RefCell<deno_core::OpState>>,
args: FfiCallPtrArgs, args: FfiCallPtrArgs,
@ -678,6 +678,7 @@ struct FfiGetArgs {
r#type: NativeType, r#type: NativeType,
} }
#[op]
fn op_ffi_get_static( fn op_ffi_get_static(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
args: FfiGetArgs, args: FfiGetArgs,
@ -735,6 +736,7 @@ fn op_ffi_get_static(
}) })
} }
#[op]
fn op_ffi_call( fn op_ffi_call(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
args: FfiCallArgs, args: FfiCallArgs,
@ -753,6 +755,7 @@ fn op_ffi_call(
} }
/// A non-blocking FFI call. /// A non-blocking FFI call.
#[op]
async fn op_ffi_call_nonblocking( async fn op_ffi_call_nonblocking(
state: Rc<RefCell<deno_core::OpState>>, state: Rc<RefCell<deno_core::OpState>>,
args: FfiCallArgs, args: FfiCallArgs,
@ -773,6 +776,7 @@ async fn op_ffi_call_nonblocking(
.unwrap() .unwrap()
} }
#[op]
fn op_ffi_ptr_of<FP>( fn op_ffi_ptr_of<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
buf: ZeroCopyBuf, buf: ZeroCopyBuf,
@ -787,6 +791,7 @@ where
Ok(U32x2::from(buf.as_ptr() as u64)) Ok(U32x2::from(buf.as_ptr() as u64))
} }
#[op]
fn op_ffi_buf_copy_into<FP>( fn op_ffi_buf_copy_into<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
(src, mut dst, len): (U32x2, ZeroCopyBuf, usize), (src, mut dst, len): (U32x2, ZeroCopyBuf, usize),
@ -809,6 +814,7 @@ where
} }
} }
#[op]
fn op_ffi_cstr_read<FP>( fn op_ffi_cstr_read<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,
@ -824,6 +830,7 @@ where
Ok(unsafe { CStr::from_ptr(ptr) }.to_str()?.to_string()) Ok(unsafe { CStr::from_ptr(ptr) }.to_str()?.to_string())
} }
#[op]
fn op_ffi_read_u8<FP>( fn op_ffi_read_u8<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,
@ -838,6 +845,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const u8) }) Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const u8) })
} }
#[op]
fn op_ffi_read_i8<FP>( fn op_ffi_read_i8<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,
@ -852,6 +860,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const i8) }) Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const i8) })
} }
#[op]
fn op_ffi_read_u16<FP>( fn op_ffi_read_u16<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,
@ -866,6 +875,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const u16) }) Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const u16) })
} }
#[op]
fn op_ffi_read_i16<FP>( fn op_ffi_read_i16<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,
@ -880,6 +890,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const i16) }) Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const i16) })
} }
#[op]
fn op_ffi_read_u32<FP>( fn op_ffi_read_u32<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,
@ -894,6 +905,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const u32) }) Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const u32) })
} }
#[op]
fn op_ffi_read_i32<FP>( fn op_ffi_read_i32<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,
@ -908,6 +920,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const i32) }) Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const i32) })
} }
#[op]
fn op_ffi_read_u64<FP>( fn op_ffi_read_u64<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,
@ -924,6 +937,7 @@ where
})) }))
} }
#[op]
fn op_ffi_read_f32<FP>( fn op_ffi_read_f32<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,
@ -938,6 +952,7 @@ where
Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const f32) }) Ok(unsafe { ptr::read_unaligned(u64::from(ptr) as *const f32) })
} }
#[op]
fn op_ffi_read_f64<FP>( fn op_ffi_read_f64<FP>(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
ptr: U32x2, ptr: U32x2,

View file

@ -20,8 +20,8 @@ use deno_core::futures::FutureExt;
use deno_core::futures::StreamExt; use deno_core::futures::StreamExt;
use deno_core::futures::TryFutureExt; use deno_core::futures::TryFutureExt;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::AsyncRefCell; use deno_core::AsyncRefCell;
use deno_core::ByteString; use deno_core::ByteString;
use deno_core::CancelFuture; use deno_core::CancelFuture;
@ -72,19 +72,13 @@ pub fn init() -> Extension {
"01_http.js", "01_http.js",
)) ))
.ops(vec![ .ops(vec![
("op_http_accept", op_async(op_http_accept)), op_http_accept::decl(),
("op_http_read", op_async(op_http_read)), op_http_read::decl(),
("op_http_write_headers", op_async(op_http_write_headers)), op_http_write_headers::decl(),
("op_http_write", op_async(op_http_write)), op_http_write::decl(),
("op_http_shutdown", op_async(op_http_shutdown)), op_http_shutdown::decl(),
( op_http_websocket_accept_header::decl(),
"op_http_websocket_accept_header", op_http_upgrade_websocket::decl(),
op_sync(op_http_websocket_accept_header),
),
(
"op_http_upgrade_websocket",
op_async(op_http_upgrade_websocket),
),
]) ])
.build() .build()
} }
@ -371,6 +365,7 @@ struct NextRequestResponse(
String, String,
); );
#[op]
async fn op_http_accept( async fn op_http_accept(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -501,6 +496,7 @@ struct RespondArgs(
Vec<(ByteString, ByteString)>, Vec<(ByteString, ByteString)>,
); );
#[op]
async fn op_http_write_headers( async fn op_http_write_headers(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: RespondArgs, args: RespondArgs,
@ -697,6 +693,7 @@ async fn op_http_write_headers(
} }
} }
#[op]
async fn op_http_write( async fn op_http_write(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, 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 /// 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 /// remove the HTTP stream resource from the resource table; it still has to be
/// closed with `Deno.core.close()`. /// closed with `Deno.core.close()`.
#[op]
async fn op_http_shutdown( async fn op_http_shutdown(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -751,6 +749,7 @@ async fn op_http_shutdown(
Ok(()) Ok(())
} }
#[op]
async fn op_http_read( async fn op_http_read(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -799,6 +798,7 @@ async fn op_http_read(
fut.try_or_cancel(cancel_handle).await fut.try_or_cancel(cancel_handle).await
} }
#[op]
fn op_http_websocket_accept_header( fn op_http_websocket_accept_header(
_: &mut OpState, _: &mut OpState,
key: String, key: String,
@ -811,6 +811,7 @@ fn op_http_websocket_accept_header(
Ok(base64::encode(digest)) Ok(base64::encode(digest))
} }
#[op]
async fn op_http_upgrade_websocket( async fn op_http_upgrade_websocket(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,

View file

@ -76,9 +76,6 @@ pub fn init<P: NetPermissions + 'static>(
unstable: bool, unstable: bool,
unsafely_ignore_certificate_errors: Option<Vec<String>>, unsafely_ignore_certificate_errors: Option<Vec<String>>,
) -> Extension { ) -> Extension {
let mut ops_to_register = vec![];
ops_to_register.extend(ops::init::<P>());
ops_to_register.extend(ops_tls::init::<P>());
Extension::builder() Extension::builder()
.js(include_js_files!( .js(include_js_files!(
prefix "deno:ext/net", prefix "deno:ext/net",
@ -86,7 +83,7 @@ pub fn init<P: NetPermissions + 'static>(
"02_tls.js", "02_tls.js",
"04_net_unstable.js", "04_net_unstable.js",
)) ))
.ops(ops_to_register) .ops([&ops::init::<P>()[..], &ops_tls::init::<P>()[..]].concat())
.state(move |state| { .state(move |state| {
state.put(DefaultTlsOptions { state.put(DefaultTlsOptions {
root_cert_store: root_cert_store.clone(), root_cert_store: root_cert_store.clone(),

View file

@ -9,8 +9,8 @@ use deno_core::error::custom_error;
use deno_core::error::generic_error; use deno_core::error::generic_error;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::AsyncRefCell; use deno_core::AsyncRefCell;
use deno_core::ByteString; use deno_core::ByteString;
use deno_core::CancelHandle; use deno_core::CancelHandle;
@ -52,14 +52,14 @@ use std::path::Path;
pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> { pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
vec![ vec![
("op_net_accept", op_async(op_net_accept)), op_net_accept::decl(),
("op_net_connect", op_async(op_net_connect::<P>)), op_net_connect::decl::<P>(),
("op_net_listen", op_sync(op_net_listen::<P>)), op_net_listen::decl::<P>(),
("op_dgram_recv", op_async(op_dgram_recv)), op_dgram_recv::decl(),
("op_dgram_send", op_async(op_dgram_send::<P>)), op_dgram_send::decl::<P>(),
("op_dns_resolve", op_async(op_dns_resolve::<P>)), op_dns_resolve::decl::<P>(),
("op_set_nodelay", op_sync(op_set_nodelay::<P>)), op_set_nodelay::decl::<P>(),
("op_set_keepalive", op_sync(op_set_keepalive::<P>)), op_set_keepalive::decl::<P>(),
] ]
} }
@ -158,6 +158,7 @@ async fn accept_tcp(
}) })
} }
#[op]
async fn op_net_accept( async fn op_net_accept(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: AcceptArgs, args: AcceptArgs,
@ -210,6 +211,7 @@ async fn receive_udp(
}) })
} }
#[op]
async fn op_dgram_recv( async fn op_dgram_recv(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: ReceiveArgs, args: ReceiveArgs,
@ -231,6 +233,7 @@ struct SendArgs {
transport_args: ArgsEnum, transport_args: ArgsEnum,
} }
#[op]
async fn op_dgram_send<NP>( async fn op_dgram_send<NP>(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: SendArgs, args: SendArgs,
@ -299,6 +302,7 @@ pub struct ConnectArgs {
transport_args: ArgsEnum, transport_args: ArgsEnum,
} }
#[op]
pub async fn op_net_connect<NP>( pub async fn op_net_connect<NP>(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: ConnectArgs, args: ConnectArgs,
@ -474,6 +478,7 @@ fn listen_udp(
Ok((rid, local_addr)) Ok((rid, local_addr))
} }
#[op]
fn op_net_listen<NP>( fn op_net_listen<NP>(
state: &mut OpState, state: &mut OpState,
args: ListenArgs, args: ListenArgs,
@ -613,6 +618,7 @@ pub struct NameServer {
port: u16, port: u16,
} }
#[op]
pub async fn op_dns_resolve<NP>( pub async fn op_dns_resolve<NP>(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: ResolveAddrArgs, args: ResolveAddrArgs,
@ -681,6 +687,7 @@ where
Ok(results) Ok(results)
} }
#[op]
pub fn op_set_nodelay<NP>( pub fn op_set_nodelay<NP>(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -692,6 +699,7 @@ pub fn op_set_nodelay<NP>(
resource.set_nodelay(nodelay) resource.set_nodelay(nodelay)
} }
#[op]
pub fn op_set_keepalive<NP>( pub fn op_set_keepalive<NP>(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -877,7 +885,7 @@ mod tests {
#[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn tcp_set_no_delay() { async fn tcp_set_no_delay() {
let set_nodelay = Box::new(|state: &mut OpState, rid| { 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| { let test_fn = Box::new(|socket: SockRef| {
assert!(socket.nodelay().unwrap()); assert!(socket.nodelay().unwrap());
@ -889,7 +897,7 @@ mod tests {
#[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn tcp_set_keepalive() { async fn tcp_set_keepalive() {
let set_keepalive = Box::new(|state: &mut OpState, rid| { 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| { let test_fn = Box::new(|socket: SockRef| {
assert!(!socket.nodelay().unwrap()); assert!(!socket.nodelay().unwrap());
@ -934,7 +942,7 @@ mod tests {
}; };
let connect_fut = 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 conn = connect_fut.await.unwrap();
let rid = conn.rid; let rid = conn.rid;

View file

@ -25,8 +25,8 @@ use deno_core::futures::task::Poll;
use deno_core::futures::task::RawWaker; use deno_core::futures::task::RawWaker;
use deno_core::futures::task::RawWakerVTable; use deno_core::futures::task::RawWakerVTable;
use deno_core::futures::task::Waker; use deno_core::futures::task::Waker;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::parking_lot::Mutex; use deno_core::parking_lot::Mutex;
use deno_core::AsyncRefCell; use deno_core::AsyncRefCell;
use deno_core::AsyncResult; use deno_core::AsyncResult;
@ -644,11 +644,11 @@ impl Write for ImplementWriteTrait<'_, TcpStream> {
pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> { pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
vec![ vec![
("op_tls_start", op_async(op_tls_start::<P>)), op_tls_start::decl::<P>(),
("op_tls_connect", op_async(op_tls_connect::<P>)), op_tls_connect::decl::<P>(),
("op_tls_listen", op_sync(op_tls_listen::<P>)), op_tls_listen::decl::<P>(),
("op_tls_accept", op_async(op_tls_accept)), op_tls_accept::decl(),
("op_tls_handshake", op_async(op_tls_handshake)), op_tls_handshake::decl(),
] ]
} }
@ -765,6 +765,7 @@ pub struct StartTlsArgs {
alpn_protocols: Option<Vec<String>>, alpn_protocols: Option<Vec<String>>,
} }
#[op]
pub async fn op_tls_start<NP>( pub async fn op_tls_start<NP>(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: StartTlsArgs, args: StartTlsArgs,
@ -857,6 +858,7 @@ where
}) })
} }
#[op]
pub async fn op_tls_connect<NP>( pub async fn op_tls_connect<NP>(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: ConnectTlsArgs, args: ConnectTlsArgs,
@ -1016,6 +1018,7 @@ pub struct ListenTlsArgs {
alpn_protocols: Option<Vec<String>>, alpn_protocols: Option<Vec<String>>,
} }
#[op]
pub fn op_tls_listen<NP>( pub fn op_tls_listen<NP>(
state: &mut OpState, state: &mut OpState,
args: ListenTlsArgs, args: ListenTlsArgs,
@ -1112,6 +1115,7 @@ where
}) })
} }
#[op]
pub async fn op_tls_accept( pub async fn op_tls_accept(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -1163,6 +1167,7 @@ pub async fn op_tls_accept(
}) })
} }
#[op]
pub async fn op_tls_handshake( pub async fn op_tls_handshake(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,

View file

@ -7,7 +7,7 @@ use deno_core::error::type_error;
use deno_core::error::uri_error; use deno_core::error::uri_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::include_js_files; 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::form_urlencoded;
use deno_core::url::quirks; use deno_core::url::quirks;
use deno_core::url::Url; use deno_core::url::Url;
@ -26,21 +26,12 @@ pub fn init() -> Extension {
"01_urlpattern.js", "01_urlpattern.js",
)) ))
.ops(vec![ .ops(vec![
("op_url_parse", op_sync(op_url_parse)), op_url_parse::decl(),
("op_url_reparse", op_sync(op_url_reparse)), op_url_reparse::decl(),
( op_url_parse_search_params::decl(),
"op_url_parse_search_params", op_url_stringify_search_params::decl(),
op_sync(op_url_parse_search_params), op_urlpattern_parse::decl(),
), op_urlpattern_process_match_input::decl(),
(
"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),
),
]) ])
.build() .build()
} }
@ -65,6 +56,7 @@ type UrlParts = String;
/// Parse `UrlParseArgs::href` with an optional `UrlParseArgs::base_href`, or an /// Parse `UrlParseArgs::href` with an optional `UrlParseArgs::base_href`, or an
/// optional part to "set" after parsing. Return `UrlParts`. /// optional part to "set" after parsing. Return `UrlParts`.
#[op]
pub fn op_url_parse( pub fn op_url_parse(
_state: &mut deno_core::OpState, _state: &mut deno_core::OpState,
href: String, href: String,
@ -98,6 +90,7 @@ pub enum UrlSetter {
Username = 9, Username = 9,
} }
#[op]
pub fn op_url_reparse( pub fn op_url_reparse(
_state: &mut deno_core::OpState, _state: &mut deno_core::OpState,
href: String, href: String,
@ -167,6 +160,7 @@ fn url_result(
) )
} }
#[op]
pub fn op_url_parse_search_params( pub fn op_url_parse_search_params(
_state: &mut deno_core::OpState, _state: &mut deno_core::OpState,
args: Option<String>, args: Option<String>,
@ -186,6 +180,7 @@ pub fn op_url_parse_search_params(
Ok(params) Ok(params)
} }
#[op]
pub fn op_url_stringify_search_params( pub fn op_url_stringify_search_params(
_state: &mut deno_core::OpState, _state: &mut deno_core::OpState,
args: Vec<(String, String)>, args: Vec<(String, String)>,

View file

@ -1,11 +1,13 @@
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use urlpattern::quirks; use urlpattern::quirks;
use urlpattern::quirks::MatchInput; use urlpattern::quirks::MatchInput;
use urlpattern::quirks::StringOrInit; use urlpattern::quirks::StringOrInit;
use urlpattern::quirks::UrlPattern; use urlpattern::quirks::UrlPattern;
#[op]
pub fn op_urlpattern_parse( pub fn op_urlpattern_parse(
_state: &mut deno_core::OpState, _state: &mut deno_core::OpState,
input: StringOrInit, input: StringOrInit,
@ -23,6 +25,7 @@ pub fn op_urlpattern_parse(
Ok(pattern) Ok(pattern)
} }
#[op]
pub fn op_urlpattern_process_match_input( pub fn op_urlpattern_process_match_input(
_state: &mut deno_core::OpState, _state: &mut deno_core::OpState,
input: StringOrInit, input: StringOrInit,

View file

@ -1,5 +1,7 @@
use async_trait::async_trait; use async_trait::async_trait;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::op;
use deno_core::parking_lot::Mutex; use deno_core::parking_lot::Mutex;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
@ -157,6 +159,7 @@ impl BlobPart for SlicedBlobPart {
} }
} }
#[op]
pub fn op_blob_create_part( pub fn op_blob_create_part(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
data: ZeroCopyBuf, data: ZeroCopyBuf,
@ -175,6 +178,7 @@ pub struct SliceOptions {
len: usize, len: usize,
} }
#[op]
pub fn op_blob_slice_part( pub fn op_blob_slice_part(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
id: Uuid, id: Uuid,
@ -200,6 +204,7 @@ pub fn op_blob_slice_part(
Ok(id) Ok(id)
} }
#[op]
pub async fn op_blob_read_part( pub async fn op_blob_read_part(
state: Rc<RefCell<deno_core::OpState>>, state: Rc<RefCell<deno_core::OpState>>,
id: Uuid, id: Uuid,
@ -215,6 +220,7 @@ pub async fn op_blob_read_part(
Ok(ZeroCopyBuf::from(buf.to_vec())) Ok(ZeroCopyBuf::from(buf.to_vec()))
} }
#[op]
pub fn op_blob_remove_part( pub fn op_blob_remove_part(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
id: Uuid, id: Uuid,
@ -225,6 +231,7 @@ pub fn op_blob_remove_part(
Ok(()) Ok(())
} }
#[op]
pub fn op_blob_create_object_url( pub fn op_blob_create_object_url(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
media_type: String, media_type: String,
@ -250,6 +257,7 @@ pub fn op_blob_create_object_url(
Ok(url.to_string()) Ok(url.to_string())
} }
#[op]
pub fn op_blob_revoke_object_url( pub fn op_blob_revoke_object_url(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
url: String, url: String,
@ -273,6 +281,7 @@ pub struct ReturnBlobPart {
pub size: usize, pub size: usize,
} }
#[op]
pub fn op_blob_from_object_url( pub fn op_blob_from_object_url(
state: &mut deno_core::OpState, state: &mut deno_core::OpState,
url: String, url: String,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::OpState; use deno_core::OpState;
use deno_core::Resource; use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
@ -32,6 +33,7 @@ impl Resource for CompressionResource {
} }
} }
#[op]
pub fn op_compression_new( pub fn op_compression_new(
state: &mut OpState, state: &mut OpState,
format: String, format: String,
@ -53,6 +55,7 @@ pub fn op_compression_new(
Ok(state.resource_table.add(resource)) Ok(state.resource_table.add(resource))
} }
#[op]
pub fn op_compression_write( pub fn op_compression_write(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -86,6 +89,7 @@ pub fn op_compression_write(
Ok(out.into()) Ok(out.into())
} }
#[op]
pub fn op_compression_finish( pub fn op_compression_finish(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,

View file

@ -9,8 +9,7 @@ use deno_core::error::range_error;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::ByteString; use deno_core::ByteString;
use deno_core::Extension; use deno_core::Extension;
@ -83,58 +82,31 @@ pub fn init<P: TimersPermission + 'static>(
"15_performance.js", "15_performance.js",
)) ))
.ops(vec![ .ops(vec![
("op_base64_decode", op_sync(op_base64_decode)), op_base64_decode::decl(),
("op_base64_encode", op_sync(op_base64_encode)), op_base64_encode::decl(),
("op_base64_atob", op_sync(op_base64_atob)), op_base64_atob::decl(),
("op_base64_btoa", op_sync(op_base64_btoa)), op_base64_btoa::decl(),
( op_encoding_normalize_label::decl(),
"op_encoding_normalize_label", op_encoding_new_decoder::decl(),
op_sync(op_encoding_normalize_label), op_encoding_decode::decl(),
), op_encoding_encode_into::decl(),
("op_encoding_new_decoder", op_sync(op_encoding_new_decoder)), op_blob_create_part::decl(),
("op_encoding_decode", op_sync(op_encoding_decode)), op_blob_slice_part::decl(),
("op_encoding_encode_into", op_sync(op_encoding_encode_into)), op_blob_read_part::decl(),
("op_blob_create_part", op_sync(op_blob_create_part)), op_blob_remove_part::decl(),
("op_blob_slice_part", op_sync(op_blob_slice_part)), op_blob_create_object_url::decl(),
("op_blob_read_part", op_async(op_blob_read_part)), op_blob_revoke_object_url::decl(),
("op_blob_remove_part", op_sync(op_blob_remove_part)), op_blob_from_object_url::decl(),
( op_message_port_create_entangled::decl(),
"op_blob_create_object_url", op_message_port_post_message::decl(),
op_sync(op_blob_create_object_url), op_message_port_recv_message::decl(),
), compression::op_compression_new::decl(),
( compression::op_compression_write::decl(),
"op_blob_revoke_object_url", compression::op_compression_finish::decl(),
op_sync(op_blob_revoke_object_url), op_now::decl::<P>(),
), op_timer_handle::decl(),
("op_blob_from_object_url", op_sync(op_blob_from_object_url)), op_sleep::decl(),
( op_sleep_sync::decl::<P>(),
"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>)),
]) ])
.state(move |state| { .state(move |state| {
state.put(blob_store.clone()); state.put(blob_store.clone());
@ -147,6 +119,7 @@ pub fn init<P: TimersPermission + 'static>(
.build() .build()
} }
#[op]
fn op_base64_decode( fn op_base64_decode(
_: &mut OpState, _: &mut OpState,
input: String, input: String,
@ -157,6 +130,7 @@ fn op_base64_decode(
Ok(b64_decode(&input)?.into()) Ok(b64_decode(&input)?.into())
} }
#[op]
fn op_base64_atob( fn op_base64_atob(
_: &mut OpState, _: &mut OpState,
s: ByteString, s: ByteString,
@ -210,6 +184,7 @@ fn b64_decode(input: &[u8]) -> Result<Vec<u8>, AnyError> {
Ok(out) Ok(out)
} }
#[op]
fn op_base64_encode( fn op_base64_encode(
_: &mut OpState, _: &mut OpState,
s: ZeroCopyBuf, s: ZeroCopyBuf,
@ -218,6 +193,7 @@ fn op_base64_encode(
Ok(b64_encode(&s)) Ok(b64_encode(&s))
} }
#[op]
fn op_base64_btoa( fn op_base64_btoa(
_: &mut OpState, _: &mut OpState,
s: ByteString, s: ByteString,
@ -240,6 +216,7 @@ struct DecoderOptions {
fatal: bool, fatal: bool,
} }
#[op]
fn op_encoding_normalize_label( fn op_encoding_normalize_label(
_state: &mut OpState, _state: &mut OpState,
label: String, label: String,
@ -255,6 +232,7 @@ fn op_encoding_normalize_label(
Ok(encoding.name().to_lowercase()) Ok(encoding.name().to_lowercase())
} }
#[op]
fn op_encoding_new_decoder( fn op_encoding_new_decoder(
state: &mut OpState, state: &mut OpState,
options: DecoderOptions, options: DecoderOptions,
@ -294,6 +272,7 @@ struct DecodeOptions {
stream: bool, stream: bool,
} }
#[op]
fn op_encoding_decode( fn op_encoding_decode(
state: &mut OpState, state: &mut OpState,
data: ZeroCopyBuf, data: ZeroCopyBuf,
@ -357,6 +336,7 @@ struct EncodeIntoResult {
written: usize, written: usize,
} }
#[op]
fn op_encoding_encode_into( fn op_encoding_encode_into(
_state: &mut OpState, _state: &mut OpState,
input: String, input: String,

View file

@ -4,6 +4,8 @@ use std::rc::Rc;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use deno_core::{CancelFuture, Resource}; use deno_core::{CancelFuture, Resource};
use deno_core::{CancelHandle, OpState}; use deno_core::{CancelHandle, OpState};
@ -104,6 +106,7 @@ impl Resource for MessagePortResource {
} }
} }
#[op]
pub fn op_message_port_create_entangled( pub fn op_message_port_create_entangled(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -185,6 +188,7 @@ pub struct JsMessageData {
transferables: Vec<JsTransferable>, transferables: Vec<JsTransferable>,
} }
#[op]
pub fn op_message_port_post_message( pub fn op_message_port_post_message(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -203,6 +207,7 @@ pub fn op_message_port_post_message(
resource.port.send(state, data) resource.port.send(state, data)
} }
#[op]
pub async fn op_message_port_recv_message( pub async fn op_message_port_recv_message(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,

View file

@ -3,6 +3,8 @@
//! This module helps deno implement timers and performance APIs. //! This module helps deno implement timers and performance APIs.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::CancelFuture; use deno_core::CancelFuture;
use deno_core::CancelHandle; use deno_core::CancelHandle;
use deno_core::OpState; use deno_core::OpState;
@ -25,6 +27,7 @@ pub type StartTime = Instant;
// since the start time of the deno runtime. // since the start time of the deno runtime.
// If the High precision flag is not set, the // If the High precision flag is not set, the
// nanoseconds are rounded on 2ms. // nanoseconds are rounded on 2ms.
#[op]
pub fn op_now<TP>( pub fn op_now<TP>(
state: &mut OpState, state: &mut OpState,
_argument: (), _argument: (),
@ -64,6 +67,7 @@ impl Resource for TimerHandle {
/// Creates a [`TimerHandle`] resource that can be used to cancel invocations of /// Creates a [`TimerHandle`] resource that can be used to cancel invocations of
/// [`op_sleep`]. /// [`op_sleep`].
#[op]
pub fn op_timer_handle( pub fn op_timer_handle(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -77,6 +81,7 @@ pub fn op_timer_handle(
/// Waits asynchronously until either `millis` milliseconds have passed or the /// Waits asynchronously until either `millis` milliseconds have passed or the
/// [`TimerHandle`] resource given by `rid` has been canceled. /// [`TimerHandle`] resource given by `rid` has been canceled.
#[op]
pub async fn op_sleep( pub async fn op_sleep(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
millis: u64, millis: u64,
@ -89,6 +94,7 @@ pub async fn op_sleep(
Ok(()) Ok(())
} }
#[op]
pub fn op_sleep_sync<TP>( pub fn op_sleep_sync<TP>(
state: &mut OpState, state: &mut OpState,
millis: u64, millis: u64,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
@ -177,6 +178,7 @@ pub struct CreateBindGroupLayoutArgs {
entries: Vec<GpuBindGroupLayoutEntry>, entries: Vec<GpuBindGroupLayoutEntry>,
} }
#[op]
pub fn op_webgpu_create_bind_group_layout( pub fn op_webgpu_create_bind_group_layout(
state: &mut OpState, state: &mut OpState,
args: CreateBindGroupLayoutArgs, args: CreateBindGroupLayoutArgs,
@ -220,6 +222,7 @@ pub struct CreatePipelineLayoutArgs {
bind_group_layouts: Vec<u32>, bind_group_layouts: Vec<u32>,
} }
#[op]
pub fn op_webgpu_create_pipeline_layout( pub fn op_webgpu_create_pipeline_layout(
state: &mut OpState, state: &mut OpState,
args: CreatePipelineLayoutArgs, args: CreatePipelineLayoutArgs,
@ -271,6 +274,7 @@ pub struct CreateBindGroupArgs {
entries: Vec<GpuBindGroupEntry>, entries: Vec<GpuBindGroupEntry>,
} }
#[op]
pub fn op_webgpu_create_bind_group( pub fn op_webgpu_create_bind_group(
state: &mut OpState, state: &mut OpState,
args: CreateBindGroupArgs, args: CreateBindGroupArgs,

View file

@ -3,6 +3,8 @@
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures::channel::oneshot; use deno_core::futures::channel::oneshot;
use deno_core::op;
use deno_core::OpState; use deno_core::OpState;
use deno_core::Resource; use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
@ -40,6 +42,7 @@ pub struct CreateBufferArgs {
mapped_at_creation: bool, mapped_at_creation: bool,
} }
#[op]
pub fn op_webgpu_create_buffer( pub fn op_webgpu_create_buffer(
state: &mut OpState, state: &mut OpState,
args: CreateBufferArgs, args: CreateBufferArgs,
@ -76,6 +79,7 @@ pub struct BufferGetMapAsyncArgs {
size: u64, size: u64,
} }
#[op]
pub async fn op_webgpu_buffer_get_map_async( pub async fn op_webgpu_buffer_get_map_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: BufferGetMapAsyncArgs, args: BufferGetMapAsyncArgs,
@ -167,6 +171,7 @@ pub struct BufferGetMappedRangeArgs {
size: Option<u64>, size: Option<u64>,
} }
#[op]
pub fn op_webgpu_buffer_get_mapped_range( pub fn op_webgpu_buffer_get_mapped_range(
state: &mut OpState, state: &mut OpState,
args: BufferGetMappedRangeArgs, args: BufferGetMappedRangeArgs,
@ -204,6 +209,7 @@ pub struct BufferUnmapArgs {
mapped_rid: ResourceId, mapped_rid: ResourceId,
} }
#[op]
pub fn op_webgpu_buffer_unmap( pub fn op_webgpu_buffer_unmap(
state: &mut OpState, state: &mut OpState,
args: BufferUnmapArgs, args: BufferUnmapArgs,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
@ -39,6 +40,7 @@ pub struct CreateRenderBundleEncoderArgs {
stencil_read_only: bool, stencil_read_only: bool,
} }
#[op]
pub fn op_webgpu_create_render_bundle_encoder( pub fn op_webgpu_create_render_bundle_encoder(
state: &mut OpState, state: &mut OpState,
args: CreateRenderBundleEncoderArgs, args: CreateRenderBundleEncoderArgs,
@ -99,6 +101,7 @@ pub struct RenderBundleEncoderFinishArgs {
label: Option<String>, label: Option<String>,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_finish( pub fn op_webgpu_render_bundle_encoder_finish(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderFinishArgs, args: RenderBundleEncoderFinishArgs,
@ -135,6 +138,7 @@ pub struct RenderBundleEncoderSetBindGroupArgs {
dynamic_offsets_data_length: usize, dynamic_offsets_data_length: usize,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_set_bind_group( pub fn op_webgpu_render_bundle_encoder_set_bind_group(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderSetBindGroupArgs, args: RenderBundleEncoderSetBindGroupArgs,
@ -189,6 +193,7 @@ pub struct RenderBundleEncoderPushDebugGroupArgs {
group_label: String, group_label: String,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_push_debug_group( pub fn op_webgpu_render_bundle_encoder_push_debug_group(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderPushDebugGroupArgs, args: RenderBundleEncoderPushDebugGroupArgs,
@ -218,6 +223,7 @@ pub struct RenderBundleEncoderPopDebugGroupArgs {
render_bundle_encoder_rid: ResourceId, render_bundle_encoder_rid: ResourceId,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_pop_debug_group( pub fn op_webgpu_render_bundle_encoder_pop_debug_group(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderPopDebugGroupArgs, args: RenderBundleEncoderPopDebugGroupArgs,
@ -242,6 +248,7 @@ pub struct RenderBundleEncoderInsertDebugMarkerArgs {
marker_label: String, marker_label: String,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_insert_debug_marker( pub fn op_webgpu_render_bundle_encoder_insert_debug_marker(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderInsertDebugMarkerArgs, args: RenderBundleEncoderInsertDebugMarkerArgs,
@ -272,6 +279,7 @@ pub struct RenderBundleEncoderSetPipelineArgs {
pipeline: ResourceId, pipeline: ResourceId,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_set_pipeline( pub fn op_webgpu_render_bundle_encoder_set_pipeline(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderSetPipelineArgs, args: RenderBundleEncoderSetPipelineArgs,
@ -304,6 +312,7 @@ pub struct RenderBundleEncoderSetIndexBufferArgs {
size: u64, size: u64,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_set_index_buffer( pub fn op_webgpu_render_bundle_encoder_set_index_buffer(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderSetIndexBufferArgs, args: RenderBundleEncoderSetIndexBufferArgs,
@ -340,6 +349,7 @@ pub struct RenderBundleEncoderSetVertexBufferArgs {
size: u64, size: u64,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer( pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderSetVertexBufferArgs, args: RenderBundleEncoderSetVertexBufferArgs,
@ -374,6 +384,7 @@ pub struct RenderBundleEncoderDrawArgs {
first_instance: u32, first_instance: u32,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_draw( pub fn op_webgpu_render_bundle_encoder_draw(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderDrawArgs, args: RenderBundleEncoderDrawArgs,
@ -406,6 +417,7 @@ pub struct RenderBundleEncoderDrawIndexedArgs {
first_instance: u32, first_instance: u32,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_draw_indexed( pub fn op_webgpu_render_bundle_encoder_draw_indexed(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderDrawIndexedArgs, args: RenderBundleEncoderDrawIndexedArgs,
@ -436,6 +448,7 @@ pub struct RenderBundleEncoderDrawIndirectArgs {
indirect_offset: u64, indirect_offset: u64,
} }
#[op]
pub fn op_webgpu_render_bundle_encoder_draw_indirect( pub fn op_webgpu_render_bundle_encoder_draw_indirect(
state: &mut OpState, state: &mut OpState,
args: RenderBundleEncoderDrawIndirectArgs, args: RenderBundleEncoderDrawIndirectArgs,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
@ -36,6 +37,7 @@ pub struct CreateCommandEncoderArgs {
_measure_execution_time: Option<bool>, // not yet implemented _measure_execution_time: Option<bool>, // not yet implemented
} }
#[op]
pub fn op_webgpu_create_command_encoder( pub fn op_webgpu_create_command_encoder(
state: &mut OpState, state: &mut OpState,
args: CreateCommandEncoderArgs, args: CreateCommandEncoderArgs,
@ -96,6 +98,7 @@ pub struct CommandEncoderBeginRenderPassArgs {
_occlusion_query_set: Option<u32>, // not yet implemented _occlusion_query_set: Option<u32>, // not yet implemented
} }
#[op]
pub fn op_webgpu_command_encoder_begin_render_pass( pub fn op_webgpu_command_encoder_begin_render_pass(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderBeginRenderPassArgs, args: CommandEncoderBeginRenderPassArgs,
@ -214,6 +217,7 @@ pub struct CommandEncoderBeginComputePassArgs {
label: Option<String>, label: Option<String>,
} }
#[op]
pub fn op_webgpu_command_encoder_begin_compute_pass( pub fn op_webgpu_command_encoder_begin_compute_pass(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderBeginComputePassArgs, args: CommandEncoderBeginComputePassArgs,
@ -252,6 +256,7 @@ pub struct CommandEncoderCopyBufferToBufferArgs {
size: u64, size: u64,
} }
#[op]
pub fn op_webgpu_command_encoder_copy_buffer_to_buffer( pub fn op_webgpu_command_encoder_copy_buffer_to_buffer(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderCopyBufferToBufferArgs, args: CommandEncoderCopyBufferToBufferArgs,
@ -310,6 +315,7 @@ pub struct CommandEncoderCopyBufferToTextureArgs {
copy_size: wgpu_types::Extent3d, copy_size: wgpu_types::Extent3d,
} }
#[op]
pub fn op_webgpu_command_encoder_copy_buffer_to_texture( pub fn op_webgpu_command_encoder_copy_buffer_to_texture(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderCopyBufferToTextureArgs, args: CommandEncoderCopyBufferToTextureArgs,
@ -360,6 +366,7 @@ pub struct CommandEncoderCopyTextureToBufferArgs {
copy_size: wgpu_types::Extent3d, copy_size: wgpu_types::Extent3d,
} }
#[op]
pub fn op_webgpu_command_encoder_copy_texture_to_buffer( pub fn op_webgpu_command_encoder_copy_texture_to_buffer(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderCopyTextureToBufferArgs, args: CommandEncoderCopyTextureToBufferArgs,
@ -414,6 +421,7 @@ pub struct CommandEncoderCopyTextureToTextureArgs {
copy_size: wgpu_types::Extent3d, copy_size: wgpu_types::Extent3d,
} }
#[op]
pub fn op_webgpu_command_encoder_copy_texture_to_texture( pub fn op_webgpu_command_encoder_copy_texture_to_texture(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderCopyTextureToTextureArgs, args: CommandEncoderCopyTextureToTextureArgs,
@ -462,6 +470,7 @@ pub struct CommandEncoderClearBufferArgs {
size: u64, size: u64,
} }
#[op]
pub fn op_webgpu_command_encoder_clear_buffer( pub fn op_webgpu_command_encoder_clear_buffer(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderClearBufferArgs, args: CommandEncoderClearBufferArgs,
@ -491,6 +500,7 @@ pub struct CommandEncoderPushDebugGroupArgs {
group_label: String, group_label: String,
} }
#[op]
pub fn op_webgpu_command_encoder_push_debug_group( pub fn op_webgpu_command_encoder_push_debug_group(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderPushDebugGroupArgs, args: CommandEncoderPushDebugGroupArgs,
@ -512,6 +522,7 @@ pub struct CommandEncoderPopDebugGroupArgs {
command_encoder_rid: ResourceId, command_encoder_rid: ResourceId,
} }
#[op]
pub fn op_webgpu_command_encoder_pop_debug_group( pub fn op_webgpu_command_encoder_pop_debug_group(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderPopDebugGroupArgs, args: CommandEncoderPopDebugGroupArgs,
@ -533,6 +544,7 @@ pub struct CommandEncoderInsertDebugMarkerArgs {
marker_label: String, marker_label: String,
} }
#[op]
pub fn op_webgpu_command_encoder_insert_debug_marker( pub fn op_webgpu_command_encoder_insert_debug_marker(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderInsertDebugMarkerArgs, args: CommandEncoderInsertDebugMarkerArgs,
@ -558,6 +570,7 @@ pub struct CommandEncoderWriteTimestampArgs {
query_index: u32, query_index: u32,
} }
#[op]
pub fn op_webgpu_command_encoder_write_timestamp( pub fn op_webgpu_command_encoder_write_timestamp(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderWriteTimestampArgs, args: CommandEncoderWriteTimestampArgs,
@ -590,6 +603,7 @@ pub struct CommandEncoderResolveQuerySetArgs {
destination_offset: u64, destination_offset: u64,
} }
#[op]
pub fn op_webgpu_command_encoder_resolve_query_set( pub fn op_webgpu_command_encoder_resolve_query_set(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderResolveQuerySetArgs, args: CommandEncoderResolveQuerySetArgs,
@ -624,6 +638,7 @@ pub struct CommandEncoderFinishArgs {
label: Option<String>, label: Option<String>,
} }
#[op]
pub fn op_webgpu_command_encoder_finish( pub fn op_webgpu_command_encoder_finish(
state: &mut OpState, state: &mut OpState,
args: CommandEncoderFinishArgs, args: CommandEncoderFinishArgs,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
@ -26,6 +27,7 @@ pub struct ComputePassSetPipelineArgs {
pipeline: ResourceId, pipeline: ResourceId,
} }
#[op]
pub fn op_webgpu_compute_pass_set_pipeline( pub fn op_webgpu_compute_pass_set_pipeline(
state: &mut OpState, state: &mut OpState,
args: ComputePassSetPipelineArgs, args: ComputePassSetPipelineArgs,
@ -56,6 +58,7 @@ pub struct ComputePassDispatchArgs {
z: u32, z: u32,
} }
#[op]
pub fn op_webgpu_compute_pass_dispatch( pub fn op_webgpu_compute_pass_dispatch(
state: &mut OpState, state: &mut OpState,
args: ComputePassDispatchArgs, args: ComputePassDispatchArgs,
@ -83,6 +86,7 @@ pub struct ComputePassDispatchIndirectArgs {
indirect_offset: u64, indirect_offset: u64,
} }
#[op]
pub fn op_webgpu_compute_pass_dispatch_indirect( pub fn op_webgpu_compute_pass_dispatch_indirect(
state: &mut OpState, state: &mut OpState,
args: ComputePassDispatchIndirectArgs, args: ComputePassDispatchIndirectArgs,
@ -112,6 +116,7 @@ pub struct ComputePassBeginPipelineStatisticsQueryArgs {
query_index: u32, query_index: u32,
} }
#[op]
pub fn op_webgpu_compute_pass_begin_pipeline_statistics_query( pub fn op_webgpu_compute_pass_begin_pipeline_statistics_query(
state: &mut OpState, state: &mut OpState,
args: ComputePassBeginPipelineStatisticsQueryArgs, args: ComputePassBeginPipelineStatisticsQueryArgs,
@ -139,6 +144,7 @@ pub struct ComputePassEndPipelineStatisticsQueryArgs {
compute_pass_rid: ResourceId, compute_pass_rid: ResourceId,
} }
#[op]
pub fn op_webgpu_compute_pass_end_pipeline_statistics_query( pub fn op_webgpu_compute_pass_end_pipeline_statistics_query(
state: &mut OpState, state: &mut OpState,
args: ComputePassEndPipelineStatisticsQueryArgs, args: ComputePassEndPipelineStatisticsQueryArgs,
@ -163,6 +169,7 @@ pub struct ComputePassWriteTimestampArgs {
query_index: u32, query_index: u32,
} }
#[op]
pub fn op_webgpu_compute_pass_write_timestamp( pub fn op_webgpu_compute_pass_write_timestamp(
state: &mut OpState, state: &mut OpState,
args: ComputePassWriteTimestampArgs, args: ComputePassWriteTimestampArgs,
@ -191,6 +198,7 @@ pub struct ComputePassEndPassArgs {
compute_pass_rid: ResourceId, compute_pass_rid: ResourceId,
} }
#[op]
pub fn op_webgpu_compute_pass_end_pass( pub fn op_webgpu_compute_pass_end_pass(
state: &mut OpState, state: &mut OpState,
args: ComputePassEndPassArgs, args: ComputePassEndPassArgs,
@ -225,6 +233,7 @@ pub struct ComputePassSetBindGroupArgs {
dynamic_offsets_data_length: usize, dynamic_offsets_data_length: usize,
} }
#[op]
pub fn op_webgpu_compute_pass_set_bind_group( pub fn op_webgpu_compute_pass_set_bind_group(
state: &mut OpState, state: &mut OpState,
args: ComputePassSetBindGroupArgs, args: ComputePassSetBindGroupArgs,
@ -278,6 +287,7 @@ pub struct ComputePassPushDebugGroupArgs {
group_label: String, group_label: String,
} }
#[op]
pub fn op_webgpu_compute_pass_push_debug_group( pub fn op_webgpu_compute_pass_push_debug_group(
state: &mut OpState, state: &mut OpState,
args: ComputePassPushDebugGroupArgs, args: ComputePassPushDebugGroupArgs,
@ -307,6 +317,7 @@ pub struct ComputePassPopDebugGroupArgs {
compute_pass_rid: ResourceId, compute_pass_rid: ResourceId,
} }
#[op]
pub fn op_webgpu_compute_pass_pop_debug_group( pub fn op_webgpu_compute_pass_pop_debug_group(
state: &mut OpState, state: &mut OpState,
args: ComputePassPopDebugGroupArgs, args: ComputePassPopDebugGroupArgs,
@ -330,6 +341,7 @@ pub struct ComputePassInsertDebugMarkerArgs {
marker_label: String, marker_label: String,
} }
#[op]
pub fn op_webgpu_compute_pass_insert_debug_marker( pub fn op_webgpu_compute_pass_insert_debug_marker(
state: &mut OpState, state: &mut OpState,
args: ComputePassInsertDebugMarkerArgs, args: ComputePassInsertDebugMarkerArgs,

View file

@ -2,10 +2,10 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpFn; use deno_core::OpPair;
use deno_core::OpState; use deno_core::OpState;
use deno_core::Resource; use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
@ -241,6 +241,7 @@ pub struct GpuAdapterDevice {
is_software: bool, is_software: bool,
} }
#[op]
pub async fn op_webgpu_request_adapter( pub async fn op_webgpu_request_adapter(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: RequestAdapterArgs, args: RequestAdapterArgs,
@ -439,6 +440,7 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
} }
} }
#[op]
pub async fn op_webgpu_request_device( pub async fn op_webgpu_request_device(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: RequestDeviceArgs, args: RequestDeviceArgs,
@ -539,6 +541,7 @@ impl From<GpuQueryType> for wgpu_types::QueryType {
} }
} }
#[op]
pub fn op_webgpu_create_query_set( pub fn op_webgpu_create_query_set(
state: &mut OpState, state: &mut OpState,
args: CreateQuerySetArgs, args: CreateQuerySetArgs,
@ -562,347 +565,102 @@ pub fn op_webgpu_create_query_set(
) => state, WebGpuQuerySet) ) => state, WebGpuQuerySet)
} }
fn declare_webgpu_ops() -> Vec<(&'static str, Box<OpFn>)> { fn declare_webgpu_ops() -> Vec<OpPair> {
vec![ vec![
// Request device/adapter // Request device/adapter
( op_webgpu_request_adapter::decl(),
"op_webgpu_request_adapter", op_webgpu_request_device::decl(),
op_async(op_webgpu_request_adapter),
),
(
"op_webgpu_request_device",
op_async(op_webgpu_request_device),
),
// Query Set // Query Set
( op_webgpu_create_query_set::decl(),
"op_webgpu_create_query_set",
op_sync(op_webgpu_create_query_set),
),
// buffer // buffer
( buffer::op_webgpu_create_buffer::decl(),
"op_webgpu_create_buffer", buffer::op_webgpu_buffer_get_mapped_range::decl(),
op_sync(buffer::op_webgpu_create_buffer), buffer::op_webgpu_buffer_unmap::decl(),
),
(
"op_webgpu_buffer_get_mapped_range",
op_sync(buffer::op_webgpu_buffer_get_mapped_range),
),
(
"op_webgpu_buffer_unmap",
op_sync(buffer::op_webgpu_buffer_unmap),
),
// buffer async // buffer async
( buffer::op_webgpu_buffer_get_map_async::decl(),
"op_webgpu_buffer_get_map_async",
op_async(buffer::op_webgpu_buffer_get_map_async),
),
// remaining sync ops // remaining sync ops
// texture // texture
( texture::op_webgpu_create_texture::decl(),
"op_webgpu_create_texture", texture::op_webgpu_create_texture_view::decl(),
op_sync(texture::op_webgpu_create_texture),
),
(
"op_webgpu_create_texture_view",
op_sync(texture::op_webgpu_create_texture_view),
),
// sampler // sampler
( sampler::op_webgpu_create_sampler::decl(),
"op_webgpu_create_sampler",
op_sync(sampler::op_webgpu_create_sampler),
),
// binding // binding
( binding::op_webgpu_create_bind_group_layout::decl(),
"op_webgpu_create_bind_group_layout", binding::op_webgpu_create_pipeline_layout::decl(),
op_sync(binding::op_webgpu_create_bind_group_layout), binding::op_webgpu_create_bind_group::decl(),
),
(
"op_webgpu_create_pipeline_layout",
op_sync(binding::op_webgpu_create_pipeline_layout),
),
(
"op_webgpu_create_bind_group",
op_sync(binding::op_webgpu_create_bind_group),
),
// pipeline // pipeline
( pipeline::op_webgpu_create_compute_pipeline::decl(),
"op_webgpu_create_compute_pipeline", pipeline::op_webgpu_compute_pipeline_get_bind_group_layout::decl(),
op_sync(pipeline::op_webgpu_create_compute_pipeline), pipeline::op_webgpu_create_render_pipeline::decl(),
), pipeline::op_webgpu_render_pipeline_get_bind_group_layout::decl(),
(
"op_webgpu_compute_pipeline_get_bind_group_layout",
op_sync(pipeline::op_webgpu_compute_pipeline_get_bind_group_layout),
),
(
"op_webgpu_create_render_pipeline",
op_sync(pipeline::op_webgpu_create_render_pipeline),
),
(
"op_webgpu_render_pipeline_get_bind_group_layout",
op_sync(pipeline::op_webgpu_render_pipeline_get_bind_group_layout),
),
// command_encoder // command_encoder
( command_encoder::op_webgpu_create_command_encoder::decl(),
"op_webgpu_create_command_encoder", command_encoder::op_webgpu_command_encoder_begin_render_pass::decl(),
op_sync(command_encoder::op_webgpu_create_command_encoder), 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(),
"op_webgpu_command_encoder_begin_render_pass", command_encoder::op_webgpu_command_encoder_copy_texture_to_buffer::decl(),
op_sync(command_encoder::op_webgpu_command_encoder_begin_render_pass), 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(),
"op_webgpu_command_encoder_begin_compute_pass", command_encoder::op_webgpu_command_encoder_pop_debug_group::decl(),
op_sync(command_encoder::op_webgpu_command_encoder_begin_compute_pass), 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(),
"op_webgpu_command_encoder_copy_buffer_to_buffer", command_encoder::op_webgpu_command_encoder_finish::decl(),
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),
),
// render_pass // render_pass
( render_pass::op_webgpu_render_pass_set_viewport::decl(),
"op_webgpu_render_pass_set_viewport", render_pass::op_webgpu_render_pass_set_scissor_rect::decl(),
op_sync(render_pass::op_webgpu_render_pass_set_viewport), 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(),
"op_webgpu_render_pass_set_scissor_rect", render_pass::op_webgpu_render_pass_end_pipeline_statistics_query::decl(),
op_sync(render_pass::op_webgpu_render_pass_set_scissor_rect), 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(),
"op_webgpu_render_pass_set_blend_constant", render_pass::op_webgpu_render_pass_set_bind_group::decl(),
op_sync(render_pass::op_webgpu_render_pass_set_blend_constant), 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(),
"op_webgpu_render_pass_set_stencil_reference", render_pass::op_webgpu_render_pass_set_pipeline::decl(),
op_sync(render_pass::op_webgpu_render_pass_set_stencil_reference), 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(),
"op_webgpu_render_pass_begin_pipeline_statistics_query", render_pass::op_webgpu_render_pass_draw_indexed::decl(),
op_sync( render_pass::op_webgpu_render_pass_draw_indirect::decl(),
render_pass::op_webgpu_render_pass_begin_pipeline_statistics_query, render_pass::op_webgpu_render_pass_draw_indexed_indirect::decl(),
),
),
(
"op_webgpu_render_pass_end_pipeline_statistics_query",
op_sync(render_pass::op_webgpu_render_pass_end_pipeline_statistics_query),
),
(
"op_webgpu_render_pass_write_timestamp",
op_sync(render_pass::op_webgpu_render_pass_write_timestamp),
),
(
"op_webgpu_render_pass_execute_bundles",
op_sync(render_pass::op_webgpu_render_pass_execute_bundles),
),
(
"op_webgpu_render_pass_end_pass",
op_sync(render_pass::op_webgpu_render_pass_end_pass),
),
(
"op_webgpu_render_pass_set_bind_group",
op_sync(render_pass::op_webgpu_render_pass_set_bind_group),
),
(
"op_webgpu_render_pass_push_debug_group",
op_sync(render_pass::op_webgpu_render_pass_push_debug_group),
),
(
"op_webgpu_render_pass_pop_debug_group",
op_sync(render_pass::op_webgpu_render_pass_pop_debug_group),
),
(
"op_webgpu_render_pass_insert_debug_marker",
op_sync(render_pass::op_webgpu_render_pass_insert_debug_marker),
),
(
"op_webgpu_render_pass_set_pipeline",
op_sync(render_pass::op_webgpu_render_pass_set_pipeline),
),
(
"op_webgpu_render_pass_set_index_buffer",
op_sync(render_pass::op_webgpu_render_pass_set_index_buffer),
),
(
"op_webgpu_render_pass_set_vertex_buffer",
op_sync(render_pass::op_webgpu_render_pass_set_vertex_buffer),
),
(
"op_webgpu_render_pass_draw",
op_sync(render_pass::op_webgpu_render_pass_draw),
),
(
"op_webgpu_render_pass_draw_indexed",
op_sync(render_pass::op_webgpu_render_pass_draw_indexed),
),
(
"op_webgpu_render_pass_draw_indirect",
op_sync(render_pass::op_webgpu_render_pass_draw_indirect),
),
(
"op_webgpu_render_pass_draw_indexed_indirect",
op_sync(render_pass::op_webgpu_render_pass_draw_indexed_indirect),
),
// compute_pass // compute_pass
( compute_pass::op_webgpu_compute_pass_set_pipeline::decl(),
"op_webgpu_compute_pass_set_pipeline", compute_pass::op_webgpu_compute_pass_dispatch::decl(),
op_sync(compute_pass::op_webgpu_compute_pass_set_pipeline), compute_pass::op_webgpu_compute_pass_dispatch_indirect::decl(),
), compute_pass::op_webgpu_compute_pass_begin_pipeline_statistics_query::decl(
(
"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_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 // bundle
( bundle::op_webgpu_create_render_bundle_encoder::decl(),
"op_webgpu_create_render_bundle_encoder", bundle::op_webgpu_render_bundle_encoder_finish::decl(),
op_sync(bundle::op_webgpu_create_render_bundle_encoder), 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(),
"op_webgpu_render_bundle_encoder_finish", bundle::op_webgpu_render_bundle_encoder_insert_debug_marker::decl(),
op_sync(bundle::op_webgpu_render_bundle_encoder_finish), 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(),
"op_webgpu_render_bundle_encoder_set_bind_group", bundle::op_webgpu_render_bundle_encoder_draw::decl(),
op_sync(bundle::op_webgpu_render_bundle_encoder_set_bind_group), bundle::op_webgpu_render_bundle_encoder_draw_indexed::decl(),
), bundle::op_webgpu_render_bundle_encoder_draw_indirect::decl(),
(
"op_webgpu_render_bundle_encoder_push_debug_group",
op_sync(bundle::op_webgpu_render_bundle_encoder_push_debug_group),
),
(
"op_webgpu_render_bundle_encoder_pop_debug_group",
op_sync(bundle::op_webgpu_render_bundle_encoder_pop_debug_group),
),
(
"op_webgpu_render_bundle_encoder_insert_debug_marker",
op_sync(bundle::op_webgpu_render_bundle_encoder_insert_debug_marker),
),
(
"op_webgpu_render_bundle_encoder_set_pipeline",
op_sync(bundle::op_webgpu_render_bundle_encoder_set_pipeline),
),
(
"op_webgpu_render_bundle_encoder_set_index_buffer",
op_sync(bundle::op_webgpu_render_bundle_encoder_set_index_buffer),
),
(
"op_webgpu_render_bundle_encoder_set_vertex_buffer",
op_sync(bundle::op_webgpu_render_bundle_encoder_set_vertex_buffer),
),
(
"op_webgpu_render_bundle_encoder_draw",
op_sync(bundle::op_webgpu_render_bundle_encoder_draw),
),
(
"op_webgpu_render_bundle_encoder_draw_indexed",
op_sync(bundle::op_webgpu_render_bundle_encoder_draw_indexed),
),
(
"op_webgpu_render_bundle_encoder_draw_indirect",
op_sync(bundle::op_webgpu_render_bundle_encoder_draw_indirect),
),
// queue // queue
( queue::op_webgpu_queue_submit::decl(),
"op_webgpu_queue_submit", queue::op_webgpu_write_buffer::decl(),
op_sync(queue::op_webgpu_queue_submit), queue::op_webgpu_write_texture::decl(),
),
(
"op_webgpu_write_buffer",
op_sync(queue::op_webgpu_write_buffer),
),
(
"op_webgpu_write_texture",
op_sync(queue::op_webgpu_write_texture),
),
// shader // shader
( shader::op_webgpu_create_shader_module::decl(),
"op_webgpu_create_shader_module",
op_sync(shader::op_webgpu_create_shader_module),
),
] ]
} }

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
@ -57,6 +58,7 @@ pub struct CreateComputePipelineArgs {
compute: GpuProgrammableStage, compute: GpuProgrammableStage,
} }
#[op]
pub fn op_webgpu_create_compute_pipeline( pub fn op_webgpu_create_compute_pipeline(
state: &mut OpState, state: &mut OpState,
args: CreateComputePipelineArgs, args: CreateComputePipelineArgs,
@ -126,6 +128,7 @@ pub struct PipelineLayout {
err: Option<WebGpuError>, err: Option<WebGpuError>,
} }
#[op]
pub fn op_webgpu_compute_pipeline_get_bind_group_layout( pub fn op_webgpu_compute_pipeline_get_bind_group_layout(
state: &mut OpState, state: &mut OpState,
args: ComputePipelineGetBindGroupLayoutArgs, args: ComputePipelineGetBindGroupLayoutArgs,
@ -303,6 +306,7 @@ pub struct CreateRenderPipelineArgs {
fragment: Option<GpuFragmentState>, fragment: Option<GpuFragmentState>,
} }
#[op]
pub fn op_webgpu_create_render_pipeline( pub fn op_webgpu_create_render_pipeline(
state: &mut OpState, state: &mut OpState,
args: CreateRenderPipelineArgs, args: CreateRenderPipelineArgs,
@ -404,6 +408,7 @@ pub struct RenderPipelineGetBindGroupLayoutArgs {
index: u32, index: u32,
} }
#[op]
pub fn op_webgpu_render_pipeline_get_bind_group_layout( pub fn op_webgpu_render_pipeline_get_bind_group_layout(
state: &mut OpState, state: &mut OpState,
args: RenderPipelineGetBindGroupLayoutArgs, args: RenderPipelineGetBindGroupLayoutArgs,

View file

@ -3,6 +3,7 @@
use std::num::NonZeroU32; use std::num::NonZeroU32;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::OpState; use deno_core::OpState;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
@ -19,6 +20,7 @@ pub struct QueueSubmitArgs {
command_buffers: Vec<ResourceId>, command_buffers: Vec<ResourceId>,
} }
#[op]
pub fn op_webgpu_queue_submit( pub fn op_webgpu_queue_submit(
state: &mut OpState, state: &mut OpState,
args: QueueSubmitArgs, args: QueueSubmitArgs,
@ -73,6 +75,7 @@ pub struct QueueWriteBufferArgs {
size: Option<usize>, size: Option<usize>,
} }
#[op]
pub fn op_webgpu_write_buffer( pub fn op_webgpu_write_buffer(
state: &mut OpState, state: &mut OpState,
args: QueueWriteBufferArgs, args: QueueWriteBufferArgs,
@ -111,6 +114,7 @@ pub struct QueueWriteTextureArgs {
size: wgpu_types::Extent3d, size: wgpu_types::Extent3d,
} }
#[op]
pub fn op_webgpu_write_texture( pub fn op_webgpu_write_texture(
state: &mut OpState, state: &mut OpState,
args: QueueWriteTextureArgs, args: QueueWriteTextureArgs,

View file

@ -2,6 +2,7 @@
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
@ -32,6 +33,7 @@ pub struct RenderPassSetViewportArgs {
max_depth: f32, max_depth: f32,
} }
#[op]
pub fn op_webgpu_render_pass_set_viewport( pub fn op_webgpu_render_pass_set_viewport(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetViewportArgs, args: RenderPassSetViewportArgs,
@ -64,6 +66,7 @@ pub struct RenderPassSetScissorRectArgs {
height: u32, height: u32,
} }
#[op]
pub fn op_webgpu_render_pass_set_scissor_rect( pub fn op_webgpu_render_pass_set_scissor_rect(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetScissorRectArgs, args: RenderPassSetScissorRectArgs,
@ -91,6 +94,7 @@ pub struct RenderPassSetBlendConstantArgs {
color: wgpu_types::Color, color: wgpu_types::Color,
} }
#[op]
pub fn op_webgpu_render_pass_set_blend_constant( pub fn op_webgpu_render_pass_set_blend_constant(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetBlendConstantArgs, args: RenderPassSetBlendConstantArgs,
@ -115,6 +119,7 @@ pub struct RenderPassSetStencilReferenceArgs {
reference: u32, reference: u32,
} }
#[op]
pub fn op_webgpu_render_pass_set_stencil_reference( pub fn op_webgpu_render_pass_set_stencil_reference(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetStencilReferenceArgs, args: RenderPassSetStencilReferenceArgs,
@ -140,6 +145,7 @@ pub struct RenderPassBeginPipelineStatisticsQueryArgs {
query_index: u32, query_index: u32,
} }
#[op]
pub fn op_webgpu_render_pass_begin_pipeline_statistics_query( pub fn op_webgpu_render_pass_begin_pipeline_statistics_query(
state: &mut OpState, state: &mut OpState,
args: RenderPassBeginPipelineStatisticsQueryArgs, args: RenderPassBeginPipelineStatisticsQueryArgs,
@ -167,6 +173,7 @@ pub struct RenderPassEndPipelineStatisticsQueryArgs {
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
} }
#[op]
pub fn op_webgpu_render_pass_end_pipeline_statistics_query( pub fn op_webgpu_render_pass_end_pipeline_statistics_query(
state: &mut OpState, state: &mut OpState,
args: RenderPassEndPipelineStatisticsQueryArgs, args: RenderPassEndPipelineStatisticsQueryArgs,
@ -191,6 +198,7 @@ pub struct RenderPassWriteTimestampArgs {
query_index: u32, query_index: u32,
} }
#[op]
pub fn op_webgpu_render_pass_write_timestamp( pub fn op_webgpu_render_pass_write_timestamp(
state: &mut OpState, state: &mut OpState,
args: RenderPassWriteTimestampArgs, args: RenderPassWriteTimestampArgs,
@ -219,6 +227,7 @@ pub struct RenderPassExecuteBundlesArgs {
bundles: Vec<u32>, bundles: Vec<u32>,
} }
#[op]
pub fn op_webgpu_render_pass_execute_bundles( pub fn op_webgpu_render_pass_execute_bundles(
state: &mut OpState, state: &mut OpState,
args: RenderPassExecuteBundlesArgs, args: RenderPassExecuteBundlesArgs,
@ -258,6 +267,7 @@ pub struct RenderPassEndPassArgs {
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
} }
#[op]
pub fn op_webgpu_render_pass_end_pass( pub fn op_webgpu_render_pass_end_pass(
state: &mut OpState, state: &mut OpState,
args: RenderPassEndPassArgs, args: RenderPassEndPassArgs,
@ -289,6 +299,7 @@ pub struct RenderPassSetBindGroupArgs {
dynamic_offsets_data_length: usize, dynamic_offsets_data_length: usize,
} }
#[op]
pub fn op_webgpu_render_pass_set_bind_group( pub fn op_webgpu_render_pass_set_bind_group(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetBindGroupArgs, args: RenderPassSetBindGroupArgs,
@ -342,6 +353,7 @@ pub struct RenderPassPushDebugGroupArgs {
group_label: String, group_label: String,
} }
#[op]
pub fn op_webgpu_render_pass_push_debug_group( pub fn op_webgpu_render_pass_push_debug_group(
state: &mut OpState, state: &mut OpState,
args: RenderPassPushDebugGroupArgs, args: RenderPassPushDebugGroupArgs,
@ -371,6 +383,7 @@ pub struct RenderPassPopDebugGroupArgs {
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
} }
#[op]
pub fn op_webgpu_render_pass_pop_debug_group( pub fn op_webgpu_render_pass_pop_debug_group(
state: &mut OpState, state: &mut OpState,
args: RenderPassPopDebugGroupArgs, args: RenderPassPopDebugGroupArgs,
@ -394,6 +407,7 @@ pub struct RenderPassInsertDebugMarkerArgs {
marker_label: String, marker_label: String,
} }
#[op]
pub fn op_webgpu_render_pass_insert_debug_marker( pub fn op_webgpu_render_pass_insert_debug_marker(
state: &mut OpState, state: &mut OpState,
args: RenderPassInsertDebugMarkerArgs, args: RenderPassInsertDebugMarkerArgs,
@ -424,6 +438,7 @@ pub struct RenderPassSetPipelineArgs {
pipeline: u32, pipeline: u32,
} }
#[op]
pub fn op_webgpu_render_pass_set_pipeline( pub fn op_webgpu_render_pass_set_pipeline(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetPipelineArgs, args: RenderPassSetPipelineArgs,
@ -455,6 +470,7 @@ pub struct RenderPassSetIndexBufferArgs {
size: Option<u64>, size: Option<u64>,
} }
#[op]
pub fn op_webgpu_render_pass_set_index_buffer( pub fn op_webgpu_render_pass_set_index_buffer(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetIndexBufferArgs, args: RenderPassSetIndexBufferArgs,
@ -496,6 +512,7 @@ pub struct RenderPassSetVertexBufferArgs {
size: Option<u64>, size: Option<u64>,
} }
#[op]
pub fn op_webgpu_render_pass_set_vertex_buffer( pub fn op_webgpu_render_pass_set_vertex_buffer(
state: &mut OpState, state: &mut OpState,
args: RenderPassSetVertexBufferArgs, args: RenderPassSetVertexBufferArgs,
@ -538,6 +555,7 @@ pub struct RenderPassDrawArgs {
first_instance: u32, first_instance: u32,
} }
#[op]
pub fn op_webgpu_render_pass_draw( pub fn op_webgpu_render_pass_draw(
state: &mut OpState, state: &mut OpState,
args: RenderPassDrawArgs, args: RenderPassDrawArgs,
@ -569,6 +587,7 @@ pub struct RenderPassDrawIndexedArgs {
first_instance: u32, first_instance: u32,
} }
#[op]
pub fn op_webgpu_render_pass_draw_indexed( pub fn op_webgpu_render_pass_draw_indexed(
state: &mut OpState, state: &mut OpState,
args: RenderPassDrawIndexedArgs, args: RenderPassDrawIndexedArgs,
@ -598,6 +617,7 @@ pub struct RenderPassDrawIndirectArgs {
indirect_offset: u64, indirect_offset: u64,
} }
#[op]
pub fn op_webgpu_render_pass_draw_indirect( pub fn op_webgpu_render_pass_draw_indirect(
state: &mut OpState, state: &mut OpState,
args: RenderPassDrawIndirectArgs, args: RenderPassDrawIndirectArgs,
@ -627,6 +647,7 @@ pub struct RenderPassDrawIndexedIndirectArgs {
indirect_offset: u64, indirect_offset: u64,
} }
#[op]
pub fn op_webgpu_render_pass_draw_indexed_indirect( pub fn op_webgpu_render_pass_draw_indexed_indirect(
state: &mut OpState, state: &mut OpState,
args: RenderPassDrawIndexedIndirectArgs, args: RenderPassDrawIndexedIndirectArgs,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
@ -32,6 +33,7 @@ pub struct CreateSamplerArgs {
max_anisotropy: u8, max_anisotropy: u8,
} }
#[op]
pub fn op_webgpu_create_sampler( pub fn op_webgpu_create_sampler(
state: &mut OpState, state: &mut OpState,
args: CreateSamplerArgs, args: CreateSamplerArgs,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
@ -24,6 +25,7 @@ pub struct CreateShaderModuleArgs {
_source_map: Option<()>, // not yet implemented _source_map: Option<()>, // not yet implemented
} }
#[op]
pub fn op_webgpu_create_shader_module( pub fn op_webgpu_create_shader_module(
state: &mut OpState, state: &mut OpState,
args: CreateShaderModuleArgs, args: CreateShaderModuleArgs,

View file

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
@ -34,6 +35,7 @@ pub struct CreateTextureArgs {
usage: u32, usage: u32,
} }
#[op]
pub fn op_webgpu_create_texture( pub fn op_webgpu_create_texture(
state: &mut OpState, state: &mut OpState,
args: CreateTextureArgs, args: CreateTextureArgs,
@ -76,6 +78,7 @@ pub struct CreateTextureViewArgs {
array_layer_count: Option<u32>, array_layer_count: Option<u32>,
} }
#[op]
pub fn op_webgpu_create_texture_view( pub fn op_webgpu_create_texture_view(
state: &mut OpState, state: &mut OpState,
args: CreateTextureViewArgs, args: CreateTextureViewArgs,

View file

@ -8,8 +8,8 @@ use deno_core::futures::stream::SplitStream;
use deno_core::futures::SinkExt; use deno_core::futures::SinkExt;
use deno_core::futures::StreamExt; use deno_core::futures::StreamExt;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::url; use deno_core::url;
use deno_core::AsyncRefCell; use deno_core::AsyncRefCell;
use deno_core::ByteString; 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 // This op is needed because creating a WS instance in JavaScript is a sync
// operation and should throw error when permissions are not fulfilled, // operation and should throw error when permissions are not fulfilled,
// but actual op that connects WS is async. // but actual op that connects WS is async.
#[op]
pub fn op_ws_check_permission_and_cancel_handle<WP>( pub fn op_ws_check_permission_and_cancel_handle<WP>(
state: &mut OpState, state: &mut OpState,
url: String, url: String,
@ -229,6 +230,7 @@ pub struct CreateResponse {
extensions: String, extensions: String,
} }
#[op]
pub async fn op_ws_create<WP>( pub async fn op_ws_create<WP>(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: CreateArgs, args: CreateArgs,
@ -378,6 +380,7 @@ pub enum SendValue {
Ping, Ping,
} }
#[op]
pub async fn op_ws_send( pub async fn op_ws_send(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -406,6 +409,7 @@ pub struct CloseArgs {
reason: Option<String>, reason: Option<String>,
} }
#[op]
pub async fn op_ws_close( pub async fn op_ws_close(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: CloseArgs, args: CloseArgs,
@ -440,6 +444,7 @@ pub enum NextEventResponse {
Closed, Closed,
} }
#[op]
pub async fn op_ws_next_event( pub async fn op_ws_next_event(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -486,14 +491,11 @@ pub fn init<P: WebSocketPermissions + 'static>(
"02_websocketstream.js", "02_websocketstream.js",
)) ))
.ops(vec![ .ops(vec![
( op_ws_check_permission_and_cancel_handle::decl::<P>(),
"op_ws_check_permission_and_cancel_handle", op_ws_create::decl::<P>(),
op_sync(op_ws_check_permission_and_cancel_handle::<P>), op_ws_send::decl(),
), op_ws_close::decl(),
("op_ws_create", op_async(op_ws_create::<P>)), op_ws_next_event::decl(),
("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)),
]) ])
.state(move |state| { .state(move |state| {
state.put::<WsUserAgent>(WsUserAgent(user_agent.clone())); state.put::<WsUserAgent>(WsUserAgent(user_agent.clone()));

View file

@ -4,7 +4,7 @@
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::include_js_files; use deno_core::include_js_files;
use deno_core::op_sync; use deno_core::op;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
use rusqlite::params; use rusqlite::params;
@ -26,16 +26,13 @@ pub fn init(origin_storage_dir: Option<PathBuf>) -> Extension {
"01_webstorage.js", "01_webstorage.js",
)) ))
.ops(vec![ .ops(vec![
("op_webstorage_length", op_sync(op_webstorage_length)), op_webstorage_length::decl(),
("op_webstorage_key", op_sync(op_webstorage_key)), op_webstorage_key::decl(),
("op_webstorage_set", op_sync(op_webstorage_set)), op_webstorage_set::decl(),
("op_webstorage_get", op_sync(op_webstorage_get)), op_webstorage_get::decl(),
("op_webstorage_remove", op_sync(op_webstorage_remove)), op_webstorage_remove::decl(),
("op_webstorage_clear", op_sync(op_webstorage_clear)), op_webstorage_clear::decl(),
( op_webstorage_iterate_keys::decl(),
"op_webstorage_iterate_keys",
op_sync(op_webstorage_iterate_keys),
),
]) ])
.state(move |state| { .state(move |state| {
if let Some(origin_storage_dir) = &origin_storage_dir { if let Some(origin_storage_dir) = &origin_storage_dir {
@ -103,6 +100,7 @@ fn get_webstorage(
Ok(conn) Ok(conn)
} }
#[op]
pub fn op_webstorage_length( pub fn op_webstorage_length(
state: &mut OpState, state: &mut OpState,
persistent: bool, persistent: bool,
@ -116,6 +114,7 @@ pub fn op_webstorage_length(
Ok(length) Ok(length)
} }
#[op]
pub fn op_webstorage_key( pub fn op_webstorage_key(
state: &mut OpState, state: &mut OpState,
index: u32, index: u32,
@ -140,6 +139,7 @@ pub struct SetArgs {
key_value: String, key_value: String,
} }
#[op]
pub fn op_webstorage_set( pub fn op_webstorage_set(
state: &mut OpState, state: &mut OpState,
args: SetArgs, args: SetArgs,
@ -167,6 +167,7 @@ pub fn op_webstorage_set(
Ok(()) Ok(())
} }
#[op]
pub fn op_webstorage_get( pub fn op_webstorage_get(
state: &mut OpState, state: &mut OpState,
key_name: String, key_name: String,
@ -182,6 +183,7 @@ pub fn op_webstorage_get(
Ok(val) Ok(val)
} }
#[op]
pub fn op_webstorage_remove( pub fn op_webstorage_remove(
state: &mut OpState, state: &mut OpState,
key_name: String, key_name: String,
@ -195,6 +197,7 @@ pub fn op_webstorage_remove(
Ok(()) Ok(())
} }
#[op]
pub fn op_webstorage_clear( pub fn op_webstorage_clear(
state: &mut OpState, state: &mut OpState,
persistent: bool, persistent: bool,
@ -208,6 +211,7 @@ pub fn op_webstorage_clear(
Ok(()) Ok(())
} }
#[op]
pub fn op_webstorage_iterate_keys( pub fn op_webstorage_iterate_keys(
state: &mut OpState, state: &mut OpState,
persistent: bool, persistent: bool,

17
ops/Cargo.toml Normal file
View file

@ -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"] }

16
ops/README.md Normal file
View file

@ -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();
```

264
ops/lib.rs Normal file
View file

@ -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,
}
}

View file

@ -8,8 +8,8 @@ use deno_core::error::bad_resource_id;
use deno_core::error::custom_error; use deno_core::error::custom_error;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
use deno_core::RcRef; use deno_core::RcRef;
@ -38,59 +38,59 @@ use deno_core::error::not_supported;
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
("op_open_sync", op_sync(op_open_sync)), op_open_sync::decl(),
("op_open_async", op_async(op_open_async)), op_open_async::decl(),
("op_seek_sync", op_sync(op_seek_sync)), op_seek_sync::decl(),
("op_seek_async", op_async(op_seek_async)), op_seek_async::decl(),
("op_fdatasync_sync", op_sync(op_fdatasync_sync)), op_fdatasync_sync::decl(),
("op_fdatasync_async", op_async(op_fdatasync_async)), op_fdatasync_async::decl(),
("op_fsync_sync", op_sync(op_fsync_sync)), op_fsync_sync::decl(),
("op_fsync_async", op_async(op_fsync_async)), op_fsync_async::decl(),
("op_fstat_sync", op_sync(op_fstat_sync)), op_fstat_sync::decl(),
("op_fstat_async", op_async(op_fstat_async)), op_fstat_async::decl(),
("op_flock_sync", op_sync(op_flock_sync)), op_flock_sync::decl(),
("op_flock_async", op_async(op_flock_async)), op_flock_async::decl(),
("op_funlock_sync", op_sync(op_funlock_sync)), op_funlock_sync::decl(),
("op_funlock_async", op_async(op_funlock_async)), op_funlock_async::decl(),
("op_umask", op_sync(op_umask)), op_umask::decl(),
("op_chdir", op_sync(op_chdir)), op_chdir::decl(),
("op_mkdir_sync", op_sync(op_mkdir_sync)), op_mkdir_sync::decl(),
("op_mkdir_async", op_async(op_mkdir_async)), op_mkdir_async::decl(),
("op_chmod_sync", op_sync(op_chmod_sync)), op_chmod_sync::decl(),
("op_chmod_async", op_async(op_chmod_async)), op_chmod_async::decl(),
("op_chown_sync", op_sync(op_chown_sync)), op_chown_sync::decl(),
("op_chown_async", op_async(op_chown_async)), op_chown_async::decl(),
("op_remove_sync", op_sync(op_remove_sync)), op_remove_sync::decl(),
("op_remove_async", op_async(op_remove_async)), op_remove_async::decl(),
("op_copy_file_sync", op_sync(op_copy_file_sync)), op_copy_file_sync::decl(),
("op_copy_file_async", op_async(op_copy_file_async)), op_copy_file_async::decl(),
("op_stat_sync", op_sync(op_stat_sync)), op_stat_sync::decl(),
("op_stat_async", op_async(op_stat_async)), op_stat_async::decl(),
("op_realpath_sync", op_sync(op_realpath_sync)), op_realpath_sync::decl(),
("op_realpath_async", op_async(op_realpath_async)), op_realpath_async::decl(),
("op_read_dir_sync", op_sync(op_read_dir_sync)), op_read_dir_sync::decl(),
("op_read_dir_async", op_async(op_read_dir_async)), op_read_dir_async::decl(),
("op_rename_sync", op_sync(op_rename_sync)), op_rename_sync::decl(),
("op_rename_async", op_async(op_rename_async)), op_rename_async::decl(),
("op_link_sync", op_sync(op_link_sync)), op_link_sync::decl(),
("op_link_async", op_async(op_link_async)), op_link_async::decl(),
("op_symlink_sync", op_sync(op_symlink_sync)), op_symlink_sync::decl(),
("op_symlink_async", op_async(op_symlink_async)), op_symlink_async::decl(),
("op_read_link_sync", op_sync(op_read_link_sync)), op_read_link_sync::decl(),
("op_read_link_async", op_async(op_read_link_async)), op_read_link_async::decl(),
("op_ftruncate_sync", op_sync(op_ftruncate_sync)), op_ftruncate_sync::decl(),
("op_ftruncate_async", op_async(op_ftruncate_async)), op_ftruncate_async::decl(),
("op_truncate_sync", op_sync(op_truncate_sync)), op_truncate_sync::decl(),
("op_truncate_async", op_async(op_truncate_async)), op_truncate_async::decl(),
("op_make_temp_dir_sync", op_sync(op_make_temp_dir_sync)), op_make_temp_dir_sync::decl(),
("op_make_temp_dir_async", op_async(op_make_temp_dir_async)), op_make_temp_dir_async::decl(),
("op_make_temp_file_sync", op_sync(op_make_temp_file_sync)), op_make_temp_file_sync::decl(),
("op_make_temp_file_async", op_async(op_make_temp_file_async)), op_make_temp_file_async::decl(),
("op_cwd", op_sync(op_cwd)), op_cwd::decl(),
("op_futime_sync", op_sync(op_futime_sync)), op_futime_sync::decl(),
("op_futime_async", op_async(op_futime_async)), op_futime_async::decl(),
("op_utime_sync", op_sync(op_utime_sync)), op_utime_sync::decl(),
("op_utime_async", op_async(op_utime_async)), op_utime_async::decl(),
]) ])
.build() .build()
} }
@ -157,6 +157,7 @@ fn open_helper(
Ok((path, open_options)) Ok((path, open_options))
} }
#[op]
fn op_open_sync( fn op_open_sync(
state: &mut OpState, state: &mut OpState,
args: OpenArgs, args: OpenArgs,
@ -172,6 +173,7 @@ fn op_open_sync(
Ok(rid) Ok(rid)
} }
#[op]
async fn op_open_async( async fn op_open_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: OpenArgs, args: OpenArgs,
@ -214,6 +216,7 @@ fn seek_helper(args: SeekArgs) -> Result<(u32, SeekFrom), AnyError> {
Ok((rid, seek_from)) Ok((rid, seek_from))
} }
#[op]
fn op_seek_sync( fn op_seek_sync(
state: &mut OpState, state: &mut OpState,
args: SeekArgs, args: SeekArgs,
@ -229,6 +232,7 @@ fn op_seek_sync(
Ok(pos) Ok(pos)
} }
#[op]
async fn op_seek_async( async fn op_seek_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: SeekArgs, args: SeekArgs,
@ -253,6 +257,7 @@ async fn op_seek_async(
Ok(pos) Ok(pos)
} }
#[op]
fn op_fdatasync_sync( fn op_fdatasync_sync(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -265,6 +270,7 @@ fn op_fdatasync_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_fdatasync_async( async fn op_fdatasync_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -287,6 +293,7 @@ async fn op_fdatasync_async(
Ok(()) Ok(())
} }
#[op]
fn op_fsync_sync( fn op_fsync_sync(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -299,6 +306,7 @@ fn op_fsync_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_fsync_async( async fn op_fsync_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -321,6 +329,7 @@ async fn op_fsync_async(
Ok(()) Ok(())
} }
#[op]
fn op_fstat_sync( fn op_fstat_sync(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -333,6 +342,7 @@ fn op_fstat_sync(
Ok(get_stat(metadata)) Ok(get_stat(metadata))
} }
#[op]
async fn op_fstat_async( async fn op_fstat_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -355,6 +365,7 @@ async fn op_fstat_async(
Ok(get_stat(metadata)) Ok(get_stat(metadata))
} }
#[op]
fn op_flock_sync( fn op_flock_sync(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -376,6 +387,7 @@ fn op_flock_sync(
}) })
} }
#[op]
async fn op_flock_async( async fn op_flock_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -416,6 +428,7 @@ async fn op_flock_async(
.await? .await?
} }
#[op]
fn op_funlock_sync( fn op_funlock_sync(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -433,6 +446,7 @@ fn op_funlock_sync(
}) })
} }
#[op]
async fn op_funlock_async( async fn op_funlock_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -469,6 +483,7 @@ async fn op_funlock_async(
.await? .await?
} }
#[op]
fn op_umask( fn op_umask(
state: &mut OpState, state: &mut OpState,
mask: Option<u32>, mask: Option<u32>,
@ -501,6 +516,7 @@ fn op_umask(
} }
} }
#[op]
fn op_chdir( fn op_chdir(
state: &mut OpState, state: &mut OpState,
directory: String, directory: String,
@ -522,6 +538,7 @@ pub struct MkdirArgs {
mode: Option<u32>, mode: Option<u32>,
} }
#[op]
fn op_mkdir_sync( fn op_mkdir_sync(
state: &mut OpState, state: &mut OpState,
args: MkdirArgs, args: MkdirArgs,
@ -544,6 +561,7 @@ fn op_mkdir_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_mkdir_async( async fn op_mkdir_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: MkdirArgs, args: MkdirArgs,
@ -582,6 +600,7 @@ pub struct ChmodArgs {
mode: u32, mode: u32,
} }
#[op]
fn op_chmod_sync( fn op_chmod_sync(
state: &mut OpState, state: &mut OpState,
args: ChmodArgs, args: ChmodArgs,
@ -611,6 +630,7 @@ fn op_chmod_sync(
} }
} }
#[op]
async fn op_chmod_async( async fn op_chmod_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: ChmodArgs, args: ChmodArgs,
@ -656,6 +676,7 @@ pub struct ChownArgs {
gid: Option<u32>, gid: Option<u32>,
} }
#[op]
fn op_chown_sync( fn op_chown_sync(
state: &mut OpState, state: &mut OpState,
args: ChownArgs, args: ChownArgs,
@ -690,6 +711,7 @@ fn op_chown_sync(
} }
} }
#[op]
async fn op_chown_async( async fn op_chown_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: ChownArgs, args: ChownArgs,
@ -738,6 +760,7 @@ pub struct RemoveArgs {
recursive: bool, recursive: bool,
} }
#[op]
fn op_remove_sync( fn op_remove_sync(
state: &mut OpState, state: &mut OpState,
args: RemoveArgs, args: RemoveArgs,
@ -783,6 +806,7 @@ fn op_remove_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_remove_async( async fn op_remove_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: RemoveArgs, args: RemoveArgs,
@ -841,6 +865,7 @@ pub struct CopyFileArgs {
to: String, to: String,
} }
#[op]
fn op_copy_file_sync( fn op_copy_file_sync(
state: &mut OpState, state: &mut OpState,
args: CopyFileArgs, args: CopyFileArgs,
@ -879,6 +904,7 @@ fn op_copy_file_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_copy_file_async( async fn op_copy_file_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: CopyFileArgs, args: CopyFileArgs,
@ -1007,6 +1033,7 @@ pub struct StatArgs {
lstat: bool, lstat: bool,
} }
#[op]
fn op_stat_sync( fn op_stat_sync(
state: &mut OpState, state: &mut OpState,
args: StatArgs, args: StatArgs,
@ -1027,6 +1054,7 @@ fn op_stat_sync(
Ok(get_stat(metadata)) Ok(get_stat(metadata))
} }
#[op]
async fn op_stat_async( async fn op_stat_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: StatArgs, args: StatArgs,
@ -1056,6 +1084,7 @@ async fn op_stat_async(
.unwrap() .unwrap()
} }
#[op]
fn op_realpath_sync( fn op_realpath_sync(
state: &mut OpState, state: &mut OpState,
path: String, path: String,
@ -1077,6 +1106,7 @@ fn op_realpath_sync(
Ok(realpath_str) Ok(realpath_str)
} }
#[op]
async fn op_realpath_async( async fn op_realpath_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
path: String, path: String,
@ -1114,6 +1144,7 @@ pub struct DirEntry {
is_symlink: bool, is_symlink: bool,
} }
#[op]
fn op_read_dir_sync( fn op_read_dir_sync(
state: &mut OpState, state: &mut OpState,
path: String, path: String,
@ -1154,6 +1185,7 @@ fn op_read_dir_sync(
Ok(entries) Ok(entries)
} }
#[op]
async fn op_read_dir_async( async fn op_read_dir_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
path: String, path: String,
@ -1206,6 +1238,7 @@ pub struct RenameArgs {
newpath: String, newpath: String,
} }
#[op]
fn op_rename_sync( fn op_rename_sync(
state: &mut OpState, state: &mut OpState,
args: RenameArgs, args: RenameArgs,
@ -1234,6 +1267,7 @@ fn op_rename_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_rename_async( async fn op_rename_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: RenameArgs, args: RenameArgs,
@ -1279,6 +1313,7 @@ pub struct LinkArgs {
newpath: String, newpath: String,
} }
#[op]
fn op_link_sync( fn op_link_sync(
state: &mut OpState, state: &mut OpState,
args: LinkArgs, args: LinkArgs,
@ -1309,6 +1344,7 @@ fn op_link_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_link_async( async fn op_link_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: LinkArgs, args: LinkArgs,
@ -1362,6 +1398,7 @@ pub struct SymlinkOptions {
_type: String, _type: String,
} }
#[op]
fn op_symlink_sync( fn op_symlink_sync(
state: &mut OpState, state: &mut OpState,
args: SymlinkArgs, args: SymlinkArgs,
@ -1423,6 +1460,7 @@ fn op_symlink_sync(
} }
} }
#[op]
async fn op_symlink_async( async fn op_symlink_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: SymlinkArgs, args: SymlinkArgs,
@ -1487,6 +1525,7 @@ async fn op_symlink_async(
.unwrap() .unwrap()
} }
#[op]
fn op_read_link_sync( fn op_read_link_sync(
state: &mut OpState, state: &mut OpState,
path: String, path: String,
@ -1510,6 +1549,7 @@ fn op_read_link_sync(
Ok(targetstr) Ok(targetstr)
} }
#[op]
async fn op_read_link_async( async fn op_read_link_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
path: String, path: String,
@ -1545,6 +1585,7 @@ pub struct FtruncateArgs {
len: i32, len: i32,
} }
#[op]
fn op_ftruncate_sync( fn op_ftruncate_sync(
state: &mut OpState, state: &mut OpState,
args: FtruncateArgs, args: FtruncateArgs,
@ -1559,6 +1600,7 @@ fn op_ftruncate_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_ftruncate_async( async fn op_ftruncate_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: FtruncateArgs, args: FtruncateArgs,
@ -1591,6 +1633,7 @@ pub struct TruncateArgs {
len: u64, len: u64,
} }
#[op]
fn op_truncate_sync( fn op_truncate_sync(
state: &mut OpState, state: &mut OpState,
args: TruncateArgs, args: TruncateArgs,
@ -1616,6 +1659,7 @@ fn op_truncate_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_truncate_async( async fn op_truncate_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: TruncateArgs, args: TruncateArgs,
@ -1699,6 +1743,7 @@ pub struct MakeTempArgs {
suffix: Option<String>, suffix: Option<String>,
} }
#[op]
fn op_make_temp_dir_sync( fn op_make_temp_dir_sync(
state: &mut OpState, state: &mut OpState,
args: MakeTempArgs, args: MakeTempArgs,
@ -1728,6 +1773,7 @@ fn op_make_temp_dir_sync(
Ok(path_str) Ok(path_str)
} }
#[op]
async fn op_make_temp_dir_async( async fn op_make_temp_dir_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: MakeTempArgs, args: MakeTempArgs,
@ -1762,6 +1808,7 @@ async fn op_make_temp_dir_async(
.unwrap() .unwrap()
} }
#[op]
fn op_make_temp_file_sync( fn op_make_temp_file_sync(
state: &mut OpState, state: &mut OpState,
args: MakeTempArgs, args: MakeTempArgs,
@ -1791,6 +1838,7 @@ fn op_make_temp_file_sync(
Ok(path_str) Ok(path_str)
} }
#[op]
async fn op_make_temp_file_async( async fn op_make_temp_file_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: MakeTempArgs, args: MakeTempArgs,
@ -1833,6 +1881,7 @@ pub struct FutimeArgs {
mtime: (i64, u32), mtime: (i64, u32),
} }
#[op]
fn op_futime_sync( fn op_futime_sync(
state: &mut OpState, state: &mut OpState,
args: FutimeArgs, args: FutimeArgs,
@ -1856,6 +1905,7 @@ fn op_futime_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_futime_async( async fn op_futime_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: FutimeArgs, args: FutimeArgs,
@ -1904,6 +1954,7 @@ pub struct UtimeArgs {
mtime: (i64, u32), mtime: (i64, u32),
} }
#[op]
fn op_utime_sync( fn op_utime_sync(
state: &mut OpState, state: &mut OpState,
args: UtimeArgs, args: UtimeArgs,
@ -1922,6 +1973,7 @@ fn op_utime_sync(
Ok(()) Ok(())
} }
#[op]
async fn op_utime_async( async fn op_utime_async(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
args: UtimeArgs, args: UtimeArgs,
@ -1949,6 +2001,7 @@ async fn op_utime_async(
.unwrap() .unwrap()
} }
#[op]
fn op_cwd(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> { fn op_cwd(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
let path = current_dir()?; let path = current_dir()?;
state state

View file

@ -11,8 +11,8 @@ use deno_core::RcRef;
use deno_core::Resource; use deno_core::Resource;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::Extension; use deno_core::Extension;
use notify::event::Event as NotifyEvent; use notify::event::Event as NotifyEvent;
use notify::Error as NotifyError; use notify::Error as NotifyError;
@ -31,10 +31,7 @@ use tokio::sync::mpsc;
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![op_fs_events_open::decl(), op_fs_events_poll::decl()])
("op_fs_events_open", op_sync(op_fs_events_open)),
("op_fs_events_poll", op_async(op_fs_events_poll)),
])
.build() .build()
} }
@ -97,6 +94,7 @@ pub struct OpenArgs {
paths: Vec<String>, paths: Vec<String>,
} }
#[op]
fn op_fs_events_open( fn op_fs_events_open(
state: &mut OpState, state: &mut OpState,
args: OpenArgs, args: OpenArgs,
@ -131,6 +129,7 @@ fn op_fs_events_open(
Ok(rid) Ok(rid)
} }
#[op]
async fn op_fs_events_poll( async fn op_fs_events_poll(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,

View file

@ -2,7 +2,7 @@ use std::rc::Rc;
use deno_core::error::bad_resource_id; use deno_core::error::bad_resource_id;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_sync; use deno_core::op;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
use deno_core::ResourceId; use deno_core::ResourceId;
@ -12,10 +12,11 @@ use deno_net::ops_tls::TlsStreamResource;
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![("op_http_start", op_sync(op_http_start))]) .ops(vec![op_http_start::decl()])
.build() .build()
} }
#[op]
fn op_http_start( fn op_http_start(
state: &mut OpState, state: &mut OpState,
tcp_stream_rid: ResourceId, tcp_stream_rid: ResourceId,

View file

@ -3,7 +3,7 @@
use deno_core::error::not_supported; use deno_core::error::not_supported;
use deno_core::error::resource_unavailable; use deno_core::error::resource_unavailable;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_sync; use deno_core::op;
use deno_core::AsyncMutFuture; use deno_core::AsyncMutFuture;
use deno_core::AsyncRefCell; use deno_core::AsyncRefCell;
use deno_core::AsyncResult; use deno_core::AsyncResult;
@ -69,10 +69,7 @@ static STDERR_HANDLE: Lazy<StdFile> = Lazy::new(|| unsafe {
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![op_read_sync::decl(), op_write_sync::decl()])
("op_read_sync", op_sync(op_read_sync)),
("op_write_sync", op_sync(op_write_sync)),
])
.build() .build()
} }
@ -354,6 +351,7 @@ impl Resource for StdFileResource {
} }
} }
#[op]
fn op_read_sync( fn op_read_sync(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -368,6 +366,7 @@ fn op_read_sync(
}) })
} }
#[op]
fn op_write_sync( fn op_write_sync(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,

View file

@ -3,7 +3,7 @@
use super::utils::into_string; use super::utils::into_string;
use crate::permissions::Permissions; use crate::permissions::Permissions;
use deno_core::error::{type_error, AnyError}; use deno_core::error::{type_error, AnyError};
use deno_core::op_sync; use deno_core::op;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
@ -17,19 +17,19 @@ use std::sync::Arc;
pub fn init(maybe_exit_code: Option<Arc<AtomicI32>>) -> Extension { pub fn init(maybe_exit_code: Option<Arc<AtomicI32>>) -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
("op_env", op_sync(op_env)), op_env::decl(),
("op_exec_path", op_sync(op_exec_path)), op_exec_path::decl(),
("op_exit", op_sync(op_exit)), op_exit::decl(),
("op_delete_env", op_sync(op_delete_env)), op_delete_env::decl(),
("op_get_env", op_sync(op_get_env)), op_get_env::decl(),
("op_getuid", op_sync(op_getuid)), op_getuid::decl(),
("op_hostname", op_sync(op_hostname)), op_hostname::decl(),
("op_loadavg", op_sync(op_loadavg)), op_loadavg::decl(),
("op_network_interfaces", op_sync(op_network_interfaces)), op_network_interfaces::decl(),
("op_os_release", op_sync(op_os_release)), op_os_release::decl(),
("op_set_env", op_sync(op_set_env)), op_set_env::decl(),
("op_set_exit_code", op_sync(op_set_exit_code)), op_set_exit_code::decl(),
("op_system_memory_info", op_sync(op_system_memory_info)), op_system_memory_info::decl(),
]) ])
.state(move |state| { .state(move |state| {
let exit_code = maybe_exit_code.clone().unwrap_or_default(); 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() .build()
} }
#[op]
fn op_exec_path(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> { fn op_exec_path(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
let current_exe = env::current_exe().unwrap(); let current_exe = env::current_exe().unwrap();
state state
@ -53,6 +54,7 @@ fn op_exec_path(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
into_string(path.into_os_string()) into_string(path.into_os_string())
} }
#[op]
fn op_set_env( fn op_set_env(
state: &mut OpState, state: &mut OpState,
key: String, key: String,
@ -68,6 +70,7 @@ fn op_set_env(
Ok(()) Ok(())
} }
#[op]
fn op_env( fn op_env(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -77,6 +80,7 @@ fn op_env(
Ok(env::vars().collect()) Ok(env::vars().collect())
} }
#[op]
fn op_get_env( fn op_get_env(
state: &mut OpState, state: &mut OpState,
key: String, key: String,
@ -93,6 +97,7 @@ fn op_get_env(
Ok(r) Ok(r)
} }
#[op]
fn op_delete_env( fn op_delete_env(
state: &mut OpState, state: &mut OpState,
key: String, key: String,
@ -106,6 +111,7 @@ fn op_delete_env(
Ok(()) Ok(())
} }
#[op]
fn op_set_exit_code( fn op_set_exit_code(
state: &mut OpState, state: &mut OpState,
code: i32, code: i32,
@ -115,11 +121,13 @@ fn op_set_exit_code(
Ok(()) Ok(())
} }
#[op]
fn op_exit(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> { fn op_exit(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
let code = state.borrow::<Arc<AtomicI32>>().load(Relaxed); let code = state.borrow::<Arc<AtomicI32>>().load(Relaxed);
std::process::exit(code) std::process::exit(code)
} }
#[op]
fn op_loadavg( fn op_loadavg(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -133,6 +141,7 @@ fn op_loadavg(
} }
} }
#[op]
fn op_hostname(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> { fn op_hostname(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
super::check_unstable(state, "Deno.hostname"); super::check_unstable(state, "Deno.hostname");
state.borrow_mut::<Permissions>().env.check_all()?; state.borrow_mut::<Permissions>().env.check_all()?;
@ -140,6 +149,7 @@ fn op_hostname(state: &mut OpState, _: (), _: ()) -> Result<String, AnyError> {
Ok(hostname) Ok(hostname)
} }
#[op]
fn op_os_release( fn op_os_release(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -151,6 +161,7 @@ fn op_os_release(
Ok(release) Ok(release)
} }
#[op]
fn op_network_interfaces( fn op_network_interfaces(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -218,6 +229,7 @@ struct MemInfo {
pub swap_free: u64, pub swap_free: u64,
} }
#[op]
fn op_system_memory_info( fn op_system_memory_info(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -240,6 +252,7 @@ fn op_system_memory_info(
} }
#[cfg(not(windows))] #[cfg(not(windows))]
#[op]
fn op_getuid( fn op_getuid(
state: &mut OpState, state: &mut OpState,
_: (), _: (),
@ -251,6 +264,7 @@ fn op_getuid(
} }
#[cfg(windows)] #[cfg(windows)]
#[op]
fn op_getuid( fn op_getuid(
state: &mut OpState, state: &mut OpState,
_: (), _: (),

View file

@ -4,7 +4,7 @@ use crate::permissions::Permissions;
use deno_core::error::custom_error; use deno_core::error::custom_error;
use deno_core::error::uri_error; use deno_core::error::uri_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_sync; use deno_core::op;
use deno_core::url; use deno_core::url;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
@ -14,9 +14,9 @@ use std::path::Path;
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
("op_query_permission", op_sync(op_query_permission)), op_query_permission::decl(),
("op_revoke_permission", op_sync(op_revoke_permission)), op_revoke_permission::decl(),
("op_request_permission", op_sync(op_request_permission)), op_request_permission::decl(),
]) ])
.build() .build()
} }
@ -30,6 +30,7 @@ pub struct PermissionArgs {
command: Option<String>, command: Option<String>,
} }
#[op]
pub fn op_query_permission( pub fn op_query_permission(
state: &mut OpState, state: &mut OpState,
args: PermissionArgs, args: PermissionArgs,
@ -61,6 +62,7 @@ pub fn op_query_permission(
Ok(perm.to_string()) Ok(perm.to_string())
} }
#[op]
pub fn op_revoke_permission( pub fn op_revoke_permission(
state: &mut OpState, state: &mut OpState,
args: PermissionArgs, args: PermissionArgs,
@ -92,6 +94,7 @@ pub fn op_revoke_permission(
Ok(perm.to_string()) Ok(perm.to_string())
} }
#[op]
pub fn op_request_permission( pub fn op_request_permission(
state: &mut OpState, state: &mut OpState,
args: PermissionArgs, args: PermissionArgs,

View file

@ -8,8 +8,8 @@ use crate::permissions::Permissions;
use deno_core::error::bad_resource_id; use deno_core::error::bad_resource_id;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::AsyncMutFuture; use deno_core::AsyncMutFuture;
use deno_core::AsyncRefCell; use deno_core::AsyncRefCell;
use deno_core::Extension; use deno_core::Extension;
@ -29,11 +29,7 @@ use std::os::unix::process::ExitStatusExt;
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![op_run::decl(), op_run_status::decl(), op_kill::decl()])
("op_run", op_sync(op_run)),
("op_run_status", op_async(op_run_status)),
("op_kill", op_sync(op_kill)),
])
.build() .build()
} }
@ -102,6 +98,7 @@ struct RunInfo {
stderr_rid: Option<ResourceId>, stderr_rid: Option<ResourceId>,
} }
#[op]
fn op_run( fn op_run(
state: &mut OpState, state: &mut OpState,
run_args: RunArgs, run_args: RunArgs,
@ -226,6 +223,7 @@ struct ProcessStatus {
exit_signal: i32, exit_signal: i32,
} }
#[op]
async fn op_run_status( async fn op_run_status(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -303,6 +301,7 @@ pub fn kill(pid: i32, signal: &str) -> Result<(), AnyError> {
} }
} }
#[op]
fn op_kill( fn op_kill(
state: &mut OpState, state: &mut OpState,
pid: i32, pid: i32,

View file

@ -3,14 +3,14 @@
use crate::permissions::Permissions; use crate::permissions::Permissions;
use deno_core::anyhow::Context; use deno_core::anyhow::Context;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_sync; use deno_core::op;
use deno_core::Extension; use deno_core::Extension;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::OpState; use deno_core::OpState;
pub fn init(main_module: ModuleSpecifier) -> Extension { pub fn init(main_module: ModuleSpecifier) -> Extension {
Extension::builder() Extension::builder()
.ops(vec![("op_main_module", op_sync(op_main_module))]) .ops(vec![op_main_module::decl()])
.state(move |state| { .state(move |state| {
state.put::<ModuleSpecifier>(main_module.clone()); state.put::<ModuleSpecifier>(main_module.clone());
Ok(()) Ok(())
@ -18,6 +18,7 @@ pub fn init(main_module: ModuleSpecifier) -> Extension {
.build() .build()
} }
#[op]
fn op_main_module( fn op_main_module(
state: &mut OpState, state: &mut OpState,
_: (), _: (),

View file

@ -4,8 +4,8 @@ use deno_core::error::generic_error;
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
use std::cell::RefCell; use std::cell::RefCell;
@ -31,9 +31,9 @@ use tokio::signal::unix::{signal, Signal, SignalKind};
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
("op_signal_bind", op_sync(op_signal_bind)), op_signal_bind::decl(),
("op_signal_unbind", op_sync(op_signal_unbind)), op_signal_unbind::decl(),
("op_signal_poll", op_async(op_signal_poll)), op_signal_poll::decl(),
]) ])
.build() .build()
} }
@ -174,6 +174,7 @@ pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
} }
#[cfg(unix)] #[cfg(unix)]
#[op]
fn op_signal_bind( fn op_signal_bind(
state: &mut OpState, state: &mut OpState,
sig: String, sig: String,
@ -195,6 +196,7 @@ fn op_signal_bind(
} }
#[cfg(unix)] #[cfg(unix)]
#[op]
async fn op_signal_poll( async fn op_signal_poll(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
rid: ResourceId, rid: ResourceId,
@ -214,6 +216,7 @@ async fn op_signal_poll(
} }
#[cfg(unix)] #[cfg(unix)]
#[op]
pub fn op_signal_unbind( pub fn op_signal_unbind(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -224,6 +227,7 @@ pub fn op_signal_unbind(
} }
#[cfg(not(unix))] #[cfg(not(unix))]
#[op]
pub fn op_signal_bind( pub fn op_signal_bind(
_state: &mut OpState, _state: &mut OpState,
_: (), _: (),
@ -233,6 +237,7 @@ pub fn op_signal_bind(
} }
#[cfg(not(unix))] #[cfg(not(unix))]
#[op]
fn op_signal_unbind( fn op_signal_unbind(
_state: &mut OpState, _state: &mut OpState,
_: (), _: (),
@ -242,6 +247,7 @@ fn op_signal_unbind(
} }
#[cfg(not(unix))] #[cfg(not(unix))]
#[op]
async fn op_signal_poll( async fn op_signal_poll(
_state: Rc<RefCell<OpState>>, _state: Rc<RefCell<OpState>>,
_: (), _: (),

View file

@ -5,7 +5,7 @@ use deno_core::error::bad_resource_id;
use deno_core::error::not_supported; use deno_core::error::not_supported;
use deno_core::error::resource_unavailable; use deno_core::error::resource_unavailable;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_sync; use deno_core::op;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
use deno_core::RcRef; use deno_core::RcRef;
@ -47,9 +47,9 @@ fn get_windows_handle(
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
("op_set_raw", op_sync(op_set_raw)), op_set_raw::decl(),
("op_isatty", op_sync(op_isatty)), op_isatty::decl(),
("op_console_size", op_sync(op_console_size)), op_console_size::decl(),
]) ])
.build() .build()
} }
@ -67,6 +67,7 @@ pub struct SetRawArgs {
options: SetRawOptions, options: SetRawOptions,
} }
#[op]
fn op_set_raw( fn op_set_raw(
state: &mut OpState, state: &mut OpState,
args: SetRawArgs, args: SetRawArgs,
@ -211,6 +212,7 @@ fn op_set_raw(
} }
} }
#[op]
fn op_isatty( fn op_isatty(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,
@ -245,6 +247,7 @@ struct ConsoleSize {
rows: u32, rows: u32,
} }
#[op]
fn op_console_size( fn op_console_size(
state: &mut OpState, state: &mut OpState,
rid: ResourceId, rid: ResourceId,

View file

@ -5,8 +5,8 @@ mod sync_fetch;
use crate::web_worker::WebWorkerInternalHandle; use crate::web_worker::WebWorkerInternalHandle;
use crate::web_worker::WebWorkerType; use crate::web_worker::WebWorkerType;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::CancelFuture; use deno_core::CancelFuture;
use deno_core::Extension; use deno_core::Extension;
use deno_core::OpState; use deno_core::OpState;
@ -19,16 +19,17 @@ use self::sync_fetch::op_worker_sync_fetch;
pub fn init() -> Extension { pub fn init() -> Extension {
Extension::builder() Extension::builder()
.ops(vec![ .ops(vec![
("op_worker_post_message", op_sync(op_worker_post_message)), op_worker_post_message::decl(),
("op_worker_recv_message", op_async(op_worker_recv_message)), op_worker_recv_message::decl(),
// Notify host that guest worker closes. // Notify host that guest worker closes.
("op_worker_close", op_sync(op_worker_close)), op_worker_close::decl(),
("op_worker_get_type", op_sync(op_worker_get_type)), op_worker_get_type::decl(),
("op_worker_sync_fetch", op_sync(op_worker_sync_fetch)), op_worker_sync_fetch::decl(),
]) ])
.build() .build()
} }
#[op]
fn op_worker_post_message( fn op_worker_post_message(
state: &mut OpState, state: &mut OpState,
data: JsMessageData, data: JsMessageData,
@ -39,6 +40,7 @@ fn op_worker_post_message(
Ok(()) Ok(())
} }
#[op]
async fn op_worker_recv_message( async fn op_worker_recv_message(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
_: (), _: (),
@ -55,6 +57,7 @@ async fn op_worker_recv_message(
.await? .await?
} }
#[op]
fn op_worker_close(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> { fn op_worker_close(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
// Notify parent that we're finished // Notify parent that we're finished
let mut handle = state.borrow_mut::<WebWorkerInternalHandle>().clone(); let mut handle = state.borrow_mut::<WebWorkerInternalHandle>().clone();
@ -63,6 +66,7 @@ fn op_worker_close(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
Ok(()) Ok(())
} }
#[op]
fn op_worker_get_type( fn op_worker_get_type(
state: &mut OpState, state: &mut OpState,
_: (), _: (),

View file

@ -4,6 +4,7 @@ use crate::web_worker::WebWorkerInternalHandle;
use crate::web_worker::WebWorkerType; use crate::web_worker::WebWorkerType;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::OpState; use deno_core::OpState;
use deno_fetch::data_url::DataUrl; use deno_fetch::data_url::DataUrl;
@ -30,6 +31,7 @@ pub struct SyncFetchScript {
script: String, script: String,
} }
#[op]
pub fn op_worker_sync_fetch( pub fn op_worker_sync_fetch(
state: &mut OpState, state: &mut OpState,
scripts: Vec<String>, scripts: Vec<String>,

View file

@ -13,8 +13,8 @@ use crate::web_worker::WorkerControlEvent;
use crate::web_worker::WorkerId; use crate::web_worker::WorkerId;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures::future::LocalFutureObj; use deno_core::futures::future::LocalFutureObj;
use deno_core::op_async; use deno_core::op;
use deno_core::op_sync;
use deno_core::serde::Deserialize; use deno_core::serde::Deserialize;
use deno_core::Extension; use deno_core::Extension;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
@ -122,14 +122,11 @@ pub fn init(
Ok(()) Ok(())
}) })
.ops(vec![ .ops(vec![
("op_create_worker", op_sync(op_create_worker)), op_create_worker::decl(),
( op_host_terminate_worker::decl(),
"op_host_terminate_worker", op_host_post_message::decl(),
op_sync(op_host_terminate_worker), op_host_recv_ctrl::decl(),
), op_host_recv_message::decl(),
("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)),
]) ])
.build() .build()
} }
@ -147,6 +144,7 @@ pub struct CreateWorkerArgs {
} }
/// Create worker as the host /// Create worker as the host
#[op]
fn op_create_worker( fn op_create_worker(
state: &mut OpState, state: &mut OpState,
args: CreateWorkerArgs, args: CreateWorkerArgs,
@ -263,6 +261,7 @@ fn op_create_worker(
Ok(worker_id) Ok(worker_id)
} }
#[op]
fn op_host_terminate_worker( fn op_host_terminate_worker(
state: &mut OpState, state: &mut OpState,
id: WorkerId, id: WorkerId,
@ -317,6 +316,7 @@ fn close_channel(
} }
/// Get control event from guest worker as host /// Get control event from guest worker as host
#[op]
async fn op_host_recv_ctrl( async fn op_host_recv_ctrl(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
id: WorkerId, id: WorkerId,
@ -348,6 +348,7 @@ async fn op_host_recv_ctrl(
Ok(WorkerControlEvent::Close) Ok(WorkerControlEvent::Close)
} }
#[op]
async fn op_host_recv_message( async fn op_host_recv_message(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
id: WorkerId, id: WorkerId,
@ -373,6 +374,7 @@ async fn op_host_recv_message(
} }
/// Post message to guest worker as host /// Post message to guest worker as host
#[op]
fn op_host_post_message( fn op_host_post_message(
state: &mut OpState, state: &mut OpState,
id: WorkerId, id: WorkerId,