Scripting: Allow basic pointer following

This commit is contained in:
Vicki Pfau 2023-01-26 04:03:32 -08:00
parent 6d8060034f
commit fc2b94f9f7
4 changed files with 81 additions and 0 deletions

View File

@ -304,6 +304,8 @@ void mScriptValueWrap(struct mScriptValue* val, struct mScriptValue* out);
struct mScriptValue* mScriptValueUnwrap(struct mScriptValue* val);
const struct mScriptValue* mScriptValueUnwrapConst(const struct mScriptValue* val);
void mScriptValueFollowPointer(struct mScriptValue* ptr, struct mScriptValue* out);
struct mScriptValue* mScriptStringCreateEmpty(size_t size);
struct mScriptValue* mScriptStringCreateFromBytes(const void* string, size_t size);
struct mScriptValue* mScriptStringCreateFromUTF8(const char* string);

View File

@ -693,6 +693,31 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v
return true;
}
}
struct mScriptValue derefPtr;
if (value->type->base == mSCRIPT_TYPE_OPAQUE) {
if (!value->type->details.type) {
return false;
}
mScriptValueFollowPointer(value, &derefPtr);
switch (derefPtr.type->base) {
case mSCRIPT_TYPE_VOID:
case mSCRIPT_TYPE_SINT:
case mSCRIPT_TYPE_UINT:
case mSCRIPT_TYPE_FLOAT:
value = &derefPtr;
break;
case mSCRIPT_TYPE_OBJECT:
value = mScriptValueAlloc(derefPtr.type);
value->value.opaque = derefPtr.value.opaque;
weakref = mScriptContextSetWeakref(luaContext->d.context, value);
needsWeakref = true;
mScriptContextDisownWeakref(luaContext->d.context, weakref);
mScriptValueDeref(value);
break;
default:
return false;
}
}
if (value->type == mSCRIPT_TYPE_MS_WEAKREF) {
weakref = value->value.u32;
value = mScriptContextAccessWeakref(luaContext->d.context, value);

View File

@ -22,6 +22,7 @@ struct Test {
void (*vfn0)(struct Test*);
void (*vfn1)(struct Test*, int);
int32_t (*icfn0)(const struct Test*);
struct Test* next;
};
static int identityInt(int in) {
@ -83,6 +84,7 @@ mSCRIPT_DECLARE_STRUCT_VOID_METHOD(Test, v1, testV1, 1, S32, b);
mSCRIPT_DEFINE_STRUCT(Test)
mSCRIPT_DEFINE_STRUCT_MEMBER(Test, S32, i)
mSCRIPT_DEFINE_STRUCT_MEMBER(Test, PS(Test), next)
mSCRIPT_DEFINE_STRUCT_METHOD(Test, ifn0)
mSCRIPT_DEFINE_STRUCT_METHOD(Test, ifn1)
mSCRIPT_DEFINE_STRUCT_METHOD(Test, icfn0)
@ -726,6 +728,42 @@ M_TEST_DEFINE(callList) {
mScriptContextDeinit(&context);
}
M_TEST_DEFINE(linkedList) {
SETUP_LUA;
struct Test first = {
.i = 1
};
struct Test second = {
.i = 2
};
struct mScriptValue a = mSCRIPT_MAKE_S(Test, &first);
assert_true(lua->setGlobal(lua, "l", &a));
TEST_PROGRAM("assert(l)");
TEST_PROGRAM("assert(l.i == 1)");
TEST_PROGRAM("assert(not l.next)");
first.next = &second;
TEST_PROGRAM("assert(l)");
TEST_PROGRAM("assert(l.i == 1)");
TEST_PROGRAM("assert(l.next)");
TEST_PROGRAM("assert(l.next.i == 2)");
TEST_PROGRAM("assert(not l.next.next)");
TEST_PROGRAM(
"n = l.next\n"
"function readN()\n"
" assert(n)\n"
" assert(n.i or not n.i)\n"
"end\n"
"assert(pcall(readN))\n");
// The weakref stored in `n` gets pruned between executions to avoid stale pointers
TEST_PROGRAM("assert(not pcall(readN))");
mScriptContextDeinit(&context);
}
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
cmocka_unit_test(create),
cmocka_unit_test(loadGood),
@ -744,4 +782,5 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
cmocka_unit_test(tableLookup),
cmocka_unit_test(tableIterate),
cmocka_unit_test(callList),
cmocka_unit_test(linkedList)
)

View File

@ -853,6 +853,21 @@ const struct mScriptValue* mScriptValueUnwrapConst(const struct mScriptValue* va
return NULL;
}
void mScriptValueFollowPointer(struct mScriptValue* ptr, struct mScriptValue* out) {
if (ptr->type->base != mSCRIPT_TYPE_OPAQUE || !ptr->type->details.type) {
return;
}
out->value.opaque = *(void**) ptr->value.opaque;
if (out->value.opaque) {
out->type = ptr->type->details.type;
} else {
out->type = mSCRIPT_TYPE_MS_VOID;
}
out->refs = mSCRIPT_VALUE_UNREF;
out->flags = 0;
}
struct mScriptValue* mScriptStringCreateEmpty(size_t size) {
struct mScriptValue* val = mScriptValueAlloc(mSCRIPT_TYPE_MS_STR);
struct mScriptString* internal = val->value.opaque;