pub struct JsStringLatin1<'env> { /* private fields */ }Implementations§
Source§impl<'env> JsStringLatin1<'env>
impl<'env> JsStringLatin1<'env>
Sourcepub fn from_data(env: &'env Env, data: Vec<u8>) -> Result<JsStringLatin1<'env>>
pub fn from_data(env: &'env Env, data: Vec<u8>) -> Result<JsStringLatin1<'env>>
Try to create a new JavaScript latin1 string from a Rust Vec<u8> without copying the data.
§Behavior
The copied parameter in the underlying node_api_create_external_string_latin1 call
indicates whether the string data was copied into V8’s heap rather than being used
as an external reference.
§When copied is true:
- String data is copied to V8’s heap
- Finalizer is called synchronously to release the source buffer
- Performance benefit of external strings is not achieved
§When copied is false:
- V8 creates an external string that references the original buffer without copying
- Original buffer must remain valid for the lifetime of the JS string
- Finalizer called when string is garbage collected
- Memory usage and copying overhead is reduced
§Common scenarios where copied is true:
- String is too short (typically < 10-15 characters)
- V8 heap is under memory pressure
- V8 is running with pointer compression or sandbox features
- Invalid Latin-1 encoding that requires sanitization
- Platform doesn’t support external strings (e.g.
wasm32-*/ emnapi) - Memory alignment issues with the provided buffer
§Platform notes
On wasm32-* (WASI / emnapi) the external-string API always falls back
to napi_create_string_latin1, which copies into the JS heap. To avoid
the double work and the use-after-free that would otherwise come with
the synchronous finalizer, this function uses napi_create_string_latin1
directly on WASM and keeps the source Vec alive in the wrapper so
as_slice() / len() / is_empty() keep returning the original bytes.
On native, when V8 chooses to copy (copied = true), the source buffer
has been freed by the finalizer before this returns. as_slice() then
returns &[]; recover the bytes via JsString::into_latin1 on
Self::into_value if needed.
Sourcepub unsafe fn from_external<T: 'env, F: FnOnce(Env, T) + 'env>(
env: &'env Env,
data: *const u8,
len: usize,
finalize_hint: T,
finalize_callback: F,
) -> Result<JsStringLatin1<'env>>
pub unsafe fn from_external<T: 'env, F: FnOnce(Env, T) + 'env>( env: &'env Env, data: *const u8, len: usize, finalize_hint: T, finalize_callback: F, ) -> Result<JsStringLatin1<'env>>
Creates an external Latin-1 string from raw data with a custom finalize callback.
§Safety
The caller must ensure that:
- The data pointer is valid for the lifetime of the string and points to a memory region of at least
lenbytes - The finalize callback properly cleans up the data
§finalize_callback invocation contract
finalize_callback is invoked exactly once for any call that
reaches the N-API layer:
- On success, V8 invokes it (synchronously when
copied = true, on GC whencopied = false) on native; on WASM this function invokes it inline after the N-API call. - On N-API failure (e.g. OOM, status !=
napi_ok), this function invokes it inline before returning the error so the caller’s buffer is released.
It is not invoked when this function returns InvalidArg from its
own pre-validation (null data or len > isize::MAX). Those are
caller bugs: we cannot safely reach the buffer at data + len, and
many real callbacks (e.g. Vec::from_raw_parts(ptr, len, len)) would
trigger UB if invoked with the bogus arguments. Validate inputs and
retain ownership of the source buffer until this returns Ok if you
rely on the callback as your only cleanup path.
§Behavior
The copied parameter in the underlying node_api_create_external_string_latin1 call
indicates whether the string data was copied into V8’s heap rather than being used
as an external reference.
§When copied is true:
- String data is copied to V8’s heap
- Finalizer is invoked during string creation if provided
- Original buffer can be freed after the call
- Performance benefit of external strings is not achieved
§When copied is false:
- V8 creates an external string that references the original buffer without copying
- Original buffer must remain valid for the lifetime of the JS string
- Finalizer called when string is garbage collected
- Memory usage and copying overhead is reduced
§Platform notes
On wasm32-* (WASI / emnapi) the external-string API always copies and
runs the finalizer synchronously, so this function makes its own copy
of the bytes into the wrapper before invoking the caller’s finalize
callback. The caller’s buffer ownership semantics are unchanged
(finalize_callback is called exactly once); on WASM, as_slice() etc.
observe the copy stored inside the wrapper.
On native, when V8 chooses to copy (copied = true), the caller’s
finalize callback has already run synchronously by the time this
returns, so the source bytes may be freed; as_slice() returns &[]
in that case. When V8 keeps the buffer external (copied = false),
as_slice() borrows the caller-provided bytes for free.