Repository: napi-rs/napi-rs
File: crates/napi/src/env.rs (Rust)

Code before:
      let status = sys::napi_create_external_arraybuffer(
        self.0,
        if length == 0 {
          // Rust uses 0x1 as the data pointer for empty buffers,
          // but NAPI/V8 only allows multiple buffers to have
          // the same data pointer if it's 0x0.
          ptr::null_mut()
        } else {
          data as *mut c_void
        },
        length,
        Some(
          raw_finalize_with_custom_callback::<Hint, Finalize>
            as unsafe extern "C" fn(
              env: sys::napi_env,
              finalize_data: *mut c_void,
              finalize_hint: *mut c_void,
            ),
        ),
        hint_ptr.cast(),
        &mut raw_value,
      );
      if status == sys::Status::napi_no_external_buffers_allowed {
        let (hint, finalize) = *Box::from_raw(hint_ptr);
        let mut underlying_data = ptr::null_mut();
        let status =
          sys::napi_create_arraybuffer(self.0, length, &mut underlying_data, &mut raw_value);
        // Copy data before calling finalize, since finalize may free the source data
        if status == sys::Status::napi_ok && length > 0 {
          ptr::copy_nonoverlapping(data, underlying_data.cast(), length);
        }
        // Always call finalize to clean up caller's resources, even on error
        finalize(*self, hint);
        check_status!(status, "Failed to create arraybuffer")?;
      } else {
        check_status!(status)?;
      }
    };
    Ok(JsArrayBufferValue::new(
      JsArrayBuffer(Value {
        env: self.0,
        value: raw_value,
        value_type: ValueType::Object,
      }),
      data as *mut c_void,
      length,
    ))
  }

  /// This API allows an add-on author to create a function object in native code.
  ///

Review comment (bug):
There's an inconsistency in error handling patterns. In the success path at line 531, check_status! is called with an error message, but at line 612, check_status! is called without a custom error message. For consistency and better debugging, consider providing a descriptive error message in both branches.
```suggestion
        check_status!(status, "Failed to create external arraybuffer")?;
```

Code after:
          ptr::null_mut()
        } else {
          data as *mut c_void
        },
        length,
        Some(
          raw_finalize_with_custom_callback::<Hint, Finalize>
            as unsafe extern "C" fn(
              env: sys::napi_env,
              finalize_data: *mut c_void,
              finalize_hint: *mut c_void,
            ),
        ),
        hint_ptr.cast(),
        &mut raw_value,
      );
      if status == sys::Status::napi_no_external_buffers_allowed {
        let (hint, finalize) = *Box::from_raw(hint_ptr);
        let mut underlying_data = ptr::null_mut();
        let status =
          sys::napi_create_arraybuffer(self.0, length, &mut underlying_data, &mut raw_value);
        ptr::copy_nonoverlapping(data, underlying_data.cast(), length);
        finalize(*self, hint);
        check_status!(status)?;
      } else {
        check_status!(status)?;
      }
    };
    Ok(JsArrayBufferValue::new(
      JsArrayBuffer(Value {
        env: self.0,
        value: raw_value,
        value_type: ValueType::Object,
      }),
      data as *mut c_void,
      length,
    ))
  }

  /// This API allows an add-on author to create a function object in native code.
  ///
  /// This is the primary mechanism to allow calling into the add-on's native code from JavaScript.
  ///
  /// The newly created function is not automatically visible from script after this call.
  ///
  /// Instead, a property must be explicitly set on any object that is visible to JavaScript, in order for the function to be accessible from script.
  pub fn create_function<Args: JsValuesTupleIntoVec, Return>(
    &self,
    name: &str,
    callback: Callback,
  ) -> Result<Function<'_, Args, Return>> {