[Debugger] JS API: Add script.abort() (#2170)

This commit is contained in:
shyguyhex 2022-01-13 14:39:21 -06:00 committed by GitHub
parent 3fd544d8f9
commit de0a59ac54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 147 additions and 73 deletions

View File

@ -193,6 +193,7 @@ namespace ScriptAPI
void Define_script(duk_context* ctx);
duk_ret_t js_script_keepalive(duk_context* ctx);
duk_ret_t js_script_timeout(duk_context* ctx);
duk_ret_t js_script_abort(duk_context* ctx);
// ScriptAPI_fs
void Define_fs(duk_context* ctx);

View File

@ -1,6 +1,8 @@
#include <stdafx.h>
#include "ScriptAPI.h"
#pragma warning(disable: 4702) // disable unreachable code warning
static void GetRange(duk_context* ctx, duk_idx_t idx, uint32_t* start, uint32_t* end);
void ScriptAPI::Define_AddressRange(duk_context* ctx)

View File

@ -1,11 +1,14 @@
#include <stdafx.h>
#include "ScriptAPI.h"
#pragma warning(disable: 4702) // disable unreachable code warning
void ScriptAPI::Define_script(duk_context *ctx)
{
const DukPropListEntry props[] = {
{ "timeout", DukCFunction(js_script_timeout) },
{ "keepalive", DukCFunction(js_script_keepalive) },
{ "abort", DukCFunction(js_script_abort) },
{ nullptr }
};
@ -46,3 +49,14 @@ duk_ret_t ScriptAPI::js_script_keepalive(duk_context *ctx)
return 0;
}
duk_ret_t ScriptAPI::js_script_abort(duk_context* ctx)
{
CheckArgs(ctx, {});
CScriptInstance* inst = GetInstance(ctx);
if (inst->PrepareAbort())
{
return duk_fatal(ctx, "aborted");
}
return 0;
}

View File

@ -2,7 +2,6 @@
#include "ScriptTypes.h"
#include "ScriptInstance.h"
#include "ScriptAPI/ScriptAPI.h"
#include <sys/stat.h>
extern "C" {
@ -22,7 +21,8 @@ CScriptInstance::CScriptInstance(CScriptSystem* sys, const char* name) :
m_ExecStartTime(0),
m_SourceCode(nullptr),
m_CurExecCallbackId(JS_INVALID_CALLBACK),
m_bStopping(false)
m_bStopping(false),
m_bAborting(false)
{
}
@ -94,18 +94,27 @@ bool CScriptInstance::Run(const char* path)
ScriptAPI::InitEnvironment(m_Ctx, this);
duk_push_string(m_Ctx, m_InstanceName.c_str());
if(duk_pcompile_string_filename(m_Ctx, DUK_COMPILE_STRICT, m_SourceCode) != 0 ||
duk_pcall(m_Ctx, 0) == DUK_EXEC_ERROR)
try
{
duk_get_prop_string(m_Ctx, -1, "stack");
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
duk_pop_n(m_Ctx, 2);
goto error_cleanup;
duk_push_string(m_Ctx, m_InstanceName.c_str());
if (duk_pcompile_string_filename(m_Ctx, DUK_COMPILE_STRICT, m_SourceCode) != 0 ||
duk_pcall(m_Ctx, 0) == DUK_EXEC_ERROR)
{
duk_get_prop_string(m_Ctx, -1, "stack");
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
duk_pop_n(m_Ctx, 2);
goto error_cleanup;
}
duk_pop(m_Ctx);
}
catch (std::runtime_error& exc)
{
FatalHandler(exc);
}
duk_pop(m_Ctx);
return true;
error_cleanup:
Cleanup();
@ -130,21 +139,39 @@ void CScriptInstance::SetStopping(bool bStopping)
m_bStopping = bStopping;
}
bool CScriptInstance::PrepareAbort()
{
if (!m_bAborting)
{
m_bAborting = true;
m_RefCount = 0;
return true;
}
return false;
}
void CScriptInstance::RawCMethodCall(void* dukThisHeapPtr, duk_c_function func, JSDukArgSetupFunc argSetupFunc, void *argSetupParam)
{
m_ExecStartTime = Timestamp();
duk_push_c_function(m_Ctx, func, DUK_VARARGS);
duk_push_heapptr(m_Ctx, dukThisHeapPtr);
duk_idx_t nargs = argSetupFunc ? argSetupFunc(m_Ctx, argSetupParam) : 0;
if (duk_pcall_method(m_Ctx, nargs) == DUK_EXEC_ERROR)
try
{
duk_get_prop_string(m_Ctx, -1, "stack");
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
m_ExecStartTime = Timestamp();
duk_push_c_function(m_Ctx, func, DUK_VARARGS);
duk_push_heapptr(m_Ctx, dukThisHeapPtr);
duk_idx_t nargs = argSetupFunc ? argSetupFunc(m_Ctx, argSetupParam) : 0;
if (duk_pcall_method(m_Ctx, nargs) == DUK_EXEC_ERROR)
{
duk_get_prop_string(m_Ctx, -1, "stack");
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
duk_pop(m_Ctx);
}
duk_pop(m_Ctx);
}
duk_pop(m_Ctx);
catch (std::runtime_error& exc)
{
FatalHandler(exc);
}
}
void CScriptInstance::PostCMethodCall(void* dukThisHeapPtr, duk_c_function func, JSDukArgSetupFunc argSetupFunc,
@ -156,67 +183,74 @@ void CScriptInstance::PostCMethodCall(void* dukThisHeapPtr, duk_c_function func,
void CScriptInstance::RawConsoleInput(const char* code)
{
m_System->ConsoleLog("> %s", code);
duk_get_global_string(m_Ctx, HS_gInputListener);
if (duk_is_function(m_Ctx, -1))
try
{
duk_get_global_string(m_Ctx, HS_gInputListener);
if (duk_is_function(m_Ctx, -1))
{
m_ExecStartTime = Timestamp();
duk_push_string(m_Ctx, code);
if (duk_pcall(m_Ctx, 1) != DUK_EXEC_SUCCESS)
{
duk_get_prop_string(m_Ctx, -1, "stack");
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
duk_pop_n(m_Ctx, 2);
return;
}
else
{
duk_pop(m_Ctx);
return;
}
}
duk_pop(m_Ctx);
m_ExecStartTime = Timestamp();
duk_push_string(m_Ctx, code);
if (duk_pcall(m_Ctx, 1) != DUK_EXEC_SUCCESS)
duk_push_string(m_Ctx, stdstr_f("<input:%s>", m_InstanceName.c_str()).c_str());
if (duk_pcompile_string_filename(m_Ctx, DUK_COMPILE_STRICT, code) != 0 ||
duk_pcall(m_Ctx, 0) == DUK_EXEC_ERROR)
{
duk_get_prop_string(m_Ctx, -1, "stack");
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
duk_pop_n(m_Ctx, 2);
return;
duk_pop(m_Ctx);
}
else
{
duk_pop(m_Ctx);
return;
}
}
duk_pop(m_Ctx);
if (duk_is_string(m_Ctx, -1))
{
m_System->ConsoleLog("\"%s\"", duk_get_string(m_Ctx, -1));
}
else if (duk_is_object(m_Ctx, -1))
{
duk_dup(m_Ctx, -1);
duk_get_global_string(m_Ctx, "JSON");
duk_get_prop_string(m_Ctx, -1, "stringify");
duk_remove(m_Ctx, -2);
duk_pull(m_Ctx, -3);
duk_push_null(m_Ctx);
duk_push_int(m_Ctx, 2);
duk_pcall(m_Ctx, 3);
m_ExecStartTime = Timestamp();
duk_push_string(m_Ctx, stdstr_f("<input:%s>", m_InstanceName.c_str()).c_str());
if (duk_pcompile_string_filename(m_Ctx, DUK_COMPILE_STRICT, code) != 0 ||
duk_pcall(m_Ctx, 0) == DUK_EXEC_ERROR)
{
duk_get_prop_string(m_Ctx, -1, "stack");
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
const char* str = duk_safe_to_string(m_Ctx, -2);
const char* res = duk_get_string(m_Ctx, -1);
m_System->ConsoleLog("%s %s", str, res);
duk_pop(m_Ctx);
}
else
{
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
}
}
duk_pop(m_Ctx);
}
else
catch (std::runtime_error& exc)
{
if (duk_is_string(m_Ctx, -1))
{
m_System->ConsoleLog("\"%s\"", duk_get_string(m_Ctx, -1));
}
else if(duk_is_object(m_Ctx, -1))
{
duk_dup(m_Ctx, -1);
duk_get_global_string(m_Ctx, "JSON");
duk_get_prop_string(m_Ctx, -1, "stringify");
duk_remove(m_Ctx, -2);
duk_pull(m_Ctx, -3);
duk_push_null(m_Ctx);
duk_push_int(m_Ctx, 2);
duk_pcall(m_Ctx, 3);
const char* str = duk_safe_to_string(m_Ctx, -2);
const char* res = duk_get_string(m_Ctx, -1);
m_System->ConsoleLog("%s %s", str, res);
duk_pop(m_Ctx);
}
else
{
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
}
FatalHandler(exc);
}
duk_pop(m_Ctx);
}
void CScriptInstance::SetExecTimeout(uint64_t timeout)
@ -299,3 +333,16 @@ void CScriptInstance::StopRegisteredWorkers()
worker->StopWorkerProc();
}
}
void CScriptInstance::FatalHandler(std::runtime_error& exc)
{
if (m_bAborting)
{
m_System->ConsoleLog("[SCRIPTSYS]: '%s' aborted", m_InstanceName.c_str());
}
else
{
m_System->ConsoleLog("%s", exc.what());
g_Notify->BreakPoint(__FILE__, __LINE__);
}
}

