Repository: denoland/deno_core
Pull request #103 (2023-07-31 14:26:20)

fix(ops): ensure unsigned #[smi] return values work


Patch:
diff --git a/core/runtime/ops.rs b/core/runtime/ops.rs
index 4803fb8..3695f93 100644
--- a/core/runtime/ops.rs
+++ b/core/runtime/ops.rs
@@ -599,6 +599,7 @@ mod tests {
       op_test_print_debug,
 
       op_test_add,
+      op_test_add_smi_unsigned,
       op_test_add_option,
       op_test_result_void_switch,
       op_test_result_void_ok,
@@ -609,8 +610,8 @@ mod tests {
       op_test_bool_result,
       op_test_float,
       op_test_float_result,
-      op_test_i64,
-      op_test_u64,
+      op_test_bigint_i64,
+      op_test_bigint_u64,
       op_test_string_owned,
       op_test_string_ref,
       op_test_string_cow,
@@ -793,6 +794,12 @@ mod tests {
     (a as i32 + b) as u32
   }
 
+  #[op2(core, fast)]
+  #[smi]
+  pub fn op_test_add_smi_unsigned(#[smi] a: u32) -> u32 {
+    a + 1
+  }
+
   /// Test various numeric coercions in fast and slow mode.
   #[tokio::test(flavor = "current_thread")]
   pub async fn test_op_add() -> Result<(), Box<dyn std::error::Error>> {
@@ -983,13 +990,13 @@ mod tests {
 
   #[op2(core)]
   #[bigint]
-  pub fn op_test_u64(#[bigint] input: u64) -> u64 {
+  pub fn op_test_bigint_u64(#[bigint] input: u64) -> u64 {
     input
   }
 
   #[op2(core)]
   #[bigint]
-  pub fn op_test_i64(#[bigint] input: i64) -> i64 {
+  pub fn op_test_bigint_i64(#[bigint] input: i64) -> i64 {
     input
   }
 
@@ -997,18 +1004,18 @@ mod tests {
   pub async fn test_op_64() -> Result<(), Box<dyn std::error::Error>> {
     run_test2(
       10,
-      "op_test_i64",
-      &format!("assert(op_test_i64({}n) == {}n)", i64::MAX, i64::MAX),
+      "op_test_bigint_i64",
+      &format!("assert(op_test_bigint_i64({}n) == {}n)", i64::MAX, i64::MAX),
     )?;
     run_test2(
       10,
-      "op_test_i64",
-      &format!("assert(op_test_i64({}n) == {}n)", i64::MIN, i64::MIN),
+      "op_test_bigint_i64",
+      &format!("assert(op_test_bigint_i64({}n) == {}n)", i64::MIN, i64::MIN),
     )?;
     run_test2(
       10,
-      "op_test_u64",
-      &format!("assert(op_test_u64({}n) == {}n)", u64::MAX, u64::MAX),
+      "op_test_bigint_u64",
+      &format!("assert(op_test_bigint_u64({}n) == {}n)", u64::MAX, u64::MAX),
     )?;
     Ok(())
   }
diff --git a/ops/op2/README.md b/ops/op2/README.md
index e436073..dd46a18 100644
--- a/ops/op2/README.md
+++ b/ops/op2/README.md
@@ -153,7 +153,7 @@ Uint32, Int32, Number, BigInt
 </td><td>
 Uint32, Int32, Number, BigInt
 </td><td>
-
+SMI is internally represented as a signed integer, but unsigned `#[smi]` types will be bit-converted to unsigned values for the Rust call. JavaScript code will continue to see signed integers.
 </td></tr>
 <tr>
 <td>
@@ -805,7 +805,7 @@ Uint32
 </td><td>
 Int32
 </td><td>
-
+SMI is internally represented as a signed integer, but unsigned `#[smi]` types will be bit-converted to unsigned values for the Rust call. JavaScript code will continue to see signed integers.
 </td></tr>
 <tr>
 <td>
diff --git a/ops/op2/dispatch_fast.rs b/ops/op2/dispatch_fast.rs
index 0d309da..fa895d8 100644
--- a/ops/op2/dispatch_fast.rs
+++ b/ops/op2/dispatch_fast.rs
@@ -283,7 +283,8 @@ pub fn generate_dispatch_fast(
         Self::call(#(#call_names),*)
       };
       #handle_error
-      #result
+      // Result may need a simple cast (eg: SMI u32->i32)
+      #result as _
     }
   );
 
diff --git a/ops/op2/valid_args.md b/ops/op2/valid_args.md
index fd46cba..5b291cf 100644
--- a/ops/op2/valid_args.md
+++ b/ops/op2/valid_args.md
@@ -7,7 +7,7 @@
 | X         | u16                              | X        | Uint32, Int32, Number, BigInt                       |                                                                                                                                                                                                                |
 | X         | i32                              | X        | Uint32, Int32, Number, BigInt                       |                                                                                                                                                                                                                |
 | X         | u32                              | X        | Uint32, Int32, Number, BigInt                       |                                                                                                                                                                                                                |
-| X         | #[smi] ResourceId                | X        | Uint32, Int32, Number, BigInt                       |                                                                                                                                                                                                                |
+| X         | #[smi] ResourceId                | X        | Uint32, Int32, Number, BigInt                       | SMI is internally represented as a signed integer, but unsigned `#[smi]` types will be bit-converted to unsigned values for the Rust call. JavaScript code will continue to see signed integers.               |
 | X         | #[bigint] i64                    | X        | Uint32, Int32, Number, BigInt                       |                                                                                                                                                                                                                |
 | X         | #[bigint] u64                    | X        | Uint32, Int32, Number, BigInt                       |                                                                                                                                                                                                                |
 | X         | #[bigint] isize                  | X        | Uint32, Int32, Number, BigInt                       |                                                                                                                                                                                                                |
diff --git a/ops/op2/valid_retvals.md b/ops/op2/valid_retvals.md
index 1dda39a..a851608 100644
--- a/ops/op2/valid_retvals.md
+++ b/ops/op2/valid_retvals.md
@@ -1,25 +1,25 @@
-| Supported | Rust                             | Fastcall | V8     | Notes |
-| --------- | -------------------------------- | -------- | ------ | ----- |
-| X         | bool                             | X        | Bool   |       |
-| X         | i8                               | X        | Int32  |       |
-| X         | u8                               | X        | Uint32 |       |
-| X         | i16                              | X        | Int32  |       |
-| X         | u16                              | X        | Uint32 |       |
-| X         | i32                              | X        | Int32  |       |
-| X         | u32                              | X        | Uint32 |       |
-| X         | #[smi] ResourceId                | X        | Int32  |       |
-| X         | #[bigint] i64                    |          | BigInt |       |
-| X         | #[bigint] u64                    |          | BigInt |       |
-| X         | #[bigint] isize                  |          | BigInt |       |
-| X         | #[bigint] usize                  |          | BigInt |       |
-| X         | f32                              | X        | Number |       |
-| X         | f64                              | X        | Number |       |
-| X         | #[string] String                 |          | String |       |
-|           | #[string] &str                   |          | String |       |
-|           | #[string] Cow<str>               |          | String |       |
-| X         | v8::Local<v8::Value>             |          | any    |       |
-| X         | v8::Local<v8::**V8**>            |          | **V8** |       |
-|           | #[global] v8::Global<v8::Value>  |          | any    |       |
-|           | #[global] v8::Global<v8::**V8**> |          | **V8** |       |
-| X         | #[serde] SerdeType               |          | any    |       |
-| X         | #[serde] (Tuple, Tuple)          |          | any    |       |
+| Supported | Rust                             | Fastcall | V8     | Notes                                                                                                                                                                                            |
+| --------- | -------------------------------- | -------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| X         | bool                             | X        | Bool   |                                                                                                                                                                                                  |
+| X         | i8                               | X        | Int32  |                                                                                                                                                                                                  |
+| X         | u8                               | X        | Uint32 |                                                                                                                                                                                                  |
+| X         | i16                              | X        | Int32  |                                                                                                                                                                                                  |
+| X         | u16                              | X        | Uint32 |                                                                                                                                                                                                  |
+| X         | i32                              | X        | Int32  |                                                                                                                                                                                                  |
+| X         | u32                              | X        | Uint32 |                                                                                                                                                                                                  |
+| X         | #[smi] ResourceId                | X        | Int32  | SMI is internally represented as a signed integer, but unsigned `#[smi]` types will be bit-converted to unsigned values for the Rust call. JavaScript code will continue to see signed integers. |
+| X         | #[bigint] i64                    |          | BigInt |                                                                                                                                                                                                  |
+| X         | #[bigint] u64                    |          | BigInt |                                                                                                                                                                                                  |
+| X         | #[bigint] isize                  |          | BigInt |                                                                                                                                                                                                  |
+| X         | #[bigint] usize                  |          | BigInt |                                                                                                                                                                                                  |
+| X         | f32                              | X        | Number |                                                                                                                                                                                                  |
+| X         | f64                              | X        | Number |                                                                                                                                                                                                  |
+| X         | #[string] String                 |          | String |                                                                                                                                                                                                  |
+|           | #[string] &str                   |          | String |                                                                                                                                                                                                  |
+|           | #[string] Cow<str>               |          | String |                                                                                                                                                                                                  |
+| X         | v8::Local<v8::Value>             |          | any    |                                                                                                                                                                                                  |
+| X         | v8::Local<v8::**V8**>            |          | **V8** |                                                                                                                                                                                                  |
+|           | #[global] v8::Global<v8::Value>  |          | any    |                                                                                                                                                                                                  |
+|           | #[global] v8::Global<v8::**V8**> |          | **V8** |                                                                                                                                                                                                  |
+| X         | #[serde] SerdeType               |          | any    |                                                                                                                                                                                                  |
+| X         | #[serde] (Tuple, Tuple)          |          | any    |                                                                                                                                                                                                  |


Test patch:
diff --git a/ops/op2/test_cases/compiler_pass/sync.rs b/ops/op2/test_cases/compiler_pass/sync.rs
index 6050be7..7c82c8a 100644
--- a/ops/op2/test_cases/compiler_pass/sync.rs
+++ b/ops/op2/test_cases/compiler_pass/sync.rs
@@ -28,3 +28,20 @@ fn op_v8_2(_s: &v8::String) {}
 
 #[op2]
 fn op_v8_3(#[global] _s: v8::Global<v8::String>) {}
+
+pub type Int16 = i16;
+pub type Int32 = i32;
+pub type Uint16 = u16;
+pub type Uint32 = u32;
+
+#[op2(fast)]
+#[smi]
+fn op_smi_unsigned_return(#[smi] a: Int16, #[smi] b: Int32, #[smi] c: Uint16, #[smi] d: Uint32) -> Uint32 {
+  a as Uint32 + b as Uint32 + c as Uint32 + d as Uint32
+}
+
+#[op2(fast)]
+#[smi]
+fn op_smi_signed_return(#[smi] a: Int16, #[smi] b: Int32, #[smi] c: Uint16, #[smi] d: Uint32) -> Int32 {
+  a as Int32 + b as Int32 + c as Int32 + d as Int32
+}
diff --git a/ops/op2/test_cases/sync/add.out b/ops/op2/test_cases/sync/add.out
index a0e0e13..64f644a 100644
--- a/ops/op2/test_cases/sync/add.out
+++ b/ops/op2/test_cases/sync/add.out
@@ -40,7 +40,7 @@ impl op_add {
             let arg1 = arg1 as _;
             Self::call(arg0, arg1)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/bool.out b/ops/op2/test_cases/sync/bool.out
index 27fd718..6558889 100644
--- a/ops/op2/test_cases/sync/bool.out
+++ b/ops/op2/test_cases/sync/bool.out
@@ -38,7 +38,7 @@ impl op_bool {
             let arg0 = arg0 as _;
             Self::call(arg0)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/bool_result.out b/ops/op2/test_cases/sync/bool_result.out
index 2feae60..86bc513 100644
--- a/ops/op2/test_cases/sync/bool_result.out
+++ b/ops/op2/test_cases/sync/bool_result.out
@@ -56,7 +56,7 @@ impl op_bool {
                 return ::std::default::Default::default();
             }
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/buffers.out b/ops/op2/test_cases/sync/buffers.out
index 24feb7a..b317b06 100644
--- a/ops/op2/test_cases/sync/buffers.out
+++ b/ops/op2/test_cases/sync/buffers.out
@@ -48,7 +48,7 @@ impl op_buffers {
                 .unwrap();
             Self::call(arg0, arg1)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut scope = unsafe { deno_core::v8::CallbackScope::new(&*info) };
diff --git a/ops/op2/test_cases/sync/buffers_copy.out b/ops/op2/test_cases/sync/buffers_copy.out
index 1f4e282..316fce9 100644
--- a/ops/op2/test_cases/sync/buffers_copy.out
+++ b/ops/op2/test_cases/sync/buffers_copy.out
@@ -58,7 +58,7 @@ impl op_buffers {
                 .into();
             Self::call(arg0, arg1, arg2)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut scope = unsafe { deno_core::v8::CallbackScope::new(&*info) };
diff --git a/ops/op2/test_cases/sync/clippy_allow.out b/ops/op2/test_cases/sync/clippy_allow.out
index 804ce31..1996eb8 100644
--- a/ops/op2/test_cases/sync/clippy_allow.out
+++ b/ops/op2/test_cases/sync/clippy_allow.out
@@ -34,7 +34,7 @@ impl op_extra_annotation {
     }
     fn v8_fn_ptr_fast(_: deno_core::v8::Local<deno_core::v8::Object>) -> () {
         let result = { Self::call() };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/doc_comment.out b/ops/op2/test_cases/sync/doc_comment.out
index d4d982a..2589d95 100644
--- a/ops/op2/test_cases/sync/doc_comment.out
+++ b/ops/op2/test_cases/sync/doc_comment.out
@@ -33,7 +33,7 @@ impl op_has_doc_comment {
     }
     fn v8_fn_ptr_fast(_: deno_core::v8::Local<deno_core::v8::Object>) -> () {
         let result = { Self::call() };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/generics.out b/ops/op2/test_cases/sync/generics.out
index 6d769fe..27431e0 100644
--- a/ops/op2/test_cases/sync/generics.out
+++ b/ops/op2/test_cases/sync/generics.out
@@ -32,7 +32,7 @@ impl<T: Trait> op_generics<T> {
     }
     fn v8_fn_ptr_fast(_: deno_core::v8::Local<deno_core::v8::Object>) -> () {
         let result = { Self::call() };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/op_state_attr.out b/ops/op2/test_cases/sync/op_state_attr.out
index 921c052..ec018dc 100644
--- a/ops/op2/test_cases/sync/op_state_attr.out
+++ b/ops/op2/test_cases/sync/op_state_attr.out
@@ -48,7 +48,7 @@ impl op_state_rc {
             let arg1 = arg1.try_borrow::<Something>();
             Self::call(arg0, arg1)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/op_state_rc.out b/ops/op2/test_cases/sync/op_state_rc.out
index b8c70f4..d3cd40f 100644
--- a/ops/op2/test_cases/sync/op_state_rc.out
+++ b/ops/op2/test_cases/sync/op_state_rc.out
@@ -45,7 +45,7 @@ impl op_state_rc {
             let arg0 = opctx.state.clone();
             Self::call(arg0)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/op_state_ref.out b/ops/op2/test_cases/sync/op_state_ref.out
index f279542..11c1f66 100644
--- a/ops/op2/test_cases/sync/op_state_ref.out
+++ b/ops/op2/test_cases/sync/op_state_ref.out
@@ -45,7 +45,7 @@ impl op_state_rc {
             let arg0 = &opctx.state.borrow();
             Self::call(arg0)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/result_primitive.out b/ops/op2/test_cases/sync/result_primitive.out
index 078768f..8fd40c3 100644
--- a/ops/op2/test_cases/sync/result_primitive.out
+++ b/ops/op2/test_cases/sync/result_primitive.out
@@ -52,7 +52,7 @@ impl op_u32_with_result {
                 return ::std::default::Default::default();
             }
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/result_void.out b/ops/op2/test_cases/sync/result_void.out
index ca1f29e..a767d48 100644
--- a/ops/op2/test_cases/sync/result_void.out
+++ b/ops/op2/test_cases/sync/result_void.out
@@ -52,7 +52,7 @@ impl op_void_with_result {
                 return ::std::default::Default::default();
             }
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/smi.out b/ops/op2/test_cases/sync/smi.out
index 580f4ce..36d8347 100644
--- a/ops/op2/test_cases/sync/smi.out
+++ b/ops/op2/test_cases/sync/smi.out
@@ -1,30 +1,30 @@
 #[allow(non_camel_case_types)]
-struct op_add {
+struct op_smi_unsigned_return {
     _unconstructable: ::std::marker::PhantomData<()>,
 }
-impl deno_core::_ops::Op for op_add {
-    const NAME: &'static str = stringify!(op_add);
+impl deno_core::_ops::Op for op_smi_unsigned_return {
+    const NAME: &'static str = stringify!(op_smi_unsigned_return);
     const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl::new_internal(
-        stringify!(op_add),
+        stringify!(op_smi_unsigned_return),
         false,
         false,
         false,
-        2usize as u8,
+        4usize as u8,
         Self::v8_fn_ptr as _,
         Some({
             use deno_core::v8::fast_api::Type;
             use deno_core::v8::fast_api::CType;
             deno_core::v8::fast_api::FastFunction::new_with_bigint(
-                &[Type::V8Value, Type::Int32, Type::Uint32],
-                CType::Uint32,
+                &[Type::V8Value, Type::Int32, Type::Int32, Type::Int32, Type::Int32],
+                CType::Int32,
                 Self::v8_fn_ptr_fast as *const ::std::ffi::c_void,
             )
         }),
     );
 }
-impl op_add {
+impl op_smi_unsigned_return {
     pub const fn name() -> &'static str {
-        stringify!(op_add)
+        stringify!(op_smi_unsigned_return)
     }
     #[deprecated(note = "Use the const op::DECL instead")]
     pub const fn decl() -> deno_core::_ops::OpDecl {
@@ -33,14 +33,18 @@ impl op_add {
     fn v8_fn_ptr_fast(
         _: deno_core::v8::Local<deno_core::v8::Object>,
         arg0: i32,
-        arg1: u32,
-    ) -> u32 {
+        arg1: i32,
+        arg2: i32,
+        arg3: i32,
+    ) -> i32 {
         let result = {
             let arg0 = arg0 as _;
             let arg1 = arg1 as _;
-            Self::call(arg0, arg1)
+            let arg2 = arg2 as _;
+            let arg3 = arg3 as _;
+            Self::call(arg0, arg1, arg2, arg3)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
@@ -65,11 +69,11 @@ impl op_add {
             };
             let arg0 = arg0 as _;
             let arg1 = args.get(1usize as i32);
-            let Some(arg1) = deno_core::_ops::to_u32_option(&arg1) else {
+            let Some(arg1) = deno_core::_ops::to_i32_option(&arg1) else {
                 let mut scope = unsafe { deno_core::v8::CallbackScope::new(&*info) };
                 let msg = deno_core::v8::String::new_from_one_byte(
                         &mut scope,
-                        "expected u32".as_bytes(),
+                        "expected i32".as_bytes(),
                         deno_core::v8::NewStringType::Normal,
                     )
                     .unwrap();
@@ -78,43 +82,71 @@ impl op_add {
                 return;
             };
             let arg1 = arg1 as _;
-            Self::call(arg0, arg1)
+            let arg2 = args.get(2usize as i32);
+            let Some(arg2) = deno_core::_ops::to_i32_option(&arg2) else {
+                let mut scope = unsafe { deno_core::v8::CallbackScope::new(&*info) };
+                let msg = deno_core::v8::String::new_from_one_byte(
+                        &mut scope,
+                        "expected i32".as_bytes(),
+                        deno_core::v8::NewStringType::Normal,
+                    )
+                    .unwrap();
+                let exc = deno_core::v8::Exception::type_error(&mut scope, msg);
+                scope.throw_exception(exc);
+                return;
+            };
+            let arg2 = arg2 as _;
+            let arg3 = args.get(3usize as i32);
+            let Some(arg3) = deno_core::_ops::to_i32_option(&arg3) else {
+                let mut scope = unsafe { deno_core::v8::CallbackScope::new(&*info) };
+                let msg = deno_core::v8::String::new_from_one_byte(
+                        &mut scope,
+                        "expected i32".as_bytes(),
+                        deno_core::v8::NewStringType::Normal,
+                    )
+                    .unwrap();
+                let exc = deno_core::v8::Exception::type_error(&mut scope, msg);
+                scope.throw_exception(exc);
+                return;
+            };
+            let arg3 = arg3 as _;
+            Self::call(arg0, arg1, arg2, arg3)
         };
-        rv.set_uint32(result as u32);
+        rv.set_int32(result as i32);
     }
     #[inline(always)]
-    fn call(id: ResourceId, extra: u16) -> u32 {
-        id as u32 + extra as u32
+    fn call(a: Int16, b: Int32, c: Uint16, d: Uint32) -> Uint32 {
+        a as Uint32 + b as Uint32 + c as Uint32 + d as Uint32
     }
 }
 
 #[allow(non_camel_case_types)]
-struct op_subtract {
+struct op_smi_signed_return {
     _unconstructable: ::std::marker::PhantomData<()>,
 }
-impl deno_core::_ops::Op for op_subtract {
-    const NAME: &'static str = stringify!(op_subtract);
+impl deno_core::_ops::Op for op_smi_signed_return {
+    const NAME: &'static str = stringify!(op_smi_signed_return);
     const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl::new_internal(
-        stringify!(op_subtract),
+        stringify!(op_smi_signed_return),
         false,
         false,
         false,
-        2usize as u8,
+        4usize as u8,
         Self::v8_fn_ptr as _,
         Some({
             use deno_core::v8::fast_api::Type;
             use deno_core::v8::fast_api::CType;
             deno_core::v8::fast_api::FastFunction::new_with_bigint(
-                &[Type::V8Value, Type::Int32, Type::Int32],
+                &[Type::V8Value, Type::Int32, Type::Int32, Type::Int32, Type::Int32],
                 CType::Int32,
                 Self::v8_fn_ptr_fast as *const ::std::ffi::c_void,
             )
         }),
     );
 }
-impl op_subtract {
+impl op_smi_signed_return {
     pub const fn name() -> &'static str {
-        stringify!(op_subtract)
+        stringify!(op_smi_signed_return)
     }
     #[deprecated(note = "Use the const op::DECL instead")]
     pub const fn decl() -> deno_core::_ops::OpDecl {
@@ -124,13 +156,17 @@ impl op_subtract {
         _: deno_core::v8::Local<deno_core::v8::Object>,
         arg0: i32,
         arg1: i32,
+        arg2: i32,
+        arg3: i32,
     ) -> i32 {
         let result = {
             let arg0 = arg0 as _;
             let arg1 = arg1 as _;
-            Self::call(arg0, arg1)
+            let arg2 = arg2 as _;
+            let arg3 = arg3 as _;
+            Self::call(arg0, arg1, arg2, arg3)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
@@ -168,12 +204,40 @@ impl op_subtract {
                 return;
             };
             let arg1 = arg1 as _;
-            Self::call(arg0, arg1)
+            let arg2 = args.get(2usize as i32);
+            let Some(arg2) = deno_core::_ops::to_i32_option(&arg2) else {
+                let mut scope = unsafe { deno_core::v8::CallbackScope::new(&*info) };
+                let msg = deno_core::v8::String::new_from_one_byte(
+                        &mut scope,
+                        "expected i32".as_bytes(),
+                        deno_core::v8::NewStringType::Normal,
+                    )
+                    .unwrap();
+                let exc = deno_core::v8::Exception::type_error(&mut scope, msg);
+                scope.throw_exception(exc);
+                return;
+            };
+            let arg2 = arg2 as _;
+            let arg3 = args.get(3usize as i32);
+            let Some(arg3) = deno_core::_ops::to_i32_option(&arg3) else {
+                let mut scope = unsafe { deno_core::v8::CallbackScope::new(&*info) };
+                let msg = deno_core::v8::String::new_from_one_byte(
+                        &mut scope,
+                        "expected i32".as_bytes(),
+                        deno_core::v8::NewStringType::Normal,
+                    )
+                    .unwrap();
+                let exc = deno_core::v8::Exception::type_error(&mut scope, msg);
+                scope.throw_exception(exc);
+                return;
+            };
+            let arg3 = arg3 as _;
+            Self::call(arg0, arg1, arg2, arg3)
         };
         rv.set_int32(result as i32);
     }
     #[inline(always)]
-    fn call(id: StubId, extra: i32) -> StubId {
-        id - extra
+    fn call(a: Int16, b: Int32, c: Uint16, d: Uint32) -> Int32 {
+        a as Int32 + b as Int32 + c as Int32 + d as Int32
     }
 }
diff --git a/ops/op2/test_cases/sync/smi.rs b/ops/op2/test_cases/sync/smi.rs
index 2bb1ca2..f25af80 100644
--- a/ops/op2/test_cases/sync/smi.rs
+++ b/ops/op2/test_cases/sync/smi.rs
@@ -2,17 +2,19 @@
 #![deny(warnings)]
 deno_ops_compile_test_runner::prelude!();
 
-pub type ResourceId = i16;
+pub type Int16 = i16;
+pub type Int32 = i32;
+pub type Uint16 = u16;
+pub type Uint32 = u32;
 
 #[op2(fast)]
-fn op_add(#[smi] id: ResourceId, extra: u16) -> u32 {
-    id as u32 + extra as u32
+#[smi]
+fn op_smi_unsigned_return(#[smi] a: Int16, #[smi] b: Int32, #[smi] c: Uint16, #[smi] d: Uint32) -> Uint32 {
+  a as Uint32 + b as Uint32 + c as Uint32 + d as Uint32
 }
 
-pub type StubId = i32;
-
 #[op2(fast)]
 #[smi]
-fn op_subtract(#[smi] id: StubId, extra: i32) -> StubId {
-    id - extra
+fn op_smi_signed_return(#[smi] a: Int16, #[smi] b: Int32, #[smi] c: Uint16, #[smi] d: Uint32) -> Int32 {
+  a as Int32 + b as Int32 + c as Int32 + d as Int32
 }
diff --git a/ops/op2/test_cases/sync/string_cow.out b/ops/op2/test_cases/sync/string_cow.out
index 8a8e791..d2954e4 100644
--- a/ops/op2/test_cases/sync/string_cow.out
+++ b/ops/op2/test_cases/sync/string_cow.out
@@ -44,7 +44,7 @@ impl op_string_cow {
             );
             Self::call(arg0)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/string_owned.out b/ops/op2/test_cases/sync/string_owned.out
index 4094398..e77324e 100644
--- a/ops/op2/test_cases/sync/string_owned.out
+++ b/ops/op2/test_cases/sync/string_owned.out
@@ -38,7 +38,7 @@ impl op_string_owned {
             let arg0 = deno_core::_ops::to_string_ptr(unsafe { &mut *arg0 });
             Self::call(arg0)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/string_ref.out b/ops/op2/test_cases/sync/string_ref.out
index abfb54e..e5fa41c 100644
--- a/ops/op2/test_cases/sync/string_ref.out
+++ b/ops/op2/test_cases/sync/string_ref.out
@@ -44,7 +44,7 @@ impl op_string_owned {
             );
             Self::call(arg0)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
diff --git a/ops/op2/test_cases/sync/v8_ref_option.out b/ops/op2/test_cases/sync/v8_ref_option.out
index 6972d8b..8e4e65f 100644
--- a/ops/op2/test_cases/sync/v8_ref_option.out
+++ b/ops/op2/test_cases/sync/v8_ref_option.out
@@ -60,7 +60,7 @@ impl op_v8_lifetime {
             };
             Self::call(arg0, arg1)
         };
-        result
+        result as _
     }
     extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) {
         let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {