@@ -26,7 +26,6 @@ const {
2626} = internalBinding ( 'ffi' ) ;
2727
2828const kFastBuffer = Symbol ( 'kFastBuffer' ) ;
29- const kStringConversionBuffer = Symbol ( 'kStringConversionBuffer' ) ;
3029
3130function throwFFIArgError ( msg ) {
3231 // eslint-disable-next-line no-restricted-syntax
@@ -79,19 +78,20 @@ function hasPointerMemoryArg(type, value) {
7978 ( isArrayBufferView ( value ) || isAnyArrayBuffer ( value ) ) ;
8079}
8180
82- function getStringConversionPointer ( owner , value , index ) {
83- const size = value . length * 3 + 1 ;
84- let buffers = owner [ kStringConversionBuffer ] ;
85- if ( buffers === undefined ) {
86- buffers = [ ] ;
87- ObjectDefineProperty ( owner , kStringConversionBuffer , {
88- __proto__ : null ,
89- configurable : false ,
90- enumerable : false ,
91- writable : false ,
92- value : buffers ,
93- } ) ;
81+ function enterStringConversion ( state ) {
82+ if ( state . buffers [ state . depth ] === undefined ) {
83+ state . buffers [ state . depth ] = [ ] ;
9484 }
85+ state . depth ++ ;
86+ }
87+
88+ function exitStringConversion ( state ) {
89+ state . depth -- ;
90+ }
91+
92+ function getStringConversionPointer ( state , value , index ) {
93+ const size = value . length * 3 + 1 ;
94+ const buffers = state . buffers [ state . depth - 1 ] ;
9595 let entry = buffers [ index ] ;
9696 if ( entry !== undefined && entry . string === value ) {
9797 return entry . pointer ;
@@ -117,13 +117,13 @@ function getStringConversionPointer(owner, value, index) {
117117 return entry . pointer ;
118118}
119119
120- function convertPointerArg ( type , value , owner , index ) {
120+ function convertPointerArg ( type , value , stringState , index ) {
121121 if ( needsNullPointerConversion ( type ) &&
122122 ( value === null || value === undefined ) ) {
123123 return 0n ;
124124 }
125125 if ( hasStringPointerArg ( type , value ) ) {
126- return getStringConversionPointer ( owner , value , index ) ;
126+ return getStringConversionPointer ( stringState , value , index ) ;
127127 }
128128 if ( hasPointerMemoryArg ( type , value ) ) {
129129 return getRawPointer ( value ) ;
@@ -181,7 +181,7 @@ function inheritMetadata(wrapper, rawFn, nargs) {
181181 return wrapper ;
182182}
183183
184- function wrapWithRawPointerConversions ( rawFn , argumentTypes , owner ) {
184+ function wrapWithRawPointerConversions ( rawFn , argumentTypes , _owner ) {
185185 if ( rawFn === undefined || rawFn === null ) {
186186 return rawFn ;
187187 }
@@ -197,6 +197,12 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, owner) {
197197 return rawFn ;
198198 }
199199
200+ const stringState = {
201+ __proto__ : null ,
202+ buffers : [ ] ,
203+ depth : 0 ,
204+ } ;
205+
200206 const nargs = argumentTypes . length ;
201207 let wrapper ;
202208 if ( nargs === 1 && indexes . length === 1 && indexes [ 0 ] === 0 ) {
@@ -214,7 +220,12 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, owner) {
214220 ( arg === null || arg === undefined ) ) {
215221 arg = 0n ;
216222 } else if ( string0 && typeof arg === 'string' ) {
217- arg = getStringConversionPointer ( owner , arg , 0 ) ;
223+ enterStringConversion ( stringState ) ;
224+ try {
225+ return rawFn ( getStringConversionPointer ( stringState , arg , 0 ) ) ;
226+ } finally {
227+ exitStringConversion ( stringState ) ;
228+ }
218229 } else if ( memory0 && ( isArrayBufferView ( arg ) || isAnyArrayBuffer ( arg ) ) ) {
219230 if ( fastBufferInvoke !== undefined ) {
220231 return fastBufferInvoke ( arg ) ;
@@ -232,8 +243,15 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, owner) {
232243 if ( arguments . length !== 2 ) {
233244 throwFFIArgCountError ( 2 , arguments . length ) ;
234245 }
235- return rawFn ( c0 ? convertPointerArg ( t0 , a0 , owner , 0 ) : a0 ,
236- c1 ? convertPointerArg ( t1 , a1 , owner , 1 ) : a1 ) ;
246+ const stringCall = ( c0 && hasStringPointerArg ( t0 , a0 ) ) ||
247+ ( c1 && hasStringPointerArg ( t1 , a1 ) ) ;
248+ if ( stringCall ) enterStringConversion ( stringState ) ;
249+ try {
250+ return rawFn ( c0 ? convertPointerArg ( t0 , a0 , stringState , 0 ) : a0 ,
251+ c1 ? convertPointerArg ( t1 , a1 , stringState , 1 ) : a1 ) ;
252+ } finally {
253+ if ( stringCall ) exitStringConversion ( stringState ) ;
254+ }
237255 } ;
238256 } else if ( nargs === 3 ) {
239257 const c0 = ArrayPrototypeIncludes ( indexes , 0 ) ;
@@ -246,21 +264,42 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, owner) {
246264 if ( arguments . length !== 3 ) {
247265 throwFFIArgCountError ( 3 , arguments . length ) ;
248266 }
249- return rawFn ( c0 ? convertPointerArg ( t0 , a0 , owner , 0 ) : a0 ,
250- c1 ? convertPointerArg ( t1 , a1 , owner , 1 ) : a1 ,
251- c2 ? convertPointerArg ( t2 , a2 , owner , 2 ) : a2 ) ;
267+ const stringCall = ( c0 && hasStringPointerArg ( t0 , a0 ) ) ||
268+ ( c1 && hasStringPointerArg ( t1 , a1 ) ) ||
269+ ( c2 && hasStringPointerArg ( t2 , a2 ) ) ;
270+ if ( stringCall ) enterStringConversion ( stringState ) ;
271+ try {
272+ return rawFn ( c0 ? convertPointerArg ( t0 , a0 , stringState , 0 ) : a0 ,
273+ c1 ? convertPointerArg ( t1 , a1 , stringState , 1 ) : a1 ,
274+ c2 ? convertPointerArg ( t2 , a2 , stringState , 2 ) : a2 ) ;
275+ } finally {
276+ if ( stringCall ) exitStringConversion ( stringState ) ;
277+ }
252278 } ;
253279 } else {
254280 wrapper = function ( ...args ) {
255281 if ( args . length !== nargs ) {
256282 throwFFIArgCountError ( nargs , args . length ) ;
257283 }
284+ let stringCall = false ;
258285 for ( let i = 0 ; i < indexes . length ; i ++ ) {
259286 const index = indexes [ i ] ;
260- args [ index ] = convertPointerArg (
261- argumentTypes [ index ] , args [ index ] , owner , index ) ;
287+ if ( hasStringPointerArg ( argumentTypes [ index ] , args [ index ] ) ) {
288+ stringCall = true ;
289+ break ;
290+ }
291+ }
292+ if ( stringCall ) enterStringConversion ( stringState ) ;
293+ try {
294+ for ( let i = 0 ; i < indexes . length ; i ++ ) {
295+ const index = indexes [ i ] ;
296+ args [ index ] = convertPointerArg (
297+ argumentTypes [ index ] , args [ index ] , stringState , index ) ;
298+ }
299+ return ReflectApply ( rawFn , undefined , args ) ;
300+ } finally {
301+ if ( stringCall ) exitStringConversion ( stringState ) ;
262302 }
263- return ReflectApply ( rawFn , undefined , args ) ;
264303 } ;
265304 }
266305
0 commit comments