Repository: denoland/deno_core
Pull request #279 (2023-10-24 21:33:20)

chore: mark op1 as deprecated and port most core ops
Before we remove `#[op]`, give embedders some notice to switch over to `#[op2]`. Note that I could not port the wasm ops yet -- we'll address that in #275


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cfa1eff..fafa18f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -55,6 +55,13 @@ jobs:
       - name: Cargo test
         run: cargo test --locked --release --all-features --bins --tests --examples && cargo test --doc
 
+      - name: Run examples
+        # Only regression tests here for now.
+        # Regression test for https://github.com/denoland/deno/pull/19615.
+        run: |-
+          cargo run -p deno_core --example op2
+          cargo run -p deno_core --example op2 --features include_js_files_for_snapshotting
+
       - name: Cargo publish
         if: |
           contains(matrix.os, 'ubuntu') &&
diff --git a/core/Cargo.toml b/core/Cargo.toml
index a57a205..f646dc6 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -40,10 +40,6 @@ tokio.workspace = true
 url.workspace = true
 v8.workspace = true
 
-[[example]]
-name = "http_bench_json_ops"
-path = "examples/http_bench_json_ops/main.rs"
-
 # These dependencies are only used for the 'http_bench_*_ops' examples.
 [dev-dependencies]
 cooked-waker.workspace = true
diff --git a/core/benches/ops/sync.rs b/core/benches/ops/sync.rs
index 14d8e3a..f3b6fc4 100644
--- a/core/benches/ops/sync.rs
+++ b/core/benches/ops/sync.rs
@@ -1,4 +1,5 @@
 // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+#![allow(deprecated)]
 use bencher::*;
 use deno_core::error::generic_error;
 use deno_core::*;
diff --git a/core/examples/hello_world.rs b/core/examples/hello_world.rs
index 8bc8d9c..aa10376 100644
--- a/core/examples/hello_world.rs
+++ b/core/examples/hello_world.rs
@@ -2,21 +2,12 @@
 //!  This example shows you how to define ops in Rust and then call them from
 //!  JavaScript.
 
-use deno_core::op;
-use deno_core::Extension;
-use deno_core::JsRuntime;
-use deno_core::Op;
-use deno_core::RuntimeOptions;
-
-// This is a hack to make the `#[op]` macro work with
-// deno_core examples.
-// You can remove this:
 use deno_core::*;
 
 /// An op for summing an array of numbers. The op-layer automatically
 /// deserializes inputs and serializes the returned Result & value.
