22#include < algorithm>
33#include < cstring>
44#include < vector>
5+ #include " Interop.h"
56#include " ObjCBridge.h"
67#include " TypeConv.h"
78#include " Util.h"
@@ -248,7 +249,23 @@ void StructObject_finalize(napi_env env, void* data, void* hint) {
248249 StructObject* object;
249250
250251 if (argType == napi_object) {
251- object = new StructObject (env, info, arg);
252+ if (Pointer::isInstance (env, arg)) {
253+ Pointer* pointer = Pointer::unwrap (env, arg);
254+ if (pointer == nullptr ) {
255+ napi_throw_error (env, nullptr , " Invalid pointer-backed struct argument" );
256+ return nullptr ;
257+ }
258+ object = new StructObject (info, pointer->data , env, arg);
259+ } else if (Reference::isInstance (env, arg)) {
260+ Reference* reference = Reference::unwrap (env, arg);
261+ if (reference == nullptr || reference->data == nullptr ) {
262+ napi_throw_error (env, nullptr , " Reference is not initialized" );
263+ return nullptr ;
264+ }
265+ object = new StructObject (info, reference->data , env, arg);
266+ } else {
267+ object = new StructObject (env, info, arg);
268+ }
252269 } else {
253270 object = new StructObject (info);
254271 }
@@ -324,8 +341,8 @@ void StructObject_finalize(napi_env env, void* data, void* hint) {
324341
325342 StructObject* structObject = StructObject::unwrap (env, value);
326343 if (structObject != nullptr ) {
327- size_t copySize = std::min ( static_cast < size_t >(info-> size ),
328- static_cast <size_t >(structObject->info ->size ));
344+ size_t copySize =
345+ std::min ( static_cast < size_t >(info-> size ), static_cast <size_t >(structObject->info ->size ));
329346 memcpy (out.data (), structObject->data , copySize);
330347 return true ;
331348 }
@@ -353,20 +370,26 @@ void StructObject_finalize(napi_env env, void* data, void* hint) {
353370 return result;
354371}
355372
356- inline StructObject::StructObject (StructInfo* info, void * data) {
373+ inline StructObject::StructObject (StructInfo* info, void * data, napi_env env,
374+ napi_value backingValue) {
357375 this ->info = info;
376+ this ->env = env;
358377 if (data == nullptr ) {
359378 this ->data = malloc (info->size );
360379 memset (this ->data , 0 , this ->info ->size );
361380 this ->owned = true ;
362381 } else {
363382 this ->data = data;
364383 this ->owned = false ;
384+ if (env != nullptr && backingValue != nullptr ) {
385+ napi_create_reference (env, backingValue, 1 , &this ->backingRef );
386+ }
365387 }
366388}
367389
368390StructObject::StructObject (napi_env env, StructInfo* info, napi_value object, void * memory) {
369391 this ->info = info;
392+ this ->env = env;
370393
371394 if (memory == nullptr ) {
372395 this ->owned = true ;
@@ -376,6 +399,8 @@ void StructObject_finalize(napi_env env, void* data, void* hint) {
376399 this ->data = memory;
377400 }
378401
402+ memset (this ->data , 0 , this ->info ->size );
403+
379404 for (auto & field : info->fields ) {
380405 bool hasProp = false ;
381406 napi_has_named_property (env, object, field.name , &hasProp);
@@ -389,6 +414,9 @@ void StructObject_finalize(napi_env env, void* data, void* hint) {
389414}
390415
391416StructObject::~StructObject () {
417+ if (this ->backingRef != nullptr && this ->env != nullptr ) {
418+ napi_delete_reference (this ->env , this ->backingRef );
419+ }
392420 if (this ->owned ) free (this ->data );
393421}
394422
0 commit comments