mirror of https://github.com/mgba-emu/mgba.git
Scripting: Allow weakrefs to be marked for auto-collection
This commit is contained in:
parent
58089fb334
commit
b5f600c0c5
|
@ -89,6 +89,7 @@ uint32_t mScriptContextSetWeakref(struct mScriptContext*, struct mScriptValue* v
|
|||
struct mScriptValue* mScriptContextMakeWeakref(struct mScriptContext*, struct mScriptValue* value);
|
||||
struct mScriptValue* mScriptContextAccessWeakref(struct mScriptContext*, struct mScriptValue* value);
|
||||
void mScriptContextClearWeakref(struct mScriptContext*, uint32_t weakref);
|
||||
void mScriptContextDisownWeakref(struct mScriptContext*, uint32_t weakref);
|
||||
|
||||
void mScriptContextAttachStdlib(struct mScriptContext* context);
|
||||
void mScriptContextAttachSocket(struct mScriptContext* context);
|
||||
|
|
|
@ -12,8 +12,9 @@ set(TEST_FILES
|
|||
if(USE_LUA)
|
||||
list(APPEND SOURCE_FILES engines/lua.c)
|
||||
list(APPEND TEST_FILES
|
||||
test/stdlib.c
|
||||
test/lua.c)
|
||||
test/context.c
|
||||
test/lua.c
|
||||
test/stdlib.c)
|
||||
endif()
|
||||
|
||||
source_group("Scripting" FILES ${SOURCE_FILES})
|
||||
|
|
|
@ -71,8 +71,8 @@ void mScriptContextInit(struct mScriptContext* context) {
|
|||
|
||||
void mScriptContextDeinit(struct mScriptContext* context) {
|
||||
HashTableDeinit(&context->rootScope);
|
||||
HashTableDeinit(&context->weakrefs);
|
||||
mScriptContextDrainPool(context);
|
||||
HashTableDeinit(&context->weakrefs);
|
||||
mScriptListDeinit(&context->refPool);
|
||||
HashTableDeinit(&context->callbacks);
|
||||
TableDeinit(&context->callbackId);
|
||||
|
@ -102,9 +102,12 @@ void mScriptContextFillPool(struct mScriptContext* context, struct mScriptValue*
|
|||
void mScriptContextDrainPool(struct mScriptContext* context) {
|
||||
size_t i;
|
||||
for (i = 0; i < mScriptListSize(&context->refPool); ++i) {
|
||||
struct mScriptValue* value = mScriptValueUnwrap(mScriptListGetPointer(&context->refPool, i));
|
||||
if (value) {
|
||||
struct mScriptValue* value = mScriptListGetPointer(&context->refPool, i);
|
||||
if (value->type->base == mSCRIPT_TYPE_WRAPPER) {
|
||||
value = mScriptValueUnwrap(value);
|
||||
mScriptValueDeref(value);
|
||||
} else if (value->type == mSCRIPT_TYPE_MS_WEAKREF) {
|
||||
mScriptContextClearWeakref(context, value->value.u32);
|
||||
}
|
||||
}
|
||||
mScriptListClear(&context->refPool);
|
||||
|
@ -201,6 +204,13 @@ void mScriptContextClearWeakref(struct mScriptContext* context, uint32_t weakref
|
|||
TableRemove(&context->weakrefs, weakref);
|
||||
}
|
||||
|
||||
void mScriptContextDisownWeakref(struct mScriptContext* context, uint32_t weakref) {
|
||||
struct mScriptValue* poolEntry = mScriptListAppend(&context->refPool);
|
||||
poolEntry->type = mSCRIPT_TYPE_MS_WEAKREF;
|
||||
poolEntry->value.u32 = weakref;
|
||||
poolEntry->refs = mSCRIPT_VALUE_UNREF;
|
||||
}
|
||||
|
||||
void mScriptContextTriggerCallback(struct mScriptContext* context, const char* callback) {
|
||||
struct mScriptValue* list = HashTableLookup(&context->callbacks, callback);
|
||||
if (!list) {
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/* Copyright (c) 2013-2023 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "util/test/suite.h"
|
||||
|
||||
#include <mgba/script/context.h>
|
||||
#include <mgba/script/macros.h>
|
||||
#include <mgba/script/types.h>
|
||||
|
||||
M_TEST_DEFINE(weakrefBasic) {
|
||||
struct mScriptContext context;
|
||||
mScriptContextInit(&context);
|
||||
|
||||
struct mScriptValue weakref = mSCRIPT_VAL(WEAKREF, 1);
|
||||
struct mScriptValue fakeVal = mSCRIPT_S32(0x7E57CA5E);
|
||||
struct mScriptValue* val;
|
||||
|
||||
assert_int_equal(TableSize(&context.weakrefs), 0);
|
||||
assert_null(TableLookup(&context.weakrefs, 1));
|
||||
assert_int_equal(context.nextWeakref, 1);
|
||||
assert_null(mScriptContextAccessWeakref(&context, &weakref));
|
||||
|
||||
assert_int_equal(mScriptContextSetWeakref(&context, &fakeVal), 1);
|
||||
assert_int_equal(context.nextWeakref, 2);
|
||||
assert_int_equal(TableSize(&context.weakrefs), 1);
|
||||
val = mScriptContextAccessWeakref(&context, &weakref);
|
||||
assert_non_null(val);
|
||||
assert_int_equal(val->value.u32, 0x7E57CA5E);
|
||||
|
||||
mScriptContextClearWeakref(&context, 1);
|
||||
|
||||
assert_int_equal(TableSize(&context.weakrefs), 0);
|
||||
assert_null(TableLookup(&context.weakrefs, 1));
|
||||
assert_int_equal(context.nextWeakref, 2);
|
||||
assert_null(mScriptContextAccessWeakref(&context, &weakref));
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(drainPool) {
|
||||
struct mScriptContext context;
|
||||
mScriptContextInit(&context);
|
||||
|
||||
assert_int_equal(mScriptListSize(&context.refPool), 0);
|
||||
|
||||
struct mScriptValue fakeVal = mSCRIPT_CHARP("foo");
|
||||
fakeVal.refs = 2;
|
||||
|
||||
mScriptContextFillPool(&context, &fakeVal);
|
||||
assert_int_equal(mScriptListSize(&context.refPool), 1);
|
||||
assert_int_equal(fakeVal.refs, 2);
|
||||
|
||||
mScriptContextDrainPool(&context);
|
||||
assert_int_equal(mScriptListSize(&context.refPool), 0);
|
||||
assert_int_equal(fakeVal.refs, 1);
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(disownWeakref) {
|
||||
struct mScriptContext context;
|
||||
mScriptContextInit(&context);
|
||||
|
||||
struct mScriptValue weakref = mSCRIPT_VAL(WEAKREF, 1);
|
||||
struct mScriptValue fakeVal = mSCRIPT_S32(0x7E57CA5E);
|
||||
struct mScriptValue* val;
|
||||
|
||||
assert_int_equal(mScriptListSize(&context.refPool), 0);
|
||||
assert_int_equal(TableSize(&context.weakrefs), 0);
|
||||
assert_null(TableLookup(&context.weakrefs, 1));
|
||||
assert_int_equal(context.nextWeakref, 1);
|
||||
assert_null(mScriptContextAccessWeakref(&context, &weakref));
|
||||
|
||||
assert_int_equal(mScriptContextSetWeakref(&context, &fakeVal), 1);
|
||||
assert_int_equal(TableSize(&context.weakrefs), 1);
|
||||
assert_int_equal(context.nextWeakref, 2);
|
||||
val = mScriptContextAccessWeakref(&context, &weakref);
|
||||
assert_non_null(val);
|
||||
assert_int_equal(val->value.u32, 0x7E57CA5E);
|
||||
|
||||
mScriptContextDisownWeakref(&context, 1);
|
||||
assert_int_equal(mScriptListSize(&context.refPool), 1);
|
||||
assert_int_equal(TableSize(&context.weakrefs), 1);
|
||||
val = mScriptContextAccessWeakref(&context, &weakref);
|
||||
assert_non_null(val);
|
||||
assert_int_equal(val->value.u32, 0x7E57CA5E);
|
||||
|
||||
mScriptContextDrainPool(&context);
|
||||
assert_int_equal(mScriptListSize(&context.refPool), 0);
|
||||
assert_int_equal(TableSize(&context.weakrefs), 0);
|
||||
assert_null(TableLookup(&context.weakrefs, 1));
|
||||
assert_null(mScriptContextAccessWeakref(&context, &weakref));
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE(mScript,
|
||||
cmocka_unit_test(weakrefBasic),
|
||||
cmocka_unit_test(drainPool),
|
||||
cmocka_unit_test(disownWeakref),
|
||||
)
|
Loading…
Reference in New Issue