project64/Source/Project64/UserInterface/Debugger/ScriptAPI/ScriptAPI_interval.cpp

151 lines
4.0 KiB
C++

#include <stdafx.h>
#include "ScriptAPI.h"
#include "JSIntervalWorker.h"
using namespace ScriptAPI;
static int AddIntervalContext(duk_context* ctx, duk_idx_t func_idx, int delayMS, bool bOnce);
static void RemoveIntervalContext(duk_context* ctx, int intervalId);
void ScriptAPI::Define_interval(duk_context* ctx)
{
DefineGlobalFunction(ctx, "setInterval", js_setInterval);
DefineGlobalFunction(ctx, "clearInterval", js_clearInterval);
DefineGlobalFunction(ctx, "setTimeout", js_setTimeout);
DefineGlobalFunction(ctx, "clearTimeout", js_clearTimeout);
}
duk_ret_t ScriptAPI::js_setInterval(duk_context* ctx)
{
CheckArgs(ctx, { Arg_Function, Arg_Number });
int delayMS = duk_get_int(ctx, 1);
int intervalId = AddIntervalContext(ctx, 0, delayMS, false);
duk_push_int(ctx, intervalId);
return 1;
}
duk_ret_t ScriptAPI::js_clearInterval(duk_context* ctx)
{
CheckArgs(ctx, { Arg_Number });
int intervalId = duk_get_int(ctx, 0);
RemoveIntervalContext(ctx, intervalId);
return 0;
}
duk_ret_t ScriptAPI::js_setTimeout(duk_context* ctx)
{
CheckArgs(ctx, { Arg_Function, Arg_Number });
int delayMS = duk_get_int(ctx, 1);
int intervalId = AddIntervalContext(ctx, 0, delayMS, true);
duk_push_int(ctx, intervalId);
return 1;
}
duk_ret_t ScriptAPI::js_clearTimeout(duk_context* ctx)
{
CheckArgs(ctx, { Arg_Number });
int intervalId = duk_get_int(ctx, 0);
RemoveIntervalContext(ctx, intervalId);
return 0;
}
duk_ret_t ScriptAPI::js__IntervalContext_invokeFunc(duk_context* ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "func");
duk_pcall(ctx, 0);
return 0;
}
duk_ret_t ScriptAPI::js__IntervalContext_remove(duk_context* ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "id");
int intervalId = duk_get_int(ctx, -1);
RemoveIntervalContext(ctx, intervalId);
return 0;
}
duk_ret_t ScriptAPI::js__IntervalContext_finalizer(duk_context* ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "worker");
CJSIntervalWorker* intervalWorker = (CJSIntervalWorker*)duk_get_pointer(ctx, -1);
if (intervalWorker != nullptr)
{
delete intervalWorker;
}
return 0;
}
int AddIntervalContext(duk_context* ctx, duk_idx_t func_idx, int delayMS, bool bOnce)
{
func_idx = duk_normalize_index(ctx, func_idx);
CScriptInstance* inst = GetInstance(ctx);
duk_push_global_object(ctx);
duk_get_prop_string(ctx, -1, HS_gNextInvervalId);
int intervalId = duk_get_int(ctx, -1);
duk_pop(ctx);
duk_push_int(ctx, intervalId + 1);
duk_put_prop_string(ctx, -2, HS_gNextInvervalId);
duk_get_prop_string(ctx, -1, HS_gIntervals);
duk_push_object(ctx);
RefObject(ctx, -1);
void* objectHeapPtr = duk_get_heapptr(ctx, -1);
CJSIntervalWorker* intervalWorker = new CJSIntervalWorker(inst, objectHeapPtr, delayMS, bOnce);
duk_dup(ctx, func_idx);
duk_put_prop_string(ctx, -2, "func");
duk_push_pointer(ctx, intervalWorker);
duk_put_prop_string(ctx, -2, "worker");
duk_push_int(ctx, intervalId);
duk_put_prop_string(ctx, -2, "id");
duk_push_c_function(ctx, js__IntervalContext_finalizer, 1);
duk_set_finalizer(ctx, -2);
duk_put_prop_index(ctx, -2, intervalId);
duk_pop_n(ctx, 2);
intervalWorker->StartWorkerProc();
return intervalId;
}
void RemoveIntervalContext(duk_context* ctx, int intervalId)
{
duk_push_global_object(ctx);
duk_get_prop_string(ctx, -1, HS_gIntervals);
if (!duk_has_prop_index(ctx, -1, intervalId))
{
return;
}
duk_get_prop_index(ctx, -1, intervalId);
UnrefObject(ctx, -1);
duk_get_prop_string(ctx, -1, "worker");
CJSIntervalWorker* intervalWorker = (CJSIntervalWorker*)duk_get_pointer(ctx, -1);
intervalWorker->StopWorkerProc();
delete intervalWorker;
duk_pop(ctx);
duk_push_pointer(ctx, nullptr);
duk_put_prop_string(ctx, -2, "worker");
duk_pop(ctx);
duk_del_prop_index(ctx, -1, intervalId);
duk_pop_n(ctx, 2);
}