Skip to content

Comments

feat(napi): provide unsafe as_mut on ArrayBuffer#3055

Merged
Brooooooklyn merged 1 commit intomainfrom
12-09-feat_napi_provide_unsafe_as_mut_on_arraybuffer
Dec 9, 2025
Merged

feat(napi): provide unsafe as_mut on ArrayBuffer#3055
Brooooooklyn merged 1 commit intomainfrom
12-09-feat_napi_provide_unsafe_as_mut_on_arraybuffer

Conversation

@Brooooooklyn
Copy link
Member

@Brooooooklyn Brooooooklyn commented Dec 9, 2025

Summary by CodeRabbit

New Features

  • Added ArrayBuffer mutation capability, enabling in-place modification of buffer contents

Tests

  • Added test cases to verify ArrayBuffer mutation functionality

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings December 9, 2025 04:43
@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

Walkthrough

A new unsafe method as_mut() is added to the ArrayBuffer type, returning a mutable slice to the underlying buffer. A corresponding public function mutate_arraybuffer is implemented in the example crate that uses this method to modify buffer data in-place. The function is exported across all module formats and includes a test case.

Changes

Cohort / File(s) Change Summary
Core Library Enhancement
crates/napi/src/bindgen_runtime/js_values/arraybuffer.rs
Added unsafe method as_mut(&mut self) -> &mut [u8] to enable mutable access to underlying ArrayBuffer data
Example Implementation
examples/napi/src/typed_array.rs
Added public function mutate_arraybuffer(mut buf: ArrayBuffer) that iterates over a mutable buffer view and doubles each element
Type Declarations
examples/napi/index.d.cts
Added TypeScript function declaration export declare function mutateArraybuffer(buf: ArrayBuffer): void
Module Exports
examples/napi/index.cjs, examples/napi/example.wasi.cjs, examples/napi/example.wasi-browser.js
Added public exports for mutateArraybuffer binding across CommonJS and ESM module formats
Tests & Snapshots
examples/napi/__tests__/values.spec.ts, examples/napi/__tests__/__snapshots__/values.spec.ts.md
Added test case for mutateArraybuffer that creates an ArrayBuffer, mutates it, and verifies results; includes WASI skip annotation

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Focus on the unsafe fn as_mut() method: verify the safety contract, buffer lifetime guarantees, and the documented undefined behavior warning regarding JS-side mutation without synchronization
  • Confirm the mutation logic in mutate_arraybuffer correctly implements the intended in-place modification
  • Verify consistent export patterns across all module format wrappers

Poem

🐰 A mutable slice—what a treat!
ArrayBuffers now mutable, oh so sweet!
Double the values with synchronized care,
From Rust to JavaScript, buffers we share.
Unsafe but documented, risk fully aware! 🎉

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(napi): provide unsafe as_mut on ArrayBuffer' accurately summarizes the main change - adding an unsafe as_mut method to ArrayBuffer. The title is concise, specific, and clearly communicates the primary feature addition.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 12-09-feat_napi_provide_unsafe_as_mut_on_arraybuffer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Member Author


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • ready-to-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an unsafe as_mut method to the ArrayBuffer type, allowing mutable access to the underlying byte buffer from Rust. The method is properly marked as unsafe with clear documentation about the undefined behavior risks from concurrent JavaScript modifications.

Key changes:

  • Adds as_mut() method to ArrayBuffer with appropriate safety documentation
  • Provides a working example function mutate_arraybuffer that demonstrates usage
  • Includes comprehensive test coverage for the new functionality

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
crates/napi/src/bindgen_runtime/js_values/arraybuffer.rs Implements the core as_mut() method with unsafe marker and safety documentation
examples/napi/src/typed_array.rs Adds example function demonstrating proper unsafe usage of the new method
examples/napi/tests/values.spec.ts Adds test case verifying the mutation behavior works correctly
examples/napi/index.d.cts Exports TypeScript type definition for the new function
examples/napi/index.cjs Exports the new function in CommonJS format
examples/napi/example.wasi.cjs Exports the new function for WASI environment
examples/napi/example.wasi-browser.js Exports the new function for WASI browser environment
examples/napi/tests/snapshots/values.spec.ts.snap Updates snapshot file with test results
examples/napi/tests/snapshots/values.spec.ts.md Updates markdown snapshot with type definition

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
examples/napi/src/typed_array.rs (1)

