diff --git a/crates/napi/src/bindgen_runtime/js_values/string.rs b/crates/napi/src/bindgen_runtime/js_values/string.rs index 9cb05176..2af44beb 100644 --- a/crates/napi/src/bindgen_runtime/js_values/string.rs +++ b/crates/napi/src/bindgen_runtime/js_values/string.rs @@ -2,7 +2,6 @@ use crate::{bindgen_prelude::*, check_status, sys, Error, Result, Status}; use std::ffi::{c_void, CStr}; use std::fmt::Display; -#[cfg(feature = "latin1")] use std::mem; use std::ops::Deref; use std::ptr; @@ -53,12 +52,15 @@ impl FromNapiValue for String { "Failed to convert napi `string` into rust type `String`" )?; - match unsafe { CStr::from_ptr(buf_ptr) }.to_str() { + let mut ret = mem::ManuallyDrop::new(ret); + let buf_ptr = ret.as_mut_ptr(); + let bytes = unsafe { Vec::from_raw_parts(buf_ptr as *mut u8, written_char_count, len) }; + match String::from_utf8(bytes) { Err(e) => Err(Error::new( Status::InvalidArg, format!("Failed to read utf8 string, {}", e), )), - Ok(s) => Ok(s.to_owned()), + Ok(s) => Ok(s), } } } diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 96a2b1a6..5ff1e771 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -126,6 +126,7 @@ Generated by [AVA](https://avajs.dev). export function concatStr(s: string): string␊ export function concatUtf16(s: string): string␊ export function concatLatin1(s: string): string␊ + export function roundtripStr(s: string): string␊ export function setSymbolInObj(symbol: symbol): object␊ export function createSymbol(): symbol␊ export function withoutAbortController(a: number, b: number): Promise␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 81724e3c..b3edb4fa 100644 Binary files a/examples/napi/__test__/typegen.spec.ts.snap and b/examples/napi/__test__/typegen.spec.ts.snap differ diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index 3dc40f32..919e1367 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -11,6 +11,7 @@ import { concatLatin1, concatStr, concatUtf16, + roundtripStr, getNums, getWords, sumNums, @@ -106,6 +107,10 @@ test('string', (t) => { concatUtf16('JavaScript 🌳 你好 napi'), 'JavaScript 🌳 你好 napi + Rust 🦀 string!', ) + t.is( + roundtripStr('what up?!\u0000after the NULL'), + 'what up?!\u0000after the NULL', + ) }) test('array', (t) => { diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index 54b7eac8..7c0e8945 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -116,6 +116,7 @@ export function contains(source: string, target: string): boolean export function concatStr(s: string): string export function concatUtf16(s: string): string export function concatLatin1(s: string): string +export function roundtripStr(s: string): string export function setSymbolInObj(symbol: symbol): object export function createSymbol(): symbol export function withoutAbortController(a: number, b: number): Promise diff --git a/examples/napi/src/string.rs b/examples/napi/src/string.rs index ee2e49df..f14f0e94 100644 --- a/examples/napi/src/string.rs +++ b/examples/napi/src/string.rs @@ -20,3 +20,8 @@ fn concat_utf16(s: Utf16String) -> Utf16String { fn concat_latin1(s: Latin1String) -> String { format!("{} + Rust 🦀 string!", s) } + +#[napi] +pub fn roundtrip_str(s: String) -> String { + s +}