wasmerio/wasmer · error

direct data pointer access is not possible in JavaScript

Error message

direct data pointer access is not possible in JavaScript

What it means

On the JS backend a Memory lives in WebAssembly.Memory, whose buffer is not exposed as a native pointer; MemoryView::data_ptr therefore panics with `unimplemented!`. Direct raw-pointer access to wasm memory is impossible in JavaScript, by design of the platform.

Source

Thrown at lib/api/src/backend/js/entities/memory/view.rs:49

        // This also works for SharedArrayBuffer.
        let size = buffer
            .unchecked_ref::<js_sys::ArrayBuffer>()
            .byte_length()
            .into();

        let view = js_sys::Uint8Array::new(&buffer);

        Self {
            view,
            size,
            marker: PhantomData,
        }
    }

    /// Returns the pointer to the raw bytes of the `Memory`.
    #[doc(hidden)]
    pub fn data_ptr(&self) -> *mut u8 {
        unimplemented!("direct data pointer access is not possible in JavaScript");
    }

    /// Returns the size (in bytes) of the `Memory`.
    pub fn data_size(&self) -> u64 {
        self.size
    }

    // TODO: do we want a proper implementation here instead?
    /// Retrieve a slice of the memory contents.
    ///
    /// # Safety
    ///
    /// Until the returned slice is dropped, it is undefined behaviour to
    /// modify the memory contents in any way including by calling a wasm
    /// function that writes to the memory or by resizing the memory.
    #[doc(hidden)]
    pub unsafe fn data_unchecked(&self) -> &[u8] {
        unimplemented!("direct data pointer access is not possible in JavaScript");

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Use memory.view::<u8>() typed views (or the ArrayBuffer via memory.buffer) to read/write JS-backed wasm memory instead of data_ptr
  2. Gate pointer-based code with cfg(feature = "sys") / backend checks and provide a js-specific access path
  3. Copy data across the boundary explicitly (e.g. via exported wasm functions or DataView) rather than by pointer
  4. Restrict data_ptr usage to the native backend only

Example fix

// before
let ptr = memory.data_ptr();
unsafe { std::slice::from_raw_parts(ptr, len) }
// after (js backend)
let view: MemoryView<u8> = memory.view();
let bytes: Vec<u8> = (0..len).map(|i| view[i].get()).collect();
Defensive patterns

Strategy: type-guard

Validate before calling

// gate pointer access behind backend feature
#[cfg(feature = "sys")]
fn raw_ptr(mem: &Memory) -> *mut u8 { mem.data_ptr() }
#[cfg(feature = "js")]
fn raw_ptr(_mem: &Memory) -> ! { panic!("use memory.view::<u8>() on js backend") }

Try / catch

// on js, catch the panic at the FFI boundary and use views
match catch_unwind(|| unsafe { slice_from_ptr(mem.data_ptr(), len) }) {
    Ok(s) => use_slice(s),
    Err(_) => use_view_copy(mem),
}

Prevention

When it happens

Trigger: Calling memory.data_ptr() (doc-hidden, but reachable via the view API) on a Memory backed by the js backend — e.g. embedder code or generated glue that assumes sys-backend raw pointers, such as C-ABI style pointer passing in a browser.

Common situations: Porting native wasmer embedders to wasmer-js; Emscripten-style code that reads/writes linear memory via pointer arithmetic; code sharing a single memory-view implementation across sys and js backends.

Related errors


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/24fa51048ac4bab4. Report an issue: GitHub.