Skip to content

Commit 98a73d7

Browse files
committed
Fix pointer-backed struct marshalling
1 parent da6e518 commit 98a73d7

File tree

3 files changed

+37
-6
lines changed

3 files changed

+37
-6
lines changed

NativeScript/ffi/Interop.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ napi_value interop_alloc(napi_env env, napi_callback_info info) {
994994
int64_t size;
995995
napi_get_value_int64(env, arg, &size);
996996

997-
void* data = malloc(size);
997+
void* data = calloc(1, size);
998998
return Pointer::create(env, data);
999999
}
10001000

NativeScript/ffi/Struct.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@ class StructObject {
3636
void* data;
3737
StructInfo* info;
3838
bool owned;
39+
napi_env env = nullptr;
40+
napi_ref backingRef = nullptr;
3941

40-
StructObject(StructInfo* info, void* data = nullptr);
42+
StructObject(StructInfo* info, void* data = nullptr, napi_env env = nullptr,
43+
napi_value backingValue = nullptr);
4144
StructObject(napi_env env, StructInfo* info, napi_value object,
4245
void* memory = nullptr);
4346

NativeScript/ffi/Struct.mm

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
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

368390
StructObject::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

391416
StructObject::~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

Comments
 (0)