diff --git a/ops/fast_call.rs b/ops/fast_call.rs index c6daa5339a..8f6348ec45 100644 --- a/ops/fast_call.rs +++ b/ops/fast_call.rs @@ -422,49 +422,3 @@ fn exclude_lifetime_params( where_clause: None, }) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::{Attributes, Op}; - use std::path::PathBuf; - - #[testing_macros::fixture("optimizer_tests/**/*.rs")] - fn test_fast_call_codegen(input: PathBuf) { - let update_expected = std::env::var("UPDATE_EXPECTED").is_ok(); - let core = quote!(deno_core); - - let source = - std::fs::read_to_string(&input).expect("Failed to read test file"); - - let mut attrs = Attributes::default(); - if source.contains("// @test-attr:fast") { - attrs.must_be_fast = true; - } - - let item = syn::parse_str(&source).expect("Failed to parse test file"); - let mut op = Op::new(item, attrs); - let mut optimizer = Optimizer::new(); - if optimizer.analyze(&mut op).is_err() { - // Tested by optimizer::test tests. - return; - } - - let expected = std::fs::read_to_string(input.with_extension("out")) - .expect("Failed to read expected file"); - - let FastImplItems { - impl_and_fn: actual, - .. - } = generate(&core, &mut optimizer, &op.item); - // Validate syntax tree. - let tree = syn::parse2(actual).unwrap(); - let actual = prettyplease::unparse(&tree); - if update_expected { - std::fs::write(input.with_extension("out"), actual) - .expect("Failed to write expected file"); - } else { - assert_eq!(actual, expected); - } - } -} diff --git a/ops/lib.rs b/ops/lib.rs index 9b0cc6a8ae..a5c196c047 100644 --- a/ops/lib.rs +++ b/ops/lib.rs @@ -725,3 +725,39 @@ fn exclude_lifetime_params( .cloned() .collect::>() } + +#[cfg(test)] +mod tests { + use crate::{Attributes, Op}; + use std::path::PathBuf; + + #[testing_macros::fixture("optimizer_tests/**/*.rs")] + fn test_codegen(input: PathBuf) { + let update_expected = std::env::var("UPDATE_EXPECTED").is_ok(); + + let source = + std::fs::read_to_string(&input).expect("Failed to read test file"); + + let mut attrs = Attributes::default(); + if source.contains("// @test-attr:fast") { + attrs.must_be_fast = true; + } + + let item = syn::parse_str(&source).expect("Failed to parse test file"); + let op = Op::new(item, attrs); + + let expected = std::fs::read_to_string(input.with_extension("out")) + .expect("Failed to read expected output file"); + + let actual = op.gen(); + // Validate syntax tree. + let tree = syn::parse2(actual).unwrap(); + let actual = prettyplease::unparse(&tree); + if update_expected { + std::fs::write(input.with_extension("out"), actual) + .expect("Failed to write expected file"); + } else { + assert_eq!(actual, expected); + } + } +} diff --git a/ops/optimizer_tests/async_nop.out b/ops/optimizer_tests/async_nop.out index 901b8a2259..08f7a87a2c 100644 --- a/ops/optimizer_tests/async_nop.out +++ b/ops/optimizer_tests/async_nop.out @@ -1,3 +1,81 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_void_async::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_void_async; +#[doc(hidden)] +impl op_void_async { + pub fn name() -> &'static str { + stringify!(op_void_async) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_void_async_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: true, + is_unstable: false, + is_v8: false, + argc: 0usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + async fn call() {} + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + use deno_core::futures::FutureExt; + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let op_id = ctx.id; + let promise_id = args.get(0); + let promise_id = deno_core::v8::Local::< + deno_core::v8::Integer, + >::try_from(promise_id) + .map(|l| l.value() as deno_core::PromiseId) + .map_err(deno_core::anyhow::Error::from); + let promise_id: deno_core::PromiseId = match promise_id { + Ok(promise_id) => promise_id, + Err(err) => { + deno_core::_ops::throw_type_error( + scope, + format!("invalid promise id: {}", err), + ); + return; + } + }; + let get_class = { + let state = ::std::cell::RefCell::borrow(&ctx.state); + state.tracker.track_async(op_id); + state.get_error_class_fn + }; + deno_core::_ops::queue_async_op( + ctx, + scope, + false, + async move { + let result = Self::call().await; + let result = Ok(result); + (promise_id, op_id, deno_core::_ops::to_op_result(get_class, result)) + }, + ); + } +} struct op_void_async_fast { _phantom: ::std::marker::PhantomData<()>, } diff --git a/ops/optimizer_tests/async_result.out b/ops/optimizer_tests/async_result.out index d312fde732..b9719d22af 100644 --- a/ops/optimizer_tests/async_result.out +++ b/ops/optimizer_tests/async_result.out @@ -1,3 +1,140 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_read::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_read; +#[doc(hidden)] +impl op_read { + pub fn name() -> &'static str { + stringify!(op_read) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_read_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: true, + is_unstable: false, + is_v8: false, + argc: 2usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + async fn call( + state: Rc>, + rid: ResourceId, + buf: &mut [u8], + ) -> Result {} + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + use deno_core::futures::FutureExt; + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let op_id = ctx.id; + let promise_id = args.get(0); + let promise_id = deno_core::v8::Local::< + deno_core::v8::Integer, + >::try_from(promise_id) + .map(|l| l.value() as deno_core::PromiseId) + .map_err(deno_core::anyhow::Error::from); + let promise_id: deno_core::PromiseId = match promise_id { + Ok(promise_id) => promise_id, + Err(err) => { + deno_core::_ops::throw_type_error( + scope, + format!("invalid promise id: {}", err), + ); + return; + } + }; + let arg_0 = args.get(1usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 1usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let arg_1 = { + let value = args.get(2usize as i32); + match deno_core::v8::Local::::try_from(value) { + Ok(b) => { + let byte_length = b.byte_length(); + if let Some(data) = b.data() { + let store = data.cast::().as_ptr(); + unsafe { ::std::slice::from_raw_parts_mut(store, byte_length) } + } else { + &mut [] + } + } + Err(_) => { + if let Ok(view) + = deno_core::v8::Local::< + deno_core::v8::ArrayBufferView, + >::try_from(value) { + let len = view.byte_length(); + let offset = view.byte_offset(); + let buffer = match view.buffer(scope) { + Some(v) => v, + None => { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 2usize), + ); + } + }; + if let Some(data) = buffer.data() { + let store = data.cast::().as_ptr(); + unsafe { + ::std::slice::from_raw_parts_mut(store.add(offset), len) + } + } else { + &mut [] + } + } else { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 2usize), + ); + } + } + } + }; + let get_class = { + let state = ::std::cell::RefCell::borrow(&ctx.state); + state.tracker.track_async(op_id); + state.get_error_class_fn + }; + deno_core::_ops::queue_async_op( + ctx, + scope, + false, + async move { + let result = Self::call(ctx.state.clone(), arg_0, arg_1).await; + (promise_id, op_id, deno_core::_ops::to_op_result(get_class, result)) + }, + ); + } +} struct op_read_fast { _phantom: ::std::marker::PhantomData<()>, } diff --git a/ops/optimizer_tests/callback_options.out b/ops/optimizer_tests/callback_options.out index 426fe0c4aa..020cc4a3ef 100644 --- a/ops/optimizer_tests/callback_options.out +++ b/ops/optimizer_tests/callback_options.out @@ -1,3 +1,56 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_fallback::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_fallback; +#[doc(hidden)] +impl op_fallback { + pub fn name() -> &'static str { + stringify!(op_fallback) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_fallback_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 1usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(options: Option<&mut FastApiCallbackOptions>) { + if let Some(options) = options { + options.fallback = true; + } + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = None; + let result = Self::call(arg_0); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + } +} struct op_fallback_fast { _phantom: ::std::marker::PhantomData<()>, } diff --git a/ops/optimizer_tests/incompatible_1.out b/ops/optimizer_tests/incompatible_1.out new file mode 100644 index 0000000000..92cf4a5764 --- /dev/null +++ b/ops/optimizer_tests/incompatible_1.out @@ -0,0 +1,71 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_sync_serialize_object_with_numbers_as_keys::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_sync_serialize_object_with_numbers_as_keys; +#[doc(hidden)] +impl op_sync_serialize_object_with_numbers_as_keys { + pub fn name() -> &'static str { + stringify!(op_sync_serialize_object_with_numbers_as_keys) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: None, + is_async: false, + is_unstable: false, + is_v8: false, + argc: 1usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(value: serde_json::Value) -> Result<(), Error> { + assert_eq!( + value.to_string(), r#"{"lines":{"100":{"unit":"m"},"200":{"unit":"cm"}}}"# + ); + Ok(()) + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = args.get(0usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 0usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let result = Self::call(arg_0); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => {} + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +} diff --git a/ops/optimizer_tests/op_state.out b/ops/optimizer_tests/op_state.out index a98db68d84..5b273960a6 100644 --- a/ops/optimizer_tests/op_state.out +++ b/ops/optimizer_tests/op_state.out @@ -1,3 +1,64 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_set_exit_code::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_set_exit_code; +#[doc(hidden)] +impl op_set_exit_code { + pub fn name() -> &'static str { + stringify!(op_set_exit_code) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_set_exit_code_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 1usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(state: &mut OpState, code: i32) { + state.borrow_mut::().set(code); + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = args.get(0usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 0usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let result = Self::call(&mut std::cell::RefCell::borrow_mut(&ctx.state), arg_0); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + } +} struct op_set_exit_code_fast { _phantom: ::std::marker::PhantomData<()>, } diff --git a/ops/optimizer_tests/op_state_basic1.out b/ops/optimizer_tests/op_state_basic1.out index 0f03f2c586..ab3404a429 100644 --- a/ops/optimizer_tests/op_state_basic1.out +++ b/ops/optimizer_tests/op_state_basic1.out @@ -1,3 +1,91 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `foo::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct foo; +#[doc(hidden)] +impl foo { + pub fn name() -> &'static str { + stringify!(foo) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(foo_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 2usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(state: &mut OpState, a: u32, b: u32) -> u32 { + a + b + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = args.get(0usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 0usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let arg_1 = args.get(1usize as i32); + let arg_1 = match deno_core::serde_v8::from_v8(scope, arg_1) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 1usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let result = Self::call( + &mut std::cell::RefCell::borrow_mut(&ctx.state), + arg_0, + arg_1, + ); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match deno_core::serde_v8::to_v8(scope, result) { + Ok(ret) => rv.set(ret), + Err(err) => { + deno_core::_ops::throw_type_error( + scope, + format!( + "Error serializing return: {}", + deno_core::anyhow::Error::from(err) + ), + ) + } + }; + } +} struct foo_fast { _phantom: ::std::marker::PhantomData<()>, } diff --git a/ops/optimizer_tests/op_state_generics.out b/ops/optimizer_tests/op_state_generics.out index d141c74457..bd5e40afe8 100644 --- a/ops/optimizer_tests/op_state_generics.out +++ b/ops/optimizer_tests/op_state_generics.out @@ -1,3 +1,63 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_foo::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_foo; +#[doc(hidden)] +impl op_foo { + pub fn name() -> &'static str { + stringify!(op_foo) + } + pub fn v8_fn_ptr<'scope, SP>() -> deno_core::v8::FunctionCallback + where + SP: SomePermission + 'static, + { + use deno_core::v8::MapFnTo; + Self::v8_func::.map_fn_to() + } + pub fn decl<'scope, SP>() -> deno_core::OpDecl + where + SP: SomePermission + 'static, + { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr::(), + enabled: true, + fast_fn: Some( + Box::new(op_foo_fast:: { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 0usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + pub fn call(state: &mut OpState) + where + SP: SomePermission + 'static, + {} + pub fn v8_func<'scope, SP>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) + where + SP: SomePermission + 'static, + { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let result = Self::call::(&mut std::cell::RefCell::borrow_mut(&ctx.state)); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + } +} struct op_foo_fast { _phantom: ::std::marker::PhantomData, } diff --git a/ops/optimizer_tests/op_state_result.out b/ops/optimizer_tests/op_state_result.out index 5174dd7f2b..76070b5363 100644 --- a/ops/optimizer_tests/op_state_result.out +++ b/ops/optimizer_tests/op_state_result.out @@ -1,3 +1,104 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `foo::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct foo; +#[doc(hidden)] +impl foo { + pub fn name() -> &'static str { + stringify!(foo) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(foo_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 2usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(state: &mut OpState, a: u32, b: u32) -> Result { + Ok(a + b) + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + { + let op_state = &mut std::cell::RefCell::borrow_mut(&ctx.state); + if let Some(err) = op_state.last_fast_op_error.take() { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + return; + } + } + let arg_0 = args.get(0usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 0usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let arg_1 = args.get(1usize as i32); + let arg_1 = match deno_core::serde_v8::from_v8(scope, arg_1) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 1usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let result = Self::call( + &mut std::cell::RefCell::borrow_mut(&ctx.state), + arg_0, + arg_1, + ); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => { + rv.set_uint32(result as u32); + } + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +} struct foo_fast { _phantom: ::std::marker::PhantomData<()>, } diff --git a/ops/optimizer_tests/op_state_warning.out b/ops/optimizer_tests/op_state_warning.out index 2c40b0f714..9917fbf79d 100644 --- a/ops/optimizer_tests/op_state_warning.out +++ b/ops/optimizer_tests/op_state_warning.out @@ -1,3 +1,95 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_listen::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_listen; +#[doc(hidden)] +impl op_listen { + pub fn name() -> &'static str { + stringify!(op_listen) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_listen_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 0usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(state: &mut OpState) -> Result { + log::debug!("listen"); + let addr = "127.0.0.1:4570".parse::().unwrap(); + let std_listener = std::net::TcpListener::bind(&addr)?; + std_listener.set_nonblocking(true)?; + let listener = TcpListener::try_from(std_listener)?; + let rid = state.resource_table.add(listener); + Ok(rid) + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + { + let op_state = &mut std::cell::RefCell::borrow_mut(&ctx.state); + if let Some(err) = op_state.last_fast_op_error.take() { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + return; + } + } + let result = Self::call(&mut std::cell::RefCell::borrow_mut(&ctx.state)); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => { + match deno_core::serde_v8::to_v8(scope, result) { + Ok(ret) => rv.set(ret), + Err(err) => { + deno_core::_ops::throw_type_error( + scope, + format!( + "Error serializing return: {}", + deno_core::anyhow::Error::from(err) + ), + ) + } + }; + } + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +} struct op_listen_fast { _phantom: ::std::marker::PhantomData<()>, } diff --git a/ops/optimizer_tests/op_state_with_transforms.out b/ops/optimizer_tests/op_state_with_transforms.out index f981748be0..541a4fd36f 100644 --- a/ops/optimizer_tests/op_state_with_transforms.out +++ b/ops/optimizer_tests/op_state_with_transforms.out @@ -1,3 +1,110 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_now::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_now; +#[doc(hidden)] +impl op_now { + pub fn name() -> &'static str { + stringify!(op_now) + } + pub fn v8_fn_ptr<'scope, TP>() -> deno_core::v8::FunctionCallback + where + TP: TimersPermission + 'static, + { + use deno_core::v8::MapFnTo; + Self::v8_func::.map_fn_to() + } + pub fn decl<'scope, TP>() -> deno_core::OpDecl + where + TP: TimersPermission + 'static, + { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr::(), + enabled: true, + fast_fn: Some( + Box::new(op_now_fast:: { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 1usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + pub fn call(state: &mut OpState, buf: &mut [u8]) + where + TP: TimersPermission + 'static, + {} + pub fn v8_func<'scope, TP>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) + where + TP: TimersPermission + 'static, + { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = { + let value = args.get(0usize as i32); + match deno_core::v8::Local::::try_from(value) { + Ok(b) => { + let byte_length = b.byte_length(); + if let Some(data) = b.data() { + let store = data.cast::().as_ptr(); + unsafe { ::std::slice::from_raw_parts_mut(store, byte_length) } + } else { + &mut [] + } + } + Err(_) => { + if let Ok(view) + = deno_core::v8::Local::< + deno_core::v8::ArrayBufferView, + >::try_from(value) { + let len = view.byte_length(); + let offset = view.byte_offset(); + let buffer = match view.buffer(scope) { + Some(v) => v, + None => { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 0usize), + ); + } + }; + if let Some(data) = buffer.data() { + let store = data.cast::().as_ptr(); + unsafe { + ::std::slice::from_raw_parts_mut(store.add(offset), len) + } + } else { + &mut [] + } + } else { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 0usize), + ); + } + } + } + }; + let result = Self::call::< + TP, + >(&mut std::cell::RefCell::borrow_mut(&ctx.state), arg_0); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + } +} struct op_now_fast { _phantom: ::std::marker::PhantomData, } diff --git a/ops/optimizer_tests/opstate_with_arity.out b/ops/optimizer_tests/opstate_with_arity.out index 20b7769e75..132e54aeff 100644 --- a/ops/optimizer_tests/opstate_with_arity.out +++ b/ops/optimizer_tests/opstate_with_arity.out @@ -1,3 +1,122 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_add_4::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_add_4; +#[doc(hidden)] +impl op_add_4 { + pub fn name() -> &'static str { + stringify!(op_add_4) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_add_4_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 4usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(x1: u32, x2: u32, x3: u32, x4: u32) -> Result { + Ok(x1 + x2 + x3 + x4) + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + { + let op_state = &mut std::cell::RefCell::borrow_mut(&ctx.state); + if let Some(err) = op_state.last_fast_op_error.take() { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + return; + } + } + let arg_0 = args.get(0usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 0usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let arg_1 = args.get(1usize as i32); + let arg_1 = match deno_core::serde_v8::from_v8(scope, arg_1) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 1usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let arg_2 = args.get(2usize as i32); + let arg_2 = match deno_core::serde_v8::from_v8(scope, arg_2) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 2usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let arg_3 = args.get(3usize as i32); + let arg_3 = match deno_core::serde_v8::from_v8(scope, arg_3) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 3usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let result = Self::call(arg_0, arg_1, arg_2, arg_3); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => { + rv.set_uint32(result as u32); + } + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +} struct op_add_4_fast { _phantom: ::std::marker::PhantomData<()>, } diff --git a/ops/optimizer_tests/param_mut_binding_warning.out b/ops/optimizer_tests/param_mut_binding_warning.out new file mode 100644 index 0000000000..daccc28abb --- /dev/null +++ b/ops/optimizer_tests/param_mut_binding_warning.out @@ -0,0 +1,89 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_read_sync::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_read_sync; +#[doc(hidden)] +impl op_read_sync { + pub fn name() -> &'static str { + stringify!(op_read_sync) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: None, + is_async: false, + is_unstable: false, + is_v8: false, + argc: 2usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call( + state: &mut OpState, + rid: ResourceId, + mut buf: ZeroCopyBuf, + ) -> Result { + Ok(23) + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = args.get(0usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 0usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let arg_1 = args.get(1usize as i32); + let arg_1 = match deno_core::serde_v8::from_v8(scope, arg_1) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 1usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let result = Self::call( + &mut std::cell::RefCell::borrow_mut(&ctx.state), + arg_0, + arg_1, + ); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => { + rv.set_uint32(result as u32); + } + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +} diff --git a/ops/optimizer_tests/raw_ptr.out b/ops/optimizer_tests/raw_ptr.out index 30943d67dc..f9f467ad9b 100644 --- a/ops/optimizer_tests/raw_ptr.out +++ b/ops/optimizer_tests/raw_ptr.out @@ -1,3 +1,136 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_ffi_ptr_of::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_ffi_ptr_of; +#[doc(hidden)] +impl op_ffi_ptr_of { + pub fn name() -> &'static str { + stringify!(op_ffi_ptr_of) + } + pub fn v8_fn_ptr<'scope, FP>() -> deno_core::v8::FunctionCallback + where + FP: FfiPermissions + 'static, + { + use deno_core::v8::MapFnTo; + Self::v8_func::.map_fn_to() + } + pub fn decl<'scope, FP>() -> deno_core::OpDecl + where + FP: FfiPermissions + 'static, + { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr::(), + enabled: true, + fast_fn: Some( + Box::new(op_ffi_ptr_of_fast:: { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 2usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(state: &mut OpState, buf: *const u8, out: &mut [u32]) + where + FP: FfiPermissions + 'static, + {} + pub fn v8_func<'scope, FP>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) + where + FP: FfiPermissions + 'static, + { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = { + let value = args.get(0usize as i32); + match deno_core::v8::Local::::try_from(value) { + Ok(b) => { + if let Some(data) = b.data() { + data.cast::().as_ptr() + } else { + std::ptr::null::() + } + } + Err(_) => { + if let Ok(view) + = deno_core::v8::Local::< + deno_core::v8::ArrayBufferView, + >::try_from(value) { + let offset = view.byte_offset(); + let buffer = match view.buffer(scope) { + Some(v) => v, + None => { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 0usize), + ); + } + }; + let store = if let Some(data) = buffer.data() { + data.cast::().as_ptr() + } else { + std::ptr::null_mut::() + }; + unsafe { store.add(offset) } + } else { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 0usize), + ); + } + } + } + }; + let arg_1 = if let Ok(view) + = deno_core::v8::Local::< + deno_core::v8::Uint32Array, + >::try_from(args.get(1usize as i32)) { + let (offset, len) = (view.byte_offset(), view.byte_length()); + let buffer = match view.buffer(scope) { + Some(v) => v, + None => { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected Uint32Array at position {}", 1usize), + ); + } + }; + if let Some(data) = buffer.data() { + let store = data.cast::().as_ptr(); + unsafe { + ::std::slice::from_raw_parts_mut( + store.add(offset) as *mut u32, + len / 4, + ) + } + } else { + &mut [] + } + } else { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected Uint32Array at position {}", 1usize), + ); + }; + let result = Self::call::< + FP, + >(&mut std::cell::RefCell::borrow_mut(&ctx.state), arg_0, arg_1); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + } +} struct op_ffi_ptr_of_fast { _phantom: ::std::marker::PhantomData, } diff --git a/ops/optimizer_tests/serde_v8_value.out b/ops/optimizer_tests/serde_v8_value.out index 8c76305476..d4f2c0321d 100644 --- a/ops/optimizer_tests/serde_v8_value.out +++ b/ops/optimizer_tests/serde_v8_value.out @@ -1,3 +1,76 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_is_proxy::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_is_proxy; +#[doc(hidden)] +impl op_is_proxy { + pub fn name() -> &'static str { + stringify!(op_is_proxy) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_is_proxy_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 1usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(value: serde_v8::Value) -> bool { + value.v8_value.is_proxy() + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = args.get(0usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 0usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let result = Self::call(arg_0); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match deno_core::serde_v8::to_v8(scope, result) { + Ok(ret) => rv.set(ret), + Err(err) => { + deno_core::_ops::throw_type_error( + scope, + format!( + "Error serializing return: {}", + deno_core::anyhow::Error::from(err) + ), + ) + } + }; + } +} struct op_is_proxy_fast { _phantom: ::std::marker::PhantomData<()>, } diff --git a/ops/optimizer_tests/u64_result.out b/ops/optimizer_tests/u64_result.out new file mode 100644 index 0000000000..0039c75751 --- /dev/null +++ b/ops/optimizer_tests/u64_result.out @@ -0,0 +1,72 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_bench_now::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_bench_now; +#[doc(hidden)] +impl op_bench_now { + pub fn name() -> &'static str { + stringify!(op_bench_now) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: None, + is_async: false, + is_unstable: false, + is_v8: false, + argc: 0usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call(state: &mut OpState) -> Result { + let ns = state.borrow::().elapsed().as_nanos(); + let ns_u64 = u64::try_from(ns)?; + Ok(ns_u64) + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let result = Self::call(&mut std::cell::RefCell::borrow_mut(&ctx.state)); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => { + match deno_core::serde_v8::to_v8(scope, result) { + Ok(ret) => rv.set(ret), + Err(err) => { + deno_core::_ops::throw_type_error( + scope, + format!( + "Error serializing return: {}", + deno_core::anyhow::Error::from(err) + ), + ) + } + }; + } + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +}