Scripting: Allow callbacks to access weakrefs

This commit is contained in:
Vicki Pfau 2023-05-01 04:44:03 -07:00
parent eb26b3c387
commit 44ab21ab35
2 changed files with 61 additions and 6 deletions

View File

@ -235,12 +235,15 @@ void mScriptContextTriggerCallback(struct mScriptContext* context, const char* c
do { do {
struct mScriptFrame frame; struct mScriptFrame frame;
struct mScriptCallbackInfo* info = TableIteratorGetValue(table, &iter); struct mScriptCallbackInfo* info = TableIteratorGetValue(table, &iter);
mScriptFrameInit(&frame); struct mScriptValue* fn = mScriptContextAccessWeakref(context, info->fn);
if (args) { if (fn) {
mScriptListCopy(&frame.arguments, args); mScriptFrameInit(&frame);
if (args) {
mScriptListCopy(&frame.arguments, args);
}
mScriptInvoke(fn, &frame);
mScriptFrameDeinit(&frame);
} }
mScriptInvoke(info->fn, &frame);
mScriptFrameDeinit(&frame);
if (info->oneshot) { if (info->oneshot) {
*UInt32ListAppend(&oneshots) = info->id; *UInt32ListAppend(&oneshots) = info->id;
@ -255,7 +258,15 @@ void mScriptContextTriggerCallback(struct mScriptContext* context, const char* c
} }
static uint32_t mScriptContextAddCallbackInternal(struct mScriptContext* context, const char* callback, struct mScriptValue* fn, bool oneshot) { static uint32_t mScriptContextAddCallbackInternal(struct mScriptContext* context, const char* callback, struct mScriptValue* fn, bool oneshot) {
if (fn->type->base != mSCRIPT_TYPE_FUNCTION) { if (fn->type == mSCRIPT_TYPE_MS_WEAKREF) {
struct mScriptValue* weakref = mScriptContextAccessWeakref(context, fn);
if (!weakref) {
return 0;
}
if (weakref->type->base != mSCRIPT_TYPE_FUNCTION) {
return 0;
}
} else if (fn->type->base != mSCRIPT_TYPE_FUNCTION) {
return 0; return 0;
} }
struct Table* table = HashTableLookup(&context->callbacks, callback); struct Table* table = HashTableLookup(&context->callbacks, callback);

View File

@ -126,9 +126,53 @@ M_TEST_DEFINE(oneshot) {
mScriptContextDeinit(&context); mScriptContextDeinit(&context);
} }
static void _tableIncrement(struct mScriptValue* table) {
assert_non_null(table);
struct mScriptValue* value = mScriptTableLookup(table, &mSCRIPT_MAKE_CHARP("key"));
assert_non_null(value);
assert_ptr_equal(value->type, mSCRIPT_TYPE_MS_S32);
++value->value.s32;
}
mSCRIPT_BIND_VOID_FUNCTION(tableIncrement, _tableIncrement, 1, WTABLE, table);
M_TEST_DEFINE(callbackWeakref) {
SETUP_LUA;
struct mScriptValue* table = mScriptValueAlloc(mSCRIPT_TYPE_MS_TABLE);
struct mScriptList args;
mScriptListInit(&args, 1);
mScriptValueWrap(table, mScriptListAppend(&args));
struct mScriptValue* lambda = mScriptLambdaCreate0(&tableIncrement, &args);
mScriptListDeinit(&args);
struct mScriptValue* weakref = mScriptContextMakeWeakref(&context, lambda);
mScriptContextAddCallback(&context, "test", weakref);
struct mScriptValue* key = mScriptStringCreateFromUTF8("key");
struct mScriptValue* value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S32);
value->value.s32 = 1;
mScriptTableInsert(table, key, value);
mScriptContextTriggerCallback(&context, "test", NULL);
assert_int_equal(value->value.s32, 2);
mScriptContextClearWeakref(&context, weakref->value.u32);
mScriptValueDeref(weakref);
mScriptContextTriggerCallback(&context, "test", NULL);
assert_int_equal(value->value.s32, 2);
mScriptValueDeref(table);
mScriptValueDeref(key);
mScriptValueDeref(value);
mScriptContextDeinit(&context);
}
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptStdlib, M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptStdlib,
cmocka_unit_test(bitMask), cmocka_unit_test(bitMask),
cmocka_unit_test(bitUnmask), cmocka_unit_test(bitUnmask),
cmocka_unit_test(callbacks), cmocka_unit_test(callbacks),
cmocka_unit_test(oneshot), cmocka_unit_test(oneshot),
cmocka_unit_test(callbackWeakref),
) )