From 7acbb49e1f454bda109da4f25df5516bf2e85ac8 Mon Sep 17 00:00:00 2001 From: Olivier Guimbal Date: Fri, 17 Nov 2023 14:27:58 +0100 Subject: [PATCH] Fix `napi_get_value_string_utf8` to match node (#7175) * fix napi_get_value_string_utf8 to match node closes #6949 * [autofix.ci] apply automated fixes * Update test/napi/napi.test.ts Co-authored-by: Jarred Sumner * Update test/napi/napi.test.ts Co-authored-by: Jarred Sumner * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Jarred Sumner --- src/bun.js/bindings/napi.cpp | 15 +++++-- test/napi/napi-app/.gitignore | 3 ++ test/napi/napi-app/binding.gyp | 18 +++++++++ test/napi/napi-app/bun.lockb | Bin 0 -> 34651 bytes test/napi/napi-app/main.cpp | 67 ++++++++++++++++++++++++++++++++ test/napi/napi-app/main.js | 9 +++++ test/napi/napi-app/package.json | 13 +++++++ test/napi/napi.test.ts | 66 +++++++++++++++++++++++++++++++ 8 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 test/napi/napi-app/.gitignore create mode 100644 test/napi/napi-app/binding.gyp create mode 100755 test/napi/napi-app/bun.lockb create mode 100644 test/napi/napi-app/main.cpp create mode 100644 test/napi/napi-app/main.js create mode 100644 test/napi/napi-app/package.json create mode 100644 test/napi/napi.test.ts diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 0b514f58f6d49b..370d98a0d1cb3a 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -1771,15 +1771,22 @@ extern "C" napi_status napi_get_value_string_utf8(napi_env env, return napi_ok; } - if (bufsize == NAPI_AUTO_LENGTH) { - bufsize = strlen(buf); + if (UNLIKELY(bufsize == 0)) { + *writtenPtr = 0; + return napi_ok; + } + + if (UNLIKELY(bufsize == NAPI_AUTO_LENGTH)) { + *writtenPtr = 0; + buf[0] = '\0'; + return napi_ok; } size_t written; if (view.is8Bit()) { - written = Bun__encoding__writeLatin1(view.characters8(), view.length(), reinterpret_cast(buf), bufsize, static_cast(WebCore::BufferEncodingType::utf8)); + written = Bun__encoding__writeLatin1(view.characters8(), view.length(), reinterpret_cast(buf), bufsize - 1, static_cast(WebCore::BufferEncodingType::utf8)); } else { - written = Bun__encoding__writeUTF16(view.characters16(), view.length(), reinterpret_cast(buf), bufsize, static_cast(WebCore::BufferEncodingType::utf8)); + written = Bun__encoding__writeUTF16(view.characters16(), view.length(), reinterpret_cast(buf), bufsize - 1, static_cast(WebCore::BufferEncodingType::utf8)); } if (writtenPtr != nullptr) { diff --git a/test/napi/napi-app/.gitignore b/test/napi/napi-app/.gitignore new file mode 100644 index 00000000000000..f9406c410e7f16 --- /dev/null +++ b/test/napi/napi-app/.gitignore @@ -0,0 +1,3 @@ +node_modules +*.log +build \ No newline at end of file diff --git a/test/napi/napi-app/binding.gyp b/test/napi/napi-app/binding.gyp new file mode 100644 index 00000000000000..ef65434cd5ace8 --- /dev/null +++ b/test/napi/napi-app/binding.gyp @@ -0,0 +1,18 @@ +{ + "targets": [{ + "target_name": "napitests", + "cflags!": [ "-fno-exceptions" ], + "cflags_cc!": [ "-fno-exceptions" ], + "sources": [ + "main.cpp" + ], + 'include_dirs': [ + "JVq>w@)g%XuRgpedelqn4;>NpM#hl69j5;v7p8fYFV4WdbfN^=@- znpGM!sEp0Gx!$#&b2d-iLihgu_`RREeebfLJ*@9ud+oLNv!DH(p4CUwAX*q{;KvIy z;D*I$_(g}w0I~Q2PDlWc&t(M&B173xte8PEk_-l8gg1*E7AGMvE(<%RJQ_&h(1!`VV1iAPE>7@Yu*6C{WY16Cn7 zG=>Xt?{*AEN5~J46mXz-fnkF1Cs#vtpMdhVI&Xp3Eo~NgCPs~k=&@r zc*y5QMzS~{>o&-jf&7&aBi}rTpUUl)i;KLhy!KkUaF zD8%y1@CVyV2O*IE9>gf`8F79bfFXYf#E9z;g;;+G#Mn=HV8WOQY3#>(NOy;L3B-th z8uBro10cwM17fV-8V=#_(p4l6!6^YSl*h1}2)Ca&{@y-{As_pb0!qYo!`V?mtPpNI zv4g9i7nEZh=o!oJDT&7!3|t8M;VX;!!wW}kF&O?_zvw`SL$MIT9;lD}7sPyrAV#@T zpbYyP1~G_`jJAsU0$C`%9@p}e^}aPWeY>wz|I-_J&(4QtyxrjX(teBH#9JO+Yb&-` ztO)S2xs>^G+0N^#iJC7De+<|kb72Uu}IUm_RR-QDGmW!Cx7U>ez4z!Z*eNtD3o}``KE6(!Sf{3?kK2^6y;q{{Mgw_i zzut=qYX=X}&CA<2Xk+_|(GpQPCdoytcDeH9$6rd%v6Z^FA!pd*K11$qI9R@c^fO@M z{66}ZHfOP z7`$F>#M->Yb;?SYXO6#8-#0iU`m8X`4vx?PiwU}X_Qo?hKg?}ll#(LCRRk;itz5m1PUU4k%jaIBP z88aBh_f^l9ZQOI>+TMx?pw(F>x>V0ryd0q-Ih^nlD^zQEj~LR)bOe<5%g0Y6OZ zUkZf3TFei(1qQbLtL=9O27PEBmU9Ndgv(X~sp|&(rvE|yg}`qN{6y}y>VdR>0vOGJ zAJd3I@>}ZwsrO0DkNQJGJ+vhdeq*@6_S?6GiB^a3^WnmZCO@r8iJ$RsHLN(k!6;w(5o5iytd$wy4QgJ zzv!3Z(sGz;6irWc_HX9TEOlz>oUF{$u#n@f!#Y+5kVnBlA#%_Vd4_ zekkw{27asw`>8eu!oME)$^1p;w%P&VzXAM~;`Y%7f0bVmn4Ey0tR26qKVRUt6Z50| zAWoYCkv~VwPvrj9_Fn@(-hZ%B>_c1akhDJp4ClY-ZvpUIL;HwFbO@KN2GV{x@YD52 z^w1gr;qM0fVqAZS-IBPi{LaAd2K=aZKjvfK+loWlzXtsOW&ffK3m@r!TXm1JlJ=v3-{wE`e;@FZ`!B&n z{MG`g`x^L1LHk5@lHXQ-OL+Ji3j6>=g45-jnJ0|=qfFH-7q<^*j2H>Z!9|T7%&QBv!&kz<&lpoV5J1nPd z3WPrm_-%k6nP4c|90>near>|gP=VyP21M#*zn(=%Ji%DQw01IfWNJL-}he@4nc7K6aAC&)?%W+(PDm-|5s!n z{7Zq~2HGd-U)A3O;79!<9}>#ZmO$F;1&4lUKiL1awvG6N-xK(;eYC%S!=EMQ|F`yc z5%{g4eY8JppU4H5Ee2Ar7u>jU{BixlJd)ocGp*ia;I{*Qtlw5%dfoNn_ObuS-&P%x zw(bHy-ha^ckoQ;lE#c6Q>>t|73(Yk3H9^cz)}OY{0V00|@Ed{rBu!#$qoqLVb%gU$ zI)6(%^fJOf6!`6F?bGYDbWQj(fZs-}|CZ{1Uq<*Z0zY~F{Ws$$4d=Kxenjsi{=U8M z)1-ZS;5QcY|Euu_escdLnBTYcqco}e9Qd7}eX{2{78Ol7^I#J z@c)E-Iq^D;dAG?!gGZEAYEO`>6YWGym2A zKi&S@I)_O66~J%zFZz#qKnx_@x5GA=lAk>PV~qC{SYD|>kC6wa9aSI9j|v#0>@XZu zz!=jY9u@bXav2PaF<(`j#u#<34TSmqfG}W;?dW0x!jEFC-yaC$0YEs0a28Fa4aD&v zh%sP{^$alqfgWSuhXG+Ztc6qz&oorP81t=xP#zl~4D=YwZGkX`v7pXy93jT~qk%Ag zj5v0N7z4&w?urQr7^A+&1EDQ>0wJFl5C)7fe=;T@&||FU1B9_J5C)8~J{t)0{eUoF zjQLzlK=@INas^VQq8RH310ha`I3Ht7^Tla;jQOGB@-T>TZzTjmoERX)j|0L$kC88) z$`!?!P5{FCiQ+g3Vhlfvu?*`Y{kH4hc1^c$w2A+{cKt>E3r>jt$3cQ2!lgqq|CIg8 zkIf$Ow_j=dDO=|4e#N{qy8q0#eP0ewo-^m=fxG>88=tgfq%7#_V$&jc5*Nnol@Sbp06b^YKMQ?;@OT5vl~b=>#KDBGvDFJ_#~@6vfNYM{wTVf@+!%< zL*poar-#=+Y^#YaK4}+!AnKsYd`FWm;gUM+g63Yc){CSCT!oJA1vD2h~@>}Lr7pwd^y!@ zm(A!$3FFW1+3mKSSDhMlu_&jiy6^E(yEaSRoMf#(uyloQC#zkztB+K_bn!l(lej=y z*?W2BhAhuneuEDI5YYqfc}QUL)BEi)jMokJ$?4cB_8NcF3t{Hvb({5OEiq70n!s%^ zT)>QczdKTHUHAOi?WbB*EPQi_dFEzP?u65)ooyqZFHHd;g4>yZLd?9jbFqSUg4NfY zO7~}*Rb%CQZyhyUTjOJ5iRYyqT@;JnR~B~Y`Qh?@PC&yPn}@Lr)~zjwA2xmSR>raV zCk+j}LE$u9SvqdNj5Rtgk}Gr@FC=z!WYxG=Z;E~KdfMyiMbTA9mmf+f7$+0F@Q7|w z+yNEy@|2y-6r?SJL0Q zsGHTPPX=l4KcCU$DeEP^U3AWH=Le04%1YDwl{T9CKP#=U>pMQXT79a0d#UF%T=^zc z&_hSJh9f%csdJySGYrz%;8=6*ZBB>MPl>DNFrKJQx+rHn*YLqyo#bJ6Rxa1IsA3Oz zqo{2DrJG8ph9xqr;!QICqCKq09=gzR>)vNyb>4n6jk#0v4#(c`@ytVYo;^Go1U`9M zJripB*DW%>(Z1B+aK=HYInpDl^Q@<@lxVR2quZ3AW&SaG*`H?8-uD=oExV`4%$}4Ib zuhzt>#i|r`EnhOhJ#fI7CGv^8R6Eb!s;2fOG*$WG-Dyv0xa4^N;hFQ(d+S}W4Hm>a zyLD#~zqZ%Bs~hI6ntwe&=E$kIPbCvyRklAlW==o%x5fS1>6-^{IVfGgRbxxWCM77j zS_Hp+?oPvnKb?M;hKqBW1m^1!Em!HQv-7SzS!=t;HN<&( zif+#ZNri*EbPCKG?bA)>t*OJkW4hT}8&-KTs@^?P$hbFkS&n4P)am|i$5c9v-2gyD zzvTG`v6(kZa_uvnq!hn)?6JUNa+;%z^McyN@pEsV6*RiqMBFTt%gSjO&GK4)V97~M znSlcae!3eu>%;T_&AscLk1NdRihU=z~2& z9%)mgo^Q?{bulDaAze@Xtru79iyhjjRv}F>Q zWe)~49Fr?@bsyF>`fn+}`-c~$RUTKGUD9{@`sB)^TY|Tah#h!9c-x+{qBz{iv%urz z*Q5yf*@hl*vH9)3@mBiJf#9 zZ8=G$%T;&BJQ}VV0*V7uVUYL!c_yw&o}UB8EFLf{qmOamYEIAiIrrl?_}A`T_I6@< ze8{a6fv-x=oC{UhzjEAWm%Vbxz`qvD@9{g!VqUeA&oO${=;XU8YGI$tM#FZUnlZk@r>?U4@~FmJ zkwd1oI}zB0A90}c{GwjYJq0qWZHlw@(QtdwaScnl*iOw%>!#gq>f^7=R6br^s%V?I z+46#~{|FBd&Ci`I2)g9K)uk|k#EV~1I< zwSWA^qfA$A*xbCY6U~XoI>` zT*al=AG5WRB_{VVxjSf1Pc7RK8`aN!GC6wZ#N{tE+&*+%?;^(2&Z$Z3E2{VAq&$0P zB315x&U)0fh#2moXSu14sj&DhP6FYKjIh-SC@`^|HhxMV=}uvSj0G) zEvH&$X1(5Pbx^{qp4I05=7j@H1}b?JEZ~^j{M@J80?Szp_h`R5jT3=gy$ri|P>quQ z)a5D-7tg^+VAfdW_8#%cOyI9+ez;#)K}@=ISXzfS4J>^b&)Q(NPyfU1Di4|#gq&75 zWOLT9^Q1^#HzrK}b%$syQ45Z^u z+ivlp@{OdkqGf@{P=lI)-A4Q?p;h5K8Z=%V*Lh&R!oYu*T1J_F-);?^qxmzJSH>UF zW%&PDY1>E7@NnLt1Ao)x)uZDYjk4Khd9-Whvr~#gubzq$jNSNT{GRLHHx79WcC=4B zUnwVB@yE(7e(C-zmL6V`z!+S;cFBc%6K8~kcKce^~GF29v?Ept+rvO5m5+D+8$=Hl1e zYr*{Cf3E}}qF+3(B!TH0E?p|$YjBNZO>U=C`T90`O1l&5=T^i{>Ur(9_k=N1O_|_=+^YT~ZhD_Tv?3$NV3L%pQmUd}0q*??t^omsn0YsKty@DkL*E0bcdS?J ztsgjV+%$eq* zGf>ewiRY*!Foz`mIr^3FpT|>j94u9&#=LOomvk)0(V%Dga$ouP4-Q*=yfWg;+T(I3 zmS0@^NiITJsn|=s_m~c2-|X|+TefnaeJB7Cd2vpY!2CGgfBwbS)?Lf9FKyFy$P3=} zX`G~ib=7Hs^fceh_oH?5r|;9X>C{p8)ySN@xi*syjhAm2KTy-KSMK^(Ixk$;SOE~h zg?BqmfjRW_?fIK3f+uFEUA%auO2H>!g!B9I`yA_SLv#9WuU?kHSf!AD_+`xC)ba%? zH}07q?fCKND3wWx__hg=uo4;%MQ>pHkkDYma z=9KU5K(oz{Os`!KT0M^5G-dvDC7%-?eR{p0Kkku*PrnXT?OA8 zf6C#@>C*LioJT`p5JYp6M<8ywuUiL-}x0t=Z$xxtF zOK&bnE$HW?diuO}i0bB*3Z}Xavl?gBFLC*L+Qz^;=tK5x0ccD~PX<##sy&p5^C-3VHu-&1~wU2$b& z)OOWaAL)o4mwQa>hG(DKnaSe5E{B?4^nQX5k5;f(vhPf$% zV{*F}u$q>oSyN7F@FGSXc34R?*YdceOnJl4l->x-;0fYe>gyW7(+X{k$b>07(dT{DKS6TO-Ubkn3%SR-b-k#)>CAl^#=W2=JyX2=c zuT(3q*;m=#S})DlKdUP~vk`l+pyQ5IkhD7eG5y&K!AcqSx%TPP%@r@}5b+3JclrCuN(_+^ZNCh4(p~FE^#m1SlDCnacjn{PL?xDo$*YE;Ntrk5}4`R*Nz`+@gS;; zv+{r&+w5ip#+106>+0#D(@E<7ywmEdG|N1DtSo=7c|mEtaknhN>C&+Snb~`u4!F5? z&49zj{t*B~aB;05fw?Zz^2xHZ0{{HPV_J&dO8E?jz6M?PBr2V%neF-cVz^U^dfM8x zRzB*weFSPYm)Jdg=Efa8^5McBX4c^Q%8#ce0uaH)HIoEpugD7>)t}8Tvka}3)vxFi zxb8{Ww3SI5X02z4T+yl=r+LBamW5UyTz9o%2^wo6)be)X$&AxFnZ z$MqA;P1QFa{BDrbwfz7@^k7RsA!d#_He+lg>yJ(M1S_r|-a9=a$E5Dc>_0#C5$uig zcE~E-(Bb*)|HJ@nx_lW_Yp{k3Sgc63~U<%(<1ERSE= zn|6890AX%vYMtlv>W3Tl@Wu{3u8-PODWy$GrMvxSMHbw%fRj=L~1q|%h1*_s+XMc(m8s;ykCu4d7%BcY(8y^l%R5(gVQ0&Nhdr13C4OGN`kH#C z@B0Uj6HjMM{!n9+?S9DHtHD}s-UZdGb|)V?-t%g>9P^om>q5tUH8gMifj2>4KRkVL zvf5&&&d$PBF$VWSwrNY$P1Ln*bk=qGXJxB+0L{#ij(K=nTXF;WZc~8xSpF1 z`93JSD(ik}WcD(_ULR)8`@bg`mB~zd)x+6TZ_d&z`7@@c2lc7m=C{J6-Az;f)BR-? z9y1@^7#R?<)hvWVmv<~3cbL-5UXQZwR5e&s&MV_yVGPheC6?m{{7+ zuB73PqvLM)^w2Pit<&RWeSK>8hg)AvUz?=asZ+_&(@)P|ka{&?L!s|hiA8=x-=ueo zs^gag#aJ%#{V~|fNB&vN?ROL3tud(U zH+(ryKTS^NfD99v;9xp$Vf98=j3P{_Lu*X)g^z;kaMlwy)koSmkeL6hw-vL z6(83WjL6<{eq3_LaNX-s5udkj-TGeTz~UPKL~y+cD8$S|9gb=n7q41(cA;}Z(c+hv zxTUkLED9NV`#x*3=XKt@>p(m6OR2ZlvAQ2rU#R7oKDoDrTzw*2zshaFtuvnzjQwd? z^h-%dknb+2!?is8o(l8U0Lj4hW{BZllMK*=X(zis0u zYWiQ54Y#r1;kO2UYv8vAerw>j27YVcw+4P|;I{^TYv8vAerw>j27YVcw+4P|;Kv#$ z7QfdRHCa?HV=0W}=<~vaQSg0dee%_5{c(|8u9b$-APpfefh!2m(=gUx^Lg;m<^Xsv z(G+qcYHUBb>K+9>EB`Fdriz^0+HXw<2y;@YY(IWgaP0C zVLkje1)4w@@SPpzNdd_LVZirom?sSc=fG6JcV(D|zw6;rISdBA=fXUcm%L-fcT^}F z93kVkL8&ka{$f3R=Rc6j5&auz%!79t3?2~T`T$`b%7J}CTwfsU2fWu|;QLU_n+k;W zP&Skw^VmSxt^yFYhZy+I2L2xu`bB-B{;*#tAL_#nXe1E+?!y5H$5a&v$E+t1zQ4lvavDIIKw3b3 zfcgUAztQLpg!;n1q1@P4>>KJ8`-T0$ac}_|4HO0>015|+1TqA|F~Q%vSpwl$uz>mj z=>P=+1p%Rrq5Yt};BOM*fue!%cTvND^npTv{D3$>I3L(RsJ1wu7@$}nYoHN8_&Y5F zAXG1oF^;7pPy~<>kTFnyAYCA3ARHSWkQ>lgARJ>Gpg};vK={5A#~5u5Z578BZ4uL0 zhOxDH49%uO0zyk;iSkPT5nj{_;-P*~R@67@7{^x<2*jfpAQ*40WLdgqTQ}*9!>SquUIY;W&*3LfHoZ zVO`WI!PbUr#Kk^n0TH{xvDXE{@kbo&r!5fb8f^n{^neH^jy;YgjvLw&+Jq?(+69gy z+SOnnb0EyeJQE-@pdsS41;j&va7>9!p^c!eSOX!}NFbaqPC%o8?13DB9Dz_KloRa& z#~y6}<#PeTJhT~CAhcn$ArBzTBV{BGnhKc^j6+4SjO8RFQ=e!vShY=?=DcC^sx7vK zWbz$pX$jvU`h)aARpbpc`BFNR7(#)*AvG_-Mv}=ls3j$Qjr5Hu9%vMLl1#o*4JCv1 z4S}WUJskN?IFtYy6b?!O9$hYswx5ArCh*tyh6?iBy5%FLN`coj^pQm`JcF5a%@`ZXRF$5kk zRN|9?e8V0}#8UsD9kF(P&hzt6_xn5w8}+3jma$?SO2={{`_EfM_@y z2mMTHKqEdehz|iV8uW*F%^+R|C< z4#=+wzFoy&@oVy9LbG`BYWV{R#M&XgL5ME}v38(8|Hi6_Clcbh0no&={^z#ylak8q6_4}uCB=g4e{6k zJZRUjR!x8!@PD$u*YRU(<=3~Dlo$a?CCq^scMil$2PGRd3Mo(m`^scPnHO~f>=l`k z5}}Zz2sy;_4Dr+fJYu{4fz-Ih!!=z#d!A^u5#N4$~~4?M(UiKIjlSP0INAM_OWA<&;6^c438(9RDe z5RbwSdWt##9^%u7_&@>Kz&@~@ALzgwO2Br0-VX5qL_DSd8cG0Y#77YEsRAW9av%Zm z21LB4Knd;>frt1FB7Rn&M7$pSU@s=t=nwW{VxAN*Ahastt%YiblI@>!j*=SgSwCMx zh|eM7qXp20h@>XohlsZps)TBX_$MO%T*M`ygMY3EWPeS3Arap(z=Jawcz!4WHMfa> zB;rp7c#L6t4OS%-dsHGGXrRPMALNGT(Qwf-0`Wydl~7U>?@Pp64TVNo2=Tu}{MATG z7=a4FK$<)>{ZoQpks1W1!Vh^U3;B6Zlf=(FB>wggOEj+fBjcjDkzs7UM^q%Z0khID zY5OgK^O}P(0dzs zjM5Jl21P}M3oQ%`BDsO!GA%M*KP)^nSg0?E3~Z`pz-qc=iS`frQGp5I0gi=J27IrD z3&OZzQ9L%E<;UiP2m%5EBiS5oKs28fAPi-PfMYmr6eoxk#10SVhEZ)(^9CiME?O3Y zssb`lF^gJevHcbVr{*4TP%(>o*lUFY_8d?j{<2`}24)TT0YVm;k1aGMesln4@l~^c z*ga0Df6JW{Jum^g=z;~-q;K4cuqYO8Q;|!2$)XIt4SeYSPRxgwpq#<5%WqkoL=AL4 z>PfH_KAHxBm6oEUrIg%)W<`&zz$m%^9#{piMbxW!-n3}GqB;N|x?l~_Hxa3p9~sS} z9O$*sdQ%lKx(l)w$P;LDHS+G7tN|_ zf#)Cd64?Kd#}XZFpw_KnUEuI}2JAqX>WC{+Aq$kthPlrX@`NltJJipgP0U3!>zh;j zXkk!ODx4S2+T`051 z%|L6@>>GiA`I|JQW5ZTjrn&;0RLp{#W$Qyp9*=>GTvAO9Zl$SaJpyNQ0vd&9_*QtE zv_b|2ApVgDD-)a(v=u1;2b&HtzIYFA0heA4km*Sn zc2s%WmSz^E1G=)P3`*gx4S&6KX^F?jkJXMO+|$KCZkP*-ZTWj-gFJJh_}twJRzIS5rR$f zqIuTgA%Vd{&}yWR%Z?0e$pF5u3g}I2IOp*>pykE#o0fr{l7K~>sv)OnRG~orVTxd#R(Q-I-G?gMHoaWYs%CNn~Sk>Y$Ut6Zd1Zqbj;F}#+oe*P*XjS zzv&vbyyD$5iUP|^JfGVVNV8mk(wv|+>y$lHFfg&WaV?0_TnSK`6D;aTtCgX^M!|bG zrE9SaBnitK+6oK^H&hVJgWWBN0e4w=IObFJDF@-KZ~;%WtNzKO_)j>Xv7eMQ-^p6& zGfgBwqNOM^YRv#?qeE0C8Y}2C?t!4saEBJ43-mB>t4=*M{G@x|)B~_@(#;cJl-N1V9v83RZNy)3&@KaldH>0lvwAWv%sl_0Nq84`y21Kz@J!1R1{1 zqINPA4kuCo2Oz?5b}TG2fpGc;_bFaWR!XY{z_b(?eCwl3YYw<+DQdl=mIz@G*N+V= z2S*SJ57qwqxRDSYy-{ahEezbZXJn}6)&}d_Gcx38ZN7ge9jf44d8vs?p^$>s7Ts^^ z(EusFHZ5V)4km;f56tAUd4yX~80|C)SZOJ$)z%)Fnjc0)%+z~=R%Qp`p$<@hjfz2K z;yEEo`mu%70}Kle8{* +#include + + + +napi_value fail(napi_env env, const char *msg) +{ + napi_value result; + napi_create_string_utf8(env, msg, NAPI_AUTO_LENGTH, &result); + return result; +} + +napi_value ok(napi_env env) +{ + napi_value result; + napi_get_undefined(env, &result); + return result; +} + + +napi_value test_napi_get_value_string_utf8_with_buffer(const Napi::CallbackInfo &info) +{ + Napi::Env env = info.Env(); + + // get how many chars we need to copy + uint32_t _len; + if (napi_get_value_uint32(env, info[1], &_len) != napi_ok) { + return fail(env, "call to napi_get_value_uint32 failed"); + } + size_t len = (size_t)_len; + + if (len == 424242) { + len = NAPI_AUTO_LENGTH; + } else if (len > 29) { + return fail(env, "len > 29"); + } + + size_t copied; + size_t BUF_SIZE = 30; + char buf[BUF_SIZE]; + memset(buf, '*', BUF_SIZE); + buf[BUF_SIZE] = '\0'; + + if (napi_get_value_string_utf8(env, info[0], buf, len, &copied) != napi_ok) { + return fail(env, "call to napi_get_value_string_utf8 failed"); + } + + std::cout << "Chars to copy: " << len << std::endl; + std::cout << "Copied chars: " << copied << std::endl; + std::cout << "Buffer: "; + for (int i = 0; i < BUF_SIZE; i++) { + std::cout << (int)buf[i] << ", "; + } + std::cout << std::endl; + std::cout << "Value str: " << buf << std::endl; + return ok(env); +} + +Napi::Object InitAll(Napi::Env env, Napi::Object exports) +{ + exports.Set( + "test_napi_get_value_string_utf8_with_buffer", Napi::Function::New(env, test_napi_get_value_string_utf8_with_buffer)); + return exports; +} + +NODE_API_MODULE(napitests, InitAll) diff --git a/test/napi/napi-app/main.js b/test/napi/napi-app/main.js new file mode 100644 index 00000000000000..64c8d8cf9664cd --- /dev/null +++ b/test/napi/napi-app/main.js @@ -0,0 +1,9 @@ +const tests = require("./build/Release/napitests.node"); +const fn = tests[process.argv[2]]; +if (typeof fn !== "function") { + throw new Error("Unknown test:", process.argv[2]); +} +const result = fn.apply(null, JSON.parse(process.argv[3] ?? "[]")); +if (result) { + throw new Error(result); +} diff --git a/test/napi/napi-app/package.json b/test/napi/napi-app/package.json new file mode 100644 index 00000000000000..d85cc5a4ac9bd0 --- /dev/null +++ b/test/napi/napi-app/package.json @@ -0,0 +1,13 @@ +{ + "name": "napitests", + "version": "1.0.0", + "gypfile": true, + "scripts": { + "build": "node-gyp rebuild", + "clean": "node-gyp clean" + }, + "devDependencies": { + "node-gyp": "^10.0.1", + "node-addon-api": "^7.0.0" + } +} \ No newline at end of file diff --git a/test/napi/napi.test.ts b/test/napi/napi.test.ts new file mode 100644 index 00000000000000..8e9841da881292 --- /dev/null +++ b/test/napi/napi.test.ts @@ -0,0 +1,66 @@ +import { it, expect, test, beforeAll, describe } from "bun:test"; +import { bunExe, bunEnv } from "harness"; +import { spawnSync } from "bun"; +import { join } from "path"; + +describe("napi", () => { + beforeAll(() => { + // build gyp + const build = spawnSync({ + cmd: ["yarn", "build"], + cwd: join(__dirname, "napi-app"), + }); + if (!build.success) { + console.error(build.stderr.toString()); + throw new Error("build failed"); + } + }); + + describe("napi_get_value_string_utf8 with buffer", () => { + // see https://github.com/oven-sh/bun/issues/6949 + it("copies one char", () => { + const result = checkSameOutput("test_napi_get_value_string_utf8_with_buffer", ["abcdef", 2]); + expect(result).toEndWith("str: a"); + }); + + it("copies null terminator", () => { + const result = checkSameOutput("test_napi_get_value_string_utf8_with_buffer", ["abcdef", 1]); + expect(result).toEndWith("str:"); + }); + + it("copies zero char", () => { + const result = checkSameOutput("test_napi_get_value_string_utf8_with_buffer", ["abcdef", 0]); + expect(result).toEndWith("str: ******************************"); + }); + + it("copies more than given len", () => { + const result = checkSameOutput("test_napi_get_value_string_utf8_with_buffer", ["abcdef", 25]); + expect(result).toEndWith("str: abcdef"); + }); + + it("copies auto len", () => { + const result = checkSameOutput("test_napi_get_value_string_utf8_with_buffer", ["abcdef", 424242]); + expect(result).toEndWith("str:"); + }); + }); +}); + +function checkSameOutput(test: string, args: any[]) { + const nodeResult = runOn("node", test, args).trim(); + let bunResult = runOn(join(__dirname, "../../build/bun-debug"), test, args); + // remove all debug logs + bunResult = bunResult.replaceAll(/^\[\w+\].+$/gm, "").trim(); + expect(bunResult).toBe(nodeResult); + return nodeResult; +} + +function runOn(executable: string, test: string, args: any[]) { + const exec = spawnSync({ + cmd: [executable, join(__dirname, "napi-app/main.js"), test, JSON.stringify(args)], + env: bunEnv, + }); + const errs = exec.stderr.toString(); + expect(errs).toBe(""); + expect(exec.success).toBeTrue(); + return exec.stdout.toString(); +}