[Debugger] JS API: Add script.abort() (#2170)
This commit is contained in:
parent
3fd544d8f9
commit
de0a59ac54
|
@ -193,6 +193,7 @@ namespace ScriptAPI
|
||||||
void Define_script(duk_context* ctx);
|
void Define_script(duk_context* ctx);
|
||||||
duk_ret_t js_script_keepalive(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_timeout(duk_context* ctx);
|
||||||
|
duk_ret_t js_script_abort(duk_context* ctx);
|
||||||
|
|
||||||
// ScriptAPI_fs
|
// ScriptAPI_fs
|
||||||
void Define_fs(duk_context* ctx);
|
void Define_fs(duk_context* ctx);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include <stdafx.h>
|
#include <stdafx.h>
|
||||||
#include "ScriptAPI.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);
|
static void GetRange(duk_context* ctx, duk_idx_t idx, uint32_t* start, uint32_t* end);
|
||||||
|
|
||||||
void ScriptAPI::Define_AddressRange(duk_context* ctx)
|
void ScriptAPI::Define_AddressRange(duk_context* ctx)
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#include <stdafx.h>
|
#include <stdafx.h>
|
||||||
#include "ScriptAPI.h"
|
#include "ScriptAPI.h"
|
||||||
|
|
||||||
|
#pragma warning(disable: 4702) // disable unreachable code warning
|
||||||
|
|
||||||
void ScriptAPI::Define_script(duk_context *ctx)
|
void ScriptAPI::Define_script(duk_context *ctx)
|
||||||
{
|
{
|
||||||
const DukPropListEntry props[] = {
|
const DukPropListEntry props[] = {
|
||||||
{ "timeout", DukCFunction(js_script_timeout) },
|
{ "timeout", DukCFunction(js_script_timeout) },
|
||||||
{ "keepalive", DukCFunction(js_script_keepalive) },
|
{ "keepalive", DukCFunction(js_script_keepalive) },
|
||||||
|
{ "abort", DukCFunction(js_script_abort) },
|
||||||
{ nullptr }
|
{ nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,3 +49,14 @@ duk_ret_t ScriptAPI::js_script_keepalive(duk_context *ctx)
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include "ScriptTypes.h"
|
#include "ScriptTypes.h"
|
||||||
#include "ScriptInstance.h"
|
#include "ScriptInstance.h"
|
||||||
#include "ScriptAPI/ScriptAPI.h"
|
#include "ScriptAPI/ScriptAPI.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -22,7 +21,8 @@ CScriptInstance::CScriptInstance(CScriptSystem* sys, const char* name) :
|
||||||
m_ExecStartTime(0),
|
m_ExecStartTime(0),
|
||||||
m_SourceCode(nullptr),
|
m_SourceCode(nullptr),
|
||||||
m_CurExecCallbackId(JS_INVALID_CALLBACK),
|
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);
|
ScriptAPI::InitEnvironment(m_Ctx, this);
|
||||||
|
|
||||||
duk_push_string(m_Ctx, m_InstanceName.c_str());
|
try
|
||||||
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");
|
duk_push_string(m_Ctx, m_InstanceName.c_str());
|
||||||
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
|
if (duk_pcompile_string_filename(m_Ctx, DUK_COMPILE_STRICT, m_SourceCode) != 0 ||
|
||||||
duk_pop_n(m_Ctx, 2);
|
duk_pcall(m_Ctx, 0) == DUK_EXEC_ERROR)
|
||||||
goto error_cleanup;
|
{
|
||||||
|
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;
|
return true;
|
||||||
|
|
||||||
|
|
||||||
error_cleanup:
|
error_cleanup:
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
@ -130,21 +139,39 @@ void CScriptInstance::SetStopping(bool bStopping)
|
||||||
m_bStopping = 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)
|
void CScriptInstance::RawCMethodCall(void* dukThisHeapPtr, duk_c_function func, JSDukArgSetupFunc argSetupFunc, void *argSetupParam)
|
||||||
{
|
{
|
||||||
m_ExecStartTime = Timestamp();
|
try
|
||||||
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_ExecStartTime = Timestamp();
|
||||||
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
|
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)
|
||||||
duk_pop(m_Ctx);
|
{
|
||||||
|
FatalHandler(exc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptInstance::PostCMethodCall(void* dukThisHeapPtr, duk_c_function func, JSDukArgSetupFunc argSetupFunc,
|
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)
|
void CScriptInstance::RawConsoleInput(const char* code)
|
||||||
{
|
{
|
||||||
m_System->ConsoleLog("> %s", code);
|
m_System->ConsoleLog("> %s", code);
|
||||||
|
|
||||||
duk_get_global_string(m_Ctx, HS_gInputListener);
|
try
|
||||||
|
|
||||||
if (duk_is_function(m_Ctx, -1))
|
|
||||||
{
|
{
|
||||||
|
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();
|
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");
|
duk_get_prop_string(m_Ctx, -1, "stack");
|
||||||
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
|
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
|
||||||
duk_pop_n(m_Ctx, 2);
|
duk_pop(m_Ctx);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
duk_pop(m_Ctx);
|
if (duk_is_string(m_Ctx, -1))
|
||||||
return;
|
{
|
||||||
}
|
m_System->ConsoleLog("\"%s\"", duk_get_string(m_Ctx, -1));
|
||||||
}
|
}
|
||||||
duk_pop(m_Ctx);
|
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();
|
const char* str = duk_safe_to_string(m_Ctx, -2);
|
||||||
|
const char* res = duk_get_string(m_Ctx, -1);
|
||||||
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 ||
|
m_System->ConsoleLog("%s %s", str, res);
|
||||||
duk_pcall(m_Ctx, 0) == DUK_EXEC_ERROR)
|
duk_pop(m_Ctx);
|
||||||
{
|
}
|
||||||
duk_get_prop_string(m_Ctx, -1, "stack");
|
else
|
||||||
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
|
{
|
||||||
|
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
duk_pop(m_Ctx);
|
duk_pop(m_Ctx);
|
||||||
}
|
}
|
||||||
else
|
catch (std::runtime_error& exc)
|
||||||
{
|
{
|
||||||
if (duk_is_string(m_Ctx, -1))
|
FatalHandler(exc);
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
duk_pop(m_Ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptInstance::SetExecTimeout(uint64_t timeout)
|
void CScriptInstance::SetExecTimeout(uint64_t timeout)
|
||||||
|
@ -299,3 +333,16 @@ void CScriptInstance::StopRegisteredWorkers()
|
||||||
worker->StopWorkerProc();
|
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__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ private:
|
||||||
JSAppCallbackID m_CurExecCallbackId;
|
JSAppCallbackID m_CurExecCallbackId;
|
||||||
std::vector<CScriptWorker*> m_Workers;
|
std::vector<CScriptWorker*> m_Workers;
|
||||||
bool m_bStopping;
|
bool m_bStopping;
|
||||||
|
bool m_bAborting;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CScriptInstance(CScriptSystem* sys, const char* name);
|
CScriptInstance(CScriptSystem* sys, const char* name);
|
||||||
|
@ -37,6 +38,7 @@ public:
|
||||||
void DecRefCount();
|
void DecRefCount();
|
||||||
void SetStopping(bool bStopping);
|
void SetStopping(bool bStopping);
|
||||||
inline bool IsStopping() { return m_bStopping; }
|
inline bool IsStopping() { return m_bStopping; }
|
||||||
|
bool PrepareAbort();
|
||||||
|
|
||||||
bool RegisterWorker(CScriptWorker* worker);
|
bool RegisterWorker(CScriptWorker* worker);
|
||||||
void UnregisterWorker(CScriptWorker* worker);
|
void UnregisterWorker(CScriptWorker* worker);
|
||||||
|
@ -62,14 +64,21 @@ public:
|
||||||
duk_push_heapptr(m_Ctx, dukFuncHeapPtr);
|
duk_push_heapptr(m_Ctx, dukFuncHeapPtr);
|
||||||
duk_idx_t nargs = argSetupFunc ? argSetupFunc(m_Ctx, param) : 0;
|
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");
|
if (duk_pcall(m_Ctx, nargs) == DUK_EXEC_ERROR)
|
||||||
m_System->ConsoleLog("%s", duk_safe_to_string(m_Ctx, -1));
|
{
|
||||||
|
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)
|
||||||
duk_pop(m_Ctx);
|
{
|
||||||
|
FatalHandler(exc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RawCMethodCall(void* dukThisHeapPtr, duk_c_function func,
|
void RawCMethodCall(void* dukThisHeapPtr, duk_c_function func,
|
||||||
|
@ -83,6 +92,7 @@ public:
|
||||||
void RawConsoleInput(const char* code);
|
void RawConsoleInput(const char* code);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void FatalHandler(std::runtime_error& exc);
|
||||||
static uint64_t Timestamp();
|
static uint64_t Timestamp();
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue