diff --git a/meshconsole/main.c b/meshconsole/main.c index 07bdb9c..5306165 100644 --- a/meshconsole/main.c +++ b/meshconsole/main.c @@ -114,6 +114,7 @@ int main(int argc, char **argv) int retCode = 0; int capabilities = 0; + #ifdef WIN32 int argvi, argvsz; char **argv = (char**)ILibMemory_SmartAllocate(argc * sizeof(void*)); diff --git a/meshcore/agentcore.c b/meshcore/agentcore.c index c075edd..3baddb8 100644 --- a/meshcore/agentcore.c +++ b/meshcore/agentcore.c @@ -2274,22 +2274,22 @@ void WritePipeResponse(AGENT_RECORD_TYPE recordType, JS_ENGINE_CONTEXT engineCon duk_context* ScriptEngine_Stop(MeshAgentHostContainer *agent, char *contextGUID) { - duk_context *oldCtx = agent->meshCoreCtx; - agent->meshCoreCtx = NULL; - SCRIPT_ENGINE_SETTINGS *settings = ILibDuktape_ScriptContainer_GetSettings(oldCtx); - duk_context *newCtx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx2(settings); - ILibDuktape_MeshAgent_Init(newCtx, agent->chain, agent); + SCRIPT_ENGINE_SETTINGS *settings = ILibDuktape_ScriptContainer_GetSettings(agent->meshCoreCtx); + Duktape_SafeDestroyHeap(agent->meshCoreCtx); - ILibDuktape_SetNativeUncaughtExceptionHandler(newCtx, settings->nExeptionHandler, settings->nExceptionUserObject); + agent->meshCoreCtx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx2(settings); + ILibDuktape_MeshAgent_Init(agent->meshCoreCtx, agent->chain, agent); + + ILibDuktape_SetNativeUncaughtExceptionHandler(agent->meshCoreCtx, settings->nExeptionHandler, settings->nExceptionUserObject); if (g_displayFinalizerMessages) { printf("\n\n==> Stopping JavaScript Engine\n"); } - duk_destroy_heap(oldCtx); - agent->meshCoreCtx = newCtx; + if (agent->proxyServer != NULL) { memcpy_s(&(ILibDuktape_GetNewGlobalTunnel(agent->meshCoreCtx)->proxyServer), sizeof(struct sockaddr_in6), agent->proxyServer, sizeof(struct sockaddr_in6)); } - return(newCtx); + ILibDuktape_ScriptContainer_FreeSettings(settings); + return(agent->meshCoreCtx); } char* ScriptEngine_Restart(MeshAgentHostContainer *agent, char *contextGUID, char *buffer, int bufferLen) { @@ -3770,10 +3770,10 @@ void MeshAgent_ChainEnd(void *chain, void *user) if (agent->meshCoreCtx != NULL) { if (g_displayFinalizerMessages) { printf("\n\n==> Stopping JavaScript Engine\n"); } - duk_destroy_heap(agent->meshCoreCtx); + Duktape_SafeDestroyHeap(agent->meshCoreCtx); if (agent->bootstrapCoreCtx != NULL) { - duk_destroy_heap(agent->bootstrapCoreCtx); + Duktape_SafeDestroyHeap(agent->bootstrapCoreCtx); agent->bootstrapCoreCtx = NULL; } } @@ -4009,7 +4009,7 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char ** break; } - duk_destroy_heap(ctxx); + Duktape_SafeDestroyHeap(ctxx); } else { @@ -4141,7 +4141,7 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char ** } } } - duk_destroy_heap(tmpCtx); + Duktape_SafeDestroyHeap(tmpCtx); // Load the mesh agent certificates if ((resetNodeId == 1 || agent_LoadCertificates(agentHost) != 0) && agent_GenerateCertificates(agentHost, NULL) != 0) { printf("Certificate error\r\n"); } diff --git a/meshservice/ServiceMain.c b/meshservice/ServiceMain.c index d846167..0fd52d6 100644 --- a/meshservice/ServiceMain.c +++ b/meshservice/ServiceMain.c @@ -125,7 +125,7 @@ void UpdateOwnerData() duk_peval_string_noresult(ctx, "global._noMessagePump=true;var key=require('win-registry').usernameToUserKey(require('user-sessions').getProcessOwnerName(process.pid).name);var reg=require('win-registry');reg.WriteKey(reg.HKEY.LocalMachine, 'SYSTEM\\\\CurrentControlSet\\\\Services\\\\Mesh Agent', '_InstalledBy', key);"); - duk_destroy_heap(ctx); + Duktape_SafeDestroyHeap(ctx); ILibChain_DestroyEx(chain); ILibMemory_Free(exePath); } diff --git a/microscript/ILibDuktapeModSearch.c b/microscript/ILibDuktapeModSearch.c index 59938a0..610250e 100644 --- a/microscript/ILibDuktapeModSearch.c +++ b/microscript/ILibDuktapeModSearch.c @@ -353,11 +353,7 @@ duk_ret_t ILibDuktape_ModSearch_setModulePath(duk_context *ctx) void ILibDuktape_ModSearch_Init(duk_context * ctx, void * chain, ILibSimpleDataStore mDB) { duk_module_duktape_init(ctx); - - duk_push_heap_stash(ctx); // [stash] - duk_push_pointer(ctx, chain); // [stash][chain] - duk_put_prop_string(ctx, -2, ILibDuktape_Context_Chain); // [stash] - duk_pop(ctx); // ... + if (duk_ctx_chain(ctx) == NULL) { duk_ctx_context_data(ctx)->chain = chain; } duk_get_global_string(ctx, "Duktape"); // [globalString] duk_push_c_function(ctx, mod_Search, 4); // [globalString][func] diff --git a/microscript/ILibDuktape_Debugger.c b/microscript/ILibDuktape_Debugger.c index edf5f3c..e374449 100644 --- a/microscript/ILibDuktape_Debugger.c +++ b/microscript/ILibDuktape_Debugger.c @@ -254,7 +254,7 @@ void ILibDuktape_Debugger_AsyncWaitConn(ILibDuktape_Debugger *dbg) void ILibDuktape_Debugger_DestroyEx(void *chain, void *user) { - duk_destroy_heap(DebugWebEngine_Context); + Duktape_SafeDestroyHeap(DebugWebEngine_Context); } void DebugWebEngine_RunEx(void *chain, void *user) diff --git a/microscript/ILibDuktape_GenericMarshal.c b/microscript/ILibDuktape_GenericMarshal.c index 800808f..5f17313 100644 --- a/microscript/ILibDuktape_GenericMarshal.c +++ b/microscript/ILibDuktape_GenericMarshal.c @@ -105,6 +105,7 @@ typedef struct Duktape_GlobalGeneric_DispatcherData typedef struct Duktape_GlobalGeneric_Data { ILibDuktape_EventEmitter *emitter; + uintptr_t ctxnonce; void *retVal; void *chain; sem_t contextWaiter; @@ -836,15 +837,16 @@ void ILibDuktape_GenericMarshal_MethodInvoke_ThreadSink_Return(void *chain, void } void ILibDuktape_GenericMarshal_MethodInvoke_ThreadSink(void *args) { + ILibDuktape_EventEmitter *e = (ILibDuktape_EventEmitter*)((void**)args)[0]; void *chain = ((void**)args)[1]; PTRSIZE *vars = (PTRSIZE*)((void**)args)[2]; int parms = (int)(PTRSIZE)((void**)args)[3]; void *fptr = ((void**)args)[4]; + uintptr_t nonce = (uintptr_t)((void**)args)[5]; PTRSIZE retVal = ILibDuktape_GenericMarshal_MethodInvoke_Native(parms, fptr, vars); ((void**)args)[3] = (void*)retVal; - ILibChain_RunOnMicrostackThreadEx(chain, ILibDuktape_GenericMarshal_MethodInvoke_ThreadSink_Return, args); - + Duktape_RunOnEventLoop(chain, nonce, e->ctx, ILibDuktape_GenericMarshal_MethodInvoke_ThreadSink_Return, NULL, args); } #define ILibDuktape_FFI_AsyncDataPtr "\xFF_FFI_AsyncDataPtr" @@ -927,7 +929,7 @@ void ILibDuktape_GenericMarshal_MethodInvokeAsync_WorkerRunLoop(void *arg) { if (data->waitingForResult == 0) { - ILibChain_RunOnMicrostackThread(data->chain, ILibDuktape_GenericMarshal_MethodInvokeAsync_ChainDispatch, data); + Duktape_RunOnEventLoop(data->chain, duk_ctx_nonce(data->ctx), data->ctx, ILibDuktape_GenericMarshal_MethodInvokeAsync_ChainDispatch, NULL, data); } else { @@ -1259,7 +1261,7 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx) duk_push_current_function(ctx); // [func] exposedName = Duktape_GetStringPropertyValue(ctx, -1, "_exposedName", NULL); int spawnThread = Duktape_GetBooleanProperty(ctx, -1, "_spawnThread", 0); - PTRSIZE *vars = spawnThread == 0 ? ILibMemory_AllocateA(sizeof(PTRSIZE)*parms) : ILibMemory_SmartAllocateEx(sizeof(PTRSIZE)*parms, 5 * sizeof(void*)); + PTRSIZE *vars = spawnThread == 0 ? ILibMemory_AllocateA(sizeof(PTRSIZE)*parms) : ILibMemory_SmartAllocateEx(sizeof(PTRSIZE)*parms, 6 * sizeof(void*)); duk_get_prop_string(ctx, -1, "_address"); // [func][addr] fptr = duk_to_pointer(ctx, -1); @@ -1319,6 +1321,7 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx) args[2] = vars; args[3] = (void*)(PTRSIZE)parms; args[4] = fptr; + args[5] = (void*)duk_ctx_nonce(ctx); void *thptr = ILibSpawnNormalThread(ILibDuktape_GenericMarshal_MethodInvoke_ThreadSink, args); duk_push_fixed_buffer(ctx, sizeof(void*)); // [ret][buffer] @@ -1591,6 +1594,7 @@ void* ILibDuktape_GlobalGenericCallback_Process(int numParms, ...) #endif sem_init(&(user->contextWaiter), 0, 0); user->chain = refList[i]->chain; + user->ctxnonce = refList[i]->ctxnonce; user->emitter = refList[i]->emitter; user->numArgs = numParms; if (numParms > 0) @@ -1603,7 +1607,7 @@ void* ILibDuktape_GlobalGenericCallback_Process(int numParms, ...) } va_end(vlist); } - ILibChain_RunOnMicrostackThreadEx3(refList[i]->chain, ILibDuktape_GlobalGenericCallback_ProcessEx, ILibDuktape_GlobalGenericCallback_ProcessEx_Abort, user); + Duktape_RunOnEventLoop(refList[i]->chain, refList[i]->ctxnonce, refList[i]->emitter->ctx, ILibDuktape_GlobalGenericCallback_ProcessEx, ILibDuktape_GlobalGenericCallback_ProcessEx_Abort, user); } else { @@ -1897,6 +1901,7 @@ duk_ret_t ILibDuktape_GenericMarshal_GetGlobalGenericCallback(duk_context *ctx) data = (Duktape_GlobalGeneric_Data*)ILibMemory_SmartAllocate(sizeof(Duktape_GlobalGeneric_Data)); data->emitter = ILibDuktape_EventEmitter_Create(ctx); + data->ctxnonce = duk_ctx_nonce(ctx); data->chain = Duktape_GetChain(ctx); ILibDuktape_EventEmitter_CreateEventEx(data->emitter, "GlobalCallback"); ILibDuktape_CreateInstanceMethod(ctx, "CallingThread", ILibDuktape_GenericMarshal_GlobalCallback_CallingThread, 0); diff --git a/microscript/ILibDuktape_HECI.c b/microscript/ILibDuktape_HECI.c index adeb9e8..3de354d 100644 --- a/microscript/ILibDuktape_HECI.c +++ b/microscript/ILibDuktape_HECI.c @@ -60,6 +60,7 @@ struct HECI_CONNECT_client_data #define ILibDuktape_HECI_IoctlWaitHandle "\xFF_HECI_IoctlWaitHandle" #define ILibDuktape_HECI_Child "\xFF_HECI_Child" #define ILibDuktape_HECI_Parent "\xFF_HECI_Parent" +#define ILibDuktape_HECI_Root "\xFF_HECI_Root" #define ILibDuktape_HECI_MaxBufferSize "\xFF_HECI_MaxBufSize" #define ILibDuktape_HECI_SessionMemPtr "\xFF_HECI_SessionMemPtr" #define ILibDuktape_HECI_Session_NoPipeline "\xFF_HECI_Session_NoPipeline" @@ -90,6 +91,7 @@ public: typedef struct ILibDuktape_HECI_ioctl_data { duk_context *ctx; + uintptr_t ctxnonce; void *heciObject; void *data; void *Q; @@ -263,9 +265,9 @@ duk_ret_t ILibDuktape_HECI_SessionFinalizer(duk_context *ctx) void ILibDuktape_HECI_Session_EmitErrorEvent(void *chain, void *session) { - if (ILibIsRunningOnChainThread(chain) == 0) { ILibChain_RunOnMicrostackThreadEx(chain, ILibDuktape_HECI_Session_EmitErrorEvent, session); return; } ILibDuktape_HECI_Session *s = (ILibDuktape_HECI_Session*)session; duk_context *ctx = s->stream->readableStream->ctx; + if (ILibIsRunningOnChainThread(chain) == 0) { Duktape_RunOnEventLoop(chain, duk_ctx_nonce(ctx), ctx, ILibDuktape_HECI_Session_EmitErrorEvent, NULL, session); return; } duk_push_heapptr(ctx, s->stream->ParentObject); // [session] duk_get_prop_string(ctx, -1, "emit"); // [session][emit] @@ -277,7 +279,7 @@ void ILibDuktape_HECI_Session_EmitErrorEvent(void *chain, void *session) } void ILibDuktape_HECI_Session_EmitStreamReady(void *chain, void *session) { - if (ILibIsRunningOnChainThread(chain) == 0) { ILibChain_RunOnMicrostackThreadEx(chain, ILibDuktape_HECI_Session_EmitStreamReady, session); return; } + if (ILibIsRunningOnChainThread(chain) == 0) { Duktape_RunOnEventLoop(chain, duk_ctx_nonce(((ILibDuktape_HECI_Session*)session)->stream->writableStream->ctx), ((ILibDuktape_HECI_Session*)session)->stream->writableStream->ctx, ILibDuktape_HECI_Session_EmitStreamReady, NULL, session); return; } ILibDuktape_DuplexStream_Ready(((ILibDuktape_HECI_Session*)session)->stream); } @@ -492,7 +494,7 @@ ILibTransport_DoneState ILibDuktape_HECI_Session_WriteSink(ILibDuktape_DuplexStr else { state->returnIgnored = 1; - ILibChain_RunOnMicrostackThreadEx(stream->readableStream->chain, (ILibChain_StartEvent)ILibDuktape_HECI_Session_WriteSink_NoPipeline, state); + Duktape_RunOnEventLoop(stream->readableStream->chain, duk_ctx_nonce(stream->readableStream->ctx), stream->readableStream->ctx, (Duktape_EventLoopDispatch)ILibDuktape_HECI_Session_WriteSink_NoPipeline, NULL, state); } } @@ -553,7 +555,7 @@ void ILibDuktape_HECI_Session_ResumeSink(ILibDuktape_DuplexStream *sender, void ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user; if (session->noPipelining != 0) { - ILibChain_RunOnMicrostackThread(sender->readableStream->chain, ILibDuktape_HECI_Session_ResumeSink_NoPipeline, session); + Duktape_RunOnEventLoop(sender->readableStream->chain, duk_ctx_nonce(sender->readableStream->ctx), sender->readableStream->ctx, ILibDuktape_HECI_Session_ResumeSink_NoPipeline, NULL, session); // Note: DO NOT 'return' here, because we still need to QueueUserAPC, to resume the stream on Windows } @@ -587,7 +589,7 @@ BOOL ILibDuktape_HECI_Session_ReceiveSink(HANDLE event, ILibWaitHandle_ErrorStat ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user; if (ILibMemory_CanaryOK(session)) { - if (GetOverlappedResult(session->descriptor, &(session->v), &(session->bytesRead), FALSE) == TRUE) { ILibChain_RunOnMicrostackThreadEx(session->chain, ILibDuktape_HECI_Session_ReceiveSink2, session); } + if (GetOverlappedResult(session->descriptor, &(session->v), &(session->bytesRead), FALSE) == TRUE) { Duktape_RunOnEventLoop(session->chain, duk_ctx_nonce(session->stream->readableStream->ctx), session->stream->readableStream->ctx, ILibDuktape_HECI_Session_ReceiveSink2, NULL, session); } } return(FALSE); } @@ -770,6 +772,11 @@ duk_ret_t ILibDuktape_HECI_Session_close(duk_context *ctx) } #endif + duk_push_this(ctx); // [Session] + duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Root); // [Session][root] + ILibDuktape_Push_ObjectStash(ctx); // [Session][root][stash] + duk_del_prop_string(ctx, -1, Duktape_GetStashKey(duk_get_heapptr(ctx, -3))); + return(0); } duk_ret_t ILibDuktape_HECI_create(duk_context *ctx) @@ -779,8 +786,17 @@ duk_ret_t ILibDuktape_HECI_create(duk_context *ctx) ILibDuktape_HECI_Push(ctx, NULL); // [Session][HECI] duk_dup(ctx, -2); // [Session][HECI][Session] duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Parent); // [Session][HECI] + duk_push_this(ctx); // [session][HECI][root] + duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Root); // [session][HECI] duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Child); // [Session] + duk_push_this(ctx); // [Session][root] + ILibDuktape_Push_ObjectStash(ctx); // [Session][root][stash] + duk_dup(ctx, -3); // [Session][root][stash][Session] + duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [Session][root][stash] + duk_pop(ctx); // [Session][root] + duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Root); // [Session] + ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_Create(ctx); ILibDuktape_EventEmitter_CreateEventEx(emitter, "connect"); ILibDuktape_EventEmitter_CreateEventEx(emitter, "error"); @@ -872,7 +888,7 @@ BOOL ILibDuktape_HECI_IoctlHandler(HANDLE h, ILibWaitHandle_ErrorStatus errors, return(FALSE); } - ILibChain_RunOnMicrostackThread(data->chain, ILibDuktape_HECI_IoctlHandler_Dispatch, data); + Duktape_RunOnEventLoop(data->chain, data->ctxnonce, data->ctx, ILibDuktape_HECI_IoctlHandler_Dispatch, NULL, data); if (ILibQueue_GetCount(Q) > 0) { @@ -961,6 +977,7 @@ duk_ret_t ILibDuktape_HECI_doIoctl(duk_context *ctx) duk_push_array(ctx); // [heci][stash][array] ILibDuktape_HECI_ioctl_data *data; data = (ILibDuktape_HECI_ioctl_data*)ILibMemory_SmartAllocate(bufferLen + sizeof(ILibDuktape_HECI_ioctl_data)); + data->ctxnonce = duk_ctx_nonce(ctx); if (ILibDuktape_HECI_Debug) { printf("-> Allocate HECI Ioctl Data [%p]\n", (void*)data); } data->reserved = Duktape_PushBuffer(ctx, sizeof(void*)); // [heci][stash][array][ptr] duk_put_prop_index(ctx, -2, 0); // [heci][stash][array] @@ -1058,7 +1075,7 @@ duk_ret_t ILibDuktape_HECI_Finalizer(duk_context *ctx) ILibQueue Q = (ILibQueue)Duktape_GetPointerProperty(ctx, 0, ILibDuktape_HECI_Q); duk_get_prop_string(ctx, 0, ILibDuktape_HECI_ChildProcess); ILibProcessPipe_Manager mgr = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager); - QueueUserAPC((PAPCFUNC)ILibDuktape_HECI_Finalizer2, ILibProcessPipe_Manager_GetWorkerThread(mgr), (ULONG_PTR)Q); + if (mgr != NULL) { QueueUserAPC((PAPCFUNC)ILibDuktape_HECI_Finalizer2, ILibProcessPipe_Manager_GetWorkerThread(mgr), (ULONG_PTR)Q); } #else duk_get_prop_string(ctx, 0, ILibDuktape_HECI_Q); ILibQueue_Destroy((ILibQueue)duk_get_pointer(ctx, -1)); diff --git a/microscript/ILibDuktape_Helpers.c b/microscript/ILibDuktape_Helpers.c index c2b9e78..31caae5 100644 --- a/microscript/ILibDuktape_Helpers.c +++ b/microscript/ILibDuktape_Helpers.c @@ -40,6 +40,56 @@ struct sockaddr_in6 duktape_internalAddress; #define ILibDuktape_UncaughtException_NativeHandler "\xFF_UncaughtNativeHandler" #define ILibDuktape_UncaughtException_NativeUser "\xFF_UncaughtNativeUser" +typedef struct Duktape_EventLoopDispatchData +{ + duk_context *ctx; + uintptr_t nonce; + Duktape_EventLoopDispatch handler; + Duktape_EventLoopDispatch abortHandler; + void *user; +}Duktape_EventLoopDispatchData; + +void Duktape_RunOnEventLoop_AbortSink(void *chain, void *user) +{ + Duktape_EventLoopDispatchData *tmp = (Duktape_EventLoopDispatchData*)user; + if (tmp->abortHandler == (Duktape_EventLoopDispatch)(uintptr_t)0x01) + { + if (tmp->user != NULL) { free(tmp->user); } + } + else if(tmp->abortHandler != NULL) + { + tmp->abortHandler(chain, tmp->user); + } + ILibMemory_Free(tmp); +} +void Duktape_RunOnEventLoop_Sink(void *chain, void *user) +{ + Duktape_EventLoopDispatchData *tmp = (Duktape_EventLoopDispatchData*)user; + if (duk_ctx_is_alive(tmp->ctx) && duk_ctx_is_valid(tmp->nonce, tmp->ctx)) + { + // duk_context matches the intended context + if (tmp->handler != NULL) { tmp->handler(chain, tmp->user); } + } + else + { + // duk_context does not match the intended context + Duktape_RunOnEventLoop_AbortSink(chain, user); + return; + } + ILibMemory_Free(tmp); +} +void Duktape_RunOnEventLoop(void *chain, uintptr_t nonce, duk_context *ctx, Duktape_EventLoopDispatch handler, Duktape_EventLoopDispatch abortHandler, void *user) +{ + Duktape_EventLoopDispatchData* tmp = (Duktape_EventLoopDispatchData*)ILibMemory_SmartAllocate(sizeof(Duktape_EventLoopDispatchData)); + tmp->ctx = ctx; + tmp->nonce = nonce; + tmp->handler = handler; + tmp->abortHandler = abortHandler; + tmp->user = user; + + ILibChain_RunOnMicrostackThreadEx3(chain, Duktape_RunOnEventLoop_Sink, Duktape_RunOnEventLoop_AbortSink, tmp); +} + int ILibDuktape_GetReferenceCount(duk_context *ctx, duk_idx_t i) { int retVal = -1; @@ -119,6 +169,21 @@ void *Duktape_GetBufferPropertyEx(duk_context *ctx, duk_idx_t i, char* propertyN } return(retVal); } +void *Duktape_Duplicate_GetBufferPropertyEx(duk_context *ctx, duk_idx_t i, char* propertyName, duk_size_t* bufferLen) +{ + duk_size_t sourceLen = 0; + void *retVal = NULL, *source; + if (bufferLen != NULL) { *bufferLen = 0; } + + source = Duktape_GetBufferPropertyEx(ctx, i, propertyName, &sourceLen); + if (sourceLen > 0) + { + retVal = ILibMemory_SmartAllocate(sourceLen); + memcpy_s(retVal, sourceLen, source, sourceLen); + if (bufferLen != NULL) { *bufferLen = sourceLen; } + } + return(retVal); +} void *Duktape_GetPointerProperty(duk_context *ctx, duk_idx_t i, char* propertyName) { void *retVal = NULL; @@ -146,6 +211,36 @@ char* Duktape_GetStringPropertyValueEx(duk_context *ctx, duk_idx_t i, char* prop } return retVal; } +char* Duktape_Duplicate_GetStringPropertyValueEx(duk_context *ctx, duk_idx_t i, char* propertyName, char* defaultValue, duk_size_t *len) +{ + char *ret = NULL; + if (len != NULL) { *len = 0; } + + duk_size_t sourceLen = 0; + char *source = Duktape_GetStringPropertyValueEx(ctx, i, propertyName, defaultValue, &sourceLen); + + if (sourceLen > 0) + { + if (len != NULL) { *len = sourceLen; } + ret = (char*)ILibMemory_SmartAllocate(sourceLen + 1); + memcpy_s(ret, sourceLen, source, sourceLen); + } + + return(ret); +} +char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *len) +{ + char *ret = NULL; + duk_size_t srcLen = 0; + char* src = (char*)duk_get_lstring(ctx, i, &srcLen); + if (len != NULL) { *len = srcLen; } + if (srcLen > 0) + { + ret = ILibMemory_SmartAllocate(srcLen); + memcpy_s(ret, srcLen, src, srcLen); + } + return(ret); +} int Duktape_GetIntPropertyValue(duk_context *ctx, duk_idx_t i, char* propertyName, int defaultValue) { int retVal = defaultValue; @@ -544,21 +639,26 @@ char* Duktape_GetContextGuidHex(duk_context *ctx, void *db) duk_pop(ctx); // ... return retVal; } +ILibDuktape_ContextData* ILibDuktape_GetContextData(duk_context *ctx) +{ + duk_memory_functions mfuncs; + memset(&mfuncs, 0, sizeof(duk_memory_functions)); + duk_get_memory_functions(ctx, &mfuncs); + return((ILibDuktape_ContextData*)mfuncs.udata); +} + +void Duktape_SafeDestroyHeap(duk_context *ctx) +{ + ILibDuktape_ContextData *ctxd = duk_ctx_context_data(ctx); + + ctxd->flags |= duk_destroy_heap_in_progress; + duk_destroy_heap(ctx); + ILibMemory_Free(ctxd); +} void *Duktape_GetChain(duk_context *ctx) { - void *retVal = NULL; - duk_push_heap_stash(ctx); // [stash] - if (duk_has_prop_string(ctx, -1, ILibDuktape_Context_Chain)) - { - duk_get_prop_string(ctx, -1, ILibDuktape_Context_Chain); // [stash][ptr] - retVal = duk_get_pointer(ctx, -1); - duk_pop_2(ctx); // ... - } - else - { - duk_pop(ctx); // ... - } - return retVal; + void *ret = duk_ctx_chain(ctx); + return(ret); } duk_ret_t ILibDuktape_ExternalEventEmitter(duk_context *ctx) { diff --git a/microscript/ILibDuktape_Helpers.h b/microscript/ILibDuktape_Helpers.h index 46c0213..8adf105 100644 --- a/microscript/ILibDuktape_Helpers.h +++ b/microscript/ILibDuktape_Helpers.h @@ -30,7 +30,6 @@ typedef void(*ILibDuktape_HelperEvent)(duk_context *ctx, void *user); #define ILibDuktape_MeshAgent_Cert_NonLeaf "\xFF_selfcert" #define ILibDuktape_MeshAgent_Cert_Server "\xFF_selftlscert" #define CONTEXT_GUID_BUFFER "_CONTEXT_GUID" -#define ILibDuktape_Context_Chain "\xFF_chainptr" #define ILibDuktape_OBJID "_ObjectID" #define ILibDuktape_CR2HTTP "\xFF_CR2HTTP" @@ -47,8 +46,29 @@ typedef enum ILibDuktape_LogTypes ILibDuktape_LogType_Info3 }ILibDuktape_LogTypes; +typedef struct ILibDuktape_ContextData +{ + uintptr_t nonce; + uint32_t flags; + void *chain; + void *user; +}ILibDuktape_ContextData; + +#define duk_destroy_heap_in_progress 0x01 +#define duk_ctx_context_data(ctx) ((ILibDuktape_ContextData*)(ILibMemory_CanaryOK(ctx)?((void**)ILibMemory_Extra(ctx))[0]:NULL)) +#define duk_ctx_nonce(ctx) (duk_ctx_context_data(ctx)->nonce) +#define duk_ctx_is_alive(ctx) (ILibMemory_CanaryOK(ctx)) +#define duk_ctx_is_valid(nvalue, ctx) (duk_ctx_is_alive(ctx) && duk_ctx_nonce(ctx) == nvalue) +#define duk_ctx_shutting_down(ctx) ((duk_ctx_context_data(ctx)->flags & duk_destroy_heap_in_progress)==duk_destroy_heap_in_progress) +#define duk_ctx_chain(ctx) (duk_ctx_is_alive(ctx)?duk_ctx_context_data(ctx)->chain:NULL) + +typedef void(*Duktape_EventLoopDispatch)(void *chain, void *user); +void Duktape_RunOnEventLoop(void *chain, uintptr_t nonce, duk_context *ctx, Duktape_EventLoopDispatch handler, Duktape_EventLoopDispatch abortHandler, void *user); +#define Duktape_RunOnEventLoopEx(chain, nonce, ctx, handler, user, freeOnShutdown) Duktape_RunOnEventLoop(chain, nonce, ctx, handler, (freeOnShutdown==0?NULL:(Duktape_EventLoopDispatch)(uintptr_t)0x01), user) + void ILibDuktape_Log_Object(duk_context *ctx, duk_idx_t i, char *meta); char* Duktape_GetContextGuidHex(duk_context *ctx, void *db); +void Duktape_SafeDestroyHeap(duk_context *ctx); void *Duktape_GetChain(duk_context *ctx); char *Duktape_GetStashKey(void* value); char* Duktape_GetBuffer(duk_context *ctx, duk_idx_t i, duk_size_t *bufLen); @@ -61,6 +81,14 @@ void *Duktape_GetPointerProperty(duk_context *ctx, duk_idx_t i, char* propertyNa void *Duktape_GetHeapptrProperty(duk_context *ctx, duk_idx_t i, char* propertyName); void *Duktape_GetBufferPropertyEx(duk_context *ctx, duk_idx_t i, char* propertyName, duk_size_t* bufferLen); #define Duktape_GetBufferProperty(ctx, i, propertyName) Duktape_GetBufferPropertyEx(ctx, i, propertyName, NULL) + +char* Duktape_Duplicate_GetStringPropertyValueEx(duk_context *ctx, duk_idx_t i, char* propertyName, char* defaultValue, duk_size_t *len); +#define Duktape_Duplicate_GetStringPropertyValue(ctx, i, propertyName, defaultValue) Duktape_Duplicate_GetStringPropertyValueEx(ctx, i, propertyName, defaultValue, NULL) +void *Duktape_Duplicate_GetBufferPropertyEx(duk_context *ctx, duk_idx_t i, char* propertyName, duk_size_t* bufferLen); +#define Duktape_Duplicate_GetBufferProperty(ctx, i, propertyName) Duktape_Duplicate_GetBufferPropertyEx(ctx, i, propertyName, NULL) +char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *len); +#define Duktape_Duplicate_GetString(ctx, i) Duktape_Duplicate_GetStringEx(ctx, i, NULL) + int Duktape_GetBooleanProperty(duk_context *ctx, duk_idx_t i, char *propertyName, int defaultValue); struct sockaddr_in6* Duktape_IPAddress4_FromString(char* address, unsigned short port); struct sockaddr_in6* Duktape_IPAddress6_FromString(char* address, unsigned short port); diff --git a/microscript/ILibDuktape_HttpStream.c b/microscript/ILibDuktape_HttpStream.c index 147f86f..9aab3b2 100644 --- a/microscript/ILibDuktape_HttpStream.c +++ b/microscript/ILibDuktape_HttpStream.c @@ -1894,7 +1894,7 @@ ILibTransport_DoneState ILibDuktape_HttpStream_WriteSink(ILibDuktape_DuplexStrea tmp->httpStream = data; tmp->bufferLen = bufferLen; memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen); - ILibChain_RunOnMicrostackThread(data->chain, ILibDuktape_HttpStream_WriteSink_ChainSink, tmp); + Duktape_RunOnEventLoop(data->chain, duk_ctx_nonce(data->DS->readableStream->ctx), data->DS->readableStream->ctx, ILibDuktape_HttpStream_WriteSink_ChainSink, NULL, tmp); return(ILibTransport_DoneState_INCOMPLETE); } @@ -2195,8 +2195,8 @@ ILibTransport_DoneState ILibDuktape_HttpStream_ServerResponse_WriteSink(struct I buffered->endBytes = stream->endBytes; buffered->chunk = state->chunkSupported; if (bufferLen > 0) { memcpy_s(buffered->buffer, bufferLen, buffer, bufferLen); } - - ILibChain_RunOnMicrostackThreadEx(state->chain, ILibDuktape_HttpStream_ServerResponse_WriteImplicitHeaders, buffered); + + Duktape_RunOnEventLoop(state->chain, duk_ctx_nonce(state->ctx), state->ctx, ILibDuktape_HttpStream_ServerResponse_WriteImplicitHeaders, NULL, buffered); return(ILibTransport_DoneState_INCOMPLETE); } } @@ -2283,7 +2283,7 @@ ILibTransport_DoneState ILibDuktape_HttpStream_ServerResponse_WriteSink(struct I data->writeStream = state->writeStream; data->bufferLen = bufferLen; memcpy_s(data->buffer, bufferLen, buffer, bufferLen); - ILibChain_RunOnMicrostackThreadEx(state->chain, ILibDuktape_HttpStream_ServerResponse_WriteSink_Chain, data); + Duktape_RunOnEventLoop(state->chain, duk_ctx_nonce(state->ctx), state->ctx, ILibDuktape_HttpStream_ServerResponse_WriteSink_Chain, NULL, data); return(ILibTransport_DoneState_INCOMPLETE); } } @@ -2384,7 +2384,7 @@ void ILibDuktape_HttpStream_ServerResponse_EndSink(struct ILibDuktape_WritableSt else { // Need to context switch before sending Implicit Headers - ILibChain_RunOnMicrostackThreadEx(state->chain, ILibDuktape_HttpStream_ServerResponse_EndSink_Chain, stream); + Duktape_RunOnEventLoop(state->chain, duk_ctx_nonce(stream->ctx), stream->ctx, ILibDuktape_HttpStream_ServerResponse_EndSink_Chain, NULL, stream); } } else @@ -2396,7 +2396,7 @@ void ILibDuktape_HttpStream_ServerResponse_EndSink(struct ILibDuktape_WritableSt } else { - ILibChain_RunOnMicrostackThread(state->chain, ILibDuktape_HttpStream_ServerResponse_EndSink_ZeroChunk_Chain, state); + Duktape_RunOnEventLoop(state->chain, duk_ctx_nonce(stream->ctx), stream->ctx, ILibDuktape_HttpStream_ServerResponse_EndSink_ZeroChunk_Chain, NULL, state); } } } @@ -2890,6 +2890,10 @@ int ILibDuktape_HttpStream_IncomingMessage_UnshiftBytes(ILibDuktape_readableStre data->bodyStream_unshiftedBytes = unshiftBytes; return(unshiftBytes); } +void ILibDuktape_HttpStream_DispatchEnd_ABORT(void *chain, void *user) +{ + free(user); +} void ILibDuktape_HttpStream_DispatchEnd(void *chain, void *user) { if(ILibMemory_CanaryOK(((void**)user)[1])) @@ -2931,6 +2935,7 @@ void ILibDuktape_HttpStream_OnReceive(ILibWebClient_StateObject WebStateObject, { ILibDuktape_HttpStream_Data *data = (ILibDuktape_HttpStream_Data*)user1; duk_context *ctx = data->DS->writableStream->ctx; + uintptr_t ctxnonce = duk_ctx_nonce(ctx); if (data->bodyStream != NULL) { @@ -3170,7 +3175,7 @@ void ILibDuktape_HttpStream_OnReceive(ILibWebClient_StateObject WebStateObject, tmp[0] = ctx; tmp[1] = data->DS; tmp[2] = data; - ILibChain_RunOnMicrostackThread(data->chain, ILibDuktape_HttpStream_DispatchEnd, tmp); + Duktape_RunOnEventLoop(data->chain, ctxnonce, ctx, ILibDuktape_HttpStream_DispatchEnd, ILibDuktape_HttpStream_DispatchEnd_ABORT, tmp); } } } @@ -3221,7 +3226,6 @@ duk_ret_t ILibduktape_HttpStream_create(duk_context *ctx) duk_put_prop_string(ctx, -2, ILibDuktape_HTTPStream2Data); // [httpStream] data->maxHeaderSize = 4096; - ILibDuktape_EventEmitter_CreateEventEx(emitter, "end"); ILibDuktape_EventEmitter_CreateEventEx(emitter, "error"); ILibDuktape_EventEmitter_CreateEventEx(emitter, "parseError"); @@ -3972,7 +3976,7 @@ void ILibDuktape_httpStream_webSocket_EncodedPauseSink(ILibDuktape_DuplexStream } else { - ILibChain_RunOnMicrostackThreadEx(state->chain, ILibDuktape_httpStream_webSocket_EncodedPauseSink_Chain, state); + Duktape_RunOnEventLoop(state->chain, duk_ctx_nonce(state->ctx), state->ctx, ILibDuktape_httpStream_webSocket_EncodedPauseSink_Chain, NULL, state); } } } @@ -4007,7 +4011,7 @@ void ILibDuktape_httpStream_webSocket_EncodedResumeSink(ILibDuktape_DuplexStream } else { - ILibChain_RunOnMicrostackThreadEx(state->chain, ILibDuktape_httpStream_webSocket_EncodedResumeSink_Chain, state); + Duktape_RunOnEventLoop(state->chain, duk_ctx_nonce(state->ctx), state->ctx, ILibDuktape_httpStream_webSocket_EncodedResumeSink_Chain, NULL, state); } } } @@ -4064,7 +4068,7 @@ void ILibDuktape_httpStream_webSocket_DecodedPauseSink(ILibDuktape_DuplexStream } else { - ILibChain_RunOnMicrostackThreadEx(state->chain, ILibDuktape_httpStream_webSocket_DecodedPauseSink_Chain, state); + Duktape_RunOnEventLoop(state->chain, duk_ctx_nonce(state->ctx), state->ctx, ILibDuktape_httpStream_webSocket_DecodedPauseSink_Chain, NULL, state); } } } @@ -4102,7 +4106,7 @@ void ILibDuktape_httpStream_webSocket_DecodedResumeSink(ILibDuktape_DuplexStream } else { - ILibChain_RunOnMicrostackThreadEx(state->chain, ILibDuktape_httpStream_webSocket_DecodedResumeSink_Chain, state); + Duktape_RunOnEventLoop(state->chain, duk_ctx_nonce(state->ctx), state->ctx, ILibDuktape_httpStream_webSocket_DecodedResumeSink_Chain, NULL, state); } } } diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index 4142556..ef5b177 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -1187,7 +1187,7 @@ ILibTransport_DoneState ILibDuktape_DynamicBuffer_WriteSink(ILibDuktape_DuplexSt tmp->data = data; tmp->bufferLen = bufferLen; memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen); - ILibChain_RunOnMicrostackThread(tmp->chain, ILibDuktape_DynamicBuffer_WriteSink_ChainThread, tmp); + Duktape_RunOnEventLoop(tmp->chain, duk_ctx_nonce(stream->readableStream->ctx), stream->readableStream->ctx, ILibDuktape_DynamicBuffer_WriteSink_ChainThread, NULL, tmp); return(ILibTransport_DoneState_INCOMPLETE); } @@ -1645,12 +1645,15 @@ void ILibDuktape_Stream_Init(duk_context *ctx, void *chain) } void ILibDuktape_Polyfills_debugGC2(duk_context *ctx, void ** args, int argsLen) { - if (g_displayFinalizerMessages) { printf("=> GC();\n"); } - duk_gc(ctx, 0); + if (duk_ctx_is_alive((duk_context*)args[1]) && duk_ctx_is_valid((uintptr_t)args[2], ctx)) + { + if (g_displayFinalizerMessages) { printf("=> GC();\n"); } + duk_gc(ctx, 0); + } } duk_ret_t ILibDuktape_Polyfills_debugGC(duk_context *ctx) { - ILibDuktape_Immediate(ctx, (void*[]) { NULL }, 0, ILibDuktape_Polyfills_debugGC2); + ILibDuktape_Immediate(ctx, (void*[]) { Duktape_GetChain(ctx), ctx, (void*)duk_ctx_nonce(ctx), NULL }, 3, ILibDuktape_Polyfills_debugGC2); return(0); } duk_ret_t ILibDuktape_Polyfills_debug(duk_context *ctx) @@ -2071,7 +2074,7 @@ void ILibDuktape_Polyfills_JS_Init(duk_context *ctx) duk_peval_string_noresult(ctx, "addModule('PE_Parser', Buffer.from('LyoKQ29weXJpZ2h0IDIwMTggSW50ZWwgQ29ycG9yYXRpb24KCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQpkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLApXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZApsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKi8KCi8vIFJldHVybiBpbmZvcm1hdGlvbiBhYm91dCB0aGlzIGV4ZWN1dGFibGUKZnVuY3Rpb24gcGFyc2UoZXhlUGF0aCkKewogICAgdmFyIHJldFZhbCA9IHt9OwogICAgdmFyIGZzID0gcmVxdWlyZSgnZnMnKTsKICAgIHZhciBmZCA9IGZzLm9wZW5TeW5jKGV4ZVBhdGgsICdyYicpOwogICAgdmFyIGJ5dGVzUmVhZDsKICAgIHZhciBkb3NIZWFkZXIgPSBCdWZmZXIuYWxsb2MoNjQpOwogICAgdmFyIG50SGVhZGVyID0gQnVmZmVyLmFsbG9jKDI0KTsKICAgIHZhciBvcHRIZWFkZXI7CgogICAgLy8gUmVhZCB0aGUgRE9TIGhlYWRlcgogICAgYnl0ZXNSZWFkID0gZnMucmVhZFN5bmMoZmQsIGRvc0hlYWRlciwgMCwgNjQsIDApOwogICAgaWYgKGRvc0hlYWRlci5yZWFkVUludDE2TEUoMCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCkgIT0gJzVBNEQnKQogICAgewogICAgICAgIHRocm93ICgndW5yZWNvZ25pemVkIGJpbmFyeSBmb3JtYXQnKTsKICAgIH0KCiAgICAvLyBSZWFkIHRoZSBOVCBoZWFkZXIKICAgIGJ5dGVzUmVhZCA9IGZzLnJlYWRTeW5jKGZkLCBudEhlYWRlciwgMCwgbnRIZWFkZXIubGVuZ3RoLCBkb3NIZWFkZXIucmVhZFVJbnQzMkxFKDYwKSk7CiAgICBpZiAobnRIZWFkZXIuc2xpY2UoMCwgNCkudG9TdHJpbmcoJ2hleCcpICE9ICc1MDQ1MDAwMCcpCiAgICB7CiAgICAgICAgdGhyb3cgKCdub3QgYSBQRSBmaWxlJyk7CiAgICB9CiAgICBzd2l0Y2ggKG50SGVhZGVyLnJlYWRVSW50MTZMRSg0KS50b1N0cmluZygxNikpCiAgICB7CiAgICAgICAgY2FzZSAnMTRjJzogLy8gMzIgYml0CiAgICAgICAgICAgIHJldFZhbC5mb3JtYXQgPSAneDg2JzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnODY2NCc6IC8vIDY0IGJpdAogICAgICAgICAgICByZXRWYWwuZm9ybWF0ID0gJ3g2NCc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6IC8vIFVua25vd24KICAgICAgICAgICAgcmV0VmFsLmZvcm1hdCA9IHVuZGVmaW5lZDsKICAgICAgICAgICAgYnJlYWs7CiAgICB9CgogICAgcmV0VmFsLm9wdGlvbmFsSGVhZGVyU2l6ZSA9IG50SGVhZGVyLnJlYWRVSW50MTZMRSgyMCk7CiAgICByZXRWYWwub3B0aW9uYWxIZWFkZXJTaXplQWRkcmVzcyA9IGRvc0hlYWRlci5yZWFkVUludDMyTEUoNjApICsgMjA7CgogICAgLy8gUmVhZCB0aGUgb3B0aW9uYWwgaGVhZGVyCiAgICBvcHRIZWFkZXIgPSBCdWZmZXIuYWxsb2MobnRIZWFkZXIucmVhZFVJbnQxNkxFKDIwKSk7CiAgICBieXRlc1JlYWQgPSBmcy5yZWFkU3luYyhmZCwgb3B0SGVhZGVyLCAwLCBvcHRIZWFkZXIubGVuZ3RoLCBkb3NIZWFkZXIucmVhZFVJbnQzMkxFKDYwKSArIDI0KTsKICAgIHZhciBudW1SVkEgPSB1bmRlZmluZWQ7CgogICAgcmV0VmFsLkNoZWNrU3VtUG9zID0gZG9zSGVhZGVyLnJlYWRVSW50MzJMRSg2MCkgKyAyNCArIDY0OwogICAgcmV0VmFsLlNpemVPZkNvZGUgPSBvcHRIZWFkZXIucmVhZFVJbnQzMkxFKDQpOwogICAgcmV0VmFsLlNpemVPZkluaXRpYWxpemVkRGF0YSA9IG9wdEhlYWRlci5yZWFkVUludDMyTEUoOCk7CiAgICByZXRWYWwuU2l6ZU9mVW5Jbml0aWFsaXplZERhdGEgPSBvcHRIZWFkZXIucmVhZFVJbnQzMkxFKDEyKTsKCiAgICBzd2l0Y2ggKG9wdEhlYWRlci5yZWFkVUludDE2TEUoMCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCkpCiAgICB7CiAgICAgICAgY2FzZSAnMTBCJzogLy8gMzIgYml0IGJpbmFyeQogICAgICAgICAgICBudW1SVkEgPSBvcHRIZWFkZXIucmVhZFVJbnQzMkxFKDkyKTsKICAgICAgICAgICAgcmV0VmFsLkNlcnRpZmljYXRlVGFibGVBZGRyZXNzID0gb3B0SGVhZGVyLnJlYWRVSW50MzJMRSgxMjgpOwogICAgICAgICAgICByZXRWYWwuQ2VydGlmaWNhdGVUYWJsZVNpemUgPSBvcHRIZWFkZXIucmVhZFVJbnQzMkxFKDEzMik7CiAgICAgICAgICAgIHJldFZhbC5DZXJ0aWZpY2F0ZVRhYmxlU2l6ZVBvcyA9IGRvc0hlYWRlci5yZWFkVUludDMyTEUoNjApICsgMjQgKyAxMzI7CiAgICAgICAgICAgIHJldFZhbC5ydmFTdGFydEFkZHJlc3MgPSBkb3NIZWFkZXIucmVhZFVJbnQzMkxFKDYwKSArIDI0ICsgOTY7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJzIwQic6IC8vIDY0IGJpdCBiaW5hcnkKICAgICAgICAgICAgbnVtUlZBID0gb3B0SGVhZGVyLnJlYWRVSW50MzJMRSgxMDgpOwogICAgICAgICAgICByZXRWYWwuQ2VydGlmaWNhdGVUYWJsZUFkZHJlc3MgPSBvcHRIZWFkZXIucmVhZFVJbnQzMkxFKDE0NCk7CiAgICAgICAgICAgIHJldFZhbC5DZXJ0aWZpY2F0ZVRhYmxlU2l6ZSA9IG9wdEhlYWRlci5yZWFkVUludDMyTEUoMTQ4KTsKICAgICAgICAgICAgcmV0VmFsLkNlcnRpZmljYXRlVGFibGVTaXplUG9zID0gZG9zSGVhZGVyLnJlYWRVSW50MzJMRSg2MCkgKyAyNCArIDE0ODsKICAgICAgICAgICAgcmV0VmFsLnJ2YVN0YXJ0QWRkcmVzcyA9IGRvc0hlYWRlci5yZWFkVUludDMyTEUoNjApICsgMjQgKyAxMTI7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93ICgnVW5rbm93biBWYWx1ZSBmb3VuZCBmb3IgT3B0aW9uYWwgTWFnaWM6ICcgKyBudEhlYWRlci5yZWFkVUludDE2TEUoMjQpLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICB9CiAgICByZXRWYWwucnZhQ291bnQgPSBudW1SVkE7CgogICAgaWYgKHJldFZhbC5DZXJ0aWZpY2F0ZVRhYmxlQWRkcmVzcykKICAgIHsKICAgICAgICAvLyBSZWFkIHRoZSBhdXRoZW50aWNvZGUgY2VydGlmaWNhdGUsIG9ubHkgb25lIGNlcnQgKG9ubHkgdGhlIGZpcnN0IGVudHJ5KQogICAgICAgIHZhciBoZHIgPSBCdWZmZXIuYWxsb2MoOCk7CiAgICAgICAgZnMucmVhZFN5bmMoZmQsIGhkciwgMCwgaGRyLmxlbmd0aCwgcmV0VmFsLkNlcnRpZmljYXRlVGFibGVBZGRyZXNzKTsKICAgICAgICByZXRWYWwuY2VydGlmaWNhdGUgPSBCdWZmZXIuYWxsb2MoaGRyLnJlYWRVSW50MzJMRSgwKSk7CiAgICAgICAgZnMucmVhZFN5bmMoZmQsIHJldFZhbC5jZXJ0aWZpY2F0ZSwgMCwgcmV0VmFsLmNlcnRpZmljYXRlLmxlbmd0aCwgcmV0VmFsLkNlcnRpZmljYXRlVGFibGVBZGRyZXNzICsgaGRyLmxlbmd0aCk7CiAgICAgICAgcmV0VmFsLmNlcnRpZmljYXRlID0gcmV0VmFsLmNlcnRpZmljYXRlLnRvU3RyaW5nKCdiYXNlNjQnKTsKICAgICAgICByZXRWYWwuY2VydGlmaWNhdGVEd0xlbmd0aCA9IGhkci5yZWFkVUludDMyTEUoMCk7CiAgICB9CiAgICBmcy5jbG9zZVN5bmMoZmQpOwogICAgcmV0dXJuIChyZXRWYWwpOwp9Cgptb2R1bGUuZXhwb3J0cyA9IHBhcnNlOwoKCv==', 'base64').toString());"); // Windows Message Pump, refer to modules/win-message-pump.js - duk_peval_string_noresult(ctx, "addModule('win-message-pump', Buffer.from('LyoKQ29weXJpZ2h0IDIwMTggSW50ZWwgQ29ycG9yYXRpb24KCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQpkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLApXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZApsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKi8KCnZhciBXSF9DQUxMV05EUFJPQyA9IDQ7CnZhciBXTV9RVUlUID0gIDB4MDAxMjsKdmFyIFdNX0NMT1NFID0gMHgwMDEwOwp2YXIgR00gPSByZXF1aXJlKCdfR2VuZXJpY01hcnNoYWwnKTsKCmZ1bmN0aW9uIFdpbmRvd3NNZXNzYWdlUHVtcChvcHRpb25zKQp7CiAgICB0aGlzLl9PYmplY3RJRCA9ICd3aW4tbWVzc2FnZS1wdW1wJzsKICAgIHRoaXMuX29wdGlvbnMgPSBvcHRpb25zOwogICAgdmFyIGVtaXR0ZXJVdGlscyA9IHJlcXVpcmUoJ2V2ZW50cycpLmluaGVyaXRzKHRoaXMpOwogICAgZW1pdHRlclV0aWxzLmNyZWF0ZUV2ZW50KCdod25kJyk7CiAgICBlbWl0dGVyVXRpbHMuY3JlYXRlRXZlbnQoJ2Vycm9yJyk7CiAgICBlbWl0dGVyVXRpbHMuY3JlYXRlRXZlbnQoJ21lc3NhZ2UnKTsKICAgIGVtaXR0ZXJVdGlscy5jcmVhdGVFdmVudCgnZXhpdCcpOwoKICAgIHRoaXMuX21zZyA9IEdNLkNyZWF0ZVZhcmlhYmxlKEdNLlBvaW50ZXJTaXplID09IDQgPyAyOCA6IDQ4KTsKICAgIHRoaXMuX2tlcm5lbDMyID0gR00uQ3JlYXRlTmF0aXZlUHJveHkoJ0tlcm5lbDMyLmRsbCcpOwogICAgdGhpcy5fa2VybmVsMzIubXAgPSB0aGlzOwogICAgdGhpcy5fa2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdHZXRMYXN0RXJyb3InKTsKICAgIHRoaXMuX2tlcm5lbDMyLkNyZWF0ZU1ldGhvZCgnR2V0TW9kdWxlSGFuZGxlQScpOwoKICAgIHRoaXMuX3VzZXIzMiA9IEdNLkNyZWF0ZU5hdGl2ZVByb3h5KCdVc2VyMzIuZGxsJyk7CiAgICB0aGlzLl91c2VyMzIubXAgPSB0aGlzOwogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnQ3JlYXRlV2luZG93RXhBJyk7CiAgICB0aGlzLl91c2VyMzIuQ3JlYXRlTWV0aG9kKCdEZWZXaW5kb3dQcm9jQScpOwogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnRGVzdHJveVdpbmRvdycpOwogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnRGlzcGF0Y2hNZXNzYWdlQScpOwogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnR2V0TWVzc2FnZUEnKTsKICAgIHRoaXMuX3VzZXIzMi5DcmVhdGVNZXRob2QoJ1Bvc3RNZXNzYWdlQScpOwogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnUmVnaXN0ZXJDbGFzc0V4QScpOwogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnU2V0V2luZG93UG9zJyk7CiAgICB0aGlzLl91c2VyMzIuQ3JlYXRlTWV0aG9kKCdTaG93V2luZG93Jyk7CiAgICB0aGlzLl91c2VyMzIuQ3JlYXRlTWV0aG9kKCdUcmFuc2xhdGVNZXNzYWdlJyk7CgoKICAgIHRoaXMud25kY2xhc3MgPSBHTS5DcmVhdGVWYXJpYWJsZShHTS5Qb2ludGVyU2l6ZSA9PSA0ID8gNDggOiA4MCk7CiAgICB0aGlzLnduZGNsYXNzLm1wID0gdGhpczsKICAgIHRoaXMud25kY2xhc3MuaGluc3RhbmNlID0gdGhpcy5fa2VybmVsMzIuR2V0TW9kdWxlSGFuZGxlQSgwKTsKICAgIHRoaXMud25kY2xhc3MuY25hbWUgPSBHTS5DcmVhdGVWYXJpYWJsZSgnTWFpbldXV0NsYXNzJyk7CiAgICB0aGlzLnduZGNsYXNzLnduZHByb2MgPSBHTS5HZXRHZW5lcmljR2xvYmFsQ2FsbGJhY2soNCk7CiAgICB0aGlzLnduZGNsYXNzLnduZHByb2MubXAgPSB0aGlzOwogICAgdGhpcy53bmRjbGFzcy50b0J1ZmZlcigpLndyaXRlVUludDMyTEUodGhpcy53bmRjbGFzcy5fc2l6ZSk7CiAgICB0aGlzLnduZGNsYXNzLmNuYW1lLnBvaW50ZXJCdWZmZXIoKS5jb3B5KHRoaXMud25kY2xhc3MuRGVyZWYoR00uUG9pbnRlclNpemUgPT0gNCA/IDQwIDogNjQsIEdNLlBvaW50ZXJTaXplKS50b0J1ZmZlcigpKTsKICAgIHRoaXMud25kY2xhc3Mud25kcHJvYy5wb2ludGVyQnVmZmVyKCkuY29weSh0aGlzLnduZGNsYXNzLkRlcmVmKDgsIEdNLlBvaW50ZXJTaXplKS50b0J1ZmZlcigpKTsKICAgIHRoaXMud25kY2xhc3MuaGluc3RhbmNlLnBvaW50ZXJCdWZmZXIoKS5jb3B5KHRoaXMud25kY2xhc3MuRGVyZWYoR00uUG9pbnRlclNpemUgPT0gNCA/IDIwIDogMjQsIEdNLlBvaW50ZXJTaXplKS50b0J1ZmZlcigpKTsKICAgIHRoaXMud25kY2xhc3Mud25kcHJvYy5vbignR2xvYmFsQ2FsbGJhY2snLCBmdW5jdGlvbiBvblduZFByb2MoeGh3bmQsIHhtc2csIHdwYXJhbSwgbHBhcmFtKQogICAgewogICAgICAgIGlmICh0aGlzLm1wLl9od25kICE9IG51bGwgJiYgdGhpcy5tcC5faHduZC5WYWwgPT0geGh3bmQuVmFsKQogICAgICAgIHsKICAgICAgICAgICAgLy8gVGhpcyBpcyBmb3IgdXMKICAgICAgICAgICAgdmFyIGQgPSB0aGlzLlN0YXJ0RGlzcGF0Y2hlcigpOwogICAgICAgICAgICB0aGlzLm1wLmVtaXQoJ21lc3NhZ2UnLCB7IG1lc3NhZ2U6IHhtc2cuVmFsLCB3cGFyYW06IHdwYXJhbS5WYWwsIGxwYXJhbTogbHBhcmFtLlZhbCwgbHBhcmFtX2hleDogbHBhcmFtLnBvaW50ZXJCdWZmZXIoKS50b1N0cmluZygnaGV4JyksIGxwYXJhbV9yYXc6IGxwYXJhbSwgaHduZDogeGh3bmQsIGRpc3BhdGNoZXI6IGQgfSk7CgogICAgICAgICAgICB2YXIgbXNnUmV0ID0gdGhpcy5tcC5lbWl0X3JldHVyblZhbHVlKCdtZXNzYWdlJyk7CiAgICAgICAgICAgIGlmIChtc2dSZXQgPT0gbnVsbCkKICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gY2FsbCBEZWZXaW5kb3dQcm9jQSwgYmVjdWFzZSB0aGlzIG1lc3NhZ2Ugd2FzIG5vdCBoYW5kbGVkDQogICAgICAgICAgICAgICAgdmFyIHAgPSB0aGlzLm1wLl91c2VyMzIuRGVmV2luZG93UHJvY0EuYXN5bmMoZCwgeGh3bmQsIHhtc2csIHdwYXJhbSwgbHBhcmFtKTsKICAgICAgICAgICAgICAgIHAuZGlzcGF0Y2hlciA9IHRoaXM7CiAgICAgICAgICAgICAgICBwLnRoZW4oZnVuY3Rpb24gKHJldCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hlci5FbmREaXNwYXRjaGVyKHJldCk7DQogICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHZhciByID0gR00uQ3JlYXRlUG9pbnRlcigpOw0KICAgICAgICAgICAgICAgIHIuVmFsID0gbXNnUmV0Ow0KICAgICAgICAgICAgICAgIHRoaXMuRW5kRGlzcGF0Y2hlcihyKTsNCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZWxzZSBpZih0aGlzLm1wLl9od25kID09IG51bGwgJiYgdGhpcy5DYWxsaW5nVGhyZWFkKCkgPT0gdGhpcy5tcC5fdXNlcjMyLlJlZ2lzdGVyQ2xhc3NFeEEuYXN5bmMudGhyZWFkSWQoKSkKICAgICAgICB7CiAgICAgICAgICAgIC8vIFRoaXMgbWVzc2FnZSB3YXMgZ2VuZXJhdGVkIGZyb20gb3VyIENyZWF0ZVdpbmRvd0V4QSBtZXRob2QKICAgICAgICAgICAgdmFyIGQgPSB0aGlzLlN0YXJ0RGlzcGF0Y2hlcigpOwoKICAgICAgICAgICAgdGhpcy5tcC5lbWl0KCdtZXNzYWdlJywgeyBtZXNzYWdlOiB4bXNnLlZhbCwgd3BhcmFtOiB3cGFyYW0uVmFsLCBscGFyYW06IGxwYXJhbS5WYWwsIGxwYXJhbV9oZXg6IGxwYXJhbS5wb2ludGVyQnVmZmVyKCkudG9TdHJpbmcoJ2hleCcpLCBod25kOiB4aHduZCwgZGlzcGF0Y2hlcjogZCB9KTsKCiAgICAgICAgICAgIHZhciBtc2dSZXQgPSB0aGlzLm1wLmVtaXRfcmV0dXJuVmFsdWUoJ21lc3NhZ2UnKTsKICAgICAgICAgICAgaWYgKG1zZ1JldCA9PSBudWxsKQ0Kew0KICAgICAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gY2FsbCBEZWZXaW5kb3dQcm9jQSwgYmVjdWFzZSB0aGlzIG1lc3NhZ2Ugd2FzIG5vdCBoYW5kbGVkDQogICAgICAgICAgICAgICAgdmFyIHAgPSB0aGlzLm1wLl91c2VyMzIuRGVmV2luZG93UHJvY0EuYXN5bmMoZCwgeGh3bmQsIHhtc2csIHdwYXJhbSwgbHBhcmFtKTsKICAgICAgICAgICAgICAgIHAuZGlzcGF0Y2hlciA9IHRoaXM7CiAgICAgICAgICAgICAgICBwLnRoZW4oZnVuY3Rpb24gKHJldCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hlci5FbmREaXNwYXRjaGVyKHJldCk7DQogICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHZhciByID0gR00uQ3JlYXRlUG9pbnRlcigpOw0KICAgICAgICAgICAgICAgIHIuVmFsID0gbXNnUmV0Ow0KICAgICAgICAgICAgICAgIHRoaXMuRW5kRGlzcGF0Y2hlcihyKTsNCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIF9kZWJ1Z0dDKCk7CiAgICB9KTsKCiAgICB0aGlzLl91c2VyMzIuUmVnaXN0ZXJDbGFzc0V4QS5hc3luYyh0aGlzLnduZGNsYXNzKS50aGVuKGZ1bmN0aW9uICgpCiAgICB7CiAgICAgICAgaWYgKCF0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zKSAgeyAgIHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMgPSB7fTsgIH0KICAgICAgICBpZiAoIXRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93KSB7IHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93ID0ge307IH0KICAgICAgICBpZiAodGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cuZXhzdHlsZXMgPT0gbnVsbCkgeyB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy5leHN0eWxlcyA9IDB4MDAwMDAwODg7IH0gICAgLy8gVG9wTW9zdCBUb29sIFdpbmRvdwogICAgICAgIGlmICh0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy53aW5zdHlsZXMgPT0gbnVsbCkgeyB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy53aW5zdHlsZXMgPSAweDAwODAwMDAwOyB9ICAvLyBXU19CT1JERVIKICAgICAgICBpZiAodGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cueCA9PSBudWxsKSB7IHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LnggPSAwOyB9CiAgICAgICAgaWYgKHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LnkgPT0gbnVsbCkgeyB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy55ID0gMDsgfQogICAgICAgIGlmICh0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy53aWR0aCA9PSBudWxsKSB7IHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LndpZHRoID0gMTAwOyB9CiAgICAgICAgaWYgKHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LmhlaWdodCA9PSBudWxsKSB7IHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LmhlaWdodCA9IDEwMDsgfQoKICAgICAgICB0aGlzLm5hdGl2ZVByb3h5LkNyZWF0ZVdpbmRvd0V4QS5hc3luYyh0aGlzLm5hdGl2ZVByb3h5LlJlZ2lzdGVyQ2xhc3NFeEEuYXN5bmMsIHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LmV4c3R5bGVzLCB0aGlzLm5hdGl2ZVByb3h5Lm1wLnduZGNsYXNzLmNuYW1lLAogICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy50aXRsZSA9PSBudWxsID8gMCA6IEdNLkNyZWF0ZVZhcmlhYmxlKHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LnRpdGxlKSwgdGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cud2luc3R5bGVzLCB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy54LCB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy55LAogICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy53aWR0aCwgdGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cuaGVpZ2h0LCAwLCAwLCAwLCAwKQogICAgICAgICAgICAudGhlbihmdW5jdGlvbihoKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoaC5WYWwgPT0gMCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAvLyBFcnJvciBjcmVhdGluZyBoaWRkZW4gd2luZG93CiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXRpdmVQcm94eS5tcC5lbWl0KCdlcnJvcicsICdFcnJvciBjcmVhdGluZyBoaWRkZW4gd2luZG93Jyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXRpdmVQcm94eS5tcC5faHduZCA9IGg7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXRpdmVQcm94eS5tcC5lbWl0KCdod25kJywgaCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXRpdmVQcm94eS5tcC5fc3RhcnRQdW1wKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgfSk7CiAgICB0aGlzLl9zdGFydFB1bXAgPSBmdW5jdGlvbiBfc3RhcnRQdW1wKCkKICAgIHsKICAgICAgICB0aGlzLl91c2VyMzIuR2V0TWVzc2FnZUEuYXN5bmModGhpcy5fdXNlcjMyLlJlZ2lzdGVyQ2xhc3NFeEEuYXN5bmMsIHRoaXMuX21zZywgdGhpcy5faHduZCwgMCwgMCkudGhlbihmdW5jdGlvbiAocikKICAgICAgICB7CiAgICAgICAgICAgIGlmKHIuVmFsID4gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdGhpcy5uYXRpdmVQcm94eS5UcmFuc2xhdGVNZXNzYWdlLmFzeW5jKHRoaXMubmF0aXZlUHJveHkuUmVnaXN0ZXJDbGFzc0V4QS5hc3luYywgdGhpcy5uYXRpdmVQcm94eS5tcC5fbXNnKS50aGVuKGZ1bmN0aW9uICgpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXRpdmVQcm94eS5EaXNwYXRjaE1lc3NhZ2VBLmFzeW5jKHRoaXMubmF0aXZlUHJveHkuUmVnaXN0ZXJDbGFzc0V4QS5hc3luYywgdGhpcy5uYXRpdmVQcm94eS5tcC5fbXNnKS50aGVuKGZ1bmN0aW9uICgpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9zdGFydFB1bXAoKTsNCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIFdlIGdvdCBhICdRVUlUJyBtZXNzYWdlCiAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5LkRlc3Ryb3lXaW5kb3cuYXN5bmModGhpcy5uYXRpdmVQcm94eS5SZWdpc3RlckNsYXNzRXhBLmFzeW5jLCB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9od25kKS50aGVuKGZ1bmN0aW9uICgpCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkuUmVnaXN0ZXJDbGFzc0V4QS5hc3luYy5hYm9ydCgpOwogICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9od25kOwogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkubXAuZW1pdCgnZXhpdCcsIDApOw0KDQogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkubXAud25kY2xhc3Mud25kcHJvYy5yZW1vdmVBbGxMaXN0ZW5lcnMoJ0dsb2JhbENhbGxiYWNrJyk7DQogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkubXAud25kY2xhc3Mud25kcHJvYyA9IG51bGw7DQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICB9LCBmdW5jdGlvbiAoZXJyKSB7IHRoaXMubmF0aXZlUHJveHkubXAuc3RvcCgpOyB9KTsKICAgIH0KCiAgICB0aGlzLnN0b3AgPSBmdW5jdGlvbiBzdG9wKCkKICAgIHsKICAgICAgICBpZiAodGhpcy5faHduZCkKICAgICAgICB7CiAgICAgICAgICAgIHRoaXMuX3VzZXIzMi5Qb3N0TWVzc2FnZUEodGhpcy5faHduZCwgV01fUVVJVCwgMCwgMCk7CiAgICAgICAgICAgIHRoaXMub25jZSgnZXhpdCcsIGZ1bmN0aW9uICgpIHsgdGhpcy53bmRjbGFzcy53bmRwcm9jLmNsb3NlKCkgfSk7CiAgICAgICAgfQogICAgfTsKICAgIHRoaXMuY2xvc2UgPSBmdW5jdGlvbiBjbG9zZSgpCiAgICB7CiAgICAgICAgaWYgKHRoaXMuX2h3bmQpCiAgICAgICAgewogICAgICAgICAgICB0aGlzLl91c2VyMzIuUG9zdE1lc3NhZ2VBKHRoaXMuX2h3bmQsIFdNX0NMT1NFLCAwLCAwKTsKICAgICAgICAgICAgdGhpcy5vbmNlKCdleGl0JywgZnVuY3Rpb24gKCkgeyB0aGlzLnduZGNsYXNzLnduZHByb2MuY2xvc2UoKTsgfSk7CiAgICAgICAgfQogICAgfTsKICAgIHRoaXMub25jZSgnficsIGZ1bmN0aW9uICgpCiAgICB7DQogICAgICAgIHRoaXMuc3RvcCgpOw0KICAgIH0pOwp9Cgptb2R1bGUuZXhwb3J0cyA9IFdpbmRvd3NNZXNzYWdlUHVtcDsKbW9kdWxlLmV4cG9ydHMuV2luZG93U3R5bGVzID0KICAgIHsNCiAgICAgICAgV1NfQk9SREVSOiAweDAwODAwMDAwLCBXU19DQVBUSU9OOiAweDAwQzAwMDAwLCBXU19DSElMRDogMHg0MDAwMDAwMCwgV1NfQ0hJTERXSU5ET1c6IDB4NDAwMDAwMDAsIFdTX0NMSVBDSElMRFJFTjogMHgwMjAwMDAwMCwKICAgICAgICBXU19DTElQU0lCTElOR1M6IDB4MDQwMDAwMDAsIFdTX0RJU0FCTEVEOiAweDA4MDAwMDAwLCBXU19ETEdGUkFNRTogMHgwMDQwMDAwMCwgV1NfR1JPVVA6IDB4MDAwMjAwMDAsIFdTX0hTQ1JPTEw6IDB4MDAxMDAwMDAsCiAgICAgICAgV1NfSUNPTklDOiAweDIwMDAwMDAwLCBXU19NQVhJTUlaRTogMHgwMTAwMDAwMCwgV1NfTUFYSU1JWkVCT1g6IDB4MDAwMTAwMDAsIFdTX01JTklNSVpFOiAweDIwMDAwMDAwLCBXU19NSU5JTUlaRUJPWDogMHgwMDAyMDAwMCwKICAgICAgICBXU19PVkVSTEFQUEVEOiAweDAwMDAwMDAwLCBXU19QT1BVUDogMHg4MDAwMDAwMCwgV1NfU0laRUJPWDogMHgwMDA0MDAwMCwgV1NfU1lTTUVOVTogMHgwMDA4MDAwMCwgV1NfVEFCU1RPUDogMHgwMDAxMDAwMCwKICAgICAgICBXU19USElDS0ZSQU1FOiAweDAwMDQwMDAwLCBXU19USUxFRDogMHgwMDAwMDAwMCwgV1NfVklTSUJMRTogMHgxMDAwMDAwMCwgV1NfVlNDUk9MTDogMHgwMDIwMDAwMA0KICAgIH07Cm1vZHVsZS5leHBvcnRzLldpbmRvd1N0eWxlc0V4ID0KICAgIHsNCiAgICAgICAgV1NfRVhfQUNDRVBURklMRVM6IDB4MDAwMDAwMTAsIFdTX0VYX0FQUFdJTkRPVzogMHgwMDA0MDAwMCwgV1NfRVhfQ0xJRU5URURHRTogMHgwMDAwMDIwMCwgV1NfRVhfQ09NUE9TSVRFRDogMHgwMjAwMDAwMCwNCiAgICAgICAgV1NfRVhfQ09OVEVYVEhFTFA6IDB4MDAwMDA0MDAsIFdTX0VYX0NPTlRST0xQQVJFTlQ6IDB4MDAwMTAwMDAsIFdTX0VYX0RMR01PREFMRlJBTUU6IDB4MDAwMDAwMDEsIFdTX0VYX0xBWUVSRUQ6IDB4MDAwODAwMCwNCiAgICAgICAgV1NfRVhfTEFZT1VUUlRMOiAweDAwNDAwMDAwLCBXU19FWF9MRUZUOiAweDAwMDAwMDAwLCBXU19FWF9MRUZUU0NST0xMQkFSOiAweDAwMDA0MDAwLCBXU19FWF9MVFJSRUFESU5HOiAweDAwMDAwMDAwLA0KICAgICAgICBXU19FWF9NRElDSElMRDogMHgwMDAwMDA0MCwgV1NfRVhfTk9BQ1RJVkFURTogMHgwODAwMDAwMCwgV1NfRVhfTk9JTkhFUklUTEFZT1VUOiAweDAwMTAwMDAwLCBXU19FWF9OT1BBUkVOVE5PVElGWTogMHgwMDAwMDAwNCwNCiAgICAgICAgV1NfRVhfTk9SRURJUkVDVElPTkJJVE1BUDogMHgwMDIwMDAwMCwgV1NfRVhfUklHSFQ6IDB4MDAwMDEwMDAsIFdTX0VYX1JJR0hUU0NST0xMQkFSOiAweDAwMDAwMDAwLCBXU19FWF9SVExSRUFESU5HOiAweDAwMDAyMDAwLA0KICAgICAgICBXU19FWF9TVEFUSUNFREdFOiAweDAwMDIwMDAwLCBXU19FWF9UT09MV0lORE9XOiAweDAwMDAwMDgwLCBXU19FWF9UT1BNT1NUOiAweDAwMDAwMDA4LCBXU19FWF9UUkFOU1BBUkVOVDogMHgwMDAwMDAyMCwgV1NfRVhfV0lORE9XRURHRTogMHgwMDAwMDEwMA0KICAgIH07Cv==', 'base64').toString());"); + duk_peval_string_noresult(ctx, "addModule('win-message-pump', Buffer.from('LyoNCkNvcHlyaWdodCAyMDE4IEludGVsIENvcnBvcmF0aW9uDQoNCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOw0KeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLg0KWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0DQoNCiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjANCg0KVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQ0KZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywNCldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLg0KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZA0KbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuDQoqLw0KDQp2YXIgV0hfQ0FMTFdORFBST0MgPSA0Ow0KdmFyIFdNX1FVSVQgPSAgMHgwMDEyOw0KdmFyIFdNX0NMT1NFID0gMHgwMDEwOw0KdmFyIEdNID0gcmVxdWlyZSgnX0dlbmVyaWNNYXJzaGFsJyk7DQoNCmZ1bmN0aW9uIFdpbmRvd3NNZXNzYWdlUHVtcChvcHRpb25zKQ0Kew0KICAgIHRoaXMuX09iamVjdElEID0gJ3dpbi1tZXNzYWdlLXB1bXAnOw0KICAgIHRoaXMuX29wdGlvbnMgPSBvcHRpb25zOw0KICAgIHZhciBlbWl0dGVyVXRpbHMgPSByZXF1aXJlKCdldmVudHMnKS5pbmhlcml0cyh0aGlzKTsNCiAgICBlbWl0dGVyVXRpbHMuY3JlYXRlRXZlbnQoJ2h3bmQnKTsNCiAgICBlbWl0dGVyVXRpbHMuY3JlYXRlRXZlbnQoJ2Vycm9yJyk7DQogICAgZW1pdHRlclV0aWxzLmNyZWF0ZUV2ZW50KCdtZXNzYWdlJyk7DQogICAgZW1pdHRlclV0aWxzLmNyZWF0ZUV2ZW50KCdleGl0Jyk7DQoNCiAgICB0aGlzLl9tc2cgPSBHTS5DcmVhdGVWYXJpYWJsZShHTS5Qb2ludGVyU2l6ZSA9PSA0ID8gMjggOiA0OCk7DQogICAgdGhpcy5fa2VybmVsMzIgPSBHTS5DcmVhdGVOYXRpdmVQcm94eSgnS2VybmVsMzIuZGxsJyk7DQogICAgdGhpcy5fa2VybmVsMzIubXAgPSB0aGlzOw0KICAgIHRoaXMuX2tlcm5lbDMyLkNyZWF0ZU1ldGhvZCgnR2V0TGFzdEVycm9yJyk7DQogICAgdGhpcy5fa2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdHZXRNb2R1bGVIYW5kbGVBJyk7DQoNCiAgICB0aGlzLl91c2VyMzIgPSBHTS5DcmVhdGVOYXRpdmVQcm94eSgnVXNlcjMyLmRsbCcpOw0KICAgIHRoaXMuX3VzZXIzMi5tcCA9IHRoaXM7DQogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnQ3JlYXRlV2luZG93RXhBJyk7DQogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnRGVmV2luZG93UHJvY0EnKTsNCiAgICB0aGlzLl91c2VyMzIuQ3JlYXRlTWV0aG9kKCdEZXN0cm95V2luZG93Jyk7DQogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnRGlzcGF0Y2hNZXNzYWdlQScpOw0KICAgIHRoaXMuX3VzZXIzMi5DcmVhdGVNZXRob2QoJ0dldE1lc3NhZ2VBJyk7DQogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnUG9zdE1lc3NhZ2VBJyk7DQogICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgnUmVnaXN0ZXJDbGFzc0V4QScpOw0KICAgIHRoaXMuX3VzZXIzMi5DcmVhdGVNZXRob2QoJ1NldFdpbmRvd1BvcycpOw0KICAgIHRoaXMuX3VzZXIzMi5DcmVhdGVNZXRob2QoJ1Nob3dXaW5kb3cnKTsNCiAgICB0aGlzLl91c2VyMzIuQ3JlYXRlTWV0aG9kKCdUcmFuc2xhdGVNZXNzYWdlJyk7DQoNCg0KICAgIHRoaXMud25kY2xhc3MgPSBHTS5DcmVhdGVWYXJpYWJsZShHTS5Qb2ludGVyU2l6ZSA9PSA0ID8gNDggOiA4MCk7DQogICAgdGhpcy53bmRjbGFzcy5tcCA9IHRoaXM7DQogICAgdGhpcy53bmRjbGFzcy5oaW5zdGFuY2UgPSB0aGlzLl9rZXJuZWwzMi5HZXRNb2R1bGVIYW5kbGVBKDApOw0KICAgIHRoaXMud25kY2xhc3MuY25hbWUgPSBHTS5DcmVhdGVWYXJpYWJsZSgnTWFpbldXV0NsYXNzJyk7DQogICAgdGhpcy53bmRjbGFzcy53bmRwcm9jID0gR00uR2V0R2VuZXJpY0dsb2JhbENhbGxiYWNrKDQpOw0KICAgIHRoaXMud25kY2xhc3Mud25kcHJvYy5tcCA9IHRoaXM7DQogICAgdGhpcy53bmRjbGFzcy50b0J1ZmZlcigpLndyaXRlVUludDMyTEUodGhpcy53bmRjbGFzcy5fc2l6ZSk7DQogICAgdGhpcy53bmRjbGFzcy5jbmFtZS5wb2ludGVyQnVmZmVyKCkuY29weSh0aGlzLnduZGNsYXNzLkRlcmVmKEdNLlBvaW50ZXJTaXplID09IDQgPyA0MCA6IDY0LCBHTS5Qb2ludGVyU2l6ZSkudG9CdWZmZXIoKSk7DQogICAgdGhpcy53bmRjbGFzcy53bmRwcm9jLnBvaW50ZXJCdWZmZXIoKS5jb3B5KHRoaXMud25kY2xhc3MuRGVyZWYoOCwgR00uUG9pbnRlclNpemUpLnRvQnVmZmVyKCkpOw0KICAgIHRoaXMud25kY2xhc3MuaGluc3RhbmNlLnBvaW50ZXJCdWZmZXIoKS5jb3B5KHRoaXMud25kY2xhc3MuRGVyZWYoR00uUG9pbnRlclNpemUgPT0gNCA/IDIwIDogMjQsIEdNLlBvaW50ZXJTaXplKS50b0J1ZmZlcigpKTsNCiAgICB0aGlzLnduZGNsYXNzLnduZHByb2Mub24oJ0dsb2JhbENhbGxiYWNrJywgZnVuY3Rpb24gb25XbmRQcm9jKHhod25kLCB4bXNnLCB3cGFyYW0sIGxwYXJhbSkNCiAgICB7DQogICAgICAgIHZhciBwcm9jZXNzZWQgPSBmYWxzZTsNCiAgICAgICAgaWYgKHRoaXMubXAuX2h3bmQgIT0gbnVsbCAmJiB0aGlzLm1wLl9od25kLlZhbCA9PSB4aHduZC5WYWwpDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIFRoaXMgaXMgZm9yIHVzDQogICAgICAgICAgICBwcm9jZXNzZWQgPSB0cnVlOw0KICAgICAgICAgICAgdmFyIGQgPSB0aGlzLlN0YXJ0RGlzcGF0Y2hlcigpOw0KICAgICAgICAgICAgdGhpcy5tcC5lbWl0KCdtZXNzYWdlJywgeyBtZXNzYWdlOiB4bXNnLlZhbCwgd3BhcmFtOiB3cGFyYW0uVmFsLCBscGFyYW06IGxwYXJhbS5WYWwsIGxwYXJhbV9oZXg6IGxwYXJhbS5wb2ludGVyQnVmZmVyKCkudG9TdHJpbmcoJ2hleCcpLCBscGFyYW1fcmF3OiBscGFyYW0sIGh3bmQ6IHhod25kLCBkaXNwYXRjaGVyOiBkIH0pOw0KDQogICAgICAgICAgICB2YXIgbXNnUmV0ID0gdGhpcy5tcC5lbWl0X3JldHVyblZhbHVlKCdtZXNzYWdlJyk7DQogICAgICAgICAgICBpZiAobXNnUmV0ID09IG51bGwpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgLy8gV2UgbmVlZCB0byBjYWxsIERlZldpbmRvd1Byb2NBLCBiZWN1YXNlIHRoaXMgbWVzc2FnZSB3YXMgbm90IGhhbmRsZWQNCiAgICAgICAgICAgICAgICB2YXIgcCA9IHRoaXMubXAuX3VzZXIzMi5EZWZXaW5kb3dQcm9jQS5hc3luYyhkLCB4aHduZCwgeG1zZywgd3BhcmFtLCBscGFyYW0pOw0KICAgICAgICAgICAgICAgIHAuZGlzcGF0Y2hlciA9IHRoaXM7DQogICAgICAgICAgICAgICAgcC50aGVuKGZ1bmN0aW9uIChyZXQpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoZXIuRW5kRGlzcGF0Y2hlcihyZXQpOw0KICAgICAgICAgICAgICAgIH0pOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHZhciByID0gR00uQ3JlYXRlUG9pbnRlcigpOw0KICAgICAgICAgICAgICAgIHIuVmFsID0gbXNnUmV0Ow0KICAgICAgICAgICAgICAgIHRoaXMuRW5kRGlzcGF0Y2hlcihyKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICBlbHNlIGlmKHRoaXMubXAuX2h3bmQgPT0gbnVsbCAmJiB0aGlzLkNhbGxpbmdUaHJlYWQoKSA9PSB0aGlzLm1wLl91c2VyMzIuUmVnaXN0ZXJDbGFzc0V4QS5hc3luYy50aHJlYWRJZCgpKQ0KICAgICAgICB7DQogICAgICAgICAgICAvLyBUaGlzIG1lc3NhZ2Ugd2FzIGdlbmVyYXRlZCBmcm9tIG91ciBDcmVhdGVXaW5kb3dFeEEgbWV0aG9kDQogICAgICAgICAgICBwcm9jZXNzZWQgPSB0cnVlOw0KDQogICAgICAgICAgICB2YXIgZCA9IHRoaXMuU3RhcnREaXNwYXRjaGVyKCk7DQoNCiAgICAgICAgICAgIHRoaXMubXAuZW1pdCgnbWVzc2FnZScsIHsgbWVzc2FnZTogeG1zZy5WYWwsIHdwYXJhbTogd3BhcmFtLlZhbCwgbHBhcmFtOiBscGFyYW0uVmFsLCBscGFyYW1faGV4OiBscGFyYW0ucG9pbnRlckJ1ZmZlcigpLnRvU3RyaW5nKCdoZXgnKSwgaHduZDogeGh3bmQsIGRpc3BhdGNoZXI6IGQgfSk7DQoNCiAgICAgICAgICAgIHZhciBtc2dSZXQgPSB0aGlzLm1wLmVtaXRfcmV0dXJuVmFsdWUoJ21lc3NhZ2UnKTsNCiAgICAgICAgICAgIGlmIChtc2dSZXQgPT0gbnVsbCkNCnsNCiAgICAgICAgICAgICAgICAvLyBXZSBuZWVkIHRvIGNhbGwgRGVmV2luZG93UHJvY0EsIGJlY3Vhc2UgdGhpcyBtZXNzYWdlIHdhcyBub3QgaGFuZGxlZA0KICAgICAgICAgICAgICAgIHZhciBwID0gdGhpcy5tcC5fdXNlcjMyLkRlZldpbmRvd1Byb2NBLmFzeW5jKGQsIHhod25kLCB4bXNnLCB3cGFyYW0sIGxwYXJhbSk7DQogICAgICAgICAgICAgICAgcC5kaXNwYXRjaGVyID0gdGhpczsNCiAgICAgICAgICAgICAgICBwLnRoZW4oZnVuY3Rpb24gKHJldCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hlci5FbmREaXNwYXRjaGVyKHJldCk7DQogICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgdmFyIHIgPSBHTS5DcmVhdGVQb2ludGVyKCk7DQogICAgICAgICAgICAgICAgci5WYWwgPSBtc2dSZXQ7DQogICAgICAgICAgICAgICAgdGhpcy5FbmREaXNwYXRjaGVyKHIpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKHByb2Nlc3NlZCkgeyBfZGVidWdHQygpOyB9DQogICAgfSk7DQoNCiAgICB0aGlzLl91c2VyMzIuUmVnaXN0ZXJDbGFzc0V4QS5hc3luYyh0aGlzLnduZGNsYXNzKS50aGVuKGZ1bmN0aW9uICgpDQogICAgew0KICAgICAgICBpZiAoIXRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMpICB7ICAgdGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucyA9IHt9OyAgfQ0KICAgICAgICBpZiAoIXRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93KSB7IHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93ID0ge307IH0NCiAgICAgICAgaWYgKHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LmV4c3R5bGVzID09IG51bGwpIHsgdGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cuZXhzdHlsZXMgPSAweDAwMDAwMDg4OyB9ICAgIC8vIFRvcE1vc3QgVG9vbCBXaW5kb3cNCiAgICAgICAgaWYgKHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LndpbnN0eWxlcyA9PSBudWxsKSB7IHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LndpbnN0eWxlcyA9IDB4MDA4MDAwMDA7IH0gIC8vIFdTX0JPUkRFUg0KICAgICAgICBpZiAodGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cueCA9PSBudWxsKSB7IHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LnggPSAwOyB9DQogICAgICAgIGlmICh0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy55ID09IG51bGwpIHsgdGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cueSA9IDA7IH0NCiAgICAgICAgaWYgKHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LndpZHRoID09IG51bGwpIHsgdGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cud2lkdGggPSAxMDA7IH0NCiAgICAgICAgaWYgKHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LmhlaWdodCA9PSBudWxsKSB7IHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LmhlaWdodCA9IDEwMDsgfQ0KDQogICAgICAgIHRoaXMubmF0aXZlUHJveHkuQ3JlYXRlV2luZG93RXhBLmFzeW5jKHRoaXMubmF0aXZlUHJveHkuUmVnaXN0ZXJDbGFzc0V4QS5hc3luYywgdGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cuZXhzdHlsZXMsIHRoaXMubmF0aXZlUHJveHkubXAud25kY2xhc3MuY25hbWUsDQogICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy50aXRsZSA9PSBudWxsID8gMCA6IEdNLkNyZWF0ZVZhcmlhYmxlKHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LnRpdGxlKSwgdGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cud2luc3R5bGVzLCB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy54LCB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9vcHRpb25zLndpbmRvdy55LA0KICAgICAgICAgICAgdGhpcy5uYXRpdmVQcm94eS5tcC5fb3B0aW9ucy53aW5kb3cud2lkdGgsIHRoaXMubmF0aXZlUHJveHkubXAuX29wdGlvbnMud2luZG93LmhlaWdodCwgMCwgMCwgMCwgMCkNCiAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uKGgpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYgKGguVmFsID09IDApDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAvLyBFcnJvciBjcmVhdGluZyBoaWRkZW4gd2luZG93DQogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkubXAuZW1pdCgnZXJyb3InLCAnRXJyb3IgY3JlYXRpbmcgaGlkZGVuIHdpbmRvdycpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9od25kID0gaDsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXRpdmVQcm94eS5tcC5lbWl0KCdod25kJywgaCk7DQogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkubXAuX3N0YXJ0UHVtcCgpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0pOw0KICAgIH0pOw0KICAgIHRoaXMuX3N0YXJ0UHVtcCA9IGZ1bmN0aW9uIF9zdGFydFB1bXAoKQ0KICAgIHsNCiAgICAgICAgdGhpcy5fdXNlcjMyLkdldE1lc3NhZ2VBLmFzeW5jKHRoaXMuX3VzZXIzMi5SZWdpc3RlckNsYXNzRXhBLmFzeW5jLCB0aGlzLl9tc2csIHRoaXMuX2h3bmQsIDAsIDApLnRoZW4oZnVuY3Rpb24gKHIpDQogICAgICAgIHsNCiAgICAgICAgICAgIGlmKHIuVmFsID4gMCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5LlRyYW5zbGF0ZU1lc3NhZ2UuYXN5bmModGhpcy5uYXRpdmVQcm94eS5SZWdpc3RlckNsYXNzRXhBLmFzeW5jLCB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9tc2cpLnRoZW4oZnVuY3Rpb24gKCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkuRGlzcGF0Y2hNZXNzYWdlQS5hc3luYyh0aGlzLm5hdGl2ZVByb3h5LlJlZ2lzdGVyQ2xhc3NFeEEuYXN5bmMsIHRoaXMubmF0aXZlUHJveHkubXAuX21zZykudGhlbihmdW5jdGlvbiAoKQ0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9zdGFydFB1bXAoKTsNCiAgICAgICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgLy8gV2UgZ290IGEgJ1FVSVQnIG1lc3NhZ2UNCiAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5LkRlc3Ryb3lXaW5kb3cuYXN5bmModGhpcy5uYXRpdmVQcm94eS5SZWdpc3RlckNsYXNzRXhBLmFzeW5jLCB0aGlzLm5hdGl2ZVByb3h5Lm1wLl9od25kKS50aGVuKGZ1bmN0aW9uICgpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZVByb3h5LlJlZ2lzdGVyQ2xhc3NFeEEuYXN5bmMuYWJvcnQoKTsNCiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMubmF0aXZlUHJveHkubXAuX2h3bmQ7DQogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkubXAuZW1pdCgnZXhpdCcsIDApOw0KDQogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkubXAud25kY2xhc3Mud25kcHJvYy5yZW1vdmVBbGxMaXN0ZW5lcnMoJ0dsb2JhbENhbGxiYWNrJyk7DQogICAgICAgICAgICAgICAgICAgIHRoaXMubmF0aXZlUHJveHkubXAud25kY2xhc3Mud25kcHJvYyA9IG51bGw7DQogICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICB9DQogICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHsgdGhpcy5uYXRpdmVQcm94eS5tcC5zdG9wKCk7IH0pOw0KICAgIH0NCg0KICAgIHRoaXMuc3RvcCA9IGZ1bmN0aW9uIHN0b3AoKQ0KICAgIHsNCiAgICAgICAgaWYgKHRoaXMuX2h3bmQpDQogICAgICAgIHsNCiAgICAgICAgICAgIHRoaXMuX3VzZXIzMi5Qb3N0TWVzc2FnZUEodGhpcy5faHduZCwgV01fUVVJVCwgMCwgMCk7DQogICAgICAgICAgICB0aGlzLm9uY2UoJ2V4aXQnLCBmdW5jdGlvbiAoKSB7IHRoaXMud25kY2xhc3Mud25kcHJvYy5jbG9zZSgpIH0pOw0KICAgICAgICB9DQogICAgfTsNCiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24gY2xvc2UoKQ0KICAgIHsNCiAgICAgICAgaWYgKHRoaXMuX2h3bmQpDQogICAgICAgIHsNCiAgICAgICAgICAgIHRoaXMuX3VzZXIzMi5Qb3N0TWVzc2FnZUEodGhpcy5faHduZCwgV01fQ0xPU0UsIDAsIDApOw0KICAgICAgICAgICAgdGhpcy5vbmNlKCdleGl0JywgZnVuY3Rpb24gKCkgeyB0aGlzLnduZGNsYXNzLnduZHByb2MuY2xvc2UoKTsgfSk7DQogICAgICAgIH0NCiAgICB9Ow0KICAgIHRoaXMub25jZSgnficsIGZ1bmN0aW9uICgpDQogICAgew0KICAgICAgICB0aGlzLnN0b3AoKTsNCiAgICB9KTsNCn0NCg0KbW9kdWxlLmV4cG9ydHMgPSBXaW5kb3dzTWVzc2FnZVB1bXA7DQptb2R1bGUuZXhwb3J0cy5XaW5kb3dTdHlsZXMgPQ0KICAgIHsNCiAgICAgICAgV1NfQk9SREVSOiAweDAwODAwMDAwLCBXU19DQVBUSU9OOiAweDAwQzAwMDAwLCBXU19DSElMRDogMHg0MDAwMDAwMCwgV1NfQ0hJTERXSU5ET1c6IDB4NDAwMDAwMDAsIFdTX0NMSVBDSElMRFJFTjogMHgwMjAwMDAwMCwNCiAgICAgICAgV1NfQ0xJUFNJQkxJTkdTOiAweDA0MDAwMDAwLCBXU19ESVNBQkxFRDogMHgwODAwMDAwMCwgV1NfRExHRlJBTUU6IDB4MDA0MDAwMDAsIFdTX0dST1VQOiAweDAwMDIwMDAwLCBXU19IU0NST0xMOiAweDAwMTAwMDAwLA0KICAgICAgICBXU19JQ09OSUM6IDB4MjAwMDAwMDAsIFdTX01BWElNSVpFOiAweDAxMDAwMDAwLCBXU19NQVhJTUlaRUJPWDogMHgwMDAxMDAwMCwgV1NfTUlOSU1JWkU6IDB4MjAwMDAwMDAsIFdTX01JTklNSVpFQk9YOiAweDAwMDIwMDAwLA0KICAgICAgICBXU19PVkVSTEFQUEVEOiAweDAwMDAwMDAwLCBXU19QT1BVUDogMHg4MDAwMDAwMCwgV1NfU0laRUJPWDogMHgwMDA0MDAwMCwgV1NfU1lTTUVOVTogMHgwMDA4MDAwMCwgV1NfVEFCU1RPUDogMHgwMDAxMDAwMCwNCiAgICAgICAgV1NfVEhJQ0tGUkFNRTogMHgwMDA0MDAwMCwgV1NfVElMRUQ6IDB4MDAwMDAwMDAsIFdTX1ZJU0lCTEU6IDB4MTAwMDAwMDAsIFdTX1ZTQ1JPTEw6IDB4MDAyMDAwMDANCiAgICB9Ow0KbW9kdWxlLmV4cG9ydHMuV2luZG93U3R5bGVzRXggPQ0KICAgIHsNCiAgICAgICAgV1NfRVhfQUNDRVBURklMRVM6IDB4MDAwMDAwMTAsIFdTX0VYX0FQUFdJTkRPVzogMHgwMDA0MDAwMCwgV1NfRVhfQ0xJRU5URURHRTogMHgwMDAwMDIwMCwgV1NfRVhfQ09NUE9TSVRFRDogMHgwMjAwMDAwMCwNCiAgICAgICAgV1NfRVhfQ09OVEVYVEhFTFA6IDB4MDAwMDA0MDAsIFdTX0VYX0NPTlRST0xQQVJFTlQ6IDB4MDAwMTAwMDAsIFdTX0VYX0RMR01PREFMRlJBTUU6IDB4MDAwMDAwMDEsIFdTX0VYX0xBWUVSRUQ6IDB4MDAwODAwMCwNCiAgICAgICAgV1NfRVhfTEFZT1VUUlRMOiAweDAwNDAwMDAwLCBXU19FWF9MRUZUOiAweDAwMDAwMDAwLCBXU19FWF9MRUZUU0NST0xMQkFSOiAweDAwMDA0MDAwLCBXU19FWF9MVFJSRUFESU5HOiAweDAwMDAwMDAwLA0KICAgICAgICBXU19FWF9NRElDSElMRDogMHgwMDAwMDA0MCwgV1NfRVhfTk9BQ1RJVkFURTogMHgwODAwMDAwMCwgV1NfRVhfTk9JTkhFUklUTEFZT1VUOiAweDAwMTAwMDAwLCBXU19FWF9OT1BBUkVOVE5PVElGWTogMHgwMDAwMDAwNCwNCiAgICAgICAgV1NfRVhfTk9SRURJUkVDVElPTkJJVE1BUDogMHgwMDIwMDAwMCwgV1NfRVhfUklHSFQ6IDB4MDAwMDEwMDAsIFdTX0VYX1JJR0hUU0NST0xMQkFSOiAweDAwMDAwMDAwLCBXU19FWF9SVExSRUFESU5HOiAweDAwMDAyMDAwLA0KICAgICAgICBXU19FWF9TVEFUSUNFREdFOiAweDAwMDIwMDAwLCBXU19FWF9UT09MV0lORE9XOiAweDAwMDAwMDgwLCBXU19FWF9UT1BNT1NUOiAweDAwMDAwMDA4LCBXU19FWF9UUkFOU1BBUkVOVDogMHgwMDAwMDAyMCwgV1NfRVhfV0lORE9XRURHRTogMHgwMDAwMDEwMA0KICAgIH07DQo=', 'base64').toString());"); duk_peval_string_noresult(ctx, "addModule('win-console', Buffer.from('LyoKQ29weXJpZ2h0IDIwMTggSW50ZWwgQ29ycG9yYXRpb24KCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQpkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLApXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZApsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKi8KCnZhciBUcmF5SWNvbkZsYWdzID0KICAgIHsKICAgICAgICBOSUZfTUVTU0FHRTogMHgwMDAwMDAwMSwKICAgICAgICBOSUZfSUNPTjogMHgwMDAwMDAwMiwKICAgICAgICBOSUZfVElQOiAweDAwMDAwMDA0LAogICAgICAgIE5JRl9TVEFURTogMHgwMDAwMDAwOCwKICAgICAgICBOSUZfSU5GTzogMHgwMDAwMDAxMCwKICAgICAgICBOSUZfR1VJRDogMHgwMDAwMDAyMCwKICAgICAgICBOSUZfUkVBTFRJTUU6IDB4MDAwMDAwNDAsCiAgICAgICAgTklGX1NIT1dUSVA6IDB4MDAwMDAwODAsCgogICAgICAgIE5JTV9BREQ6IDB4MDAwMDAwMDAsCiAgICAgICAgTklNX01PRElGWTogMHgwMDAwMDAwMSwKICAgICAgICBOSU1fREVMRVRFOiAweDAwMDAwMDAyLAogICAgICAgIE5JTV9TRVRGT0NVUzogMHgwMDAwMDAwMywKICAgICAgICBOSU1fU0VUVkVSU0lPTjogMHgwMDAwMDAwNAogICAgfTsKdmFyIE5PVElGWUlDT05fVkVSU0lPTl80ID0gNDsKdmFyIE1lc3NhZ2VUeXBlcyA9IHsgV01fQVBQOiAweDgwMDAsIFdNX1VTRVI6IDB4MDQwMCB9OwpmdW5jdGlvbiBXaW5kb3dzQ29uc29sZSgpCnsKICAgIGlmIChwcm9jZXNzLnBsYXRmb3JtID09ICd3aW4zMicpCiAgICB7CiAgICAgICAgdGhpcy5fT2JqZWN0SUQgPSAnd2luLWNvbnNvbGUnOwogICAgICAgIHRoaXMuX01hcnNoYWwgPSByZXF1aXJlKCdfR2VuZXJpY01hcnNoYWwnKTsKICAgICAgICB0aGlzLl9rZXJuZWwzMiA9IHRoaXMuX01hcnNoYWwuQ3JlYXRlTmF0aXZlUHJveHkoImtlcm5lbDMyLmRsbCIpOwogICAgICAgIHRoaXMuX3VzZXIzMiA9IHRoaXMuX01hcnNoYWwuQ3JlYXRlTmF0aXZlUHJveHkoInVzZXIzMi5kbGwiKTsKICAgICAgICB0aGlzLl9rZXJuZWwzMi5DcmVhdGVNZXRob2QoIkdldENvbnNvbGVXaW5kb3ciKTsKICAgICAgICB0aGlzLl9rZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0dldEN1cnJlbnRUaHJlYWQnKTsKICAgICAgICB0aGlzLl91c2VyMzIuQ3JlYXRlTWV0aG9kKCJTaG93V2luZG93Iik7CiAgICAgICAgdGhpcy5fdXNlcjMyLkNyZWF0ZU1ldGhvZCgiTG9hZEltYWdlQSIpOwogICAgICAgIHRoaXMuX3VzZXIzMi5DcmVhdGVNZXRob2QoeyBtZXRob2Q6ICdHZXRNZXNzYWdlQScsIHRocmVhZERpc3BhdGNoOiAxIH0pOwogICAgICAgIHRoaXMuX3NoZWxsMzIgPSB0aGlzLl9NYXJzaGFsLkNyZWF0ZU5hdGl2ZVByb3h5KCdTaGVsbDMyLmRsbCcpOwogICAgICAgIHRoaXMuX3NoZWxsMzIuQ3JlYXRlTWV0aG9kKCdTaGVsbF9Ob3RpZnlJY29uQScpOwoKICAgICAgICB0aGlzLl9oYW5kbGUgPSB0aGlzLl9rZXJuZWwzMi5HZXRDb25zb2xlV2luZG93KCk7CiAgICAgICAgdGhpcy5taW5pbWl6ZSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgdGhpcy5fdXNlcjMyLlNob3dXaW5kb3codGhpcy5faGFuZGxlLCA2KTsKICAgICAgICB9OwogICAgICAgIHRoaXMucmVzdG9yZSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgdGhpcy5fdXNlcjMyLlNob3dXaW5kb3codGhpcy5faGFuZGxlLCA5KTsKICAgICAgICB9OwogICAgICAgIHRoaXMuaGlkZSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgdGhpcy5fdXNlcjMyLlNob3dXaW5kb3codGhpcy5faGFuZGxlLCAwKTsKICAgICAgICB9OwogICAgICAgIHRoaXMuc2hvdyA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgdGhpcy5fdXNlcjMyLlNob3dXaW5kb3codGhpcy5faGFuZGxlLCA1KTsKICAgICAgICB9OwoKCiAgICAgICAgdGhpcy5fbG9hZGljb24gPSBmdW5jdGlvbiAoaW1hZ2VQYXRoKSB7CiAgICAgICAgICAgIHZhciBoID0gdGhpcy5fdXNlcjMyLkxvYWRJbWFnZUEoMCwgdGhpcy5fTWFyc2hhbC5DcmVhdGVWYXJpYWJsZShpbWFnZVBhdGgpLCAxLCAwLCAwLCAweDAwMDAwMDEwIHwgMHgwMDAwODAwMCB8IDB4MDAwMDAwNDApOyAvLyBMUl9MT0FERlJPTUZJTEUgfCBMUl9TSEFSRUQgfCBMUl9ERUZBVUxUU0laRQogICAgICAgICAgICByZXR1cm4gKGgpOwogICAgICAgIH07CgogICAgICAgIHRoaXMuU2V0VHJheUljb24gPSBmdW5jdGlvbiBTZXRUcmF5SWNvbihvcHRpb25zKQogICAgICAgIHsKICAgICAgICAgICAgdmFyIGRhdGEgPSB0aGlzLl9NYXJzaGFsLkNyZWF0ZVZhcmlhYmxlKHRoaXMuX01hcnNoYWwuUG9pbnRlclNpemUgPT0gNCA/IDUwOCA6IDUyOCk7CiAgICAgICAgICAgIC8vY29uc29sZS5sb2coJ3N0cnVjdCBzaXplID0gJyArIGRhdGEuX3NpemUpOwogICAgICAgICAgICAvL2NvbnNvbGUubG9nKCdUcnlJY29uLCBXTV9NRVNTQUdFIGZpbHRlciA9ICcgKyBvcHRpb25zLmZpbHRlcik7CiAgICAgICAgICAgIGRhdGEudG9CdWZmZXIoKS53cml0ZVVJbnQzMkxFKGRhdGEuX3NpemUsIDApOwoKICAgICAgICAgICAgdmFyIHRyYXlUeXBlID0gVHJheUljb25GbGFncy5OSUZfVElQIHwgVHJheUljb25GbGFncy5OSUZfTUVTU0FHRQogICAgICAgICAgICBvcHRpb25zLmZpbHRlciA9IE1lc3NhZ2VUeXBlcy5XTV9BUFAgKyAxOwogICAgICAgICAgICBkYXRhLkRlcmVmKHRoaXMuX01hcnNoYWwuUG9pbnRlclNpemUgPT0gNCA/IDE2IDogMjQsIDQpLnRvQnVmZmVyKCkud3JpdGVVSW50MzJMRShvcHRpb25zLmZpbHRlcik7CgogICAgICAgICAgICBpZiAoIW9wdGlvbnMubm9CYWxsb29uKSB7IHRyYXlUeXBlIHw9IFRyYXlJY29uRmxhZ3MuTklGX0lORk87IH0KCiAgICAgICAgICAgIGlmIChvcHRpb25zLmljb24pCiAgICAgICAgICAgIHsgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB0cmF5VHlwZSB8PSBUcmF5SWNvbkZsYWdzLk5JRl9JQ09OOwogICAgICAgICAgICAgICAgdmFyIGhJY29uID0gZGF0YS5EZXJlZih0aGlzLl9NYXJzaGFsLlBvaW50ZXJTaXplID09IDQgPyAyMCA6IDMyLCB0aGlzLl9NYXJzaGFsLlBvaW50ZXJTaXplKTsKICAgICAgICAgICAgICAgIG9wdGlvbnMuaWNvbi5wb2ludGVyQnVmZmVyKCkuY29weShoSWNvbi50b0J1ZmZlcigpKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgZGF0YS5EZXJlZih0aGlzLl9NYXJzaGFsLlBvaW50ZXJTaXplICogMiwgNCkudG9CdWZmZXIoKS53cml0ZVVJbnQzMkxFKDEpOwogICAgICAgICAgICBkYXRhLkRlcmVmKHRoaXMuX01hcnNoYWwuUG9pbnRlclNpemUgPT0gNCA/IDEyIDogMjAsIDQpLnRvQnVmZmVyKCkud3JpdGVVSW50MzJMRSh0cmF5VHlwZSk7CiAgICAgICAgICAgIGRhdGEuRGVyZWYodGhpcy5fTWFyc2hhbC5Qb2ludGVyU2l6ZSA9PSA0ID8gNDE2IDogNDMyLCA0KS50b0J1ZmZlcigpLndyaXRlVUludDMyTEUoTk9USUZZSUNPTl9WRVJTSU9OXzQpOwoKICAgICAgICAgICAgdmFyIHN6VGlwID0gZGF0YS5EZXJlZih0aGlzLl9NYXJzaGFsLlBvaW50ZXJTaXplID09IDQgPyAyNCA6IDQwLCAxMjgpOwogICAgICAgICAgICB2YXIgc3pJbmZvID0gZGF0YS5EZXJlZih0aGlzLl9NYXJzaGFsLlBvaW50ZXJTaXplID09IDQgPyAxNjAgOiAxNzYsIDI1Nik7CiAgICAgICAgICAgIHZhciBzekluZm9UaXRsZSA9IGRhdGEuRGVyZWYodGhpcy5fTWFyc2hhbC5Qb2ludGVyU2l6ZSA9PSA0ID8gNDIwIDogNDM2LCA2NCk7CgogICAgICAgICAgICBpZiAob3B0aW9ucy5zelRpcCkgeyBCdWZmZXIuZnJvbShvcHRpb25zLnN6VGlwKS5jb3B5KHN6VGlwLnRvQnVmZmVyKCkpOyB9CiAgICAgICAgICAgIGlmIChvcHRpb25zLnN6SW5mbykgeyBCdWZmZXIuZnJvbShvcHRpb25zLnN6SW5mbykuY29weShzekluZm8udG9CdWZmZXIoKSk7IH0KICAgICAgICAgICAgaWYgKG9wdGlvbnMuc3pJbmZvVGl0bGUpIHsgQnVmZmVyLmZyb20ob3B0aW9ucy5zekluZm9UaXRsZSkuY29weShzekluZm9UaXRsZS50b0J1ZmZlcigpKTsgfQoKCiAgICAgICAgICAgIHZhciBNZXNzYWdlUHVtcCA9IHJlcXVpcmUoJ3dpbi1tZXNzYWdlLXB1bXAnKTsKICAgICAgICAgICAgcmV0VmFsID0geyBfT2JqZWN0SUQ6ICdXaW5kb3dzQ29uc29sZS5UcmF5SWNvbicsIE1lc3NhZ2VQdW1wOiBuZXcgTWVzc2FnZVB1bXAob3B0aW9ucykgfTsKICAgICAgICAgICAgdmFyIHJldFZhbEV2ZW50cyA9IHJlcXVpcmUoJ2V2ZW50cycpLmluaGVyaXRzKHJldFZhbCk7CiAgICAgICAgICAgIHJldFZhbEV2ZW50cy5jcmVhdGVFdmVudCgnVG9hc3RDbGlja2VkJyk7CiAgICAgICAgICAgIHJldFZhbEV2ZW50cy5jcmVhdGVFdmVudCgnSWNvbkhvdmVyJyk7CiAgICAgICAgICAgIHJldFZhbEV2ZW50cy5jcmVhdGVFdmVudCgnVG9hc3REaXNtaXNzZWQnKTsKICAgICAgICAgICAgcmV0VmFsLk9wdGlvbnMgPSBvcHRpb25zOwogICAgICAgICAgICByZXRWYWwuTWVzc2FnZVB1bXAuVHJheUljb24gPSByZXRWYWw7CiAgICAgICAgICAgIHJldFZhbC5NZXNzYWdlUHVtcC5Ob3RpZnlEYXRhID0gZGF0YTsKICAgICAgICAgICAgcmV0VmFsLk1lc3NhZ2VQdW1wLldpbmRvd3NDb25zb2xlID0gdGhpczsKICAgICAgICAgICAgcmV0VmFsLk1lc3NhZ2VQdW1wLm9uKCdleGl0JywgZnVuY3Rpb24gb25FeGl0KGNvZGUpIHsgY29uc29sZS5sb2coJ1B1bXAgRXhpdGVkJyk7IGlmICh0aGlzLlRyYXlJY29uKSB7IHRoaXMuVHJheUljb24ucmVtb3ZlKCk7IH0gfSk7CiAgICAgICAgICAgIHJldFZhbC5NZXNzYWdlUHVtcC5vbignaHduZCcsIGZ1bmN0aW9uIG9uSHduZChoKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKCdHb3QgSFdORCcpOwogICAgICAgICAgICAgICAgb3B0aW9ucy5od25kID0gaDsKICAgICAgICAgICAgICAgIGgucG9pbnRlckJ1ZmZlcigpLmNvcHkodGhpcy5Ob3RpZnlEYXRhLkRlcmVmKHRoaXMuV2luZG93c0NvbnNvbGUuX01hcnNoYWwuUG9pbnRlclNpemUsIHRoaXMuV2luZG93c0NvbnNvbGUuX01hcnNoYWwuUG9pbnRlclNpemUpLnRvQnVmZmVyKCkpOwoKICAgICAgICAgICAgICAgIGlmKHRoaXMuV2luZG93c0NvbnNvbGUuX3NoZWxsMzIuU2hlbGxfTm90aWZ5SWNvbkEoVHJheUljb25GbGFncy5OSU1fQURELCB0aGlzLk5vdGlmeURhdGEpLlZhbCA9PSAwKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIC8vIFNvbWV0aGluZyB3ZW50IHdyb25nCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICByZXRWYWwuTWVzc2FnZVB1bXAub24oJ21lc3NhZ2UnLCBmdW5jdGlvbiBvbldpbmRvd3NNZXNzYWdlKG1zZykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaWYobXNnLm1lc3NhZ2UgPT0gdGhpcy5UcmF5SWNvbi5PcHRpb25zLmZpbHRlcikKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICB2YXIgaGFuZGxlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGlmIChtc2cud3BhcmFtID09IDEgJiYgbXNnLmxwYXJhbSA9PSAxMDI5KQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5UcmF5SWNvbi5lbWl0KCdUb2FzdENsaWNrZWQnKTsKICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChtc2cud3BhcmFtID09IDEgJiYgbXNnLmxwYXJhbSA9PSA1MTIpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLlRyYXlJY29uLmVtaXQoJ0ljb25Ib3ZlcicpOwogICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuVHJheUljb24uT3B0aW9ucy5iYWxsb29uT25seSAmJiBtc2cud3BhcmFtID09IDEgJiYgKG1zZy5scGFyYW0gPT0gMTAyOCB8fCBtc2cubHBhcmFtID09IDEwMjkpKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5UcmF5SWNvbi5lbWl0KCdUb2FzdERpc21pc3NlZCcpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLlRyYXlJY29uLnJlbW92ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICByZXRWYWwucmVtb3ZlID0gZnVuY3Rpb24gcmVtb3ZlKCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdGhpcy5NZXNzYWdlUHVtcC5XaW5kb3dzQ29uc29sZS5fc2hlbGwzMi5TaGVsbF9Ob3RpZnlJY29uQShUcmF5SWNvbkZsYWdzLk5JTV9ERUxFVEUsIHRoaXMuTWVzc2FnZVB1bXAuTm90aWZ5RGF0YSk7CiAgICAgICAgICAgICAgICB0aGlzLk1lc3NhZ2VQdW1wLnN0b3AoKTsKICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLk1lc3NhZ2VQdW1wLlRyYXlJY29uOwogICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuTWVzc2FnZVB1bXA7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHJldHVybiAocmV0VmFsKTsKICAgICAgICAgICAgCiAgICAgICAgfTsKICAgIH0KfQoKbW9kdWxlLmV4cG9ydHMgPSBuZXcgV2luZG93c0NvbnNvbGUoKTs=', 'base64').toString());"); // Windows Cert Store, refer to modules/win-certstore.js @@ -2421,7 +2424,7 @@ void __stdcall ILibDuktape_DescriptorEvents_WaitHandleSignaled(void *user, BOOLE { if (!ILibMemory_CanaryOK(user)) { return; } ILibDuktape_DescriptorEvents_WindowsWaitHandle *v = (ILibDuktape_DescriptorEvents_WindowsWaitHandle*)user; - ILibChain_RunOnMicrostackThreadEx(v->chain, ILibDuktape_DescriptorEvents_WaitHandle_EventThread, user); + Duktape_RunOnEventLoop(v->chain, duk_ctx_nonce(v->ctx), v->ctx, ILibDuktape_DescriptorEvents_WaitHandle_EventThread, NULL, user); } #endif duk_ret_t ILibDuktape_DescriptorEvents_Add(duk_context *ctx) diff --git a/microscript/ILibDuktape_ReadableStream.c b/microscript/ILibDuktape_ReadableStream.c index 2aa37e9..95ac7e7 100644 --- a/microscript/ILibDuktape_ReadableStream.c +++ b/microscript/ILibDuktape_ReadableStream.c @@ -102,6 +102,7 @@ public: typedef struct ILibDuktape_readableStream_bufferedData { struct ILibDuktape_readableStream_bufferedData *Next; + duk_context *ctx; int bufferLen; int Reserved; char buffer[]; @@ -123,6 +124,7 @@ void ILibDuktape_ReadableStream_DestroyPausedData(ILibDuktape_readableStream *st void ILibDuktape_readableStream_WriteData_buffer(ILibDuktape_readableStream *stream, int streamReserved, char *buffer, int bufferLen) { ILibDuktape_readableStream_bufferedData *buffered = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(bufferLen + sizeof(ILibDuktape_readableStream_bufferedData), 0, NULL, NULL); + buffered->ctx = stream->ctx; buffered->Reserved = streamReserved; buffered->bufferLen = bufferLen; memcpy_s(buffered->buffer, bufferLen, buffer, bufferLen); @@ -282,7 +284,7 @@ void __stdcall ILibDuktape_readableStream_WriteData_OnData_ChainThread_APC(ULONG // This APC interrupted a winsock (select) call, so we must unroll the callstack to continue, // because winsock is not re-entrant, so we cannot risk making another winsock call directly. // - ILibChain_RunOnMicrostackThreadEx2(chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, (void*)obj, 0); + Duktape_RunOnEventLoop(chain, duk_ctx_nonce(data->ctx), data->ctx, ILibDuktape_readableStream_WriteData_OnData_ChainThread, NULL, (void*)obj); } else { @@ -351,13 +353,14 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i if (ILibIsRunningOnChainThread(stream->chain) == 0) { ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, 0, NULL, NULL); + tmp->ctx = stream->ctx; tmp->Next = (ILibDuktape_readableStream_bufferedData*)stream; tmp->Reserved = streamReserved; tmp->bufferLen = bufferLen; memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen); dispatchedNonNative = 1; needPause = 1; - ILibChain_RunOnMicrostackThreadEx(stream->chain, ILibDuktape_readableStream_WriteDataEx_Chain, tmp); + Duktape_RunOnEventLoop(stream->chain, duk_ctx_nonce(stream->ctx), stream->ctx, ILibDuktape_readableStream_WriteDataEx_Chain, NULL, tmp); } else { @@ -423,6 +426,7 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i #else ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, 0, NULL, NULL); #endif + tmp->ctx = stream->ctx; tmp->bufferLen = bufferLen; tmp->Reserved = streamReserved; tmp->Next = (ILibDuktape_readableStream_bufferedData*)stream; @@ -435,7 +439,7 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i QueueUserAPC((PAPCFUNC)ILibDuktape_readableStream_WriteData_OnData_ChainThread_APC, ILibChain_GetMicrostackThreadHandle(stream->chain), (ULONG_PTR)tmp); return(stream->paused); #else - ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, tmp); + Duktape_RunOnEventLoop(stream->chain, duk_ctx_nonce(stream->ctx), stream->ctx, ILibDuktape_readableStream_WriteData_OnData_ChainThread, NULL, tmp); #endif } } @@ -469,7 +473,7 @@ int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream) if (ILibIsRunningOnChainThread(stream->chain) == 0) { // Must context switch to Microstack Thread, in order to dispatch into Java Script - ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteEnd_ChainSink, stream); + Duktape_RunOnEventLoop(stream->chain, duk_ctx_nonce(stream->ctx), stream->ctx, ILibDuktape_readableStream_WriteEnd_ChainSink, NULL, stream); } else { diff --git a/microscript/ILibDuktape_ScriptContainer.c b/microscript/ILibDuktape_ScriptContainer.c index b552883..3706e08 100644 --- a/microscript/ILibDuktape_ScriptContainer.c +++ b/microscript/ILibDuktape_ScriptContainer.c @@ -165,6 +165,7 @@ typedef struct ILibDuktape_ScriptContainer_Master ILibProcessPipe_Process child; void *chain; void *PeerThread, *PeerChain; + duk_context *PeerCTX; unsigned int ChildSecurityFlags; }ILibDuktape_ScriptContainer_Master; @@ -225,7 +226,7 @@ void ILibDuktape_ScriptContainer_Slave_SendJSON(duk_context *ctx) cmd->container.master = master; memcpy_s(cmd->json, jsonLen, json, jsonLen); cmd->json[jsonLen] = 0; - ILibChain_RunOnMicrostackThread2(master->chain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); + Duktape_RunOnEventLoopEx(master->chain, duk_ctx_nonce(master->ctx), master->ctx, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); return; } @@ -496,7 +497,7 @@ void ILibDuktape_ScriptContainer_Process_ExitCallback(void *obj) if (ILibMemory_CanaryOK(obj)) { duk_context *ctx = ((void**)obj)[0]; - duk_destroy_heap(ctx); + Duktape_SafeDestroyHeap(ctx); } } duk_ret_t ILibDuktape_ScriptContainer_Process_Exit(duk_context *ctx) @@ -1313,51 +1314,71 @@ void ILibDuktape_ScriptContainer_ExecTimeout(void *obj) duk_put_prop_string(ctx, -2, ILibDuktape_ScriptContainer_ExitCode); // [g][process] duk_pop_2(ctx); // ... - duk_destroy_heap(ctx); + Duktape_SafeDestroyHeap(ctx); } -SCRIPT_ENGINE_SETTINGS *ILibDuktape_ScriptContainer_GetSettings(duk_context *ctx) +SCRIPT_ENGINE_SETTINGS* ILibDuktape_ScriptContainer_GetSettings(duk_context *ctx) { - SCRIPT_ENGINE_SETTINGS *retVal = (SCRIPT_ENGINE_SETTINGS*)ILibScratchPad; - memset(retVal, 0, sizeof(SCRIPT_ENGINE_SETTINGS)); + SCRIPT_ENGINE_SETTINGS *settings = (SCRIPT_ENGINE_SETTINGS*)ILibMemory_SmartAllocate(sizeof(SCRIPT_ENGINE_SETTINGS)); + memset(settings, 0, sizeof(SCRIPT_ENGINE_SETTINGS)); - retVal->chain = Duktape_GetChain(ctx); + settings->chain = Duktape_GetChain(ctx); duk_push_heap_stash(ctx); // [s] - retVal->securityFlags = (SCRIPT_ENGINE_SECURITY_FLAGS)Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_ScriptContainer_Settings_SecurityFlags, 0); // [s] - retVal->executionTimeout = (unsigned int)Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_ScriptContainer_Settings_ExecutionTimeout, 0); // [s] - retVal->exitHandler = (ILibDuktape_HelperEvent)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ScriptContainer_Settings_ExitHandler); // [s] - retVal->exitUserObject = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ScriptContainer_Settings_ExitUser); // [s] - retVal->db = (ILibSimpleDataStore)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ScriptContainer_Settings_DB); // [s] - retVal->exePath = Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_ScriptContainer_ExePath, NULL); // [s] - retVal->pipeManager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ScriptContainer_PipeManager); // [s] + settings->securityFlags = (SCRIPT_ENGINE_SECURITY_FLAGS)Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_ScriptContainer_Settings_SecurityFlags, 0); // [s] + settings->executionTimeout = (unsigned int)Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_ScriptContainer_Settings_ExecutionTimeout, 0); // [s] + settings->exitHandler = (ILibDuktape_HelperEvent)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ScriptContainer_Settings_ExitHandler); // [s] + settings->exitUserObject = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ScriptContainer_Settings_ExitUser); // [s] + settings->db = (ILibSimpleDataStore)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ScriptContainer_Settings_DB); // [s] + settings->exePath = Duktape_Duplicate_GetStringPropertyValue(ctx, -1, ILibDuktape_ScriptContainer_ExePath, NULL); // [s] + settings->pipeManager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ScriptContainer_PipeManager); // [s] duk_pop(ctx); // ... duk_push_global_object(ctx); // [g] duk_get_prop_string(ctx, -1, "process"); // [g][process] - retVal->coreDumpLocation = (char*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_ScriptContainer_Process_CoreDumpPath); + settings->coreDumpLocation = (char*)Duktape_Duplicate_GetBufferProperty(ctx, -1, ILibDuktape_ScriptContainer_Process_CoreDumpPath); duk_get_prop_string(ctx, -1, ILibDuktape_ScriptContainer_Process_ArgArray); // [g][process][array] int i, count = (int)duk_get_length(ctx, -1); - for (i = 0; i < count; ++i) + if (count > 0) { - duk_get_prop_index(ctx, -1, i); // [g][process][array][index] - retVal->argList[i] = (char*)duk_get_string(ctx, -1); - duk_pop(ctx); // [g][process][array] + settings->argList = (char**)ILibMemory_SmartAllocate((1 + count) * sizeof(char*)); + for (i = 0; i < count; ++i) + { + duk_get_prop_index(ctx, -1, i); // [g][process][array][index] + settings->argList[i] = Duktape_Duplicate_GetString(ctx, -1); + duk_pop(ctx); // [g][process][array] + } + settings->argList[i] = NULL; } - retVal->argList[i] = NULL; duk_pop(ctx); // [g][process] if (duk_has_prop_string(ctx, -1, ILibDuktape_NativeUncaughtExceptionPtr)) { duk_get_prop_string(ctx, -1, ILibDuktape_NativeUncaughtExceptionPtr); // [g][process][handler] duk_get_prop_string(ctx, -2, ILibDuktape_NativeUncaughtExceptionUserPtr); // [g][process][handler][user] - retVal->nExeptionHandler = (ILibDuktape_NativeUncaughtExceptionHandler)duk_get_pointer(ctx, -2); - retVal->nExceptionUserObject = duk_get_pointer(ctx, -1); + settings->nExeptionHandler = (ILibDuktape_NativeUncaughtExceptionHandler)duk_get_pointer(ctx, -2); + settings->nExceptionUserObject = duk_get_pointer(ctx, -1); duk_pop_2(ctx); // [g][process] } duk_pop_2(ctx); // ... + return(settings); +} +void ILibDuktape_ScriptContainer_FreeSettings(SCRIPT_ENGINE_SETTINGS *settings) +{ + if (!ILibMemory_CanaryOK(settings)) { return; } + ILibMemory_Free(settings->exePath); + ILibMemory_Free(settings->coreDumpLocation); - return(retVal); + if (settings->argList != NULL) + { + int i; + for (i = 0; settings->argList[i] != NULL; ++i) + { + ILibMemory_Free(settings->argList[i]); + } + ILibMemory_Free(settings->argList); + } + ILibMemory_Free(settings); } duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx2(SCRIPT_ENGINE_SETTINGS *settings) { @@ -1381,20 +1402,15 @@ size_t ILibDuktape_ScriptContainer_TotalAllocations = 0; void *ILibDuktape_ScriptContainer_Engine_malloc(void *udata, duk_size_t size) { ILibDuktape_ScriptContainer_TotalAllocations += size; - return(ILibMemory_SmartAllocate(size)); + void *ptr = ILibMemory_SmartAllocateEx(size, sizeof(void*)); + ((void**)ILibMemory_Extra(ptr))[0] = udata; + return(ptr); } void *ILibDuktape_ScriptContainer_Engine_realloc(void *udata, void *ptr, duk_size_t size) { size_t difference = 0; - if (ptr != NULL) { - ptr = ILibMemory_RawPtr(ptr); - if ((ptr = realloc(ptr, size + sizeof(ILibMemory_Header))) == NULL) - { - ILIBCRITICALEXITMSG(255, "REALLOC FAILURE"); - } - ptr = ILibMemory_FromRaw(ptr); if (ILibMemory_Size(ptr) > size) { // Memory Shrink @@ -1406,13 +1422,22 @@ void *ILibDuktape_ScriptContainer_Engine_realloc(void *udata, void *ptr, duk_siz difference = size - ILibMemory_Size(ptr); ILibDuktape_ScriptContainer_TotalAllocations += difference; } - ILibMemory_Size(ptr) = size; + if (size == 0) + { + ILibMemory_Free(ptr); + ptr = NULL; + } + else + { + ptr = ILibMemory_SmartReAllocate(ptr, size); + } } else { if (size > 0) { - ptr = ILibMemory_SmartAllocate(size); + ptr = ILibMemory_SmartAllocateEx(size, sizeof(void*)); + ((void**)ILibMemory_Extra(ptr))[0] = udata; ILibDuktape_ScriptContainer_TotalAllocations += size; } } @@ -1421,9 +1446,11 @@ void *ILibDuktape_ScriptContainer_Engine_realloc(void *udata, void *ptr, duk_siz } void ILibDuktape_ScriptContainer_Engine_free(void *udata, void *ptr) { + size_t sz = ptr == NULL ? 0 : ILibMemory_Size(ptr); + ILibDuktape_ContextData *x = ptr != NULL ? (ILibDuktape_ContextData*)ILibMemory_Extra(ptr) : NULL; + if (ptr != NULL) { - size_t sz = ILibMemory_Size(ptr); ILibDuktape_ScriptContainer_TotalAllocations -= ILibMemory_Size(ptr); memset(ptr, 0xDEADBEEF, sz); ILibMemory_Free(ptr); @@ -2246,7 +2273,10 @@ void ILibDuktape_ScriptContainer_OS_Init(duk_context *ctx) extern void ILibDuktape_HttpStream_Init(duk_context *ctx); duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngine_minimal() { - duk_context *ctx = duk_create_heap(ILibDuktape_ScriptContainer_Engine_malloc, ILibDuktape_ScriptContainer_Engine_realloc, ILibDuktape_ScriptContainer_Engine_free, NULL, ILibDuktape_ScriptContainer_Engine_fatal); + ILibDuktape_ContextData *ctxd = (ILibDuktape_ContextData*)ILibMemory_SmartAllocate(sizeof(ILibDuktape_ContextData)); + do { util_random(sizeof(ctxd->nonce), (char*)&(ctxd->nonce)); } while (ctxd->nonce == 0); + + duk_context *ctx = duk_create_heap(ILibDuktape_ScriptContainer_Engine_malloc, ILibDuktape_ScriptContainer_Engine_realloc, ILibDuktape_ScriptContainer_Engine_free, ctxd, ILibDuktape_ScriptContainer_Engine_fatal); if (ctx == NULL) { ILIBCRITICALEXIT(254); } return(ctx); } @@ -2261,10 +2291,9 @@ int ILibDuktape_ScriptContainer_DebuggingOK(duk_context *ctx) duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx3(duk_context *ctx, SCRIPT_ENGINE_SECURITY_FLAGS securityFlags, unsigned int executionTimeout, void *chain, char **argList, ILibSimpleDataStore *db, char *exePath, ILibProcessPipe_Manager pipeManager, ILibDuktape_HelperEvent exitHandler, void *exitUser) { void **timeoutKey = executionTimeout > 0 ? (void**)ILibMemory_Allocate(sizeof(void*), 0, NULL, NULL) : NULL; + duk_ctx_context_data(ctx)->chain = chain; duk_push_heap_stash(ctx); // [s] - duk_push_pointer(ctx, chain); // [s][chain] - duk_put_prop_string(ctx, -2, ILibDuktape_Context_Chain); // [s] duk_push_int(ctx, (int)securityFlags); // [s][flags] duk_put_prop_string(ctx, -2, ILibDuktape_ScriptContainer_Settings_SecurityFlags); // [s] duk_push_int(ctx, (int)executionTimeout); // [s][timeout] @@ -2520,7 +2549,7 @@ void ILibDuktape_ScriptContainer_Slave_ProcessCommands(ILibDuktape_ScriptContain } } - if (slave->ctx != NULL) { duk_destroy_heap(slave->ctx); slave->ctx = codec = NULL; } + if (slave->ctx != NULL) { Duktape_SafeDestroyHeap(slave->ctx); slave->ctx = codec = NULL; } slave->ctx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngine(securityFlags, executionTimeout, slave->chain, (char**)argList, NULL, ILibDuktape_ScriptContainer_Slave_HeapDestroyed, slave); duk_push_heap_stash(slave->ctx); // [s] @@ -2692,7 +2721,7 @@ void ILibDuktape_ScriptContainer_Slave_ProcessCommands(ILibDuktape_ScriptContain break; } case SCRIPT_ENGINE_COMMAND_EXIT: - if (slave->ctx != NULL) { duk_destroy_heap(slave->ctx); } + if (slave->ctx != NULL) { Duktape_SafeDestroyHeap(slave->ctx); } break; default: break; @@ -2701,7 +2730,7 @@ void ILibDuktape_ScriptContainer_Slave_ProcessCommands(ILibDuktape_ScriptContain if (codec != NULL && slave->ctx == NULL) { - duk_destroy_heap(codec); + Duktape_SafeDestroyHeap(codec); } } @@ -2731,7 +2760,7 @@ void ILibDuktape_ScriptContainer_Slave_OnReadStdIn(ILibProcessPipe_Pipe sender, ((void**)ILibMemory_Extra(sender))[1] = buffer; ILibProcessPipe_Pipe_Pause(sender); - ILibChain_RunOnMicrostackThread(slave->chain, ILibDuktape_ScriptContainer_Slave_OnReadStdInEx, sender); + Duktape_RunOnEventLoop(slave->chain, duk_ctx_nonce(slave->ctx), slave->ctx, ILibDuktape_ScriptContainer_Slave_OnReadStdInEx, NULL, sender); #else ILibDuktape_ScriptContainer_Slave_ProcessCommands(slave, buffer, sender); #endif @@ -2853,7 +2882,7 @@ duk_ret_t ILibDuktape_ScriptContainer_Exit(duk_context *ctx) ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = ILibMemory_Allocate(sizeof(json) + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL); cmd->container.slave = ((void**)ILibMemory_GetExtraMemory(master->PeerChain, ILibMemory_CHAIN_CONTAINERSIZE))[1]; memcpy_s(cmd->json, sizeof(json), json, sizeof(json)); - ILibChain_RunOnMicrostackThread2(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd, 1); + Duktape_RunOnEventLoopEx(master->PeerChain, duk_ctx_nonce(master->PeerCTX), master->PeerCTX, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd, 1); return(0); } @@ -2912,7 +2941,7 @@ duk_ret_t ILibDuktape_ScriptContainer_ExecuteString(duk_context *ctx) i += ILibBase64Encode((unsigned char*)payload, (int)payloadLen, (unsigned char**)&output); sprintf_s(cmd->json + i - 2, 3, "\"}"); - ILibChain_RunOnMicrostackThread2(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd, 1); + Duktape_RunOnEventLoopEx(master->PeerChain, duk_ctx_nonce(master->PeerCTX), master->PeerCTX, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd, 1); return(0); } @@ -2987,7 +3016,7 @@ void ILibDuktape_ScriptContainer_StdOutSink(ILibProcessPipe_Process sender, char void *tmp = ILibMemory_SmartAllocateEx(sizeof(void*), bufferLen + 1); ((void**)tmp)[0] = master; memcpy_s(ILibMemory_Extra(tmp), ILibMemory_ExtraSize(tmp), buffer, bufferLen); - ILibChain_RunOnMicrostackThread(master->chain, ILibDuktape_ScriptContainer_StdOutSink_Chain, tmp); + Duktape_RunOnEventLoop(master->chain, duk_ctx_nonce(master->ctx), master->ctx, ILibDuktape_ScriptContainer_StdOutSink_Chain, NULL, tmp); } *bytesConsumed = bufferLen; @@ -3102,7 +3131,7 @@ void ILibDuktape_ScriptContainer_StdErrSink(ILibProcessPipe_Process sender, char ptr[0] = master; ptr[1] = buffer; ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Process_GetStdErr(sender)); - ILibChain_RunOnMicrostackThread(master->chain, ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread, ptr); + Duktape_RunOnEventLoop(master->chain, duk_ctx_nonce(master->ctx), master->ctx, ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread, NULL, ptr); } #else void *ptr[2] = { master, buffer }; @@ -3126,7 +3155,7 @@ duk_ret_t ILibDuktape_ScriptContainer_Finalizer(duk_context *ctx) ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = ILibMemory_Allocate(sizeof(json) + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL); cmd->container.slave = ((void**)ILibMemory_GetExtraMemory(master->PeerChain, ILibMemory_CHAIN_CONTAINERSIZE))[1]; memcpy_s(cmd->json, sizeof(json), json, sizeof(json)); - ILibChain_RunOnMicrostackThread2(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd, 1); + Duktape_RunOnEventLoopEx(master->PeerChain, duk_ctx_nonce(master->PeerCTX), master->PeerCTX, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd, 1); #ifdef WIN32 WaitForSingleObject(master->PeerThread, INFINITE); #endif @@ -3166,7 +3195,7 @@ duk_ret_t ILibDuktape_ScriptContainer_SendToSlave(duk_context *ctx) ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = ILibMemory_Allocate(sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command) + (int)payloadLen + 1, 0, NULL, NULL); cmd->container.slave = (ILibDuktape_ScriptContainer_Slave*)((void**)ILibMemory_GetExtraMemory(master->PeerChain, ILibMemory_CHAIN_CONTAINERSIZE))[1]; memcpy_s(cmd->json, payloadLen + 1, payload, payloadLen + 1); - ILibChain_RunOnMicrostackThread2(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd, 1); + Duktape_RunOnEventLoopEx(master->PeerChain, duk_ctx_nonce(master->PeerCTX), master->PeerCTX, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd, 1); } return(0); } @@ -3217,7 +3246,7 @@ void ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster(void *chain, ILibDuktape_ScriptContainer_NonIsolated_Command* initCmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)ILibMemory_Allocate(sizeof(json) + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL); initCmd->container.slave = slave; memcpy_s(initCmd->json, sizeof(json), json, sizeof(json)); - ILibChain_RunOnMicrostackThread2(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, initCmd, 1); + Duktape_RunOnEventLoopEx(master->PeerChain, duk_ctx_nonce(master->PeerCTX), master->PeerCTX, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, initCmd, 1); break; } case 1: @@ -3250,6 +3279,7 @@ void ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster(void *chain, if (duk_pcall_method(master->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "Error Emitting ScriptContainer Exit: "); } duk_pop(master->ctx); // [json] master->PeerChain = NULL; + master->PeerCTX = NULL; break; case SCRIPT_ENGINE_COMMAND_SEND_JSON: ILibDuktape_EventEmitter_SetupEmit(master->ctx, master->emitter->object, "data"); // [json][emit][this][data] @@ -3285,7 +3315,7 @@ void ILibDuktape_ScriptContainer_NonIsolatedWorker_ExceptionSink(duk_context *ct duk_pop(ctx); // ... - ILibChain_RunOnMicrostackThread2(cmd->container.master->chain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); + Duktape_RunOnEventLoopEx(cmd->container.master->chain, duk_ctx_nonce(cmd->container.master->ctx), cmd->container.master->ctx, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); } void ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave(void *chain, void *user) { @@ -3308,7 +3338,7 @@ void ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave(void *chain, v ILibDuktape_ScriptContainer_NonIsolated_Command* cmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)ILibMemory_Allocate(sizeof(json) + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL); cmd->container.master = master; memcpy_s(cmd->json, sizeof(json), json, sizeof(json)); - ILibChain_RunOnMicrostackThread2(master->chain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); + Duktape_RunOnEventLoopEx(master->chain, duk_ctx_nonce(master->ctx), master->ctx, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); break; case SCRIPT_ENGINE_COMMAND_EXEC: { @@ -3350,7 +3380,7 @@ void ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave(void *chain, v case SCRIPT_ENGINE_COMMAND_EXIT: slave->noRespond = Duktape_GetIntPropertyValue(slave->ctx, -1, "noResponse", 0); duk_pop(slave->ctx); - duk_destroy_heap(slave->ctx); + Duktape_SafeDestroyHeap(slave->ctx); return; } duk_pop(slave->ctx); // ... @@ -3367,6 +3397,7 @@ void ILibDuktape_ScriptContainer_NonIsolatedWorker(void *arg) ((void**)ILibMemory_GetExtraMemory(slave->chain, ILibMemory_CHAIN_CONTAINERSIZE))[1] = slave; master->PeerChain = slave->chain; slave->ctx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngine_minimal(); + master->PeerCTX = slave->ctx; duk_push_heap_stash(slave->ctx); duk_push_pointer(slave->ctx, slave); @@ -3378,7 +3409,7 @@ void ILibDuktape_ScriptContainer_NonIsolatedWorker(void *arg) ILibDuktape_ScriptContainer_NonIsolated_Command* cmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)ILibMemory_Allocate(sizeof(json) + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL); cmd->container.master = master; memcpy_s(cmd->json, sizeof(json), json, sizeof(json)); - ILibChain_RunOnMicrostackThread2(master->chain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); + Duktape_RunOnEventLoopEx(master->chain, duk_ctx_nonce(master->ctx), master->ctx, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); ILibChain_DisableWatchDog(slave->chain); ILibStartChain(slave->chain); @@ -3387,7 +3418,7 @@ void ILibDuktape_ScriptContainer_NonIsolatedWorker(void *arg) cmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)ILibMemory_Allocate(64 + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL); cmd->container.master = master; sprintf_s(cmd->json, 64, "{\"command\": \"128\", \"exitCode\": \"%d\"}", slave->exitCode); - ILibChain_RunOnMicrostackThread2(master->chain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); + Duktape_RunOnEventLoopEx(master->chain, duk_ctx_nonce(master->ctx), master->ctx, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd, 1); } } duk_ret_t ILibDuktape_ScriptContainer_Create(duk_context *ctx) diff --git a/microscript/ILibDuktape_ScriptContainer.h b/microscript/ILibDuktape_ScriptContainer.h index a88f56d..217a7ca 100644 --- a/microscript/ILibDuktape_ScriptContainer.h +++ b/microscript/ILibDuktape_ScriptContainer.h @@ -138,7 +138,7 @@ typedef struct SCRIPT_ENGINE_SETTINGS char *coreDumpLocation; ILibProcessPipe_Manager pipeManager; - char *argList[]; + char **argList; }SCRIPT_ENGINE_SETTINGS; void ILibDuktape_ScriptContainer_CheckEmbedded(char **script, int *scriptLen); @@ -154,7 +154,8 @@ duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx2(SCRIPT_EN #define ILibDuktape_ScriptContainer_InitializeJavaScriptEngine(securityFlags, executionTimeout, chain, pp_argList, db, exitHandler, exitUser) ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx((securityFlags), (executionTimeout), (chain), (pp_argList), (db), NULL, NULL, (exitHandler), (exitUser)) int ILibDuktape_ScriptContainer_DebuggingOK(duk_context *ctx); -SCRIPT_ENGINE_SETTINGS *ILibDuktape_ScriptContainer_GetSettings(duk_context *ctx); +SCRIPT_ENGINE_SETTINGS* ILibDuktape_ScriptContainer_GetSettings(duk_context *ctx); +void ILibDuktape_ScriptContainer_FreeSettings(SCRIPT_ENGINE_SETTINGS *settings); int ILibDuktape_ScriptContainer_CompileJavaScript_FromFile(duk_context *ctx, char *path, int pathLen); int ILibDuktape_ScriptContainer_CompileJavaScriptEx(duk_context *ctx, char *payload, int payloadLen, char *filename, int filenameLen); #define ILibDuktape_ScriptContainer_CompileJavaScript(ctx, payload, payloadLen) ILibDuktape_ScriptContainer_CompileJavaScriptEx(ctx, payload, payloadLen, NULL, 0) diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index cacdfe3..a85b2aa 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -1047,11 +1047,11 @@ void ILibDuktape_fs_watch_iocompletionEx(void *chain, void *user) } BOOL ILibDuktape_fs_watch_iocompletion(HANDLE h, ILibWaitHandle_ErrorStatus errors, void *user) { - if (errors != ILibWaitHandle_ErrorStatus_NONE) { return(FALSE); } + if (errors != ILibWaitHandle_ErrorStatus_NONE || !ILibMemory_CanaryOK(user)) { return(FALSE); } ILibDuktape_fs_watcherData *data = (ILibDuktape_fs_watcherData*)user; ILibProcessPipe_WaitHandle_Remove(data->pipeManager, h); - ILibChain_RunOnMicrostackThread(data->chain, ILibDuktape_fs_watch_iocompletionEx, data); + Duktape_RunOnEventLoop(data->chain, duk_ctx_nonce(data->ctx), data->ctx, ILibDuktape_fs_watch_iocompletionEx, NULL, data); return(TRUE); } #endif diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index da162c8..fdcf934 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -84,7 +84,7 @@ typedef struct ILibDuktape_net_WindowsIPC { ILibProcessPipe_Manager manager; duk_context *ctx; - void *mServer, *mSocket; + void *mServer, *mSocket, *mChain; HANDLE mPipeHandle; ILibProcessPipe_Pipe mPipe; @@ -380,6 +380,7 @@ duk_ret_t ILibDuktape_net_socket_connect(duk_context *ctx) winIPC->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); winIPC->ctx = ctx; winIPC->mSocket = duk_get_heapptr(ctx, -1); + winIPC->mChain = Duktape_GetChain(ctx); duk_eval_string(ctx, "require('child_process');"); winIPC->manager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager); @@ -905,7 +906,7 @@ void ILibDuktape_net_server_IPC_readsink(ILibProcessPipe_Pipe sender, void *user winIPC->_reserved[3] = (ULONG_PTR)buffer; winIPC->_reserved[4] = (ULONG_PTR)bufferLen; - ILibChain_RunOnMicrostackThreadEx(Duktape_GetChain(winIPC->ctx), ILibDuktape_net_server_IPC_readsink_safe, winIPC); + Duktape_RunOnEventLoop(winIPC->mChain, duk_ctx_nonce(winIPC->ctx), winIPC->ctx, ILibDuktape_net_server_IPC_readsink_safe, NULL, winIPC); } void ILibDuktape_net_server_IPC_PauseSink(ILibDuktape_DuplexStream *sender, void *user) { @@ -1211,7 +1212,7 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx) winIPC->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); winIPC->ctx = ctx; winIPC->mServer = duk_get_heapptr(ctx, -1); - + winIPC->mChain = Duktape_GetChain(ctx); duk_eval_string(ctx, "require('child_process');"); winIPC->manager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager); diff --git a/microstack/ILibParsers.c b/microstack/ILibParsers.c index 6816538..5521e20 100644 --- a/microstack/ILibParsers.c +++ b/microstack/ILibParsers.c @@ -936,11 +936,30 @@ void* ILibMemory_SmartReAllocate(void *ptr, size_t len) { if (ILibMemory_CanaryOK(ptr)) { + size_t originalRawSize = ILibMemory_Init_Size(ILibMemory_Size(ptr), ILibMemory_ExtraSize(ptr)); + size_t originalSize = ILibMemory_Size(ptr); + size_t originalExtraSize = ILibMemory_ExtraSize(ptr); + size_t newRawSize = ILibMemory_Init_Size(len, originalExtraSize); + + if (newRawSize < originalRawSize && originalExtraSize > 0) + { + // Memory is going to contract, so we need to move the extra block before we realloc + size_t offset = originalSize - len; + memmove_s((char*)ILibMemory_Extra(ptr) - sizeof(ILibMemory_Header) - offset, originalExtraSize + sizeof(ILibMemory_Header), ILibMemory_Extra(ptr) - sizeof(ILibMemory_Header), originalExtraSize + sizeof(ILibMemory_Header)); + } + void *ret = NULL; void *raw = ILibMemory_RawPtr(ptr); - if ((raw = realloc(raw, len + sizeof(ILibMemory_Header))) == NULL) { ILIBCRITICALEXIT(254); } + if ((raw = realloc(raw, newRawSize)) == NULL) { ILIBCRITICALEXIT(254); } ret = ILibMemory_FromRaw(raw); + if (newRawSize > originalRawSize && originalExtraSize > 0) + { + // Memory was expanded, so now we need to move the extra block, before we adjust the headers + size_t offset = len - originalSize; + memmove_s(ILibMemory_Extra(ret) - sizeof(ILibMemory_Header) + offset, originalExtraSize + sizeof(ILibMemory_Header), ILibMemory_Extra(ret) - sizeof(ILibMemory_Header), originalExtraSize + sizeof(ILibMemory_Header)); + } + ILibMemory_Size(ret) = len; return(ret); } @@ -1830,7 +1849,7 @@ void ILibPrependToChain(void *Chain, void *object) void* ILibGetBaseTimer(void *chain) { //return ILibCreateLifeTime(chain); - return ((struct ILibBaseChain*)chain)->Timer; + return (chain == NULL ? NULL : ((struct ILibBaseChain*)chain)->Timer); } #ifdef WIN32 @@ -6473,7 +6492,7 @@ void ILibLifeTime_Remove(void *LifeTimeToken, void *data) struct ILibLifeTime *UPnPLifeTime = (struct ILibLifeTime*)LifeTimeToken; void *EventQueue; - if (UPnPLifeTime->ObjectList == NULL) return; + if (UPnPLifeTime == NULL || UPnPLifeTime->ObjectList == NULL) return; EventQueue = ILibQueue_Create(); ILibLinkedList_Lock(UPnPLifeTime->ObjectList); diff --git a/microstack/ILibParsers.h b/microstack/ILibParsers.h index 2885cdd..6f6eeba 100644 --- a/microstack/ILibParsers.h +++ b/microstack/ILibParsers.h @@ -375,6 +375,7 @@ int ILibIsRunningOnChainThread(void* chain); #define ILibMemory_SmartAllocate(len) ILibMemory_Init(malloc(len+sizeof(ILibMemory_Header)), (int)len, 0, ILibMemory_Types_HEAP) #define ILibMemory_SmartAllocateEx(primaryLen, extraLen) ILibMemory_Init(malloc(primaryLen + extraLen + sizeof(ILibMemory_Header) + (extraLen>0?sizeof(ILibMemory_Header):0)), (int)primaryLen, (int)extraLen, ILibMemory_Types_HEAP) void* ILibMemory_SmartReAllocate(void *ptr, size_t len); + void ILibMemory_Free(void *ptr); void* ILibMemory_AllocateTemp(void* chain, size_t sz); diff --git a/modules/win-message-pump.js b/modules/win-message-pump.js index 34789d4..ae52850 100644 --- a/modules/win-message-pump.js +++ b/modules/win-message-pump.js @@ -61,9 +61,11 @@ function WindowsMessagePump(options) this.wndclass.hinstance.pointerBuffer().copy(this.wndclass.Deref(GM.PointerSize == 4 ? 20 : 24, GM.PointerSize).toBuffer()); this.wndclass.wndproc.on('GlobalCallback', function onWndProc(xhwnd, xmsg, wparam, lparam) { + var processed = false; if (this.mp._hwnd != null && this.mp._hwnd.Val == xhwnd.Val) { // This is for us + processed = true; var d = this.StartDispatcher(); this.mp.emit('message', { message: xmsg.Val, wparam: wparam.Val, lparam: lparam.Val, lparam_hex: lparam.pointerBuffer().toString('hex'), lparam_raw: lparam, hwnd: xhwnd, dispatcher: d }); @@ -88,6 +90,8 @@ function WindowsMessagePump(options) else if(this.mp._hwnd == null && this.CallingThread() == this.mp._user32.RegisterClassExA.async.threadId()) { // This message was generated from our CreateWindowExA method + processed = true; + var d = this.StartDispatcher(); this.mp.emit('message', { message: xmsg.Val, wparam: wparam.Val, lparam: lparam.Val, lparam_hex: lparam.pointerBuffer().toString('hex'), hwnd: xhwnd, dispatcher: d }); @@ -111,7 +115,7 @@ function WindowsMessagePump(options) } } - _debugGC(); + if (processed) { _debugGC(); } }); this._user32.RegisterClassExA.async(this.wndclass).then(function ()