309-315: ArrayBuffer mutation mirrors existing TypedArray pattern; looks good

Implementation is minimal, mirrors mutate_typed_array, and keeps the unsafe usage tightly scoped to iterating over buf.as_mut(). No issues from the example-layer perspective.

crates/napi/src/bindgen_runtime/js_values/arraybuffer.rs (1)

331-338: Tighten ArrayBuffer::as_mut safety surface and align with existing lint conventions

The implementation itself looks fine and consistent with other raw mut accessors, but two small improvements would help:

  • This is a pub method named as_mut, so Clippy’s should_implement_trait lint will likely fire. Other similar APIs in this file use #[allow(clippy::should_implement_trait)]; it would be good to do the same here for consistency.
  • Since ArrayBuffer<'env> is Copy and you’re exposing a mutable slice into JS-managed memory, it’s worth spelling out in the safety docs that callers must ensure there are no other active Rust references (including cloned ArrayBuffers) used while the returned &mut [u8] is alive, in addition to the JS-side synchronization caveat you already mention.

A minimal change along these lines could look like:

-  /// # Safety
-  ///
-  /// This is literally undefined behavior, as the JS side may always modify the underlying buffer,
-  /// without synchronization.
-  pub unsafe fn as_mut(&mut self) -> &mut [u8] {
-    std::slice::from_raw_parts_mut(self.data.as_ptr() as *mut u8, self.data.len())
-  }
+  #[allow(clippy::should_implement_trait)]
+  /// # Safety
+  ///
+  /// This is literally undefined behavior, as the JS side may always modify the underlying buffer,
+  /// without synchronization.
+  ///
+  /// In addition, the caller must ensure there are no other active Rust references
+  /// (including cloned `ArrayBuffer` values) used to access this buffer while the
+  /// returned slice is alive.
+  pub unsafe fn as_mut(&mut self) -> &mut [u8] {
+    std::slice::from_raw_parts_mut(self.data.as_ptr() as *mut u8, self.data.len())
+  }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0fd40a7 and 68c69e5.

⛔ Files ignored due to path filters (1)
  • examples/napi/__tests__/__snapshots__/values.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • crates/napi/src/bindgen_runtime/js_values/arraybuffer.rs (1 hunks)
  • examples/napi/__tests__/__snapshots__/values.spec.ts.md (1 hunks)
  • examples/napi/__tests__/values.spec.ts (2 hunks)
  • examples/napi/example.wasi-browser.js (1 hunks)
  • examples/napi/example.wasi.cjs (1 hunks)
  • examples/napi/index.cjs (1 hunks)
  • examples/napi/index.d.cts (1 hunks)
  • examples/napi/src/typed_array.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
crates/napi/src/bindgen_runtime/js_values/arraybuffer.rs (2)
crates/napi/src/bindgen_runtime/js_values/buffer.rs (1)
  • as_mut (424-429)
crates/napi/src/js_values/arraybuffer.rs (1)
  • as_mut (231-236)
examples/napi/src/typed_array.rs (1)
crates/macro/src/lib.rs (1)
  • napi (29-43)
examples/napi/index.d.cts (1)
examples/napi/example.wasi-browser.js (2)
  • mutateArraybuffer (297-297)
  • mutateArraybuffer (297-297)
