More cleanup

This commit is contained in:
2026-05-01 09:43:50 -05:00
parent 0fb3ba2f91
commit 1efa9a9f7b
22 changed files with 230 additions and 280 deletions
@@ -81,14 +81,11 @@ errorret_t assetScriptLoader(assetfile_t *file) {
errorret_t assetScriptLoad(
const char_t *path,
scriptcontext_t *ctx,
jerry_value_t *resultOut
) {
assertNotNull(path, "Script path cannot be NULL");
assertNotNull(ctx, "Script context cannot be NULL");
assetscript_t scriptData;
scriptData.ctx = ctx;
scriptData.resultOut = resultOut;
return assetLoad(path, assetScriptLoader, NULL, &scriptData);
@@ -7,16 +7,10 @@
#pragma once
#include "asset/asset.h"
#include "script/scriptcontext.h"
#define ASSET_SCRIPT_CHUNK_SIZE 1024
typedef struct {
void *nothing;
} assetscriptloaderparams_t;
typedef struct {
scriptcontext_t *ctx;
jerry_value_t *resultOut;
} assetscript_t;
@@ -33,7 +27,6 @@ errorret_t assetScriptLoader(assetfile_t *file);
* Loads a script from the specified path.
*
* @param path Path to the script asset.
* @param ctx Script context to load the script into.
* @param resultOut Optional out-parameter for the script return value.
* Caller must call jerry_value_free() if non-NULL.
* Pass NULL to discard the return value.
@@ -41,6 +34,5 @@ errorret_t assetScriptLoader(assetfile_t *file);
*/
errorret_t assetScriptLoad(
const char_t *path,
scriptcontext_t *ctx,
jerry_value_t *resultOut
);
+1 -1
View File
@@ -60,7 +60,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
/* Run the init script. */
consolePrint("Engine initialized");
errorChain(scriptContextExecFile(&SCRIPT_MANAGER.mainContext, "init.js", NULL));
errorChain(scriptManagerExecFile("init.js", NULL));
errorOk();
}
+8 -5
View File
@@ -80,7 +80,7 @@ eventsub_t eventSubscribe(
eventsub_t eventSubscribeScriptContext(
event_t *event,
scriptcontext_t *context,
scriptmanager_t *context,
jerry_value_t funcValue
) {
assertNotNull(context, "Script context cannot be NULL");
@@ -94,7 +94,7 @@ eventsub_t eventSubscribeScriptContext(
break;
}
i++;
} while(i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS);
} while(i < SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS);
if(!alreadySubbed) {
i = 0;
@@ -104,10 +104,10 @@ eventsub_t eventSubscribeScriptContext(
break;
}
i++;
} while(i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS);
} while(i < SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS);
assertTrue(
i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS,
i < SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS,
"Script context has reached maximum event subscriptions"
);
}
@@ -149,7 +149,10 @@ void eventUnsubscribe(event_t *event, const eventsub_t id) {
} while(index < event->listenerCount);
}
void eventUnsubscribeScriptContext(event_t *event, const scriptcontext_t *ctx) {
void eventUnsubscribeScriptContext(
event_t *event,
const scriptmanager_t *ctx
) {
assertNotNull(event, "Event cannot be NULL");
assertNotNull(ctx, "Script context cannot be NULL");
+5 -2
View File
@@ -83,7 +83,7 @@ eventsub_t eventSubscribe(
*/
eventsub_t eventSubscribeScriptContext(
event_t *event,
scriptcontext_t *context,
scriptmanager_t *context,
jerry_value_t funcValue
);
@@ -101,7 +101,10 @@ void eventUnsubscribe(event_t *event, const eventsub_t subscription);
* @param event The event to unsubscribe from.
* @param context The script context whose listeners should be removed.
*/
void eventUnsubscribeScriptContext(event_t *event, const scriptcontext_t *ctx);
void eventUnsubscribeScriptContext(
event_t *event,
const scriptmanager_t *ctx
);
/**
* Invoke an event, calling all subscribed listeners. Optionally provide event
+2 -2
View File
@@ -7,7 +7,7 @@
#pragma once
#include "eventcallback.h"
#include "script/scriptcontext.h"
#include "script/scriptmanager.h"
typedef enum {
EVENT_TYPE_C = 0,
@@ -15,7 +15,7 @@ typedef enum {
} eventtype_t;
typedef struct {
scriptcontext_t *context;
scriptmanager_t *context;
jerry_value_t funcValue;
} eventscript_t;
+1 -3
View File
@@ -187,9 +187,7 @@ errorret_t sceneSetImmediate(const char_t *scene) {
if(scene != NULL) {
jerry_value_t sceneClass = SCENE_SCRIPT_REF_NONE;
errorChain(scriptContextExecFile(
&SCRIPT_MANAGER.mainContext, scene, &sceneClass
));
errorChain(scriptManagerExecFile(scene, &sceneClass));
if(!jerry_value_is_function(sceneClass)) {
if(sceneClass != SCENE_SCRIPT_REF_NONE) jerry_value_free(sceneClass);
+1 -1
View File
@@ -6,7 +6,7 @@
*/
#pragma once
#include "script/scriptcontext.h"
#include "script/scriptmanager.h"
#include "asset/assetfile.h"
#include "event/event.h"
-1
View File
@@ -7,7 +7,6 @@
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
scriptmanager.c
scriptcontext.c
scriptproto.c
)
@@ -0,0 +1,67 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/scriptproto.h"
#include "console/console.h"
static scriptproto_t MODULE_CONSOLE_PROTO;
moduleBaseFunction(moduleConsolePrint) {
char_t buf[512];
char_t msg[4096];
size_t msgLen = 0;
for(jerry_length_t i = 0; i < argc; ++i) {
jerry_value_t strVal = jerry_value_to_string(args[i]);
moduleBaseToString(strVal, buf, sizeof(buf));
jerry_value_free(strVal);
size_t partLen = strlen(buf);
if(msgLen + partLen + 1 < sizeof(msg)) {
stringCopy(msg + msgLen, buf, sizeof(msg) - msgLen);
msgLen += partLen;
}
if(i + 1 < argc && msgLen + 1 < sizeof(msg)) {
msg[msgLen++] = '\t';
msg[msgLen] = '\0';
}
}
consolePrint("%s", msg);
return jerry_undefined();
}
moduleBaseFunction(moduleConsoleGetVisible) {
return jerry_boolean(consoleVarGetBool("console", false));
}
moduleBaseFunction(moduleConsoleSetVisible) {
moduleBaseRequireArgs(1);
if(!jerry_value_is_boolean(args[0])) {
return moduleBaseThrow("Console.visible: expected boolean");
}
consoleVarSetBool("console", jerry_value_is_true(args[0]));
return jerry_undefined();
}
static void moduleConsole(void) {
scriptProtoInit(
&MODULE_CONSOLE_PROTO, "Console",
sizeof(uint8_t), NULL
);
scriptProtoDefineStaticFunc(
&MODULE_CONSOLE_PROTO, "print", moduleConsolePrint
);
scriptProtoDefineStaticProp(
&MODULE_CONSOLE_PROTO, "visible",
moduleConsoleGetVisible, moduleConsoleSetVisible
);
}
@@ -144,4 +144,4 @@ static void moduleEntityPOSITION(void) {
&MODULE_ENTITY_POSITION_PROTO, "lookAt",
moduleEntityPositionLookAt
);
}
}
+1 -15
View File
@@ -114,17 +114,6 @@ moduleBaseFunction(moduleInputAxis2D) {
return moduleVec2Push(result);
}
moduleBaseFunction(moduleInputGetEventAction) {
moduleBaseRequireArgs(1);
const inputevent_t *event = (const inputevent_t *)(
moduleBaseUnwrapPointer(args[0])
);
if(event == NULL) {
return moduleBaseThrow("Input.getEventAction: expected input event object");
}
return jerry_number(event->action);
}
static void moduleInput(void) {
moduleBaseEval(INPUT_ACTION_SCRIPT);
@@ -169,7 +158,4 @@ static void moduleInput(void) {
scriptProtoDefineStaticFunc(
&MODULE_INPUT_PROTO, "axis2D", moduleInputAxis2D
);
scriptProtoDefineStaticFunc(
&MODULE_INPUT_PROTO, "getEventAction", moduleInputGetEventAction
);
}
}
+4 -2
View File
@@ -6,7 +6,7 @@
*/
#pragma once
#include "script/module/script/modulescript.h"
#include "script/module/script/moduleinclude.h"
#include "script/module/math/modulemath.h"
#include "script/module/entity/moduleentity.h"
#include "script/module/input/moduleinput.h"
@@ -15,9 +15,10 @@
#include "script/module/display/modulecolor.h"
#include "script/module/display/modulescreen.h"
#include "script/module/scene/modulescene.h"
#include "script/module/console/moduleconsole.h"
static void moduleRegister(void) {
moduleScript();
moduleInclude();
moduleMath();
moduleEntity();
moduleInput();
@@ -26,4 +27,5 @@ static void moduleRegister(void) {
moduleColor();
moduleScreen();
moduleScene();
moduleConsole();
}
+16 -3
View File
@@ -6,7 +6,7 @@
*/
#pragma once
#include "script/scriptcontext.h"
#include "script/scriptmanager.h"
#include "assert/assert.h"
#include "util/string.h"
#include "util/memory.h"
@@ -257,8 +257,6 @@ static void moduleBaseCreateGlobalObject(
} \
} while(0)
/* JS_PTR_NATIVE_INFO is declared in scriptcontext.h and defined in
scriptcontext.c so all TUs share a single address for native-ptr lookups. */
/**
* Set a global numeric constant.
@@ -410,3 +408,18 @@ static inline void moduleBaseExceptionMessage(
jerry_value_free(errStr);
jerry_value_free(errVal);
}
/**
* Define a named global function.
*
* @param name The name of the function as seen in JavaScript.
* @param fn The C handler function for the method.
*/
static inline void moduleBaseDefineGlobalMethod(
const char_t *name,
jerry_external_handler_t fn
) {
jerry_value_t global = jerry_current_realm();
moduleBaseDefineMethod(global, name, fn);
jerry_value_free(global);
}
+2 -5
View File
@@ -12,7 +12,6 @@
static scriptproto_t MODULE_SCENE_PROTO;
// Default no-op lifecycle methods — JS scene instances override these.
moduleBaseFunction(moduleSceneDefaultUpdate) {
return jerry_undefined();
}
@@ -21,9 +20,7 @@ moduleBaseFunction(moduleSceneDefaultDispose) {
return jerry_undefined();
}
// Constructor — returns undefined so JerryScript uses `this`, which already
// has Scene.prototype set. Scenes carry no C struct; all state lives in JS.
moduleBaseFunction(moduleSceneConstructor) {
moduleBaseFunction(moduleSceneDefaultConstructor) {
return jerry_undefined();
}
@@ -96,7 +93,7 @@ static void moduleScene(void) {
&MODULE_SCENE_PROTO,
"Scene",
sizeof(uint8_t),
moduleSceneConstructor
moduleSceneDefaultConstructor
);
scriptProtoDefineFunc(
@@ -8,7 +8,7 @@
#pragma once
#include "script/module/modulebase.h"
moduleBaseFunction(moduleInclude) {
moduleBaseFunction(moduleIncludeInclude) {
if(argc < 1 || !jerry_value_is_string(args[0])) {
return moduleBaseThrow("Expected string filename");
}
@@ -38,7 +38,7 @@ moduleBaseFunction(moduleInclude) {
jerry_value_free(undef);
jerry_value_t result = 0;
errorret_t err = scriptContextExecFile(scriptContextCurrent, buffer, &result);
errorret_t err = scriptManagerExecFile(buffer, &result);
if(result != 0) jerry_value_free(result);
// Capture whatever the module assigned to 'module', then restore the
@@ -57,3 +57,7 @@ moduleBaseFunction(moduleInclude) {
return moduleVal;
}
static void moduleInclude(void) {
moduleBaseDefineGlobalMethod("include", moduleIncludeInclude);
}
@@ -1,42 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/module/script/moduleinclude.h"
#include "console/console.h"
moduleBaseFunction(moduleScriptPrint) {
char_t buf[512];
char_t msg[4096];
size_t msgLen = 0;
for(jerry_length_t i = 0; i < argc; ++i) {
jerry_value_t strVal = jerry_value_to_string(args[i]);
moduleBaseToString(strVal, buf, sizeof(buf));
jerry_value_free(strVal);
size_t partLen = strlen(buf);
if(msgLen + partLen + 1 < sizeof(msg)) {
stringCopy(msg + msgLen, buf, sizeof(msg) - msgLen);
msgLen += partLen;
}
if(i + 1 < argc && msgLen + 1 < sizeof(msg)) {
msg[msgLen++] = '\t';
msg[msgLen] = '\0';
}
}
consolePrint("%s", msg);
return jerry_undefined();
}
static void moduleScript(void) {
moduleBaseFunctionRegister("print", moduleScriptPrint);
moduleBaseFunctionRegister("include", moduleInclude);
}
-94
View File
@@ -1,94 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "scriptcontext.h"
#include "assert/assert.h"
#include "asset/asset.h"
#include "util/memory.h"
#include "event/event.h"
#include "asset/loader/script/assetscriptloader.h"
#include "script/module/module.h"
#ifdef SCRIPT_GAME_INIT
#include "script/scriptgame.h"
#endif
scriptcontext_t *scriptContextCurrent = NULL;
const jerry_object_native_info_t JS_PTR_NATIVE_INFO = {
.free_cb = NULL,
.number_of_references = 0,
.offset_of_references = 0
};
errorret_t scriptContextInit(scriptcontext_t *context) {
assertNotNull(context, "Script context cannot be NULL");
memoryZero(context, sizeof(scriptcontext_t));
jerry_init(JERRY_INIT_EMPTY);
scriptContextCurrent = context;
moduleRegister();
#ifdef SCRIPT_GAME_INIT
SCRIPT_GAME_INIT();
#endif
errorOk();
}
errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script) {
assertNotNull(context, "Script context cannot be NULL");
assertNotNull(script, "Script cannot be NULL");
jerry_value_t result = jerry_eval(
(const jerry_char_t *)script,
strlen(script),
JERRY_PARSE_NO_OPTS
);
if(jerry_value_is_exception(result)) {
jerry_value_t errVal = jerry_exception_value(result, false);
jerry_value_t errStr = jerry_value_to_string(errVal);
char_t buf[256];
jerry_size_t len = jerry_string_to_buffer(
errStr, JERRY_ENCODING_UTF8, (jerry_char_t *)buf, sizeof(buf) - 1
);
buf[len] = '\0';
jerry_value_free(errStr);
jerry_value_free(errVal);
jerry_value_free(result);
errorThrow("Failed to execute script: %s", buf);
}
jerry_value_free(result);
errorOk();
}
errorret_t scriptContextExecFile(
scriptcontext_t *ctx,
const char_t *fname,
jerry_value_t *resultOut
) {
assertNotNull(ctx, "Script context cannot be NULL");
assertNotNull(fname, "Filename cannot be NULL");
return assetScriptLoad(fname, ctx, resultOut);
}
void scriptContextDispose(scriptcontext_t *context) {
assertNotNull(context, "Script context cannot be NULL");
for(uint8_t i = 0; i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS; i++) {
event_t *event = context->subscribedEvents[i];
if(event == NULL) continue;
eventUnsubscribeScriptContext(event, context);
}
jerry_cleanup();
scriptContextCurrent = NULL;
}
-68
View File
@@ -1,68 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/error.h"
#include "scriptvalue.h"
typedef struct event_s event_t;
#define SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS 64
typedef struct scriptcontext_s {
event_t* subscribedEvents[SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS];
} scriptcontext_t;
/** Points to the currently active script context. Set by scriptContextInit. */
extern scriptcontext_t *scriptContextCurrent;
/**
* Singleton native-info tag for engine-owned C pointers wrapped in JS objects.
* A single global instance ensures jerry_object_get_native_ptr() matches across
* all compilation units (including event.c and module headers).
*/
extern const jerry_object_native_info_t JS_PTR_NATIVE_INFO;
/**
* Initialize a script context.
*
* @param context The script context to initialize.
* @return The error return value.
*/
errorret_t scriptContextInit(scriptcontext_t *context);
/**
* Execute a script string within a script context.
*
* @param context The script context to use.
* @param script The JS source to execute.
* @return The error return value.
*/
errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script);
/**
* Execute a script from a file within a script context.
*
* @param ctx The script context to use.
* @param fname The filename of the script to execute.
* @param result Optional out-parameter for the script's return value.
* Caller must call jerry_value_free() on it when done.
* Pass NULL to discard the return value.
* @return The error return value.
*/
errorret_t scriptContextExecFile(
scriptcontext_t *ctx,
const char_t *fname,
jerry_value_t *result
);
/**
* Dispose of a script context.
*
* @param context The script context to dispose of.
*/
void scriptContextDispose(scriptcontext_t *context);
+69 -9
View File
@@ -1,26 +1,86 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "scriptmanager.h"
#include "util/memory.h"
#include "assert/assert.h"
#include "asset/asset.h"
#include "util/memory.h"
#include "event/event.h"
#include "asset/loader/script/assetscriptloader.h"
#include "script/module/module.h"
#ifdef SCRIPT_GAME_INIT
#include "script/scriptgame.h"
#endif
scriptmanager_t SCRIPT_MANAGER;
errorret_t scriptManagerInit() {
const jerry_object_native_info_t JS_PTR_NATIVE_INFO = {
.free_cb = NULL,
.number_of_references = 0,
.offset_of_references = 0
};
errorret_t scriptManagerInit(void) {
memoryZero(&SCRIPT_MANAGER, sizeof(scriptmanager_t));
errorChain(scriptContextInit(&SCRIPT_MANAGER.mainContext));
jerry_init(JERRY_INIT_EMPTY);
moduleRegister();
#ifdef SCRIPT_GAME_INIT
SCRIPT_GAME_INIT();
#endif
errorOk();
}
errorret_t scriptManagerDispose() {
scriptContextDispose(&SCRIPT_MANAGER.mainContext);
errorret_t scriptManagerExec(const char_t *script) {
assertNotNull(script, "Script cannot be NULL");
jerry_value_t result = jerry_eval(
(const jerry_char_t *)script,
strlen(script),
JERRY_PARSE_NO_OPTS
);
if(jerry_value_is_exception(result)) {
jerry_value_t errVal = jerry_exception_value(result, false);
jerry_value_t errStr = jerry_value_to_string(errVal);
char_t buf[256];
jerry_size_t len = jerry_string_to_buffer(
errStr, JERRY_ENCODING_UTF8, (jerry_char_t *)buf, sizeof(buf) - 1
);
buf[len] = '\0';
jerry_value_free(errStr);
jerry_value_free(errVal);
jerry_value_free(result);
errorThrow("Failed to execute script: %s", buf);
}
jerry_value_free(result);
errorOk();
}
}
errorret_t scriptManagerExecFile(
const char_t *fname,
jerry_value_t *resultOut
) {
assertNotNull(fname, "Filename cannot be NULL");
return assetScriptLoad(fname, resultOut);
}
errorret_t scriptManagerDispose(void) {
for(uint8_t i = 0; i < SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS; i++) {
event_t *event = SCRIPT_MANAGER.subscribedEvents[i];
if(event == NULL) continue;
eventUnsubscribeScriptContext(event, &SCRIPT_MANAGER);
}
jerry_cleanup();
errorOk();
}
+43 -10
View File
@@ -1,30 +1,63 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/error.h"
#include "scriptcontext.h"
#include "scriptvalue.h"
typedef struct scriptmanager_s {
scriptcontext_t mainContext;
typedef struct event_s event_t;
#define SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS 64
typedef struct {
event_t *subscribedEvents[SCRIPT_MANAGER_MAX_EVENT_SUBSCRIPTIONS];
} scriptmanager_t;
extern scriptmanager_t SCRIPT_MANAGER;
/**
* Initialize the script manager.
*
* Singleton native-info tag for engine-owned C pointers wrapped in JS objects.
* A single global instance ensures jerry_object_get_native_ptr() matches across
* all compilation units (including event.c and module headers).
*/
extern const jerry_object_native_info_t JS_PTR_NATIVE_INFO;
/**
* Initialize the script manager (and the underlying JerryScript context).
*
* @return The error return value.
*/
errorret_t scriptManagerInit();
errorret_t scriptManagerInit(void);
/**
* Execute a JS string in the active script context.
*
* @param script The JS source to execute.
* @return The error return value.
*/
errorret_t scriptManagerExec(const char_t *script);
/**
* Execute a JS file in the active script context.
*
* @param fname The filename of the script to execute.
* @param result Optional out-parameter for the script's return value.
* Caller must call jerry_value_free() on it when done.
* Pass NULL to discard the return value.
* @return The error return value.
*/
errorret_t scriptManagerExecFile(
const char_t *fname,
jerry_value_t *result
);
/**
* Dispose of the script manager.
*
*
* @return The error return value.
*/
errorret_t scriptManagerDispose();
errorret_t scriptManagerDispose(void);
@@ -6,8 +6,8 @@
*/
#pragma once
#include "script/scriptcontext.h"
#include "script/scriptmanager.h"
void modulePlatformVita(scriptcontext_t *ctx) {
scriptContextExec(ctx, "VITA = true\n");
void modulePlatformVita(void) {
scriptManagerExec("VITA = true\n");
}