-#[op]
-fn op_sum(nums: Vec<f64>) -> Result<f64, deno_core::error::AnyError> {
+#[op2]
+fn op_sum(#[serde] nums: Vec<f64>) -> Result<f64, deno_core::error::AnyError> {
   // Sum inputs
   let sum = nums.iter().fold(0.0, |a, v| a + v);
   // return as a Result<f64, AnyError>
diff --git a/core/examples/http_bench_json_ops/http_bench_json_ops.js b/core/examples/http_bench_json_ops/http_bench_json_ops.js
deleted file mode 100644
index a840e4e..0000000
--- a/core/examples/http_bench_json_ops/http_bench_json_ops.js
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-// This is not a real HTTP server. We read blindly one time into 'requestBuf',
-// then write this fixed 'responseBuf'. The point of this benchmark is to
-// exercise the event loop in a simple yet semi-realistic way.
-
-// deno-lint-ignore-file camelcase
-
-const { op_listen } = Deno.core.ops;
-const {
-  op_accept,
-  op_read_socket,
-} = Deno.core.ensureFastOps();
-
-const requestBuf = new Uint8Array(64 * 1024);
-const responseBuf = new Uint8Array(
-  "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n"
-    .split("")
-    .map((c) => c.charCodeAt(0)),
-);
-
-async function serve(rid) {
-  try {
-    while (true) {
-      await op_read_socket(rid, requestBuf);
-      if (!ops.op_try_write(rid, responseBuf)) {
-        await Deno.core.writeAll(rid, responseBuf);
-      }
-    }
-  } catch {
-    // pass
-  }
-  Deno.core.close(rid);
-}
-
-async function main() {
-  /** Listens on 0.0.0.0:4570, returns rid. */
-  const listenerRid = op_listen();
-  Deno.core.print(`http_bench_ops listening on http://127.0.0.1:4570/\n`);
-
-  while (true) {
-    const rid = await op_accept(listenerRid);
-    serve(rid);
-  }
-}
-
-main();
diff --git a/core/examples/http_bench_json_ops/main.rs b/core/examples/http_bench_json_ops/main.rs
deleted file mode 100644
index ca86fd4..0000000
--- a/core/examples/http_bench_json_ops/main.rs
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use deno_core::anyhow::Error;
-use deno_core::op;
-use deno_core::AsyncRefCell;
-use deno_core::AsyncResult;
-use deno_core::JsBuffer;
-use deno_core::JsRuntimeForSnapshot;
-use deno_core::Op;
-use deno_core::OpState;
-use deno_core::Resource;
-use deno_core::ResourceId;
-use std::cell::RefCell;
-use std::env;
-use std::net::SocketAddr;
-use std::rc::Rc;
-use tokio::io::AsyncReadExt;
-use tokio::io::AsyncWriteExt;
-
-// This is a hack to make the `#[op]` macro work with
-// deno_core examples.
-// You can remove this:
-use deno_core::*;
-
-// Note: a `tokio::net::TcpListener` doesn't need to be wrapped in a cell,
-// because it only supports one op (`accept`) which does not require a mutable
-// reference to the listener.
-struct TcpListener {
-  inner: tokio::net::TcpListener,
-}
-
-impl TcpListener {
-  async fn accept(self: Rc<Self>) -> Result<TcpStream, std::io::Error> {
-    let stream = self.inner.accept().await?.0.into();
-    Ok(stream)
-  }
-}
-
-impl Resource for TcpListener {
-  fn close(self: Rc<Self>) {}
-}
-
-impl TryFrom<std::net::TcpListener> for TcpListener {
-  type Error = std::io::Error;
-  fn try_from(
-    std_listener: std::net::TcpListener,
-  ) -> Result<Self, Self::Error> {
-    tokio::net::TcpListener::try_from(std_listener).map(|tokio_listener| Self {
-      inner: tokio_listener,
-    })
-  }
-}
-
-struct TcpStream {
-  rd: AsyncRefCell<tokio::net::tcp::OwnedReadHalf>,
-  wr: AsyncRefCell<tokio::net::tcp::OwnedWriteHalf>,
-}
-
-impl TcpStream {
-  async fn read(self: Rc<Self>, data: &mut [u8]) -> Result<usize, Error> {
-    let mut rd = RcRef::map(&self, |r| &r.rd).borrow_mut().await;
-    let nread = rd.read(data).await?;
-    Ok(nread)
-  }
-
-  async fn write(self: Rc<Self>, data: &[u8]) -> Result<usize, Error> {
-    let mut wr = RcRef::map(self, |r| &r.wr).borrow_mut().await;
-    let nwritten = wr.write(data).await?;
-    Ok(nwritten)
-  }
-
-  fn try_write(self: Rc<Self>, data: &[u8]) -> Result<usize, Error> {
-    let wr = RcRef::map(self, |r| &r.wr)
-      .try_borrow_mut()
-      .ok_or_else(|| Error::msg("Failed to acquire lock on TcpStream"))?;
-    let nwritten = wr.try_write(data)?;
-    Ok(nwritten)
-  }
-}
-
-impl Resource for TcpStream {
-  deno_core::impl_readable_byob!();
-  deno_core::impl_writable!();
-
-  fn close(self: Rc<Self>) {}
-}
-
-impl From<tokio::net::TcpStream> for TcpStream {
-  fn from(s: tokio::net::TcpStream) -> Self {
-    let (rd, wr) = s.into_split();
-    Self {
-      rd: rd.into(),
-      wr: wr.into(),
-    }
-  }
-}
-
-fn create_js_runtime() -> JsRuntimeForSnapshot {
-  let ext = deno_core::Extension {
-    name: "my_ext",
-    ops: std::borrow::Cow::Borrowed(&[
-      op_listen::DECL,
-      op_accept::DECL,
-      op_try_write::DECL,
-      op_read_socket::DECL,
-    ]),
-    ..Default::default()
-  };
-
-  JsRuntimeForSnapshot::new(deno_core::RuntimeOptions {
-    extensions: vec![ext],
-    ..Default::default()
-  })
-}
-
-#[op]
-async fn op_read_socket(
-  state: Rc<RefCell<OpState>>,
-  rid: ResourceId,
-  mut data: JsBuffer,
-) -> Result<u32, Error> {
-  let resource = state.borrow_mut().resource_table.get::<TcpStream>(rid)?;
-  let nread = resource.read(&mut data).await?;
-  Ok(nread as u32)
-}
-
-#[op]
-fn op_listen(state: &mut OpState) -> Result<ResourceId, Error> {
-  let addr = "127.0.0.1:4570".parse::<SocketAddr>().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)
-}
-
-#[op]
-async fn op_accept(
-  state: Rc<RefCell<OpState>>,
-  rid: ResourceId,
-) -> Result<ResourceId, Error> {
-  let listener = state.borrow().resource_table.get::<TcpListener>(rid)?;
-  let stream = listener.accept().await?;
-  let rid = state.borrow_mut().resource_table.add(stream);
-  Ok(rid)
-}
-
-#[op(fast)]
-fn op_try_write(
-  state: &mut OpState,
-  rid: u32,
-  value: &[u8],
-) -> Result<bool, Error> {
-  let stream = state.resource_table.get::<TcpStream>(rid)?;
-  Ok(stream.try_write(value).is_ok())
-}
-
-fn main() {
-  // NOTE: `--help` arg will display V8 help and exit
-  deno_core::v8_set_flags(env::args().collect());
-
-  let mut js_runtime = create_js_runtime();
-  let runtime = tokio::runtime::Builder::new_current_thread()
-    .enable_io()
-    .build()
-    .unwrap();
-  let future = async move {
-    js_runtime
-      .execute_script(
-        "http_bench_json_ops.js",
-        include_ascii_string!("http_bench_json_ops.js"),
-      )
-      .unwrap();
-    js_runtime.run_event_loop(false).await
-  };
-  runtime.block_on(future).unwrap();
-}
diff --git a/core/examples/op2.rs b/core/examples/op2.rs
index 101e180..73bd01a 100644
--- a/core/examples/op2.rs
+++ b/core/examples/op2.rs
@@ -1,12 +1,6 @@
 use anyhow::Context;
 use deno_core::anyhow::Error;
-use deno_core::extension;
-use deno_core::op2;
-use deno_core::resolve_path;
-use deno_core::v8;
-use deno_core::FsModuleLoader;
-use deno_core::JsRuntime;
-use deno_core::OpState;
+use deno_core::*;
 use std::rc::Rc;
 
 #[op2]
diff --git a/core/examples/panik.rs b/core/examples/panik.rs
index 8ad1734..9f5ae9b 100644
--- a/core/examples/panik.rs
+++ b/core/examples/panik.rs
@@ -8,19 +8,10 @@
 //!    - https://github.com/rust-lang/rust/issues/74990
 //!    - https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html
 
-use deno_core::op;
-use deno_core::Extension;
-use deno_core::JsRuntime;
-use deno_core::Op;
-use deno_core::RuntimeOptions;
-
-// This is a hack to make the `#[op]` macro work with
-// deno_core examples.
-// You can remove this:
 use deno_core::*;
 
 fn main() {
-  #[op]
+  #[op2(fast)]
   fn op_panik() {
     panic!("panik !!!")
   }
diff --git a/core/examples/schedule_task.rs b/core/examples/schedule_task.rs
index 53ae564..b0b4eff 100644
--- a/core/examples/schedule_task.rs
+++ b/core/examples/schedule_task.rs
@@ -1,7 +1,7 @@
 // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
 
 use deno_core::anyhow::Error;
-use deno_core::op;
+use deno_core::op2;
 use deno_core::Extension;
 use deno_core::JsRuntime;
 use deno_core::Op;
@@ -11,11 +11,6 @@ use futures::channel::mpsc;
 use futures::stream::StreamExt;
 use std::task::Poll;
 
-// This is a hack to make the `#[op]` macro work with
-// deno_core examples.
-// You can remove this:
-use deno_core::*;
-
 type Task = Box<dyn FnOnce()>;
 
 fn main() {
@@ -63,7 +58,7 @@ fn main() {
   runtime.block_on(future).unwrap();
 }
 
-#[op]
+#[op2(fast)]
 fn op_schedule_task(state: &mut OpState, i: u8) -> Result<(), Error> {
   let tx = state.borrow_mut::<mpsc::UnboundedSender<Task>>();
   tx.unbounded_send(Box::new(move || println!("Hello, world! x{i}")))
diff --git a/core/examples/wasm.rs b/core/examples/wasm.rs
index dd59e14..903d87b 100644
--- a/core/examples/wasm.rs
+++ b/core/examples/wasm.rs
@@ -1,19 +1,9 @@
 // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use deno_core::op;
-use deno_core::Extension;
-use deno_core::JsRuntime;
-use deno_core::Op;
-use deno_core::RuntimeOptions;
+#![allow(deprecated)]
+use deno_core::*;
 use std::mem::transmute;
 use std::ptr::NonNull;
 
-// This is a hack to make the `#[op]` macro work with
-// deno_core examples.
-// You can remove this:
-
-use deno_core::*;
-
 struct WasmMemory(NonNull<v8::WasmMemoryObject>);
 
 fn wasm_memory_unchecked(state: &mut OpState) -> &mut [u8] {
diff --git a/core/extensions.rs b/core/extensions.rs
index 0602cea..84e70e9 100644
--- a/core/extensions.rs
+++ b/core/extensions.rs
@@ -96,7 +96,9 @@ pub struct OpDecl {
   pub name: &'static str,
   pub enabled: bool,
   pub is_async: bool,
+  #[deprecated = "Will be removed with op1"]
   pub is_unstable: bool,
+  #[deprecated = "Will be removed with op1"]
   pub is_v8: bool,
   pub arg_count: u8,
   /// The slow dispatch call. If metrics are disabled, the `v8::Function` is created with this callback.
@@ -112,6 +114,7 @@ pub struct OpDecl {
 impl OpDecl {
   /// For use by internal op implementation only.
   #[doc(hidden)]
+  #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
   pub const fn new_internal(
     name: &'static str,
     is_async: bool,
@@ -121,6 +124,7 @@ impl OpDecl {
     slow_fn: OpFnRef,
     fast_fn: Option<FastFunction>,
   ) -> Self {
+    #[allow(deprecated)]
     Self {
       name,
       enabled: true,
@@ -146,6 +150,7 @@ impl OpDecl {
     fast_fn: Option<FastFunction>,
     fast_fn_with_metrics: Option<FastFunction>,
   ) -> Self {
+    #[allow(deprecated)]
     Self {
       name,
       enabled: true,
diff --git a/core/runtime/bindings.rs b/core/runtime/bindings.rs
index 719659a..32179f4 100644
--- a/core/runtime/bindings.rs
+++ b/core/runtime/bindings.rs
@@ -1,5 +1,4 @@
 // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
 use log::debug;
 use std::fmt::Write;
 use std::option::Option;
diff --git a/ops/lib.rs b/ops/lib.rs
index c28e371..aaf42af 100644
--- a/ops/lib.rs
+++ b/ops/lib.rs
@@ -127,6 +127,7 @@ impl Op {
         #[doc=""]
         #[doc=#docline]
         #[doc="you can include in a `deno_core::Extension`."]
+        #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
         pub struct #name #generics {
           _phantom_data: ::std::marker::PhantomData<(#(#params),*)>
         }
@@ -193,7 +194,9 @@ impl Op {
       }
 
       impl #generics #core::_ops::Op for #name #generics #where_clause {
+        #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
         const NAME: &'static str = stringify!(#name);
+        #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
         const DECL: #core::OpDecl = #core::_ops::OpDecl::new_internal(
           Self::name(),
           #is_async,
@@ -207,6 +210,7 @@ impl Op {
 
       #[doc(hidden)]
       impl #generics #name #generics #where_clause {
+        #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
         pub const fn name() -> &'static str {
           stringify!(#name)
         }


Test patch:
diff --git a/core/modules/tests.rs b/core/modules/tests.rs
index fbd8075..7c83e16 100644
--- a/core/modules/tests.rs
+++ b/core/modules/tests.rs
@@ -7,7 +7,7 @@ use crate::runtime::JsRuntime;
 use crate::runtime::JsRuntimeForSnapshot;
 use crate::RuntimeOptions;
 use crate::Snapshot;
-use deno_ops::op;
+use deno_ops::op2;
 use futures::future::poll_fn;
 use futures::future::FutureExt;
 use parking_lot::Mutex;
@@ -302,7 +302,7 @@ fn test_mods() {
   let loader = Rc::new(CountingModuleLoader::new(NoopModuleLoader));
   static DISPATCH_COUNT: AtomicUsize = AtomicUsize::new(0);
 
-  #[op]
+  #[op2(fast)]
   fn op_test(control: u8) -> u8 {
     DISPATCH_COUNT.fetch_add(1, Ordering::Relaxed);
     assert_eq!(control, 42);
diff --git a/core/runtime/tests/error.rs b/core/runtime/tests/error.rs
index bd5a0bc..77434d5 100644
--- a/core/runtime/tests/error.rs
+++ b/core/runtime/tests/error.rs
@@ -4,13 +4,12 @@ use crate::error::custom_error;
 use crate::error::JsError;
 use crate::*;
 use anyhow::Error;
-use deno_ops::op;
 use futures::future::poll_fn;
 use std::task::Poll;
 
 #[tokio::test]
 async fn test_error_builder() {
-  #[op]
+  #[op2(core, fast)]
   fn op_err() -> Result<(), Error> {
     Err(custom_error("DOMExceptionOperationError", "abc"))
   }
@@ -125,12 +124,12 @@ async fn test_error_async_stack() {
 async fn test_error_context() {
   use anyhow::anyhow;
 
-  #[op]
+  #[op2(fast)]
   fn op_err_sync() -> Result<(), Error> {
     Err(anyhow!("original sync error").context("higher-level sync error"))
   }
 
-  #[op]
+  #[op2(async)]
   async fn op_err_async() -> Result<(), Error> {
     Err(anyhow!("original async error").context("higher-level async error"))
   }
diff --git a/core/runtime/tests/jsrealm.rs b/core/runtime/tests/jsrealm.rs
index f00a0f4..16b3d62 100644
--- a/core/runtime/tests/jsrealm.rs
+++ b/core/runtime/tests/jsrealm.rs
@@ -5,7 +5,7 @@ use crate::modules::StaticModuleLoader;
 use crate::runtime::tests::snapshot::generic_es_snapshot_without_runtime_module_loader;
 use crate::*;
 use anyhow::Error;
-use deno_ops::op;
+use deno_ops::op2;
 use futures::channel::oneshot;
 use futures::future::poll_fn;
 use futures::future::Future;
@@ -161,7 +161,8 @@ fn js_realm_simple() {
 
 #[test]
 fn js_realm_init() {
-  #[op]
+  #[op2]
+  #[string]
   fn op_test() -> Result<String, Error> {
     Ok(String::from("Test"))
   }
@@ -191,7 +192,8 @@ fn js_realm_init_snapshot() {
     Vec::from(snap).into_boxed_slice()
   };
 
-  #[op]
+  #[op2]
+  #[string]
   fn op_test() -> Result<String, Error> {
     Ok(String::from("Test"))
   }
@@ -218,7 +220,8 @@ fn js_realm_sync_ops() {
   // don't test the result of returning structs, because they will be
   // serialized to objects with null prototype.
 
-  #[op]
+  #[op2]
+  #[serde]
   fn op_test(fail: bool) -> Result<ToJsBuffer, Error> {
     if !fail {
       Ok(ToJsBuffer::empty())
@@ -266,7 +269,8 @@ async fn js_realm_async_ops() {
   // don't test the result of returning structs, because they will be
   // serialized to objects with null prototype.
 
-  #[op]
+  #[op2(async)]
+  #[serde]
   async fn op_test(fail: bool) -> Result<ToJsBuffer, Error> {
     if !fail {
       Ok(ToJsBuffer::empty())
@@ -346,7 +350,7 @@ async fn js_realm_gc() {
   }
 
   // Never resolves.
-  #[op]
+  #[op2(async)]
   async fn op_pending() {
     assert_eq!(INVOKE_COUNT.fetch_add(1, Ordering::SeqCst), 0);
     PendingFuture {}.await
@@ -394,7 +398,7 @@ async fn js_realm_gc() {
 #[tokio::test]
 async fn js_realm_ref_unref_ops() {
   // Never resolves.
-  #[op]
+  #[op2(async)]
   async fn op_pending() {
     futures::future::pending().await
   }
@@ -638,7 +642,7 @@ async fn test_realms_concurrent_module_evaluations() {
     ascii_str!(r#"await Deno.core.opAsync("op_wait");"#),
   ));
 
-  #[op]
+  #[op2(async)]
   async fn op_wait(op_state: Rc<RefCell<OpState>>) {
     let (sender, receiver) = oneshot::channel::<()>();
     op_state
@@ -720,7 +724,7 @@ async fn test_realm_concurrent_dynamic_imports() {
     ascii_str!(r#"await Deno.core.opAsync("op_wait");"#),
   ));
 
-  #[op]
+  #[op2(async)]
   async fn op_wait(op_state: Rc<RefCell<OpState>>) {
     let (sender, receiver) = oneshot::channel::<()>();
     op_state
@@ -893,7 +897,7 @@ fn non_snapshot_preserve_snapshotted_modules() {
 /// with non-snapshotted ESM extensions.
 #[tokio::test]
 async fn realm_creation_during_async_op_hang() {
-  #[op]
+  #[op2(async)]
   async fn op_listen(op_state: Rc<RefCell<OpState>>) -> Result<(), Error> {
     let (sender, receiver) = oneshot::channel::<()>();
     op_state.borrow_mut().put(sender);
diff --git a/core/runtime/tests/misc.rs b/core/runtime/tests/misc.rs
index 6bb8f3e..cc2acf5 100644
--- a/core/runtime/tests/misc.rs
+++ b/core/runtime/tests/misc.rs
@@ -11,7 +11,7 @@ use anyhow::Error;
 use cooked_waker::IntoWaker;
 use cooked_waker::Wake;
 use cooked_waker::WakeRef;
-use deno_ops::op;
+use deno_ops::op2;
 use futures::future::poll_fn;
 use std::borrow::Cow;
 use std::rc::Rc;
@@ -86,7 +86,7 @@ impl WakeRef for LoggingWaker {
 async fn test_wakers_for_async_ops() {
   static STATE: AtomicI8 = AtomicI8::new(0);
 
-  #[op]
+  #[op2(async)]
   async fn op_async_sleep() -> Result<(), Error> {
     STATE.store(1, Ordering::SeqCst);
     tokio::time::sleep(std::time::Duration::from_millis(1)).await;
@@ -635,7 +635,7 @@ fn test_is_proxy() {
 
 #[tokio::test]
 async fn test_set_macrotask_callback_set_next_tick_callback() {
-  #[op]
+  #[op2(async)]
   async fn op_async_sleep() -> Result<(), Error> {
     // Future must be Poll::Pending on first call
     tokio::time::sleep(std::time::Duration::from_millis(1)).await;
@@ -685,13 +685,13 @@ fn test_has_tick_scheduled() {
   static MACROTASK: AtomicUsize = AtomicUsize::new(0);
   static NEXT_TICK: AtomicUsize = AtomicUsize::new(0);
 
-  #[op]
+  #[op2(fast)]
   fn op_macrotask() -> Result<(), AnyError> {
     MACROTASK.fetch_add(1, Ordering::Relaxed);
     Ok(())
   }
 
-  #[op]
+  #[op2(fast)]
   fn op_next_tick() -> Result<(), AnyError> {
     NEXT_TICK.fetch_add(1, Ordering::Relaxed);
     Ok(())
@@ -798,7 +798,7 @@ async fn test_unhandled_rejection_order() {
 async fn test_set_promise_reject_callback() {
   static PROMISE_REJECT: AtomicUsize = AtomicUsize::new(0);
 
-  #[op]
+  #[op2(fast)]
   fn op_promise_reject() -> Result<(), AnyError> {
     PROMISE_REJECT.fetch_add(1, Ordering::Relaxed);
     Ok(())
@@ -855,7 +855,7 @@ async fn test_set_promise_reject_callback() {
 async fn test_set_promise_reject_callback_top_level_await() {
   static PROMISE_REJECT: AtomicUsize = AtomicUsize::new(0);
 
-  #[op]
+  #[op2(fast)]
   fn op_promise_reject() -> Result<(), AnyError> {
     PROMISE_REJECT.fetch_add(1, Ordering::Relaxed);
     Ok(())
@@ -956,7 +956,7 @@ async fn test_stalled_tla() {
 // Regression test for https://github.com/denoland/deno/issues/20034.
 #[tokio::test]
 async fn test_dynamic_import_module_error_stack() {
-  #[op]
+  #[op2(async)]
   async fn op_async_error() -> Result<(), Error> {
     tokio::time::sleep(std::time::Duration::from_millis(1)).await;
     Err(crate::error::type_error("foo"))
@@ -1003,8 +1003,8 @@ async fn test_dynamic_import_module_error_stack() {
   expected = "Top-level await is not allowed in extensions (mod:tla:2:1)"
 )]
 async fn tla_in_esm_extensions_panics() {
-  #[op]
-  async fn op_wait(ms: usize) {
+  #[op2(async)]
+  async fn op_wait(#[number] ms: usize) {
     tokio::time::sleep(Duration::from_millis(ms as u64)).await
   }
 
diff --git a/core/runtime/tests/mod.rs b/core/runtime/tests/mod.rs
index 1eb1c84..8475df7 100644
--- a/core/runtime/tests/mod.rs
+++ b/core/runtime/tests/mod.rs
@@ -4,7 +4,7 @@ use crate::CrossIsolateStore;
 use crate::JsRuntime;
 use crate::OpState;
 use crate::RuntimeOptions;
-use deno_ops::op;
+use deno_ops::op2;
 use serde_v8::JsBuffer;
 use std::cell::RefCell;
 use std::rc::Rc;
@@ -30,13 +30,13 @@ struct TestState {
   dispatch_count: Arc<AtomicUsize>,
 }
 
-#[op]
+#[allow(clippy::await_holding_refcell_ref)] // False positive.
+#[op2(async)]
 async fn op_test(
   rc_op_state: Rc<RefCell<OpState>>,
   control: u8,
-  buf: Option<JsBuffer>,
+  #[buffer] buf: Option<JsBuffer>,
 ) -> Result<u8, AnyError> {
-  #![allow(clippy::await_holding_refcell_ref)] // False positive.
   let op_state_ = rc_op_state.borrow();
   let test_state = op_state_.borrow::<TestState>();
   test_state.dispatch_count.fetch_add(1, Ordering::Relaxed);
diff --git a/core/runtime/tests/ops.rs b/core/runtime/tests/ops.rs
index d8f7f93..8d6c19a 100644
--- a/core/runtime/tests/ops.rs
+++ b/core/runtime/tests/ops.rs
@@ -9,7 +9,6 @@ use crate::runtime::tests::Mode;
 use crate::*;
 use anyhow::bail;
 use anyhow::Error;
-use deno_ops::op;
 use log::debug;
 use pretty_assertions::assert_eq;
 use std::cell::RefCell;
@@ -166,12 +165,13 @@ fn test_op_return_serde_v8_error() {
 
 #[test]
 fn test_op_high_arity() {
-  #[op]
+  #[op2(fast)]
+  #[number]
   fn op_add_4(
-    x1: i64,
-    x2: i64,
-    x3: i64,
-    x4: i64,
+    #[number] x1: i64,
+    #[number] x2: i64,
+    #[number] x3: i64,
+    #[number] x4: i64,
   ) -> Result<i64, anyhow::Error> {
     Ok(x1 + x2 + x3 + x4)
   }
@@ -190,7 +190,8 @@ fn test_op_high_arity() {
 
 #[test]
 fn test_op_disabled() {
-  #[op]
+  #[op2(fast)]
+  #[number]
   fn op_foo() -> Result<i64, anyhow::Error> {
     Ok(42)
   }
@@ -288,42 +289,6 @@ fn test_op_detached_buffer() {
     .unwrap();
 }
 
-#[test]
-fn test_op_unstable_disabling() {
-  #[op]
-  fn op_foo() -> Result<i64, anyhow::Error> {
-    Ok(42)
-  }
-
-  #[op(unstable)]
-  fn op_bar() -> Result<i64, anyhow::Error> {
-    Ok(42)
-  }
-
-  deno_core::extension!(
-    test_ext,
-    ops = [op_foo, op_bar],
-    middleware = |op| if op.is_unstable { op.disable() } else { op }
-  );
-  let mut runtime = JsRuntime::new(RuntimeOptions {
-    extensions: vec![test_ext::init_ops()],
-    ..Default::default()
-  });
-  runtime
-    .execute_script_static(
-      "test.js",
-      r#"
-      if (Deno.core.ops.op_foo() !== 42) {
-        throw new Error("Expected op_foo() === 42");
-      }
-      if (typeof Deno.core.ops.op_bar !== "undefined") {
-        throw new Error("Expected op_bar to be disabled")
-      }
-    "#,
-    )
-    .unwrap();
-}
-
 #[cfg(debug_assertions)]
 #[test]
 #[should_panic(expected = "Found ops with duplicate names:")]
@@ -359,7 +324,8 @@ fn ops_in_js_have_proper_names() {
     Ok(String::from("Test"))
   }
 
-  #[op]
+  #[op2(async)]
+  #[string]
   async fn op_test_async() -> Result<String, Error> {
     Ok(String::from("Test"))
   }
diff --git a/core/runtime/tests/snapshot.rs b/core/runtime/tests/snapshot.rs
index 41e0949..e8b7b05 100644
--- a/core/runtime/tests/snapshot.rs
+++ b/core/runtime/tests/snapshot.rs
@@ -1,4 +1,5 @@
 // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+use crate as deno_core;
 use crate::extensions::Op;
 use crate::modules::AssertedModuleType;
 use crate::modules::LoggingModuleLoader;
@@ -8,7 +9,6 @@ use crate::modules::ModuleType;
 use crate::modules::SymbolicModule;
 use crate::*;
 use anyhow::Error;
-use deno_ops::op;
 use std::borrow::Cow;
 use std::rc::Rc;
 use url::Url;
@@ -197,7 +197,8 @@ fn es_snapshot() {
     }
   }
 
-  #[op]
+  #[op2]
+  #[string]
   fn op_test() -> Result<String, Error> {
     Ok(String::from("test"))
   }
diff --git a/ops/optimizer_tests/async_nop.out b/ops/optimizer_tests/async_nop.out
index 7bfef16..d013534 100644
--- a/ops/optimizer_tests/async_nop.out
+++ b/ops/optimizer_tests/async_nop.out
@@ -7,7 +7,9 @@ pub struct op_void_async {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_void_async {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_void_async);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         true,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_void_async {
 }
 #[doc(hidden)]
 impl op_void_async {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_void_async)
     }
diff --git a/ops/optimizer_tests/async_result.out b/ops/optimizer_tests/async_result.out
index fbedb98..72de5e1 100644
--- a/ops/optimizer_tests/async_result.out
+++ b/ops/optimizer_tests/async_result.out
@@ -7,7 +7,9 @@ pub struct op_async_result {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_async_result {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_async_result);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         true,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_async_result {
 }
 #[doc(hidden)]
 impl op_async_result {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_async_result)
     }
diff --git a/ops/optimizer_tests/callback_options.out b/ops/optimizer_tests/callback_options.out
index 12ce3fe..c5896c3 100644
--- a/ops/optimizer_tests/callback_options.out
+++ b/ops/optimizer_tests/callback_options.out
@@ -7,7 +7,9 @@ pub struct op_fallback {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_fallback {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_fallback);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_fallback {
 }
 #[doc(hidden)]
 impl op_fallback {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_fallback)
     }
diff --git a/ops/optimizer_tests/cow_str.out b/ops/optimizer_tests/cow_str.out
index 88053c1..784fdd8 100644
--- a/ops/optimizer_tests/cow_str.out
+++ b/ops/optimizer_tests/cow_str.out
@@ -7,7 +7,9 @@ pub struct op_cow_str {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_cow_str {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_cow_str);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_cow_str {
 }
 #[doc(hidden)]
 impl op_cow_str {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_cow_str)
     }
diff --git a/ops/optimizer_tests/f64_slice.out b/ops/optimizer_tests/f64_slice.out
index 2a2011b..186add2 100644
--- a/ops/optimizer_tests/f64_slice.out
+++ b/ops/optimizer_tests/f64_slice.out
@@ -7,7 +7,9 @@ pub struct op_f64_buf {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_f64_buf {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_f64_buf);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_f64_buf {
 }
 #[doc(hidden)]
 impl op_f64_buf {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_f64_buf)
     }
diff --git a/ops/optimizer_tests/incompatible_1.out b/ops/optimizer_tests/incompatible_1.out
index ce2fc90..583a874 100644
--- a/ops/optimizer_tests/incompatible_1.out
+++ b/ops/optimizer_tests/incompatible_1.out
@@ -7,7 +7,9 @@ pub struct op_sync_serialize_object_with_numbers_as_keys {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_sync_serialize_object_with_numbers_as_keys {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_sync_serialize_object_with_numbers_as_keys);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -20,6 +22,7 @@ impl deno_core::_ops::Op for op_sync_serialize_object_with_numbers_as_keys {
 }
 #[doc(hidden)]
 impl op_sync_serialize_object_with_numbers_as_keys {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_sync_serialize_object_with_numbers_as_keys)
     }
diff --git a/ops/optimizer_tests/issue16934.out b/ops/optimizer_tests/issue16934.out
index e2380a8..4be2365 100644
--- a/ops/optimizer_tests/issue16934.out
+++ b/ops/optimizer_tests/issue16934.out
@@ -7,7 +7,9 @@ pub struct send_stdin {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for send_stdin {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(send_stdin);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         true,
@@ -20,6 +22,7 @@ impl deno_core::_ops::Op for send_stdin {
 }
 #[doc(hidden)]
 impl send_stdin {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(send_stdin)
     }
diff --git a/ops/optimizer_tests/issue16934_fast.out b/ops/optimizer_tests/issue16934_fast.out
index 294d8aa..25b5897 100644
--- a/ops/optimizer_tests/issue16934_fast.out
+++ b/ops/optimizer_tests/issue16934_fast.out
@@ -7,7 +7,9 @@ pub struct send_stdin {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for send_stdin {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(send_stdin);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         true,
@@ -20,6 +22,7 @@ impl deno_core::_ops::Op for send_stdin {
 }
 #[doc(hidden)]
 impl send_stdin {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(send_stdin)
     }
diff --git a/ops/optimizer_tests/op_blob_revoke_object_url.out b/ops/optimizer_tests/op_blob_revoke_object_url.out
index c88e88c..7d845c6 100644
--- a/ops/optimizer_tests/op_blob_revoke_object_url.out
+++ b/ops/optimizer_tests/op_blob_revoke_object_url.out
@@ -7,7 +7,9 @@ pub struct op_blob_revoke_object_url {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_blob_revoke_object_url {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_blob_revoke_object_url);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -20,6 +22,7 @@ impl deno_core::_ops::Op for op_blob_revoke_object_url {
 }
 #[doc(hidden)]
 impl op_blob_revoke_object_url {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_blob_revoke_object_url)
     }
diff --git a/ops/optimizer_tests/op_ffi_ptr_value.out b/ops/optimizer_tests/op_ffi_ptr_value.out
index 56741f2..b159051 100644
--- a/ops/optimizer_tests/op_ffi_ptr_value.out
+++ b/ops/optimizer_tests/op_ffi_ptr_value.out
@@ -7,7 +7,9 @@ pub struct op_ffi_ptr_value {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_ffi_ptr_value {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_ffi_ptr_value);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_ffi_ptr_value {
 }
 #[doc(hidden)]
 impl op_ffi_ptr_value {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_ffi_ptr_value)
     }
diff --git a/ops/optimizer_tests/op_print.out b/ops/optimizer_tests/op_print.out
index 9a4540e..784da3e 100644
--- a/ops/optimizer_tests/op_print.out
+++ b/ops/optimizer_tests/op_print.out
@@ -7,7 +7,9 @@ pub struct op_print {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_print {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_print);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -20,6 +22,7 @@ impl deno_core::_ops::Op for op_print {
 }
 #[doc(hidden)]
 impl op_print {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_print)
     }
diff --git a/ops/optimizer_tests/op_state.out b/ops/optimizer_tests/op_state.out
index 0e0b633..adffc77 100644
--- a/ops/optimizer_tests/op_state.out
+++ b/ops/optimizer_tests/op_state.out
@@ -7,7 +7,9 @@ pub struct op_set_exit_code {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_set_exit_code {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_set_exit_code);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_set_exit_code {
 }
 #[doc(hidden)]
 impl op_set_exit_code {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_set_exit_code)
     }
diff --git a/ops/optimizer_tests/op_state_basic1.out b/ops/optimizer_tests/op_state_basic1.out
index a7eccde..4861554 100644
--- a/ops/optimizer_tests/op_state_basic1.out
+++ b/ops/optimizer_tests/op_state_basic1.out
@@ -7,7 +7,9 @@ pub struct foo {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for foo {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(foo);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for foo {
 }
 #[doc(hidden)]
 impl foo {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(foo)
     }
diff --git a/ops/optimizer_tests/op_state_generics.out b/ops/optimizer_tests/op_state_generics.out
index b62a352..1315644 100644
--- a/ops/optimizer_tests/op_state_generics.out
+++ b/ops/optimizer_tests/op_state_generics.out
@@ -10,7 +10,9 @@ impl<SP> deno_core::_ops::Op for op_foo<SP>
 where
     SP: SomePermission + 'static,
 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_foo);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -36,6 +38,7 @@ impl<SP> op_foo<SP>
 where
     SP: SomePermission + 'static,
 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_foo)
     }
diff --git a/ops/optimizer_tests/op_state_result.out b/ops/optimizer_tests/op_state_result.out
index d66d041..09eac34 100644
--- a/ops/optimizer_tests/op_state_result.out
+++ b/ops/optimizer_tests/op_state_result.out
@@ -7,7 +7,9 @@ pub struct foo {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for foo {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(foo);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for foo {
 }
 #[doc(hidden)]
 impl foo {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(foo)
     }
diff --git a/ops/optimizer_tests/op_state_warning.out b/ops/optimizer_tests/op_state_warning.out
index 5d74e08..5e35fe6 100644
--- a/ops/optimizer_tests/op_state_warning.out
+++ b/ops/optimizer_tests/op_state_warning.out
@@ -7,7 +7,9 @@ pub struct op_listen {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_listen {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_listen);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_listen {
 }
 #[doc(hidden)]
 impl op_listen {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_listen)
     }
diff --git a/ops/optimizer_tests/op_state_with_transforms.out b/ops/optimizer_tests/op_state_with_transforms.out
index b17ab75..095b207 100644
--- a/ops/optimizer_tests/op_state_with_transforms.out
+++ b/ops/optimizer_tests/op_state_with_transforms.out
@@ -10,7 +10,9 @@ impl<TP> deno_core::_ops::Op for op_now<TP>
 where
     TP: TimersPermission + 'static,
 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_now);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -36,6 +38,7 @@ impl<TP> op_now<TP>
 where
     TP: TimersPermission + 'static,
 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_now)
     }
diff --git a/ops/optimizer_tests/opstate_with_arity.out b/ops/optimizer_tests/opstate_with_arity.out
index 6a8c92c..6b20d67 100644
--- a/ops/optimizer_tests/opstate_with_arity.out
+++ b/ops/optimizer_tests/opstate_with_arity.out
@@ -7,7 +7,9 @@ pub struct op_add_4 {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_add_4 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_add_4);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_add_4 {
 }
 #[doc(hidden)]
 impl op_add_4 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_add_4)
     }
diff --git a/ops/optimizer_tests/option_arg.out b/ops/optimizer_tests/option_arg.out
index 17fd0c2..6ee3cb7 100644
--- a/ops/optimizer_tests/option_arg.out
+++ b/ops/optimizer_tests/option_arg.out
@@ -7,7 +7,9 @@ pub struct op_try_close {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_try_close {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_try_close);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -20,6 +22,7 @@ impl deno_core::_ops::Op for op_try_close {
 }
 #[doc(hidden)]
 impl op_try_close {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_try_close)
     }
diff --git a/ops/optimizer_tests/owned_string.out b/ops/optimizer_tests/owned_string.out
index cb9323c..ff68ec0 100644
--- a/ops/optimizer_tests/owned_string.out
+++ b/ops/optimizer_tests/owned_string.out
@@ -7,7 +7,9 @@ pub struct op_string_length {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_string_length {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_string_length);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_string_length {
 }
 #[doc(hidden)]
 impl op_string_length {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_string_length)
     }
diff --git a/ops/optimizer_tests/param_mut_binding_warning.out b/ops/optimizer_tests/param_mut_binding_warning.out
index af5225c..53bd030 100644
--- a/ops/optimizer_tests/param_mut_binding_warning.out
+++ b/ops/optimizer_tests/param_mut_binding_warning.out
@@ -7,7 +7,9 @@ pub struct op_read_sync {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_read_sync {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_read_sync);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -20,6 +22,7 @@ impl deno_core::_ops::Op for op_read_sync {
 }
 #[doc(hidden)]
 impl op_read_sync {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_read_sync)
     }
diff --git a/ops/optimizer_tests/raw_ptr.out b/ops/optimizer_tests/raw_ptr.out
index a7bc5ab..2e418e3 100644
--- a/ops/optimizer_tests/raw_ptr.out
+++ b/ops/optimizer_tests/raw_ptr.out
@@ -10,7 +10,9 @@ impl<FP> deno_core::_ops::Op for op_ffi_ptr_of<FP>
 where
     FP: FfiPermissions + 'static,
 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_ffi_ptr_of);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -41,6 +43,7 @@ impl<FP> op_ffi_ptr_of<FP>
 where
     FP: FfiPermissions + 'static,
 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_ffi_ptr_of)
     }
diff --git a/ops/optimizer_tests/serde_v8_value.out b/ops/optimizer_tests/serde_v8_value.out
index a956288..4a76fa2 100644
--- a/ops/optimizer_tests/serde_v8_value.out
+++ b/ops/optimizer_tests/serde_v8_value.out
@@ -7,7 +7,9 @@ pub struct op_is_proxy {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_is_proxy {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_is_proxy);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_is_proxy {
 }
 #[doc(hidden)]
 impl op_is_proxy {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_is_proxy)
     }
diff --git a/ops/optimizer_tests/strings.out b/ops/optimizer_tests/strings.out
index 01f89b5..a1ea053 100644
--- a/ops/optimizer_tests/strings.out
+++ b/ops/optimizer_tests/strings.out
@@ -7,7 +7,9 @@ pub struct op_string_length {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_string_length {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_string_length);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_string_length {
 }
 #[doc(hidden)]
 impl op_string_length {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_string_length)
     }
diff --git a/ops/optimizer_tests/strings_result.out b/ops/optimizer_tests/strings_result.out
index e79e686..3eca689 100644
--- a/ops/optimizer_tests/strings_result.out
+++ b/ops/optimizer_tests/strings_result.out
@@ -7,7 +7,9 @@ pub struct op_string_length {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_string_length {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_string_length);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -20,6 +22,7 @@ impl deno_core::_ops::Op for op_string_length {
 }
 #[doc(hidden)]
 impl op_string_length {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_string_length)
     }
diff --git a/ops/optimizer_tests/u64_result.out b/ops/optimizer_tests/u64_result.out
index d638966..e31d6c0 100644
--- a/ops/optimizer_tests/u64_result.out
+++ b/ops/optimizer_tests/u64_result.out
@@ -7,7 +7,9 @@ pub struct op_bench_now {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_bench_now {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_bench_now);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -20,6 +22,7 @@ impl deno_core::_ops::Op for op_bench_now {
 }
 #[doc(hidden)]
 impl op_bench_now {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_bench_now)
     }
diff --git a/ops/optimizer_tests/uint8array.out b/ops/optimizer_tests/uint8array.out
index db7d63a..f88bc96 100644
--- a/ops/optimizer_tests/uint8array.out
+++ b/ops/optimizer_tests/uint8array.out
@@ -7,7 +7,9 @@ pub struct op_import_spki_x25519 {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_import_spki_x25519 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_import_spki_x25519);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_import_spki_x25519 {
 }
 #[doc(hidden)]
 impl op_import_spki_x25519 {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_import_spki_x25519)
     }
diff --git a/ops/optimizer_tests/unit_result.out b/ops/optimizer_tests/unit_result.out
index df44dab..45e83c6 100644
--- a/ops/optimizer_tests/unit_result.out
+++ b/ops/optimizer_tests/unit_result.out
@@ -7,7 +7,9 @@ pub struct op_unit_result {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_unit_result {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_unit_result);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_unit_result {
 }
 #[doc(hidden)]
 impl op_unit_result {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_unit_result)
     }
diff --git a/ops/optimizer_tests/unit_result2.out b/ops/optimizer_tests/unit_result2.out
index fa990c6..ed73683 100644
--- a/ops/optimizer_tests/unit_result2.out
+++ b/ops/optimizer_tests/unit_result2.out
@@ -7,7 +7,9 @@ pub struct op_set_nodelay {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_set_nodelay {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_set_nodelay);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_set_nodelay {
 }
 #[doc(hidden)]
 impl op_set_nodelay {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_set_nodelay)
     }
diff --git a/ops/optimizer_tests/unit_ret.out b/ops/optimizer_tests/unit_ret.out
index 9cab2ca..fa3e77e 100644
--- a/ops/optimizer_tests/unit_ret.out
+++ b/ops/optimizer_tests/unit_ret.out
@@ -7,7 +7,9 @@ pub struct op_unit {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_unit {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_unit);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_unit {
 }
 #[doc(hidden)]
 impl op_unit {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_unit)
     }
diff --git a/ops/optimizer_tests/wasm_op.out b/ops/optimizer_tests/wasm_op.out
index f622bd2..0bb8333 100644
--- a/ops/optimizer_tests/wasm_op.out
+++ b/ops/optimizer_tests/wasm_op.out
@@ -7,7 +7,9 @@ pub struct op_wasm {
     _phantom_data: ::std::marker::PhantomData<()>,
 }
 impl deno_core::_ops::Op for op_wasm {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const NAME: &'static str = stringify!(op_wasm);
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     const DECL: deno_core::OpDecl = deno_core::_ops::OpDecl::new_internal(
         Self::name(),
         false,
@@ -30,6 +32,7 @@ impl deno_core::_ops::Op for op_wasm {
 }
 #[doc(hidden)]
 impl op_wasm {
+    #[deprecated = "#[op] is deprecated. Please switch this op to #[op2]."]
     pub const fn name() -> &'static str {
         stringify!(op_wasm)
     }