examples/napi/__tests__/values.spec.ts (1)
examples/napi/example.wasi-browser.js (2)
  • mutateArraybuffer (297-297)
  • mutateArraybuffer (297-297)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (41)
  • GitHub Check: Agent
  • GitHub Check: Build only test - riscv64gc-unknown-linux-gnu
  • GitHub Check: build - aarch64-unknown-linux-gnu
  • GitHub Check: build - x86_64-unknown-linux-gnu
  • GitHub Check: build - powerpc64le-unknown-linux-gnu
  • GitHub Check: Build only test - aarch64-unknown-linux-ohos
  • GitHub Check: build - s390x-unknown-linux-gnu
  • GitHub Check: x86_64-unknown-linux-gnu - node@24 - toolchain@ stable
  • GitHub Check: Test freebsd target
  • GitHub Check: Build only test - armv7-linux-androideabi
  • GitHub Check: i686-pc-windows-msvc - node@24 - toolchain@ stable
  • GitHub Check: Build only test - aarch64-linux-android
  • GitHub Check: aarch64-pc-windows-msvc - node@24 - toolchain@ stable
  • GitHub Check: Build only test - loongarch64-unknown-linux-gnu
  • GitHub Check: x86_64-unknown-linux-gnu - node@24 - toolchain@ 1.88.0
  • GitHub Check: x86_64-pc-windows-msvc - node@24 - toolchain@ stable
  • GitHub Check: aarch64-apple-darwin - node@24 - toolchain@ stable
  • GitHub Check: i686-pc-windows-msvc - node@22 - toolchain@ stable
  • GitHub Check: aarch64-apple-darwin - node@20 - toolchain@ stable
  • GitHub Check: aarch64-apple-darwin - node@22 - toolchain@ stable
  • GitHub Check: aarch64-pc-windows-msvc - node@22 - toolchain@ stable
  • GitHub Check: x86_64-unknown-linux-gnu - node@22 - toolchain@ stable
  • GitHub Check: x86_64-pc-windows-msvc - node@22 - toolchain@ stable
  • GitHub Check: x86_64-unknown-linux-gnu - node@22 - toolchain@ 1.88.0
  • GitHub Check: x86_64-pc-windows-msvc - node@20 - toolchain@ stable
  • GitHub Check: x86_64-unknown-linux-gnu - node@20 - toolchain@ stable
  • GitHub Check: build - aarch64-unknown-linux-musl
  • GitHub Check: stable - armv7-unknown-linux-gnueabihf - node@22
  • GitHub Check: build - x86_64-unknown-linux-musl
  • GitHub Check: build-and-test-msys2 (CLANG64)
  • GitHub Check: build-and-test-msys2 (MINGW64)
  • GitHub Check: build-and-test-msys2 (UCRT64)
  • GitHub Check: Test node wasi target (--cfg tokio_unstable)
  • GitHub Check: Test node wasi target
  • GitHub Check: Zig-Cross-Compile-On-Linux (aarch64-apple-darwin)
  • GitHub Check: Zig-Cross-Compile-On-Linux (aarch64-unknown-linux-musl)
  • GitHub Check: Zig-Cross-Compile-On-Linux (x86_64-unknown-linux-musl)
  • GitHub Check: Zig-Cross-Compile-On-Linux (armv7-unknown-linux-musleabihf)
  • GitHub Check: Memory leak detect job
  • GitHub Check: ASAN - ubuntu-24.04
  • GitHub Check: ASAN - windows-latest
🔇 Additional comments (6)
examples/napi/index.cjs (1)

806-806: CJS export for mutateArraybuffer is wired correctly

Export name and source (nativeBinding.mutateArraybuffer) are consistent with the rest of the binding surface.

examples/napi/__tests__/values.spec.ts (1)

145-145: New mutateArraybuffer test is consistent and effective

Import and test setup mirror the existing mutateTypedArray case, including the WASI skip guard, and correctly assert in‑place mutation of the underlying ArrayBuffer bytes.

Also applies to: 1295-1309

examples/napi/__tests__/__snapshots__/values.spec.ts.md (1)

891-892: Snapshot update for mutateArraybuffer matches the new API

The added declaration in the snapshot aligns with the TypeScript d.ts and the runtime export; no issues.

examples/napi/index.d.cts (1)

851-852: Type declaration for mutateArraybuffer is consistent with implementation

ArrayBuffer parameter and void return type correctly describe the new native function and line up with the tests and exports.

examples/napi/example.wasi-browser.js (1)

297-297: WASI browser wrapper correctly re-exports mutateArraybuffer

Re-export follows the existing pattern and keeps the WASI/browser surface in sync with the main binding.

examples/napi/example.wasi.cjs (1)

342-342: WASI CJS wrapper export for mutateArraybuffer is correctly wired

The new assignment cleanly exposes the underlying N-API export without altering existing behavior.

@Brooooooklyn Brooooooklyn merged commit bff17ac into main Dec 9, 2025
81 checks passed
@Brooooooklyn Brooooooklyn deleted the 12-09-feat_napi_provide_unsafe_as_mut_on_arraybuffer branch December 9, 2025 05:15

#[napi]
pub fn mutate_arraybuffer(mut buf: ArrayBuffer) {
for item in unsafe { buf.as_mut() } {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should provide a user document explaining in what scenarios this capability needs to be used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants