From 19e3488efcbc601afa1f11a979372eb6c5ea6130 Mon Sep 17 00:00:00 2001 From: Ranger <32590310+southorange0929@users.noreply.github.com> Date: Wed, 12 Jun 2024 15:20:27 +0800 Subject: [PATCH] fix(napi): JsString should respect \0 character to align with String (#2138) * fix(napi): JsString should respect \0 character to align with String * chore(test): update snapshot --- crates/napi/src/js_values/string/mod.rs | 6 +++++- crates/napi/src/js_values/string/utf8.rs | 16 +++++++++------- .../__tests__/__snapshots__/string.spec.ts.md | Bin 529 -> 703 bytes .../__tests__/__snapshots__/string.spec.ts.snap | Bin 252 -> 297 bytes .../napi-compat-mode/__tests__/string.spec.ts | 6 ++++++ 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/crates/napi/src/js_values/string/mod.rs b/crates/napi/src/js_values/string/mod.rs index 313e46b1..d18db289 100644 --- a/crates/napi/src/js_values/string/mod.rs +++ b/crates/napi/src/js_values/string/mod.rs @@ -69,9 +69,13 @@ impl JsString { ) })?; + // respect '\0' with js string, for example: `let hello = [a,'\0',b,'\0',c].join('')` + let mut result = mem::ManuallyDrop::new(result); + let buf_ptr = result.as_mut_ptr(); + let bytes = unsafe { Vec::from_raw_parts(buf_ptr as *mut u8, written_char_count, len) }; Ok(JsStringUtf8 { inner: self, - buf: result, + buf: bytes, }) } diff --git a/crates/napi/src/js_values/string/utf8.rs b/crates/napi/src/js_values/string/utf8.rs index 56f18f61..602709b0 100644 --- a/crates/napi/src/js_values/string/utf8.rs +++ b/crates/napi/src/js_values/string/utf8.rs @@ -1,24 +1,26 @@ use std::convert::TryFrom; -use std::ffi::CStr; -use std::os::raw::c_char; use std::str; use crate::{Error, JsString, Result, Status}; pub struct JsStringUtf8 { pub(crate) inner: JsString, - pub(crate) buf: Vec, + pub(crate) buf: Vec, } impl JsStringUtf8 { pub fn as_str(&self) -> Result<&str> { - unsafe { CStr::from_ptr(self.buf.as_ptr()) } - .to_str() - .map_err(|e| Error::new(Status::InvalidArg, format!("{}", e))) + match str::from_utf8(&self.buf) { + Err(e) => Err(Error::new( + Status::InvalidArg, + format!("Failed to read utf8 string, {}", e), + )), + Ok(s) => Ok(s), + } } pub fn as_slice(&self) -> &[u8] { - unsafe { CStr::from_ptr(self.buf.as_ptr()) }.to_bytes() + self.buf.as_slice() } pub fn len(&self) -> usize { diff --git a/examples/napi-compat-mode/__tests__/__snapshots__/string.spec.ts.md b/examples/napi-compat-mode/__tests__/__snapshots__/string.spec.ts.md index be7f6f2d0156cde8284ffb27685d3432588376a7..ab46dd1b836448678a0db22bfad89c0c0c09ab53 100644 GIT binary patch delta 99 zcmbQpvY&N>IOD{1Y&;6(nI#zt$r*`73JepsD7Y{ve3;*}S>egv1y7gmRbWuaODxD# p=i;(c2nMo>GxAFmjJUWIfI!_Vu`Dq-xhS)s1gH!})5iNoi~#9EB-#J~ delta 11 ScmdnbI+10AIOF7_jK2UFp#*gR diff --git a/examples/napi-compat-mode/__tests__/__snapshots__/string.spec.ts.snap b/examples/napi-compat-mode/__tests__/__snapshots__/string.spec.ts.snap index ac85c784b629bb302786ec20648ece16643776b9..87889fcf9803f3d73d5e2edd58d76a92ba858c07 100644 GIT binary patch delta 192 zcmV;x06+iy0jUB;K~_N^Q*L2!b7*gLAa*kf0|3l`*&wb3*J#$b}z^2mk;800003TbP!Vlb@Vj+`5rQa&eo0y$a=-B^e6I8Hq&-3;s$vnH!z^Mf&uIfs3u1gO~wQ?;d8tyPREy)q#2sgIOx=H+MbhGl9^|S(|SV` u>y-~LJGAZ4-b4FbTzx=-qh(7_wV|0ssJFDpAY; delta 147 zcmV;E0BrxM0{j6+K~_N^Q*L2!b7*gLAa*kf0|0tW8aTk76OFi(RQVG}?gkmAfp_PaB0|3pkO;N-F006-a BJa_;A diff --git a/examples/napi-compat-mode/__tests__/string.spec.ts b/examples/napi-compat-mode/__tests__/string.spec.ts index 17080393..ebbcc314 100644 --- a/examples/napi-compat-mode/__tests__/string.spec.ts +++ b/examples/napi-compat-mode/__tests__/string.spec.ts @@ -7,6 +7,12 @@ test('should be able to concat string', (t) => { t.snapshot(bindings.concatString(fixture)) }) +test('should be able to concat string with char \0', (t) => { + const fixture = 'JavaScript \0 🌳 你好 \0 napi' + t.snapshot(fixture) + t.snapshot(bindings.concatString(fixture)) +}) + test('should be able to concat utf16 string', (t) => { const fixture = 'JavaScript 🌳 你好 napi' t.snapshot(bindings.concatUTF16String(fixture))