From 1efa9a9f7b98ee235545274c75c93515e09efae5 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 1 May 2026 09:43:50 -0500 Subject: [PATCH] More cleanup --- .../asset/loader/script/assetscriptloader.c | 3 - .../asset/loader/script/assetscriptloader.h | 8 -- src/dusk/engine/engine.c | 2 +- src/dusk/event/event.c | 13 ++- src/dusk/event/event.h | 7 +- src/dusk/event/eventuser.h | 4 +- src/dusk/scene/scene.c | 4 +- src/dusk/scene/scene.h | 2 +- src/dusk/script/CMakeLists.txt | 1 - .../script/module/console/moduleconsole.h | 67 +++++++++++++ .../entity/component/moduleentityposition.h | 2 +- src/dusk/script/module/input/moduleinput.h | 16 +--- src/dusk/script/module/module.h | 6 +- src/dusk/script/module/modulebase.h | 19 +++- src/dusk/script/module/scene/modulescene.h | 7 +- src/dusk/script/module/script/moduleinclude.h | 8 +- src/dusk/script/module/script/modulescript.h | 42 --------- src/dusk/script/scriptcontext.c | 94 ------------------- src/dusk/script/scriptcontext.h | 68 -------------- src/dusk/script/scriptmanager.c | 78 +++++++++++++-- src/dusk/script/scriptmanager.h | 53 +++++++++-- .../script/module/moduleplatformvita.h | 6 +- 22 files changed, 230 insertions(+), 280 deletions(-) create mode 100644 src/dusk/script/module/console/moduleconsole.h delete mode 100644 src/dusk/script/module/script/modulescript.h delete mode 100644 src/dusk/script/scriptcontext.c delete mode 100644 src/dusk/script/scriptcontext.h diff --git a/src/dusk/asset/loader/script/assetscriptloader.c b/src/dusk/asset/loader/script/assetscriptloader.c index 6637e817..88b6f574 100644 --- a/src/dusk/asset/loader/script/assetscriptloader.c +++ b/src/dusk/asset/loader/script/assetscriptloader.c @@ -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); diff --git a/src/dusk/asset/loader/script/assetscriptloader.h b/src/dusk/asset/loader/script/assetscriptloader.h index 3abfe63b..aafd5275 100644 --- a/src/dusk/asset/loader/script/assetscriptloader.h +++ b/src/dusk/asset/loader/script/assetscriptloader.h @@ -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 ); diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index ab743b50..4bd4cc55 100644 --- a/src/dusk/engine/engine.c +++ b/src/dusk/engine/engine.c @@ -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(); } diff --git a/src/dusk/event/event.c b/src/dusk/event/event.c index c289f8ba..52d222ef 100644 --- a/src/dusk/event/event.c +++ b/src/dusk/event/event.c @@ -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"); diff --git a/src/dusk/event/event.h b/src/dusk/event/event.h index 56ab4d92..f7825572 100644 --- a/src/dusk/event/event.h +++ b/src/dusk/event/event.h @@ -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 diff --git a/src/dusk/event/eventuser.h b/src/dusk/event/eventuser.h index f61cd970..a142a94d 100644 --- a/src/dusk/event/eventuser.h +++ b/src/dusk/event/eventuser.h @@ -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; diff --git a/src/dusk/scene/scene.c b/src/dusk/scene/scene.c index a33734e8..4f4ef63f 100644 --- a/src/dusk/scene/scene.c +++ b/src/dusk/scene/scene.c @@ -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); diff --git a/src/dusk/scene/scene.h b/src/dusk/scene/scene.h index 7c0a9233..034cbfb3 100644 --- a/src/dusk/scene/scene.h +++ b/src/dusk/scene/scene.h @@ -6,7 +6,7 @@ */ #pragma once -#include "script/scriptcontext.h" +#include "script/scriptmanager.h" #include "asset/assetfile.h" #include "event/event.h" diff --git a/src/dusk/script/CMakeLists.txt b/src/dusk/script/CMakeLists.txt index dd9a86da..751142f2 100644 --- a/src/dusk/script/CMakeLists.txt +++ b/src/dusk/script/CMakeLists.txt @@ -7,7 +7,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC scriptmanager.c - scriptcontext.c scriptproto.c ) diff --git a/src/dusk/script/module/console/moduleconsole.h b/src/dusk/script/module/console/moduleconsole.h new file mode 100644 index 00000000..e1057dbd --- /dev/null +++ b/src/dusk/script/module/console/moduleconsole.h @@ -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 + ); +} diff --git a/src/dusk/script/module/entity/component/moduleentityposition.h b/src/dusk/script/module/entity/component/moduleentityposition.h index 149375cd..693f7eb7 100644 --- a/src/dusk/script/module/entity/component/moduleentityposition.h +++ b/src/dusk/script/module/entity/component/moduleentityposition.h @@ -144,4 +144,4 @@ static void moduleEntityPOSITION(void) { &MODULE_ENTITY_POSITION_PROTO, "lookAt", moduleEntityPositionLookAt ); -} +} \ No newline at end of file diff --git a/src/dusk/script/module/input/moduleinput.h b/src/dusk/script/module/input/moduleinput.h index 5d3ea443..7923b8a2 100644 --- a/src/dusk/script/module/input/moduleinput.h +++ b/src/dusk/script/module/input/moduleinput.h @@ -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 - ); -} +} \ No newline at end of file diff --git a/src/dusk/script/module/module.h b/src/dusk/script/module/module.h index 03a2680b..8776c654 100644 --- a/src/dusk/script/module/module.h +++ b/src/dusk/script/module/module.h @@ -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(); } diff --git a/src/dusk/script/module/modulebase.h b/src/dusk/script/module/modulebase.h index 627a9bfb..d6cf90cf 100644 --- a/src/dusk/script/module/modulebase.h +++ b/src/dusk/script/module/modulebase.h @@ -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); +} \ No newline at end of file diff --git a/src/dusk/script/module/scene/modulescene.h b/src/dusk/script/module/scene/modulescene.h index 89999a4e..a97dffd3 100644 --- a/src/dusk/script/module/scene/modulescene.h +++ b/src/dusk/script/module/scene/modulescene.h @@ -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( diff --git a/src/dusk/script/module/script/moduleinclude.h b/src/dusk/script/module/script/moduleinclude.h index 9b04920b..2ae49ce0 100644 --- a/src/dusk/script/module/script/moduleinclude.h +++ b/src/dusk/script/module/script/moduleinclude.h @@ -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); +} \ No newline at end of file diff --git a/src/dusk/script/module/script/modulescript.h b/src/dusk/script/module/script/modulescript.h deleted file mode 100644 index 7d20281c..00000000 --- a/src/dusk/script/module/script/modulescript.h +++ /dev/null @@ -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); -} diff --git a/src/dusk/script/scriptcontext.c b/src/dusk/script/scriptcontext.c deleted file mode 100644 index 1ac561e7..00000000 --- a/src/dusk/script/scriptcontext.c +++ /dev/null @@ -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; -} diff --git a/src/dusk/script/scriptcontext.h b/src/dusk/script/scriptcontext.h deleted file mode 100644 index 4b78cb71..00000000 --- a/src/dusk/script/scriptcontext.h +++ /dev/null @@ -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); diff --git a/src/dusk/script/scriptmanager.c b/src/dusk/script/scriptmanager.c index 9606f411..5ba512ac 100644 --- a/src/dusk/script/scriptmanager.c +++ b/src/dusk/script/scriptmanager.c @@ -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(); -} \ No newline at end of file +} + +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(); +} diff --git a/src/dusk/script/scriptmanager.h b/src/dusk/script/scriptmanager.h index 04ebe8e3..d5e47584 100644 --- a/src/dusk/script/scriptmanager.h +++ b/src/dusk/script/scriptmanager.h @@ -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(); \ No newline at end of file +errorret_t scriptManagerDispose(void); diff --git a/src/duskvita/script/module/moduleplatformvita.h b/src/duskvita/script/module/moduleplatformvita.h index 3f4f4643..7125d028 100644 --- a/src/duskvita/script/module/moduleplatformvita.h +++ b/src/duskvita/script/module/moduleplatformvita.h @@ -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"); }