Repository: denoland/deno_core
Pull request #686 (2024-04-07 04:32:51)

op2++: codegen for `&self` parameter
Refactor out codegen for `&self` from #682 

```rust
struct State {
  name: &'static str,
}

impl State {
  #[op2(fast, method(State)]
  fn print(&self) {
    println!("{}", self.name);
  }
}

const STATE_DECL: [OpDecl; 1] = [
  State::print()
];
```

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/denoland/deno_core/pull/686?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=denoland) Report
Attention: Patch coverage is `87.25490%` with `13 lines` in your changes are missing coverage. Please review.
> Project coverage is 81.29%. Comparing base [(`5245f5d`)](https://app.codecov.io/gh/denoland/deno_core/commit/5245f5defd9c4f4f05323c38ad5a097c87d48346?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=denoland) to head [(`4f95660`)](https://app.codecov.io/gh/denoland/deno_core/pull/686?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=denoland).

| [Files](https://app.codecov.io/gh/denoland/deno_core/pull/686?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=denoland) | Patch % | Lines |
|---|---|---|
| [testing/checkin/runner/ops.rs](https://app.codecov.io/gh/denoland/deno_core/pull/686?src=pr&el=tree&filepath=testing%2Fcheckin%2Frunner%2Fops.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=denoland#diff-dGVzdGluZy9jaGVja2luL3J1bm5lci9vcHMucnM=) | 0.00% | [13 Missing :warning: ](https://app.codecov.io/gh/denoland/deno_core/pull/686?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=denoland) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #686      +/-   ##
==========================================
+ Coverage   81.26%   81.29%   +0.02%     
==========================================
  Files          95       95              
  Lines       24295    24385      +90     
==========================================
+ Hits        19744    19823      +79     
- Misses       4551     4562      +11     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/denoland/deno_core/pull/686?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=denoland).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=denoland).


Patch:
diff --git a/ops/op2/config.rs b/ops/op2/config.rs
index 17436ae..87b7b7d 100644
--- a/ops/op2/config.rs
+++ b/ops/op2/config.rs
@@ -22,6 +22,8 @@ pub(crate) struct MacroConfig {
   pub async_deferred: bool,
   /// Marks an op as re-entrant (can safely call other ops).
   pub reentrant: bool,
+  /// Marks an op as a method on a wrapped object.
+  pub method: Option<String>,
 }
 
 impl MacroConfig {
@@ -85,6 +87,17 @@ impl MacroConfig {
         config.async_deferred = true;
       } else if flag == "reentrant" {
         config.reentrant = true;
+      } else if flag.starts_with("method(") {
+        let tokens =
+          syn::parse_str::<TokenTree>(&flag[6..])?.into_token_stream();
+        config.method = std::panic::catch_unwind(|| {
+          rules!(tokens => {
+            ( ( $s:ty ) ) => {
+              Some(s.into_token_stream().to_string())
+            }
+          })
+        })
+        .map_err(|_| Op2Error::PatternMatchFailed("attribute", flag))?;
       } else {
         return Err(Op2Error::InvalidAttribute(flag));
       }
@@ -226,5 +239,21 @@ mod tests {
         ..Default::default()
       },
     );
+
+    test_parse(
+      "(method(A))",
+      MacroConfig {
+        method: Some("A".to_owned()),
+        ..Default::default()
+      },
+    );
+    test_parse(
+      "(fast, method(T))",
+      MacroConfig {
+        method: Some("T".to_owned()),
+        fast: true,
+        ..Default::default()
+      },
+    );
   }
 }
diff --git a/ops/op2/dispatch_async.rs b/ops/op2/dispatch_async.rs
index 6634238..d9cfbea 100644
--- a/ops/op2/dispatch_async.rs
+++ b/ops/op2/dispatch_async.rs
@@ -10,6 +10,7 @@ use super::dispatch_slow::with_opctx;
 use super::dispatch_slow::with_opstate;
 use super::dispatch_slow::with_retval;
 use super::dispatch_slow::with_scope;
+use super::dispatch_slow::with_self;
 use super::generator_state::gs_quote;
 use super::generator_state::GeneratorState;
 use super::signature::ParsedSignature;
@@ -136,6 +137,12 @@ pub(crate) fn generate_dispatch_async(
     quote!()
   };
 