View File

@ -18,6 +18,7 @@ private:
JSAppCallbackID m_CurExecCallbackId;
std::vector<CScriptWorker*> m_Workers;
bool m_bStopping;
bool m_bAborting;
public:
CScriptInstance(CScriptSystem* sys, const char* name);
@ -37,6 +38,7 @@ public:
void DecRefCount();
void SetStopping(bool bStopping);
inline bool IsStopping() { return m_bStopping; }
bool PrepareAbort();
bool RegisterWorker(CScriptWorker* worker);
void UnregisterWorker(CScriptWorker* worker);
@ -62,14 +64,21 @@ public:
duk_push_heapptr(m_Ctx, dukFuncHeapPtr);
duk_idx_t nargs = argSetupFunc ? argSetupFunc(m_Ctx, param) : 0;
if (duk_pcall(m_Ctx, nargs) == DUK_EXEC_ERROR)
try
{
duk_get_prop_string(m_Ctx, -1, "stack");
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
if (duk_pcall(m_Ctx, nargs) == DUK_EXEC_ERROR)
{
duk_get_prop_string(m_Ctx, -1, "stack");
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
duk_pop(m_Ctx);
}
duk_pop(m_Ctx);
}
duk_pop(m_Ctx);
catch (std::runtime_error& exc)
{
FatalHandler(exc);
}
}
void RawCMethodCall(void* dukThisHeapPtr, duk_c_function func,
@ -83,6 +92,7 @@ public:
void RawConsoleInput(const char* code);
private:
void FatalHandler(std::runtime_error& exc);
static uint64_t Timestamp();
void Cleanup();
};