+  let with_self = if generator_state.needs_self {
+    with_self(generator_state)
+  } else {
+    quote!()
+  };
+
   Ok(
     gs_quote!(generator_state(info, slow_function, slow_function_metrics, opctx) => {
       #[inline(always)]
@@ -148,6 +155,7 @@ pub(crate) fn generate_dispatch_async(
         #with_args
         #with_opctx
         #with_opstate
+        #with_self
 
         #output
       }
diff --git a/ops/op2/dispatch_fast.rs b/ops/op2/dispatch_fast.rs
index 8c4bdb2..ae6cbc2 100644
--- a/ops/op2/dispatch_fast.rs
+++ b/ops/op2/dispatch_fast.rs
@@ -451,6 +451,21 @@ pub(crate) fn generate_dispatch_fast(
     quote!()
   };
 
+  let with_self = if generator_state.needs_self {
+    gs_quote!(generator_state(self_ty) => {
+      let self_: &#self_ty = deno_core::cppgc::try_unwrap_cppgc_object(this.into()).unwrap();
+    })
+  } else {
+    quote!()
+  };
+
+  let name = &generator_state.name;
+  let call = if generator_state.needs_self {
+    quote!(self_. #name)
+  } else {
+    quote!(Self:: #name)
+  };
+
   let mut fastsig_metrics = fastsig.clone();
   fastsig_metrics.ensure_fast_api_callback_options();
 
@@ -503,7 +518,7 @@ pub(crate) fn generate_dispatch_fast(
 
     #[allow(clippy::too_many_arguments)]
     extern "C" fn #fast_function(
-      _: deno_core::v8::Local<deno_core::v8::Object>,
+      this: deno_core::v8::Local<deno_core::v8::Object>,
       #( #fastcall_names: #fastcall_types, )*
     ) -> #output_type {
       #[cfg(debug_assertions)]
@@ -512,9 +527,10 @@ pub(crate) fn generate_dispatch_fast(
       #with_fast_api_callback_options
       #with_opctx
       #with_js_runtime_state
+      #with_self
       let #result = {
         #(#call_args)*
-        Self::call(#(#call_names),*)
+        #call (#(#call_names),*)
       };
       #handle_error
       #handle_result
diff --git a/ops/op2/dispatch_slow.rs b/ops/op2/dispatch_slow.rs
index 748223a..0c06752 100644
--- a/ops/op2/dispatch_slow.rs
+++ b/ops/op2/dispatch_slow.rs
@@ -135,6 +135,12 @@ pub(crate) fn generate_dispatch_slow(
     quote!()
   };
 
+  let with_self = if generator_state.needs_self {
+    with_self(generator_state)
+  } else {
+    quote!()
+  };
+
   Ok(
     gs_quote!(generator_state(opctx, info, slow_function, slow_function_metrics) => {
       #[inline(always)]
@@ -149,6 +155,7 @@ pub(crate) fn generate_dispatch_slow(
         #with_isolate
         #with_opstate
         #with_js_runtime_state
+        #with_self
 
         #output;
         return 0;
@@ -236,6 +243,13 @@ pub(crate) fn with_js_runtime_state(
   )
 }
 
+pub(crate) fn with_self(generator_state: &mut GeneratorState) -> TokenStream {
+  generator_state.needs_opctx = true;
+  gs_quote!(generator_state(fn_args, self_ty) =>
+    (let self_: &#self_ty = unsafe { deno_core::cppgc::try_unwrap_cppgc_object(#fn_args.this().into()).unwrap() };)
+  )
+}
+
 pub fn extract_arg(
   generator_state: &mut GeneratorState,
   index: usize,
@@ -679,7 +693,15 @@ pub fn call(generator_state: &mut GeneratorState) -> TokenStream {
   for arg in &generator_state.args {
     tokens.extend(quote!( #arg , ));
   }
-  quote!(Self::call( #tokens ))
+
+  let name = &generator_state.name;
+  let call_ = if generator_state.needs_self {
+    quote!(self_. #name)
+  } else {
+    quote!(Self:: #name)
+  };
+
+  quote!(#call_ ( #tokens ))
 }
 
 pub fn return_value(
diff --git a/ops/op2/generator_state.rs b/ops/op2/generator_state.rs
index cfbfd94..0b35564 100644
--- a/ops/op2/generator_state.rs
+++ b/ops/op2/generator_state.rs
@@ -2,6 +2,7 @@
 use proc_macro2::Ident;
 
 pub struct GeneratorState {
+  pub name: Ident,
   /// Identifiers for each of the arguments of the original function
   pub args: Vec<Ident>,
   /// The result of the `call` function
@@ -33,6 +34,8 @@ pub struct GeneratorState {
   pub fast_function_metrics: Ident,
   /// The async function promise ID argument
   pub promise_id: Ident,
+  /// Type of the self argument
+  pub self_ty: Ident,
 
   pub needs_args: bool,
   pub needs_retval: bool,
@@ -44,6 +47,7 @@ pub struct GeneratorState {
   pub needs_fast_opctx: bool,
   pub needs_fast_api_callback_options: bool,
   pub needs_fast_js_runtime_state: bool,
+  pub needs_self: bool,
 }
 
 /// Quotes a set of generator_state fields, along with variables captured from
diff --git a/ops/op2/mod.rs b/ops/op2/mod.rs
index c5560fe..5017817 100644
--- a/ops/op2/mod.rs
+++ b/ops/op2/mod.rs
@@ -122,13 +122,14 @@ fn generate_op2(
     zip(signature.args.iter(), &func.sig.inputs).collect::<Vec<_>>();
 
   let mut args = vec![];
-  let mut needs_args = false;
+  let mut needs_args = config.method.is_some();
   for (index, _) in processed_args.iter().enumerate() {
     let input = format_ident!("arg{index}");
     args.push(input);
     needs_args = true;
   }
 
+  let name = op_fn.sig.ident.clone();
   let retval = Ident::new("rv", Span::call_site());
   let result = Ident::new("result", Span::call_site());
   let fn_args = Ident::new("args", Span::call_site());
@@ -146,8 +147,14 @@ fn generate_op2(
     Ident::new("v8_fn_ptr_fast_metrics", Span::call_site());
   let fast_api_callback_options =
     Ident::new("fast_api_callback_options", Span::call_site());
+  let self_ty = if let Some(ref ty) = config.method {
+    format_ident!("{ty}")
+  } else {
+    Ident::new("UNINIT", Span::call_site())
+  };
 
   let mut generator_state = GeneratorState {
+    name,
     args,
     fn_args,
     scope,
@@ -164,6 +171,7 @@ fn generate_op2(
     fast_function,
     fast_function_metrics,
     promise_id,
+    self_ty,
     needs_retval: false,
     needs_scope: false,
     needs_isolate: false,
@@ -173,6 +181,7 @@ fn generate_op2(
     needs_fast_opctx: false,
     needs_fast_api_callback_options: false,
     needs_fast_js_runtime_state: false,
+    needs_self: config.method.is_some(),
   };
 
   let name = func.sig.ident;
@@ -241,6 +250,28 @@ fn generate_op2(
 
   let meta_key = signature.metadata.keys().collect::<Vec<_>>();
   let meta_value = signature.metadata.values().collect::<Vec<_>>();
+  let op_fn_sig = &op_fn.sig;
+  let callable = if let Some(ty) = config.method {
+    let ident = format_ident!("{ty}");
+    quote! {
+        trait Callable {
+          #op_fn_sig;
+        }
+        impl Callable for #ident {
+          #[inline(always)]
+          #(#attrs)*
+          #op_fn
+        }
+    }
+  } else {
+    quote! {
+      impl <#(#generic : #bound),*> #name <#(#generic),*> {
+        #[inline(always)]
+        #(#attrs)*
+        #op_fn
+      }
+    }
+  };
 
   Ok(quote! {
     #[allow(non_camel_case_types)]
@@ -277,12 +308,10 @@ fn generate_op2(
 
         #fast_fn
         #slow_fn
-
-        #[inline(always)]
-        #(#attrs)*
-        #op_fn
       }
 
+      #callable
+
       <#name <#(#generic),*>  as ::deno_core::_ops::Op>::DECL
     }
   })
diff --git a/ops/op2/signature.rs b/ops/op2/signature.rs
index 9a403f4..167b2e8 100644
--- a/ops/op2/signature.rs
+++ b/ops/op2/signature.rs
@@ -989,7 +989,8 @@ pub fn parse_signature(
   let mut names = vec![];
   for input in signature.inputs {
     let name = match &input {
-      FnArg::Receiver(_) => "self".to_owned(),
+      // Skip receiver
+      FnArg::Receiver(_) => continue,
       FnArg::Typed(ty) => match &*ty.pat {
         Pat::Ident(ident) => ident.ident.to_string(),
         _ => "(complex)".to_owned(),


Test patch:
diff --git a/ops/op2/test_cases/async/async_arg_return.out b/ops/op2/test_cases/async/async_arg_return.out
index 1255c03..4ef7416 100644
--- a/ops/op2/test_cases/async/async_arg_return.out
+++ b/ops/op2/test_cases/async/async_arg_return.out
@@ -104,6 +104,8 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async {
         #[inline(always)]
         pub async fn call(x: i32) -> i32 {
             x
diff --git a/ops/op2/test_cases/async/async_arg_return_result.out b/ops/op2/test_cases/async/async_arg_return_result.out
index 928cb9b..6fa35cc 100644
--- a/ops/op2/test_cases/async/async_arg_return_result.out
+++ b/ops/op2/test_cases/async/async_arg_return_result.out
@@ -121,6 +121,8 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async {
         #[inline(always)]
         pub async fn call(x: i32) -> std::io::Result<i32> {
             Ok(x)
diff --git a/ops/op2/test_cases/async/async_deferred.out b/ops/op2/test_cases/async/async_deferred.out
index fb31f50..cc4ace5 100644
--- a/ops/op2/test_cases/async/async_deferred.out
+++ b/ops/op2/test_cases/async/async_deferred.out
@@ -66,7 +66,7 @@ pub const fn op_async_deferred() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             promise_id: i32,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> () {
@@ -152,6 +152,8 @@ pub const fn op_async_deferred() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async_deferred {
         #[inline(always)]
         pub async fn call() -> std::io::Result<i32> {
             Ok(0)
diff --git a/ops/op2/test_cases/async/async_jsbuffer.out b/ops/op2/test_cases/async/async_jsbuffer.out
index 1f5a6ac..a14ac56 100644
--- a/ops/op2/test_cases/async/async_jsbuffer.out
+++ b/ops/op2/test_cases/async/async_jsbuffer.out
@@ -128,6 +128,8 @@ pub const fn op_async_v8_buffer() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async_v8_buffer {
         #[inline(always)]
         pub async fn call(buf: JsBuffer) -> JsBuffer {
             buf
diff --git a/ops/op2/test_cases/async/async_lazy.out b/ops/op2/test_cases/async/async_lazy.out
index e459306..abb064f 100644
--- a/ops/op2/test_cases/async/async_lazy.out
+++ b/ops/op2/test_cases/async/async_lazy.out
@@ -66,7 +66,7 @@ pub const fn op_async_lazy() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             promise_id: i32,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> () {
@@ -152,6 +152,8 @@ pub const fn op_async_lazy() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async_lazy {
         #[inline(always)]
         pub async fn call() -> std::io::Result<i32> {
             Ok(0)
diff --git a/ops/op2/test_cases/async/async_op_metadata.out b/ops/op2/test_cases/async/async_op_metadata.out
index d155221..1e4aa9c 100644
--- a/ops/op2/test_cases/async/async_op_metadata.out
+++ b/ops/op2/test_cases/async/async_op_metadata.out
@@ -90,6 +90,8 @@ const fn op_blob_read_part() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_blob_read_part {
         #[inline(always)]
         async fn call() {
             return;
@@ -190,6 +192,8 @@ const fn op_broadcast_recv() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_broadcast_recv {
         #[inline(always)]
         async fn call() {
             return;
diff --git a/ops/op2/test_cases/async/async_opstate.out b/ops/op2/test_cases/async/async_opstate.out
index ce23f2f..78ca507 100644
--- a/ops/op2/test_cases/async/async_opstate.out
+++ b/ops/op2/test_cases/async/async_opstate.out
@@ -109,6 +109,8 @@ pub const fn op_async_opstate() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async_opstate {
         #[inline(always)]
         pub async fn call(state: Rc<RefCell<OpState>>) -> std::io::Result<i32> {
             Ok(*state.borrow().borrow::<i32>())
diff --git a/ops/op2/test_cases/async/async_result.out b/ops/op2/test_cases/async/async_result.out
index 68fb97f..490e42e 100644
--- a/ops/op2/test_cases/async/async_result.out
+++ b/ops/op2/test_cases/async/async_result.out
@@ -105,6 +105,8 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async {
         #[inline(always)]
         pub async fn call() -> std::io::Result<i32> {
             Ok(0)
diff --git a/ops/op2/test_cases/async/async_result_impl.out b/ops/op2/test_cases/async/async_result_impl.out
index b6bc5fd..0ceeb96 100644
--- a/ops/op2/test_cases/async/async_result_impl.out
+++ b/ops/op2/test_cases/async/async_result_impl.out
@@ -135,6 +135,8 @@ pub const fn op_async_result_impl() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async_result_impl {
         #[inline(always)]
         pub fn call(
             x: i32,
diff --git a/ops/op2/test_cases/async/async_result_smi.out b/ops/op2/test_cases/async/async_result_smi.out
index dd237e6..13c2404 100644
--- a/ops/op2/test_cases/async/async_result_smi.out
+++ b/ops/op2/test_cases/async/async_result_smi.out
@@ -137,6 +137,8 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async {
         #[inline(always)]
         pub async fn call(rid: ResourceId) -> std::io::Result<ResourceId> {
             Ok(rid as _)
diff --git a/ops/op2/test_cases/async/async_v8_global.out b/ops/op2/test_cases/async/async_v8_global.out
index f35b4a5..1cc4d8b 100644
--- a/ops/op2/test_cases/async/async_v8_global.out
+++ b/ops/op2/test_cases/async/async_v8_global.out
@@ -107,6 +107,8 @@ pub const fn op_async_v8_global() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async_v8_global {
         #[inline(always)]
         pub async fn call(_s: v8::Global<v8::String>) {}
     }
diff --git a/ops/op2/test_cases/async/async_void.out b/ops/op2/test_cases/async/async_void.out
index 9454d7a..50d6601 100644
--- a/ops/op2/test_cases/async/async_void.out
+++ b/ops/op2/test_cases/async/async_void.out
@@ -88,6 +88,8 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_async {
         #[inline(always)]
         pub async fn call() {}
     }
diff --git a/ops/op2/test_cases/sync/add.out b/ops/op2/test_cases/sync/add.out
index 6d20964..f426e53 100644
--- a/ops/op2/test_cases/sync/add.out
+++ b/ops/op2/test_cases/sync/add.out
@@ -67,7 +67,7 @@ const fn op_add() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: u32,
             arg1: u32,
         ) -> u32 {
@@ -160,6 +160,8 @@ const fn op_add() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_add {
         #[inline(always)]
         fn call(a: u32, b: u32) -> u32 {
             a + b
diff --git a/ops/op2/test_cases/sync/add_options.out b/ops/op2/test_cases/sync/add_options.out
index 0999106..8a8526f 100644
--- a/ops/op2/test_cases/sync/add_options.out
+++ b/ops/op2/test_cases/sync/add_options.out
@@ -109,6 +109,8 @@ pub const fn op_test_add_option() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_test_add_option {
         #[inline(always)]
         pub fn call(a: u32, b: Option<u32>) -> u32 {
             a + b.unwrap_or(100)
diff --git a/ops/op2/test_cases/sync/bigint.out b/ops/op2/test_cases/sync/bigint.out
index 861a103..daf3e76 100644
--- a/ops/op2/test_cases/sync/bigint.out
+++ b/ops/op2/test_cases/sync/bigint.out
@@ -65,7 +65,7 @@ pub const fn op_bigint() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
         ) -> u64 {
             #[cfg(debug_assertions)]
             let _reentrancy_check_guard = deno_core::_ops::reentrancy_check(
@@ -120,6 +120,8 @@ pub const fn op_bigint() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_bigint {
         #[inline(always)]
         pub fn call() -> u64 {
             0
diff --git a/ops/op2/test_cases/sync/bool.out b/ops/op2/test_cases/sync/bool.out
index ff05a04..e945474 100644
--- a/ops/op2/test_cases/sync/bool.out
+++ b/ops/op2/test_cases/sync/bool.out
@@ -66,7 +66,7 @@ pub const fn op_bool() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: bool,
         ) -> bool {
             #[cfg(debug_assertions)]
@@ -131,6 +131,8 @@ pub const fn op_bool() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_bool {
         #[inline(always)]
         pub fn call(arg: bool) -> bool {
             arg
diff --git a/ops/op2/test_cases/sync/bool_result.out b/ops/op2/test_cases/sync/bool_result.out
index 8d16663..14494df 100644
--- a/ops/op2/test_cases/sync/bool_result.out
+++ b/ops/op2/test_cases/sync/bool_result.out
@@ -66,7 +66,7 @@ pub const fn op_bool() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: bool,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> bool {
@@ -178,6 +178,8 @@ pub const fn op_bool() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_bool {
         #[inline(always)]
         pub fn call(arg: bool) -> Result<bool, AnyError> {
             Ok(arg)
diff --git a/ops/op2/test_cases/sync/buffers.out b/ops/op2/test_cases/sync/buffers.out
index 398314b..07b5a28 100644
--- a/ops/op2/test_cases/sync/buffers.out
+++ b/ops/op2/test_cases/sync/buffers.out
@@ -82,7 +82,7 @@ const fn op_buffers() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: *mut deno_core::v8::fast_api::FastApiTypedArray<u8>,
             arg1: *mut deno_core::v8::fast_api::FastApiTypedArray<u8>,
             arg2: *mut deno_core::v8::fast_api::FastApiTypedArray<u8>,
@@ -271,6 +271,8 @@ const fn op_buffers() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_buffers {
         #[inline(always)]
         fn call(_a: &[u8], _b: &mut [u8], _c: *const u8, _d: *mut u8) {}
     }
@@ -361,7 +363,7 @@ const fn op_buffers_32() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: *mut deno_core::v8::fast_api::FastApiTypedArray<u32>,
             arg1: *mut deno_core::v8::fast_api::FastApiTypedArray<u32>,
             arg2: *mut deno_core::v8::fast_api::FastApiTypedArray<u32>,
@@ -550,6 +552,8 @@ const fn op_buffers_32() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_buffers_32 {
         #[inline(always)]
         fn call(_a: &[u32], _b: &mut [u32], _c: *const u32, _d: *mut u32) {}
     }
@@ -692,6 +696,8 @@ const fn op_buffers_option() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_buffers_option {
         #[inline(always)]
         fn call(_a: Option<&[u8]>, _b: Option<JsBuffer>) {}
     }
diff --git a/ops/op2/test_cases/sync/buffers_copy.out b/ops/op2/test_cases/sync/buffers_copy.out
index 6ed0d37..4eab3ee 100644
--- a/ops/op2/test_cases/sync/buffers_copy.out
+++ b/ops/op2/test_cases/sync/buffers_copy.out
@@ -79,7 +79,7 @@ const fn op_buffers() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: *mut deno_core::v8::fast_api::FastApiTypedArray<u8>,
             arg1: *mut deno_core::v8::fast_api::FastApiTypedArray<u8>,
             arg2: *mut deno_core::v8::fast_api::FastApiTypedArray<u8>,
@@ -224,6 +224,8 @@ const fn op_buffers() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_buffers {
         #[inline(always)]
         fn call(_a: Vec<u8>, _b: Box<[u8]>, _c: bytes::Bytes) {}
     }
@@ -308,7 +310,7 @@ const fn op_buffers_32() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: *mut deno_core::v8::fast_api::FastApiTypedArray<u32>,
             arg1: *mut deno_core::v8::fast_api::FastApiTypedArray<u32>,
         ) -> () {
@@ -425,6 +427,8 @@ const fn op_buffers_32() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_buffers_32 {
         #[inline(always)]
         fn call(_a: Vec<u32>, _b: Box<[u32]>) {}
     }
diff --git a/ops/op2/test_cases/sync/buffers_out.out b/ops/op2/test_cases/sync/buffers_out.out
index a8c9eb3..a5d7213 100644
--- a/ops/op2/test_cases/sync/buffers_out.out
+++ b/ops/op2/test_cases/sync/buffers_out.out
@@ -107,6 +107,8 @@ const fn op_buffers() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_buffers {
         #[inline(always)]
         fn call(buffer: JsBuffer) -> JsBuffer {
             buffer
@@ -234,6 +236,8 @@ const fn op_buffers_option() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_buffers_option {
         #[inline(always)]
         fn call(buffer: Option<JsBuffer>) -> Option<JsBuffer> {
             buffer
@@ -347,6 +351,8 @@ const fn op_arraybuffers() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_arraybuffers {
         #[inline(always)]
         fn call(buffer: JsBuffer) -> JsBuffer {
             buffer
diff --git a/ops/op2/test_cases/sync/cfg.out b/ops/op2/test_cases/sync/cfg.out
index e6cc770..c847813 100644
--- a/ops/op2/test_cases/sync/cfg.out
+++ b/ops/op2/test_cases/sync/cfg.out
@@ -67,7 +67,7 @@ pub const fn op_maybe_windows() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
         ) -> () {
             #[cfg(debug_assertions)]
             let _reentrancy_check_guard = deno_core::_ops::reentrancy_check(
@@ -121,6 +121,8 @@ pub const fn op_maybe_windows() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_maybe_windows {
         #[inline(always)]
         /// This is a doc comment.
         #[cfg(windows)]
@@ -198,7 +200,7 @@ pub const fn op_maybe_windows() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
         ) -> () {
             #[cfg(debug_assertions)]
             let _reentrancy_check_guard = deno_core::_ops::reentrancy_check(
@@ -252,6 +254,8 @@ pub const fn op_maybe_windows() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_maybe_windows {
         #[inline(always)]
         /// This is a doc comment.
         #[cfg(not(windows))]
diff --git a/ops/op2/test_cases/sync/clippy_allow.out b/ops/op2/test_cases/sync/clippy_allow.out
index 1b62b8f..a54fd4b 100644
--- a/ops/op2/test_cases/sync/clippy_allow.out
+++ b/ops/op2/test_cases/sync/clippy_allow.out
@@ -67,7 +67,7 @@ pub const fn op_extra_annotation() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
         ) -> () {
             #[cfg(debug_assertions)]
             let _reentrancy_check_guard = deno_core::_ops::reentrancy_check(
@@ -121,6 +121,8 @@ pub const fn op_extra_annotation() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_extra_annotation {
         #[inline(always)]
         /// This is a doc comment.
         #[allow(clippy::some_annotation)]
@@ -196,7 +198,7 @@ pub const fn op_clippy_internal() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
         ) -> () {
             #[cfg(debug_assertions)]
             let _reentrancy_check_guard = deno_core::_ops::reentrancy_check(
@@ -250,6 +252,8 @@ pub const fn op_clippy_internal() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_clippy_internal {
         #[inline(always)]
         pub fn call() -> () {
             { #![allow(clippy::await_holding_refcell_ref)] }
diff --git a/ops/op2/test_cases/sync/cppgc_resource.out b/ops/op2/test_cases/sync/cppgc_resource.out
index e505b9b..f0c5617 100644
--- a/ops/op2/test_cases/sync/cppgc_resource.out
+++ b/ops/op2/test_cases/sync/cppgc_resource.out
@@ -66,7 +66,7 @@ const fn op_file() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: deno_core::v8::Local<deno_core::v8::Value>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> () {
@@ -151,6 +151,8 @@ const fn op_file() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_file {
         #[inline(always)]
         fn call(_file: &std::fs::File) {}
     }
@@ -235,6 +237,8 @@ const fn op_make_cppgc_object() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_make_cppgc_object {
         #[inline(always)]
         fn call() -> Wrap {
             Wrap
@@ -346,6 +350,8 @@ const fn op_make_cppgc_object_async() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_make_cppgc_object_async {
         #[inline(always)]
         async fn call() -> Wrap {
             Wrap
diff --git a/ops/op2/test_cases/sync/doc_comment.out b/ops/op2/test_cases/sync/doc_comment.out
index b61c53c..3c6ca3b 100644
--- a/ops/op2/test_cases/sync/doc_comment.out
+++ b/ops/op2/test_cases/sync/doc_comment.out
@@ -66,7 +66,7 @@ pub const fn op_has_doc_comment() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
         ) -> () {
             #[cfg(debug_assertions)]
             let _reentrancy_check_guard = deno_core::_ops::reentrancy_check(
@@ -120,6 +120,8 @@ pub const fn op_has_doc_comment() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_has_doc_comment {
         #[inline(always)]
         /// This is a doc comment.
         pub fn call() -> () {}
diff --git a/ops/op2/test_cases/sync/fast_alternative.out b/ops/op2/test_cases/sync/fast_alternative.out
index e1b29ee..963542d 100644
--- a/ops/op2/test_cases/sync/fast_alternative.out
+++ b/ops/op2/test_cases/sync/fast_alternative.out
@@ -102,6 +102,8 @@ const fn op_slow() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_slow {
         #[inline(always)]
         fn call(_scope: &v8::HandleScope, a: u32, b: u32) -> u32 {
             a + b
@@ -179,7 +181,7 @@ const fn op_fast() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: u32,
             arg1: u32,
         ) -> u32 {
@@ -272,6 +274,8 @@ const fn op_fast() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_fast {
         #[inline(always)]
         fn call(a: u32, b: u32) -> u32 {
             a + b
@@ -384,6 +388,8 @@ const fn op_slow_generic<T: Trait>() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl<T: Trait> op_slow_generic<T> {
         #[inline(always)]
         fn call(_scope: &v8::HandleScope, a: u32, b: u32) -> u32 {
             a + b
@@ -461,7 +467,7 @@ const fn op_fast_generic<T: Trait>() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: u32,
             arg1: u32,
         ) -> u32 {
@@ -554,6 +560,8 @@ const fn op_fast_generic<T: Trait>() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl<T: Trait> op_fast_generic<T> {
         #[inline(always)]
         fn call(a: u32, b: u32) -> u32 {
             a + b
diff --git a/ops/op2/test_cases/sync/generics.out b/ops/op2/test_cases/sync/generics.out
index 5190d96..1d8dd81 100644
--- a/ops/op2/test_cases/sync/generics.out
+++ b/ops/op2/test_cases/sync/generics.out
@@ -65,7 +65,7 @@ pub const fn op_generics<T: Trait>() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
         ) -> () {
             #[cfg(debug_assertions)]
             let _reentrancy_check_guard = deno_core::_ops::reentrancy_check(
@@ -119,6 +119,8 @@ pub const fn op_generics<T: Trait>() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl<T: Trait> op_generics<T> {
         #[inline(always)]
         pub fn call() {}
     }
@@ -192,7 +194,7 @@ pub const fn op_generics_static<T: Trait + 'static>() -> ::deno_core::_ops::OpDe
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
         ) -> () {
             #[cfg(debug_assertions)]
             let _reentrancy_check_guard = deno_core::_ops::reentrancy_check(
@@ -246,6 +248,8 @@ pub const fn op_generics_static<T: Trait + 'static>() -> ::deno_core::_ops::OpDe
                 );
             }
         }
+    }
+    impl<T: Trait + 'static> op_generics_static<T> {
         #[inline(always)]
         pub fn call() {}
     }
@@ -319,7 +323,7 @@ pub const fn op_generics_static_where<T: Trait + 'static>() -> ::deno_core::_ops
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
         ) -> () {
             #[cfg(debug_assertions)]
             let _reentrancy_check_guard = deno_core::_ops::reentrancy_check(
@@ -373,6 +377,8 @@ pub const fn op_generics_static_where<T: Trait + 'static>() -> ::deno_core::_ops
                 );
             }
         }
+    }
+    impl<T: Trait + 'static> op_generics_static_where<T> {
         #[inline(always)]
         pub fn call()
         where
diff --git a/ops/op2/test_cases/sync/nofast.out b/ops/op2/test_cases/sync/nofast.out
index 92753e1..e63868c 100644
--- a/ops/op2/test_cases/sync/nofast.out
+++ b/ops/op2/test_cases/sync/nofast.out
@@ -102,6 +102,8 @@ const fn op_nofast() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_nofast {
         #[inline(always)]
         fn call(a: u32, b: u32) -> u32 {
             a + b
diff --git a/ops/op2/test_cases/sync/op_state_attr.out b/ops/op2/test_cases/sync/op_state_attr.out
index ed6c15a..dc762de 100644
--- a/ops/op2/test_cases/sync/op_state_attr.out
+++ b/ops/op2/test_cases/sync/op_state_attr.out
@@ -65,7 +65,7 @@ const fn op_state_rc() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> () {
             #[cfg(debug_assertions)]
@@ -147,6 +147,8 @@ const fn op_state_rc() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_state_rc {
         #[inline(always)]
         fn call(_arg: &Something, _arg_opt: Option<&Something>) {}
     }
diff --git a/ops/op2/test_cases/sync/op_state_rc.out b/ops/op2/test_cases/sync/op_state_rc.out
index 98825d5..fabdce9 100644
--- a/ops/op2/test_cases/sync/op_state_rc.out
+++ b/ops/op2/test_cases/sync/op_state_rc.out
@@ -65,7 +65,7 @@ const fn op_state_rc() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> () {
             #[cfg(debug_assertions)]
@@ -141,6 +141,8 @@ const fn op_state_rc() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_state_rc {
         #[inline(always)]
         fn call(_state: Rc<RefCell<OpState>>) {}
     }
diff --git a/ops/op2/test_cases/sync/op_state_ref.out b/ops/op2/test_cases/sync/op_state_ref.out
index 63ecf48..62838a6 100644
--- a/ops/op2/test_cases/sync/op_state_ref.out
+++ b/ops/op2/test_cases/sync/op_state_ref.out
@@ -65,7 +65,7 @@ const fn op_state_ref() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> () {
             #[cfg(debug_assertions)]
@@ -141,6 +141,8 @@ const fn op_state_ref() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_state_ref {
         #[inline(always)]
         fn call(_state: &OpState) {}
     }
@@ -214,7 +216,7 @@ const fn op_state_mut() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> () {
             #[cfg(debug_assertions)]
@@ -290,6 +292,8 @@ const fn op_state_mut() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_state_mut {
         #[inline(always)]
         fn call(_state: &mut OpState) {}
     }
@@ -395,6 +399,8 @@ const fn op_state_and_v8() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_state_and_v8 {
         #[inline(always)]
         fn call(_state: &mut OpState, _callback: v8::Global<v8::Function>) {}
     }
@@ -469,7 +475,7 @@ const fn op_state_and_v8_local() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg1: deno_core::v8::Local<deno_core::v8::Value>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> () {
@@ -569,6 +575,8 @@ const fn op_state_and_v8_local() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_state_and_v8_local {
         #[inline(always)]
         fn call(_state: &mut OpState, _callback: v8::Local<v8::Function>) {}
     }
diff --git a/ops/op2/test_cases/sync/result_external.out b/ops/op2/test_cases/sync/result_external.out
index 182eb9b..ebfc6ff 100644
--- a/ops/op2/test_cases/sync/result_external.out
+++ b/ops/op2/test_cases/sync/result_external.out
@@ -65,7 +65,7 @@ pub const fn op_external_with_result() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> *mut ::std::ffi::c_void {
             #[cfg(debug_assertions)]
@@ -177,6 +177,8 @@ pub const fn op_external_with_result() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_external_with_result {
         #[inline(always)]
         pub fn call() -> Result<*mut std::ffi::c_void, AnyError> {
             Ok(0 as _)
diff --git a/ops/op2/test_cases/sync/result_primitive.out b/ops/op2/test_cases/sync/result_primitive.out
index 01d633e..4014372 100644
--- a/ops/op2/test_cases/sync/result_primitive.out
+++ b/ops/op2/test_cases/sync/result_primitive.out
@@ -65,7 +65,7 @@ pub const fn op_u32_with_result() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> u32 {
             #[cfg(debug_assertions)]
@@ -175,6 +175,8 @@ pub const fn op_u32_with_result() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_u32_with_result {
         #[inline(always)]
         pub fn call() -> Result<u32, AnyError> {
             Ok(0)
diff --git a/ops/op2/test_cases/sync/result_scope.out b/ops/op2/test_cases/sync/result_scope.out
index 40fa654..e546b9b 100644
--- a/ops/op2/test_cases/sync/result_scope.out
+++ b/ops/op2/test_cases/sync/result_scope.out
@@ -94,6 +94,8 @@ pub const fn op_void_with_result() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_void_with_result {
         #[inline(always)]
         pub fn call(_scope: &mut v8::HandleScope) -> Result<(), AnyError> {
             Ok(())
diff --git a/ops/op2/test_cases/sync/result_void.out b/ops/op2/test_cases/sync/result_void.out
index b09419e..0c6501d 100644
--- a/ops/op2/test_cases/sync/result_void.out
+++ b/ops/op2/test_cases/sync/result_void.out
@@ -65,7 +65,7 @@ pub const fn op_void_with_result() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
         ) -> () {
             #[cfg(debug_assertions)]
@@ -175,6 +175,8 @@ pub const fn op_void_with_result() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_void_with_result {
         #[inline(always)]
         pub fn call() -> std::io::Result<()> {
             Ok(())
diff --git a/ops/op2/test_cases/sync/serde_v8.out b/ops/op2/test_cases/sync/serde_v8.out
index 3c6c69d..ad678da 100644
--- a/ops/op2/test_cases/sync/serde_v8.out
+++ b/ops/op2/test_cases/sync/serde_v8.out
@@ -107,6 +107,8 @@ pub const fn op_serde_v8() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_serde_v8 {
         #[inline(always)]
         pub fn call(_input: Input) -> Output {
             Output {}
diff --git a/ops/op2/test_cases/sync/smi.out b/ops/op2/test_cases/sync/smi.out
index af8f464..514937c 100644
--- a/ops/op2/test_cases/sync/smi.out
+++ b/ops/op2/test_cases/sync/smi.out
@@ -76,7 +76,7 @@ const fn op_smi_unsigned_return() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: i32,
             arg1: i32,
             arg2: i32,
@@ -207,6 +207,8 @@ const fn op_smi_unsigned_return() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_smi_unsigned_return {
         #[inline(always)]
         fn call(a: Int16, b: Int32, c: Uint16, d: Uint32) -> Uint32 {
             a as Uint32 + b as Uint32 + c as Uint32 + d as Uint32
@@ -293,7 +295,7 @@ const fn op_smi_signed_return() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: i32,
             arg1: i32,
             arg2: i32,
@@ -424,6 +426,8 @@ const fn op_smi_signed_return() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_smi_signed_return {
         #[inline(always)]
         fn call(a: Int16, b: Int32, c: Uint16, d: Uint32) -> Int32 {
             a as Int32 + b as Int32 + c as Int32 + d as Int32
@@ -529,6 +533,8 @@ const fn op_smi_option() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_smi_option {
         #[inline(always)]
         fn call(a: Option<Uint32>) -> Option<Uint32> {
             a
diff --git a/ops/op2/test_cases/sync/string_cow.out b/ops/op2/test_cases/sync/string_cow.out
index b6a7fa4..c34c6d4 100644
--- a/ops/op2/test_cases/sync/string_cow.out
+++ b/ops/op2/test_cases/sync/string_cow.out
@@ -66,7 +66,7 @@ const fn op_string_cow() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: *mut deno_core::v8::fast_api::FastApiOneByteString,
         ) -> u32 {
             #[cfg(debug_assertions)]
@@ -145,6 +145,8 @@ const fn op_string_cow() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_string_cow {
         #[inline(always)]
         fn call(s: Cow<str>) -> u32 {
             s.len() as _
diff --git a/ops/op2/test_cases/sync/string_onebyte.out b/ops/op2/test_cases/sync/string_onebyte.out
index 70b3fcd..437e0c4 100644
--- a/ops/op2/test_cases/sync/string_onebyte.out
+++ b/ops/op2/test_cases/sync/string_onebyte.out
@@ -66,7 +66,7 @@ const fn op_string_onebyte() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: *mut deno_core::v8::fast_api::FastApiOneByteString,
         ) -> u32 {
             #[cfg(debug_assertions)]
@@ -152,6 +152,8 @@ const fn op_string_onebyte() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_string_onebyte {
         #[inline(always)]
         fn call(s: Cow<[u8]>) -> u32 {
             s.len() as _
diff --git a/ops/op2/test_cases/sync/string_option_return.out b/ops/op2/test_cases/sync/string_option_return.out
index 48cee1f..dad7cf8 100644
--- a/ops/op2/test_cases/sync/string_option_return.out
+++ b/ops/op2/test_cases/sync/string_option_return.out
@@ -93,6 +93,8 @@ pub const fn op_string_return() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_string_return {
         #[inline(always)]
         pub fn call(s: Option<String>) -> Option<String> {
             s
diff --git a/ops/op2/test_cases/sync/string_owned.out b/ops/op2/test_cases/sync/string_owned.out
index 8467ab0..7277f0f 100644
--- a/ops/op2/test_cases/sync/string_owned.out
+++ b/ops/op2/test_cases/sync/string_owned.out
@@ -66,7 +66,7 @@ const fn op_string_owned() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: *mut deno_core::v8::fast_api::FastApiOneByteString,
         ) -> u32 {
             #[cfg(debug_assertions)]
@@ -136,6 +136,8 @@ const fn op_string_owned() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_string_owned {
         #[inline(always)]
         fn call(s: String) -> u32 {
             s.len() as _
diff --git a/ops/op2/test_cases/sync/string_ref.out b/ops/op2/test_cases/sync/string_ref.out
index 3685a8e..bbdb77d 100644
--- a/ops/op2/test_cases/sync/string_ref.out
+++ b/ops/op2/test_cases/sync/string_ref.out
@@ -66,7 +66,7 @@ const fn op_string_owned() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: *mut deno_core::v8::fast_api::FastApiOneByteString,
         ) -> u32 {
             #[cfg(debug_assertions)]
@@ -145,6 +145,8 @@ const fn op_string_owned() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_string_owned {
         #[inline(always)]
         fn call(s: &str) -> u32 {
             s.len() as _
diff --git a/ops/op2/test_cases/sync/string_return.out b/ops/op2/test_cases/sync/string_return.out
index 15f416d..18cae4b 100644
--- a/ops/op2/test_cases/sync/string_return.out
+++ b/ops/op2/test_cases/sync/string_return.out
@@ -82,6 +82,8 @@ pub const fn op_string_return() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_string_return {
         #[inline(always)]
         pub fn call() -> String {
             "".into()
@@ -174,6 +176,8 @@ pub const fn op_string_return_ref() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_string_return_ref {
         #[inline(always)]
         pub fn call() -> &'static str {
             ""
@@ -266,6 +270,8 @@ pub const fn op_string_return_cow() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_string_return_cow {
         #[inline(always)]
         pub fn call<'a>() -> Cow<'a, str> {
             "".into()
diff --git a/ops/op2/test_cases/sync/v8_global.out b/ops/op2/test_cases/sync/v8_global.out
index 4f6406f..f2b5b33 100644
--- a/ops/op2/test_cases/sync/v8_global.out
+++ b/ops/op2/test_cases/sync/v8_global.out
@@ -91,6 +91,8 @@ pub const fn op_global() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_global {
         #[inline(always)]
         pub fn call(g: v8::Global<v8::String>) -> v8::Global<v8::String> {
             g
diff --git a/ops/op2/test_cases/sync/v8_handlescope.out b/ops/op2/test_cases/sync/v8_handlescope.out
index 01fe092..b6f5f0a 100644
--- a/ops/op2/test_cases/sync/v8_handlescope.out
+++ b/ops/op2/test_cases/sync/v8_handlescope.out
@@ -91,6 +91,8 @@ const fn op_handlescope() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_handlescope {
         #[inline(always)]
         fn call<'a>(
             _scope: &v8::HandleScope<'a>,
diff --git a/ops/op2/test_cases/sync/v8_lifetime.out b/ops/op2/test_cases/sync/v8_lifetime.out
index f2d8a23..00b0f42 100644
--- a/ops/op2/test_cases/sync/v8_lifetime.out
+++ b/ops/op2/test_cases/sync/v8_lifetime.out
@@ -90,6 +90,8 @@ pub const fn op_v8_lifetime() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_v8_lifetime {
         #[inline(always)]
         pub fn call<'s>(_s: v8::Local<'s, v8::String>) -> v8::Local<'s, v8::String> {
             unimplemented!()
diff --git a/ops/op2/test_cases/sync/v8_ref_option.out b/ops/op2/test_cases/sync/v8_ref_option.out
index 4ad4682..8b99077 100644
--- a/ops/op2/test_cases/sync/v8_ref_option.out
+++ b/ops/op2/test_cases/sync/v8_ref_option.out
@@ -77,7 +77,7 @@ pub const fn op_v8_lifetime() -> ::deno_core::_ops::OpDecl {
         }
         #[allow(clippy::too_many_arguments)]
         extern "C" fn v8_fn_ptr_fast(
-            _: deno_core::v8::Local<deno_core::v8::Object>,
+            this: deno_core::v8::Local<deno_core::v8::Object>,
             arg0: deno_core::v8::Local<deno_core::v8::Value>,
             arg1: deno_core::v8::Local<deno_core::v8::Value>,
             fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
@@ -200,6 +200,8 @@ pub const fn op_v8_lifetime() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_v8_lifetime {
         #[inline(always)]
         pub fn call<'s>(_s: Option<&v8::String>, _s2: Option<&v8::String>) {}
     }
diff --git a/ops/op2/test_cases/sync/v8_string.out b/ops/op2/test_cases/sync/v8_string.out
index deefbd4..a352e68 100644
--- a/ops/op2/test_cases/sync/v8_string.out
+++ b/ops/op2/test_cases/sync/v8_string.out
@@ -106,6 +106,8 @@ const fn op_v8_string() -> ::deno_core::_ops::OpDecl {
                 );
             }
         }
+    }
+    impl op_v8_string {
         #[inline(always)]
         fn call<'a>(
             _str1: &v8::String,
diff --git a/testing/checkin/runner/ops.rs b/testing/checkin/runner/ops.rs
index 529091a..c2aae63 100644
--- a/testing/checkin/runner/ops.rs
+++ b/testing/checkin/runner/ops.rs
@@ -9,6 +9,7 @@ use deno_core::stats::RuntimeActivityStats;
 use deno_core::stats::RuntimeActivityStatsFactory;
 use deno_core::stats::RuntimeActivityStatsFilter;
 use deno_core::v8;
+use deno_core::OpDecl;
 use deno_core::OpState;
 
 use super::testing::Output;
@@ -76,3 +77,32 @@ pub fn op_stats_delete(
 ) {
   test_data.take::<RuntimeActivityStats>(name);
 }
+
+pub struct Stateful {
+  name: String,
+}
+
+impl Stateful {
+  #[op2(method(Stateful))]
+  #[string]
+  fn get_name(&self) -> String {
+    self.name.clone()
+  }
+
+  #[op2(fast, method(Stateful))]
+  #[smi]
+  fn len(&self) -> u32 {
+    self.name.len() as u32
+  }
+
+  #[op2(async, method(Stateful))]
+  async fn delay(&self, #[smi] millis: u32) {
+    tokio::time::sleep(std::time::Duration::from_millis(millis as u64)).await;
+    println!("name: {}", self.name);
+  }
+}
+
+// Make sure this compiles, we'll use it when we add registration.
+#[allow(dead_code)]
+const STATEFUL_DECL: [OpDecl; 3] =
+  [Stateful::get_name(), Stateful::len(), Stateful::delay()];