diff --git a/makefile b/makefile
index eb004da..a217685 100644
--- a/makefile
+++ b/makefile
@@ -118,7 +118,7 @@ SOURCES += microscript/ILibDuktape_SimpleDataStore.c microscript/ILibDuktape_Gen
SOURCES += microscript/ILibDuktape_fs.c microscript/ILibDuktape_SHA256.c microscript/ILibduktape_EventEmitter.c
SOURCES += microscript/ILibDuktape_EncryptionStream.c microscript/ILibDuktape_Polyfills.c microscript/ILibDuktape_Dgram.c
SOURCES += microscript/ILibDuktape_ScriptContainer.c microscript/ILibDuktape_MemoryStream.c microscript/ILibDuktape_NetworkMonitor.c
-SOURCES += microscript/ILibDuktape_ChildProcess.c microscript/ILibDuktape_HECI.c microscript/ILibDuktape_HttpStream.c microscript/ILibDuktape_Debugger.c
+SOURCES += microscript/ILibDuktape_ChildProcess.c microscript/ILibDuktape_HttpStream.c microscript/ILibDuktape_Debugger.c
SOURCES += $(ADDITIONALSOURCES)
# Mesh Agent core
diff --git a/meshconsole/MeshConsole.vcxproj b/meshconsole/MeshConsole.vcxproj
index 29eac37..b5b7376 100644
--- a/meshconsole/MeshConsole.vcxproj
+++ b/meshconsole/MeshConsole.vcxproj
@@ -68,7 +68,6 @@
-
@@ -118,7 +117,6 @@
-
diff --git a/meshservice/MeshService.vcxproj b/meshservice/MeshService.vcxproj
index 096bb1a..7c72d1c 100644
--- a/meshservice/MeshService.vcxproj
+++ b/meshservice/MeshService.vcxproj
@@ -573,7 +573,6 @@
-
@@ -625,7 +624,6 @@
-
diff --git a/microscript/ILibDuktape_ChildProcess.c b/microscript/ILibDuktape_ChildProcess.c
index 538fa58..5c0f5cc 100644
--- a/microscript/ILibDuktape_ChildProcess.c
+++ b/microscript/ILibDuktape_ChildProcess.c
@@ -170,7 +170,8 @@ duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx)
}
duk_push_this(ctx); // [spawnedProcess]
- char *_target = Duktape_GetStringPropertyValue(ctx, -1, "_target", NULL);
+ //char *_target = Duktape_GetStringPropertyValue(ctx, -1, "_target", NULL);
+
if (!ILibChain_IsLinkAlive(Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager)))
{
return(ILibDuktape_Error(ctx, "Cannot waitExit() because JS Engine is exiting"));
diff --git a/microscript/ILibDuktape_EventEmitter.h b/microscript/ILibDuktape_EventEmitter.h
index 53ef34a..d040788 100644
--- a/microscript/ILibDuktape_EventEmitter.h
+++ b/microscript/ILibDuktape_EventEmitter.h
@@ -62,6 +62,7 @@ int ILibDuktape_EventEmitter_HasListeners2(ILibDuktape_EventEmitter *emitter, ch
#define ILibDuktape_EventEmitter_SetupEmit(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "emit");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName)
#define ILibDuktape_EventEmitter_SetupOn(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "on");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName)
#define ILibDuktape_EventEmitter_SetupPrependOnce(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "prependOnceListener");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName)
+#define ILibDuktape_EventEmitter_GetEmitReturn(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "emit_returnValue");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName);if(duk_pcall_method(ctx, 1)!=0){duk_push_null(ctx);}
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler
int ILibDuktape_EventEmitter_AddOnEx(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func);
diff --git a/microscript/ILibDuktape_GenericMarshal.c b/microscript/ILibDuktape_GenericMarshal.c
index 355e34d..61dae19 100644
--- a/microscript/ILibDuktape_GenericMarshal.c
+++ b/microscript/ILibDuktape_GenericMarshal.c
@@ -33,11 +33,7 @@ limitations under the License.
#include
#endif
-#if defined(_WIN64) || defined(__LP64__)
- typedef uint_fast64_t PTRSIZE;
-#else
- typedef uint_fast32_t PTRSIZE;
-#endif
+typedef uintptr_t PTRSIZE;
#ifdef WIN32
#define APICALLTYPE __stdcall
@@ -1209,7 +1205,7 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvokeAsync(duk_context *ctx)
}
else if (duk_is_number(ctx, i))
{
- data->vars[i] = (PTRSIZE)duk_require_int(ctx, i);
+ data->vars[i] = (uintptr_t)(duk_require_uint(ctx, i) == 0 ? duk_require_int(ctx, i) : duk_require_uint(ctx, i));
}
else if (duk_is_pointer(ctx, i))
{
@@ -1320,7 +1316,7 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx)
}
else if (duk_is_number(ctx, i))
{
- vars[i] = (PTRSIZE)duk_require_int(ctx, i);
+ vars[i] = (uintptr_t)(duk_require_uint(ctx, i) == 0 ? duk_require_int(ctx, i) : duk_require_uint(ctx, i));
}
else if (duk_is_pointer(ctx, i))
{
diff --git a/microscript/ILibDuktape_HECI.c b/microscript/ILibDuktape_HECI.c
deleted file mode 100644
index d14313a..0000000
--- a/microscript/ILibDuktape_HECI.c
+++ /dev/null
@@ -1,1261 +0,0 @@
-/*
-Copyright 2006 - 2018 Intel Corporation
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-#include "ILibDuktape_HECI.h"
-#include "ILibDuktapeModSearch.h"
-#include "ILibDuktape_Helpers.h"
-#include "ILibDuktape_DuplexStream.h"
-#include "ILibDuktape_EventEmitter.h"
-#include "ILibDuktape_ChildProcess.h"
-#include "../microstack/ILibParsers.h"
-#include "../microstack/ILibProcessPipe.h"
-#include "../microstack/ILibRemoteLogging.h"
-
-#ifndef _NOHECI
-
-#ifdef WIN32
-#include
-#include
-#include
-#include
-DEFINE_GUID(GUID_DEVINTERFACE_HECI, 0xE2D1FF34, 0x3458, 0x49A9, 0x88, 0xDA, 0x8E, 0x69, 0x15, 0xCE, 0x9B, 0xE5);
-#elif defined(_POSIX)
-typedef struct HECI_client
-{
- unsigned int max_msg_length;
- unsigned char protocol_version;
- unsigned char reserved[3];
-}HECI_client;
-typedef struct uuid_le
-{
- unsigned char b[16];
-}uuid_le;
-struct HECI_CONNECT_client_data
-{
- union
- {
- uuid_le uuid;
- HECI_client properties;
- };
-};
-#endif
-
-#define ILibDuktape_HECI_ChainLink "\xFF_HECI_ChainLink"
-#define ILibDuktape_HECI_Descriptor "\xFF_HECI_Descriptor"
-#define ILibDuktape_HECI_ChildProcess "\xFF_HECI_ChildProcess"
-#define ILibDuktape_HECI_Q "\xFF_HECI_Q"
-#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"
-
-#ifdef __DOXY__
-/*!
-\implements EventEmitter
-\brief JavaScript object interface for HECI calls. require('heci') to use;
-*/
-class Heci
-{
-public:
- /*!
- \brief Performs an Ioctl on the HECI device
- \param code Ioctl Code to invoke
- \param inBuffer \ Input data for Ioctl. Can be null
- \param outBuffer \ Optional. Output data from Ioctl. Must be specified if Ioctl code returns data
- \param callback Dispatched when a response is received from the HECI device\n
- status Success Code. 0 = Success, Error code on failure\n
- buffer \ Output Buffer\n
- args Optional parameters that were passed in\n
- \param args Optional arguments to pass when the callback is called
- */
- void doIoctl(code, inBuffer[, outBuffer], callback[, ...args]);
-};
-#endif
-
-typedef struct ILibDuktape_HECI_ioctl_data
-{
- duk_context *ctx;
- uintptr_t ctxnonce;
- void *heciObject;
- void *data;
- void *Q;
- void *chain;
- ILibProcessPipe_Manager pipeManager;
-#ifdef WIN32
- OVERLAPPED v;
- HANDLE device;
- DWORD bytesReceived;
- DWORD abort;
-#elif defined(_POSIX)
- int device;
-#endif
- void *reserved;
-
- int code;
- char *outBuffer;
- void *outBuffer_obj;
- duk_size_t outBufferLen;
- duk_size_t bufferLen;
- char buffer[];
-}ILibDuktape_HECI_ioctl_data;
-
-typedef struct ILibDuktape_HECI_Session
-{
- void *chain;
- int noPipelining;
- ILibDuktape_DuplexStream *stream;
-#ifdef WIN32
- OVERLAPPED v;
- OVERLAPPED wv;
- ILibProcessPipe_Manager mgr;
- HANDLE descriptor;
- DWORD bytesRead;
-#else
- int descriptor;
-#endif
- ILibQueue PendingWrites;
- duk_size_t bufferSize;
- char buffer[];
-}ILibDuktape_HECI_Session;
-typedef struct ILibDuktape_HECI_WriteState
-{
- ILibDuktape_HECI_Session *session;
- int returnIgnored;
-#ifndef WIN32
- int bufferOffset;
-#endif
- int bufferLen;
- char buffer[];
-}ILibDuktape_HECI_WriteState;
-
-typedef struct HECI_chainLink
-{
- ILibChain_Link link;
- duk_context *ctx;
- void *Q;
- ILibDuktape_HECI_Session *session;
- void *heciObject;
- int descriptor;
- int paused;
-}HECI_chainLink;
-
-void ILibDuktape_HECI_Push(duk_context *ctx, void *chain);
-ILibTransport_DoneState ILibDuktape_HECI_Session_WriteHandler_Process(ILibDuktape_HECI_Session *session);
-extern int ILibDuktape_HECI_Debug;
-
-#ifdef WIN32
-BOOL ILibDuktape_HECI_Session_ReceiveSink(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user);
-
-HANDLE ILibDuktape_HECI_windowsInit()
-{
- PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail = NULL;
- HDEVINFO hDeviceInfo;
- DWORD bufferSize;
- SP_DEVICE_INTERFACE_DATA interfaceData;
- LONG ii = 0;
- HANDLE retVal = NULL;
-
- if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_windowsInit()\n"); }
-
- // Find all devices that have our interface
- hDeviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_HECI, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
- if (hDeviceInfo == INVALID_HANDLE_VALUE)
- {
- if (ILibDuktape_HECI_Debug) { printf("...[FAILED]\n"); }
- return(NULL);
- }
- if (ILibDuktape_HECI_Debug) { printf("...[Acquired hDeviceInfo]\n"); }
-
-
- // Setup the interface data struct
- interfaceData.cbSize = sizeof(interfaceData);
- for (ii = 0;
- SetupDiEnumDeviceInterfaces(hDeviceInfo, NULL, (LPGUID)&GUID_DEVINTERFACE_HECI, ii, &interfaceData);
- ++ii)
- {
- // Found our device instance
- if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &interfaceData, NULL, 0, &bufferSize, NULL))
- {
- DWORD err = GetLastError();
- if (err != ERROR_INSUFFICIENT_BUFFER)
- {
- continue;
- }
- }
-
- // Allocate a big enough buffer to get detail data
- deviceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)ILibMemory_AllocateA(bufferSize);
- if (deviceDetail == NULL) { continue; }
-
- // Setup the device interface struct
- deviceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
-
- // Try again to get the device interface detail info
- if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &interfaceData, deviceDetail, bufferSize, NULL, NULL))
- {
- deviceDetail = NULL;
- continue;
- }
-
- break;
- }
- SetupDiDestroyDeviceInfoList(hDeviceInfo);
-
- if (deviceDetail == NULL)
- {
- if (ILibDuktape_HECI_Debug) { printf("...[deviceDetail FAILED]\n"); }
- return(NULL);
- }
-
- retVal = CreateFile(deviceDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (retVal == INVALID_HANDLE_VALUE)
- {
- if (ILibDuktape_HECI_Debug) { printf("...[FAILED to acquire descriptor]\n"); }
- return(NULL);
- }
- if (ILibDuktape_HECI_Debug) { printf("...[Acquired Descriptor]\n"); }
-
- return(retVal);
-}
-#else
-int ILibDuktape_HECI_linuxInit()
-{
- int fd, flags;
-
- if ((fd = open("/dev/mei", O_RDWR)) == -1 && (fd = open("/dev/mei0", O_RDWR)) == -1)
- {
- return(-1);
- }
- else
- {
- flags = fcntl(fd, F_GETFL, 0);
- if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) { printf("Failed to set O_NONBLOCK\n"); close(fd); fd = -1; }
- return(fd);
- }
-}
-#endif
-
-duk_ret_t ILibDuktape_HECI_SessionFinalizer(duk_context *ctx)
-{
- if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_SessionFinalizer()\n"); }
- if (duk_has_prop_string(ctx, 0, ILibDuktape_HECI_SessionMemPtr))
- {
- duk_get_prop_string(ctx, 0, ILibDuktape_HECI_SessionMemPtr);
- ILibDuktape_HECI_Session *s = (ILibDuktape_HECI_Session*)Duktape_GetBuffer(ctx, -1, NULL);
- if (s != NULL && s->PendingWrites != NULL) { ILibQueue_Destroy(s->PendingWrites); } // ToDo: If there is anything pending, we need to clear that too
- if (s != NULL) { s->stream = NULL; }
- }
- return(0);
-}
-
-
-void ILibDuktape_HECI_Session_EmitErrorEvent(void *chain, void *session)
-{
- 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]
- duk_swap_top(ctx, -2); // [emit][this]
- duk_push_string(ctx, "error"); // [emit][this][error]
- duk_push_error_object(ctx, DUK_ERR_ERROR, "HECI Connection Error"); // [emit][this][error][err]
- if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "HECI.session.onError(): "); }
- duk_pop(ctx); // ...
-}
-void ILibDuktape_HECI_Session_EmitStreamReady(void *chain, void *session)
-{
- 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);
-}
-
-#ifdef WIN32
-BOOL ILibDuktape_HECI_Session_WriteHandler_Ready(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user)
-{
- if (errors != ILibWaitHandle_ErrorStatus_NONE) { return(FALSE); }
-
- ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user;
- DWORD bytesWritten;
-
- if (!ILibMemory_CanaryOK(session)) { return(FALSE); }
-
- ILibChain_RemoveWaitHandle(session->chain, session->wv.hEvent);
-
- if (session->noPipelining == 0)
- {
- ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)ILibQueue_DeQueue(session->PendingWrites);
- free(state);
- }
-
- if (GetOverlappedResult(session->descriptor, &(session->wv), &bytesWritten, FALSE) == 0)
- {
- // Broken Connection
- ILibDuktape_HECI_Session_EmitErrorEvent(session->chain, (void*)session);
- }
- else
- {
- if (session->noPipelining == 0)
- {
- // Write Completed
- ILibDuktape_HECI_Session_WriteHandler_Process(session);
- }
- }
- return(TRUE);
-}
-#endif
-
-ILibTransport_DoneState ILibDuktape_HECI_Session_WriteHandler_Process(ILibDuktape_HECI_Session *session)
-{
- ILibTransport_DoneState retVal = ILibTransport_DoneState_ERROR;
- int returnIgnored = 0;
-
-#ifdef WIN32
- DWORD bytesWritten;
- BOOL result = TRUE;
-#else
- ssize_t bytesWritten;
-#endif
-
- while (session->noPipelining || ILibQueue_GetCount(session->PendingWrites) > 0)
- {
- ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)ILibQueue_PeekQueue(session->PendingWrites);
- returnIgnored = state->returnIgnored;
-
-#ifdef WIN32
- if ((result = WriteFile(state->session->descriptor, state->buffer, state->bufferLen, &bytesWritten, &(state->session->wv))) == TRUE)
- {
- if (session->noPipelining == 0) { ILibQueue_DeQueue(state->session->PendingWrites); free(state); }
- }
- else
- {
- break;
- }
-#elif defined(_POSIX)
-
- bytesWritten = write(state->session->descriptor, state->buffer + state->bufferOffset, state->bufferLen - state->bufferOffset);
- if (bytesWritten > 0)
- {
- state->bufferOffset += bytesWritten;
- if (state->bufferOffset == state->bufferLen) { ILibQueue_DeQueue(state->session->PendingWrites); free(state); retVal = session->noPipelining == 0 ? ILibTransport_DoneState_COMPLETE:ILibTransport_DoneState_INCOMPLETE; }
- }
- else
- {
- if (errno != EAGAIN)
- {
- // Error Occured
- retVal = ILibTransport_DoneState_ERROR;
- ILibDuktape_HECI_Session_EmitErrorEvent(session->chain, (void*)session);
- }
- else
- {
- retVal = ILibTransport_DoneState_INCOMPLETE;
- }
- break;
- }
-#endif
-
- if (session->noPipelining != 0) { break; }
- }
-
-#ifdef WIN32
- if (result == FALSE)
- {
- if (GetLastError() == ERROR_IO_PENDING)
- {
- // Not done writing
- retVal = ILibTransport_DoneState_INCOMPLETE;
- ILibChain_AddWaitHandle(session->chain, session->wv.hEvent, -1, ILibDuktape_HECI_Session_WriteHandler_Ready, session);
- }
- else
- {
- // Error Occured
- retVal = ILibTransport_DoneState_ERROR;
- ILibDuktape_HECI_Session_EmitErrorEvent(session->chain, (void*)session);
- }
- }
- else
- {
- if (session->noPipelining == 0)
- {
- // No more Pending Writes
- retVal = ILibTransport_DoneState_COMPLETE;
- if (returnIgnored != 0) { ILibDuktape_HECI_Session_EmitStreamReady(session->chain, (void*)session); }
- }
- else
- {
- retVal = ILibTransport_DoneState_INCOMPLETE;
- }
- }
-#else
- if (ILibQueue_GetCount(session->PendingWrites) == 0 && session->noPipelining == 0)
- {
- // No more Pending Writes
- retVal = ILibTransport_DoneState_COMPLETE;
- if (returnIgnored != 0) { ILibDuktape_HECI_Session_EmitStreamReady(session->chain, (void*)session); }
- }
-#endif
- return(retVal);
-}
-
-#ifdef WIN32
-void __stdcall ILibDuktape_HECI_Session_WriteHandler(ULONG_PTR obj)
-{
- // This Method is always dispatched from the WindowsRunLoop APC Thread
-
- ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)obj;
- ILibQueue_EnQueue(state->session->PendingWrites, state);
-
- if (ILibQueue_GetCount(state->session->PendingWrites) == 1)
- {
- // No Pending Writes, so we can go ahead and send out the first block
- ILibDuktape_HECI_Session_WriteHandler_Process(state->session);
- }
-}
-#elif defined(_POSIX)
-ILibTransport_DoneState ILibDuktape_HECI_Session_WriteHandler(void *chain, ILibDuktape_HECI_WriteState* state)
-{
- // This Method is always dispatched from the Microstack Thread
- ILibQueue_EnQueue(state->session->PendingWrites, state);
-
- if (ILibQueue_GetCount(state->session->PendingWrites) == 1)
- {
- return(ILibDuktape_HECI_Session_WriteHandler_Process(state->session));
- }
- else
- {
- return(ILibTransport_DoneState_INCOMPLETE);
- }
-}
-#endif
-
-ILibTransport_DoneState ILibDuktape_HECI_Session_WriteSink_NoPipeline(void *chain, void *user)
-{
- // This is always called from the Microstack Thread
-
- ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)user;
- ILibQueue_EnQueue(state->session->PendingWrites, state);
- if (ILibQueue_GetCount(state->session->PendingWrites) == 1)
- {
- return(ILibDuktape_HECI_Session_WriteHandler_Process(state->session));
- }
- else
- {
- return(ILibTransport_DoneState_INCOMPLETE);
- }
-}
-ILibTransport_DoneState ILibDuktape_HECI_Session_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
-{
- if ((duk_size_t)bufferLen > ((ILibDuktape_HECI_Session*)user)->bufferSize) { return(ILibTransport_DoneState_ERROR); }
-
- ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user;
- ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)ILibMemory_Allocate(bufferLen + sizeof(ILibDuktape_HECI_WriteState), 0, NULL, NULL);
- state->session = session;
- state->bufferLen = bufferLen;
- memcpy_s(state->buffer, bufferLen, buffer, bufferLen);
-
- if (session->noPipelining == 0)
- {
-#if defined(WIN32)
- state->returnIgnored = 1;
- ILibDuktape_HECI_Session_WriteHandler((ULONG_PTR)state);
-#elif defined(_POSIX)
- if (ILibIsRunningOnChainThread(stream->readableStream->chain) != 0)
- {
- return(ILibDuktape_HECI_Session_WriteHandler(NULL, state));
- }
- else
- {
- state->returnIgnored = 1;
- ILibChain_RunOnMicrostackThreadEx(stream->readableStream->chain, (ILibChain_StartEvent)ILibDuktape_HECI_Session_WriteHandler, state);
- }
-#endif
- }
- else
- {
- // We can't pipeline write requests
- if (ILibIsRunningOnChainThread(stream->readableStream->chain) != 0)
- {
- return(ILibDuktape_HECI_Session_WriteSink_NoPipeline(stream->readableStream->chain, state));
- }
- else
- {
- state->returnIgnored = 1;
- Duktape_RunOnEventLoop(stream->readableStream->chain, duk_ctx_nonce(stream->readableStream->ctx), stream->readableStream->ctx, (Duktape_EventLoopDispatch)ILibDuktape_HECI_Session_WriteSink_NoPipeline, NULL, state);
- }
- }
-
- return(ILibTransport_DoneState_INCOMPLETE);
-}
-void ILibDuktape_HECI_Session_EndSink(ILibDuktape_DuplexStream *stream, void *user)
-{
- duk_context *ctx = stream->readableStream->ctx;
- duk_push_this(ctx);
- duk_get_prop_string(ctx, -1, "disconnect");
- duk_swap_top(ctx, -2);
- if (duk_pcall_method(ctx, 0) != 0) { ILibDuktape_Process_UncaughtException(ctx); }
- duk_pop(ctx);
-}
-void ILibDuktape_HECI_Session_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
-{
-#ifdef WIN32
- // NO-OP Because we are already PAUSED, since we context switched
- UNREFERENCED_PARAMETER(sender);
- UNREFERENCED_PARAMETER(user);
-#else
- UNREFERENCED_PARAMETER(sender);
- UNREFERENCED_PARAMETER(user);
-#endif
-}
-void ILibDuktape_HECI_Session_ResumeSink_NoPipeline(void *chain, void *user)
-{
- // This is always called from the Microstack Thread
- ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user;
- ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)ILibQueue_DeQueue(session->PendingWrites);
- free(state);
-
- if (ILibQueue_GetCount(session->PendingWrites) == 0)
- {
- ILibDuktape_HECI_Session_EmitStreamReady(session->chain, session);
- }
- else
- {
- ILibDuktape_HECI_Session_WriteHandler_Process(session);
- }
-}
-void ILibDuktape_HECI_Session_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
-{
- ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user;
- if (session->noPipelining != 0)
- {
- ILibDuktape_HECI_Session_ResumeSink_NoPipeline(sender->readableStream->chain, session);
- }
-
-#ifdef WIN32
- BOOL result = ReadFile(session->descriptor, session->buffer, (DWORD)session->bufferSize, &(session->bytesRead), &(session->v));
- if (result == TRUE || GetLastError() == ERROR_IO_PENDING)
- {
- //if (ILibDuktape_HECI_Debug) { printf("...[Wait Handle Added]\n"); }
- ILibChain_AddWaitHandle(session->chain, session->v.hEvent, -1, ILibDuktape_HECI_Session_ReceiveSink, session);
- }
-#endif
-}
-#ifdef WIN32
-void ILibDuktape_HECI_Session_ReceiveSink2(void *chain, void *user)
-{
- ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user;
- if (!ILibMemory_CanaryOK(session)) { return; }
-
- ILibDuktape_DuplexStream_WriteData(session->stream, session->buffer, session->bytesRead);
- if (session->stream != NULL && !session->stream->readableStream->paused)
- {
- ILibDuktape_HECI_Session_ResumeSink(session->stream, session->stream->user);
- }
-}
-BOOL ILibDuktape_HECI_Session_ReceiveSink(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user)
-{
- //if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Session_ReceiveSink\n"); }
- if (errors != ILibWaitHandle_ErrorStatus_NONE)
- {
- if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Session_ReceiveSink\n"); }
- if (ILibDuktape_HECI_Debug) { printf("...[ERROR: %d]\n", errors); }
- return(FALSE);
- }
- //if (ILibDuktape_HECI_Debug) { printf("...[SIGNALED]\n"); }
- ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user;
- if (ILibMemory_CanaryOK(session))
- {
- if (GetOverlappedResult(session->descriptor, &(session->v), &(session->bytesRead), FALSE) == TRUE)
- {
- ILibDuktape_DuplexStream_WriteData(session->stream, session->buffer, session->bytesRead);
- if (session->stream != NULL && !session->stream->readableStream->paused)
- {
- ILibDuktape_HECI_Session_ResumeSink(session->stream, session->stream->user);
- }
- }
- }
- return(FALSE);
-}
-void __stdcall ILibDuktape_HECI_Session_Start(ULONG_PTR obj)
-{
- ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)obj;
- DWORD bytesRead;
- if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Session_Start()\n"); }
- BOOL result = ReadFile(session->descriptor, session->buffer, (DWORD)session->bufferSize, &bytesRead, &(session->v));
- //if (ILibDuktape_HECI_Debug) { printf("...[WaitHandle Added]\n"); }
-
- ILibChain_AddWaitHandle(session->chain, session->v.hEvent, -1, ILibDuktape_HECI_Session_ReceiveSink, session);
-}
-#endif
-
-duk_ret_t ILibDuktape_HECI_create_OnClientConnect(duk_context *ctx)
-{
- int statusCode = duk_require_int(ctx, 0);
- ILibDuktape_HECI_Session *session = NULL;
- duk_dup(ctx, 2); // [Session]
- if (statusCode != 0)
- {
- duk_get_prop_string(ctx, -1, "emit"); // [session][emit]
- duk_swap_top(ctx, -2); // [emit][this]
- duk_push_string(ctx, "error"); // [emit][this][error]
- duk_push_error_object(ctx, DUK_ERR_ERROR, "HECI Connection Error [%d]", statusCode); // [emit][this][error][err]
- duk_push_int(ctx, statusCode); duk_put_prop_string(ctx, -2, "errno");
- if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "HECI.session.onError(): "); }
- duk_pop(ctx); // ...
- }
- else
- {
- duk_size_t bufferLen;
- char *buffer = (char*)Duktape_GetBuffer(ctx, 1, &bufferLen);
- if (bufferLen > 4)
- {
- duk_push_int(ctx, ((int*)buffer)[0]);
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_MaxBufferSize); // [session]
-
- session = (ILibDuktape_HECI_Session*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_HECI_Session) + ((int*)buffer)[0]); // [session][buffer]
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_SessionMemPtr); // [session]
-#ifdef WIN32
- session->v.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- session->wv.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-#endif
- session->chain = Duktape_GetChain(ctx);
- session->bufferSize = (duk_size_t)((int*)buffer)[0];
- session->stream = ILibDuktape_DuplexStream_Init(ctx,
- ILibDuktape_HECI_Session_WriteSink, ILibDuktape_HECI_Session_EndSink,
- ILibDuktape_HECI_Session_PauseSink, ILibDuktape_HECI_Session_ResumeSink, session);
- ILibDuktape_CreateReadonlyProperty_int(ctx, "maxBufferSize", (int)session->bufferSize);
- session->PendingWrites = ILibQueue_Create();
- duk_push_current_function(ctx);
- session->noPipelining = Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_HECI_Session_NoPipeline, 0);
- duk_pop(ctx);
-#ifdef _POSIX
- //printf("Session: %p\n", session);
- duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Child); // [session][heci]
- duk_get_prop_string(ctx, -1, ILibDuktape_HECI_ChainLink); // [session][heci][link]
- HECI_chainLink *link = (HECI_chainLink*)duk_get_pointer(ctx, -1);
- link->session = session;
- duk_pop_2(ctx); // [session]
-#endif
-
- //printf("NoPipeline: %d\n", session->noPipelining);
- }
- else
- {
- // Even tho it was a success, the result buffer is invalid
- duk_get_prop_string(ctx, -1, "emit"); // [session][emit]
- duk_swap_top(ctx, -2); // [emit][this]
- duk_push_string(ctx, "error"); // [emit][this][error]
- duk_push_error_object(ctx, DUK_ERR_ERROR, "HECI Connection Error"); // [emit][this][error][err]
- if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "HECI.session.onError(): "); }
- duk_pop(ctx); // ...
- }
- }
-
- if (session != NULL)
- {
- // Hookup the Send/Receive logic
-#ifdef WIN32
- duk_push_this(ctx); // [HECI]
- session->descriptor = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor);
- duk_get_prop_string(ctx, -1, ILibDuktape_HECI_ChildProcess); // [HECI][childProcess]
- duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager); // [HECI][childProcess][manager]
- session->mgr = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
- ILibDuktape_HECI_Session_Start((ULONG_PTR)session);
-#else
- duk_push_this(ctx); // [HECI]
- session->descriptor = Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_HECI_Descriptor, -1);
- ILibForceUnBlockChain(session->chain);
-#endif
-
- duk_dup(ctx, 2);
- duk_get_prop_string(ctx, -1, "emit"); // [session][emit]
- duk_swap_top(ctx, -2); // [emit][this]
- duk_push_string(ctx, "connect"); // [emit][this][connect]
- if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "HECI.session.onConnect(): "); }
- duk_pop(ctx); // ...
-
-
- }
- return(0);
-}
-duk_ret_t ILibDuktape_HECI_Session_connect(duk_context *ctx)
-{
- int i;
- int nargs = duk_get_top(ctx);
- duk_push_this(ctx); // [Session]
- duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Child); // [Session][HECI]
- duk_remove(ctx, -2); // [HECI]
-
- duk_get_prop_string(ctx, -1, "doIoctl"); // [HECI][func]
- duk_swap_top(ctx, -2); // [doIoctl][this]
- duk_get_prop_string(ctx, -1, "IOCTL"); // [doIoctl][this][IOCTL]
- duk_get_prop_string(ctx, -1, "CLIENT_CONNECT"); // [doIoctl][this][IOCTL][CLIENT_CONNECT]
- duk_remove(ctx, -2); // [doIoctl][this][CLIENT_CONNECT]
- duk_dup(ctx, 0); // [doIoctl][this][CLIENT_CONNECT][guid]
- duk_push_fixed_buffer(ctx, 16); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer]
- duk_push_c_function(ctx, ILibDuktape_HECI_create_OnClientConnect, DUK_VARARGS); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer][callback]
- duk_push_int(ctx, 0);
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Session_NoPipeline);
-
- for (i = 1; i < nargs; ++i)
- {
- if (duk_is_function(ctx, i)) { ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter_GetEmitter_fromThis(ctx), "connect", duk_require_heapptr(ctx, i)); }
- else if (duk_is_object(ctx, i))
- {
- int noPipeline = Duktape_GetIntPropertyValue(ctx, i, "noPipeline", 0);
- duk_push_int(ctx, noPipeline);
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Session_NoPipeline);
- }
- }
- duk_push_this(ctx); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer][callback][Session]
- duk_call_method(ctx, 5); // [retVal]
- duk_pop(ctx); // ...
- return(0);
-}
-#ifdef WIN32
-void __stdcall ILibDuktape_HECI_Session_CloseSink2(ULONG_PTR obj)
-{
- HANDLE h = (HANDLE)obj;
- CloseHandle(h);
-}
-#endif
-duk_ret_t ILibDuktape_HECI_Session_close(duk_context *ctx)
-{
- duk_push_this(ctx); // [session]
-
- if (duk_has_prop_string(ctx, -1, ILibDuktape_HECI_Child))
- {
- duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Child); // [session][heci]
- duk_get_prop_string(ctx, -1, "disconnect"); // [session][heci][close]
- duk_swap_top(ctx, -2); // [session][close][this]
- duk_call_method(ctx, 0);
- }
-
- duk_push_this(ctx);
-#ifdef WIN32
- ILibDuktape_HECI_Session *session = NULL;
- if (duk_has_prop_string(ctx, -1, ILibDuktape_HECI_SessionMemPtr))
- {
- duk_get_prop_string(ctx, -1, ILibDuktape_HECI_SessionMemPtr); // [HECI][SESSION]
- session = (ILibDuktape_HECI_Session*)Duktape_GetBuffer(ctx, -1, NULL);
-
- ILibChain_RemoveWaitHandle(session->chain, session->v.hEvent);
- ILibChain_RemoveWaitHandle(session->chain, session->wv.hEvent);
- session->stream = NULL;
- CloseHandle(session->descriptor);
- }
-#else
- int d = Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_HECI_Descriptor, -1);
- HECI_chainLink *hcl = (HECI_chainLink*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_ChainLink);
- if (hcl != NULL)
- {
- hcl->descriptor = -1;
- if (d != -1) { close(d); };
- duk_del_prop_string(ctx, -1, ILibDuktape_HECI_Descriptor);
- }
-#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)
-{
- duk_push_object(ctx); // [Session]
- ILibDuktape_WriteID(ctx, "heci.session");
- 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");
- ILibDuktape_CreateProperty_InstanceMethod(ctx, "connect", ILibDuktape_HECI_Session_connect, DUK_VARARGS);
- ILibDuktape_CreateFinalizer(ctx, ILibDuktape_HECI_SessionFinalizer);
- ILibDuktape_CreateInstanceMethod(ctx, "disconnect", ILibDuktape_HECI_Session_close, 0);
- return(1);
-}
-
-
-void ILibDuktape_HECI_IoctlHandler_Dispatch(void *chain, void *user)
-{
- ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)user;
- duk_size_t count;
- int i;
- duk_context *ctx;
-
- if (!ILibMemory_CanaryOK(data) || ! ILibMemory_CanaryOK(data->reserved))
- {
- // Abort Dispatch, becuase the HECI object was GC'ed.
- if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_IoctlHandler_Dispatch() [ABORTED]\n"); }
- if (ILibMemory_CanaryOK(data))
- {
- if (ILibDuktape_HECI_Debug) { printf("...Release HECI Ioctl Data [%p]\n", (void*)data); }
- ILibMemory_Free(data);
- }
- return;
- }
-
- ctx = data->ctx;
- duk_push_heapptr(data->ctx, data->data); // [array]
- duk_push_heapptr(data->ctx, data->heciObject); // [array][heci]
- duk_get_prop_index(data->ctx, -2, 2); // [array][heci][callback]
- duk_swap_top(data->ctx, -2); // [array][callback][this]
- count = duk_get_length(data->ctx, -3);
- duk_push_int(data->ctx, data->code); // [array][callback][this][status]
- duk_get_prop_index(data->ctx, -4, 1); // [array][callback][this][status][buffer]
-
- for (i = 3; i < (int)count; ++i)
- {
- duk_get_prop_index(data->ctx, -i - 2, i); // [array][callback][this][status][buffer][...args...]
- }
- if (duk_pcall_method(data->ctx, (duk_idx_t)count - 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "heci.ioctlHandler_Dispatch.callback(): "); }
- duk_pop_2(data->ctx); // ...
-
- duk_push_heapptr(data->ctx, data->heciObject); // [heci]
- ILibDuktape_Push_ObjectStash(data->ctx); // [heci][stash]
- duk_del_prop_string(data->ctx, -1, Duktape_GetStashKey(data->data)); // (This will dereference args passed to doIoctl)
- duk_pop_2(ctx); // ...
- if (ILibDuktape_HECI_Debug) { printf("** Release HECI Ioctl Data [%p]\n", (void*)data); }
- ILibMemory_Free(data);
-}
-#ifdef WIN32
-void ILibDuktape_HECI_NextIoctl(ILibQueue q);
-BOOL ILibDuktape_HECI_IoctlHandler(void * chain, HANDLE h, ILibWaitHandle_ErrorStatus errors, void *user)
-{
- if (errors == ILibWaitHandle_ErrorStatus_INVALID_HANDLE || errors == ILibWaitHandle_ErrorStatus_REMOVED) { return(FALSE); }
- if (!ILibMemory_CanaryOK(user)) { return(FALSE); }
-
- ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)user;
- ILibQueue Q = data->Q;
-
- if (errors == ILibWaitHandle_ErrorStatus_NONE)
- {
- BOOL result = GetOverlappedResult(data->device, &(data->v), &(data->bytesReceived), FALSE);
- data->code = result == TRUE ? 0 : (int)GetLastError();
- }
- else
- {
- data->code = -1;
- }
-
- ILibQueue_DeQueue(data->Q);
- ILibChain_RemoveWaitHandle(data->chain, h);
-
- if (data->abort != 0 || !ILibMemory_CanaryOK(data->reserved))
- {
- // ABORT
- ILibQueue Q = (ILibQueue)data->Q;
- void *node = ILibLinkedList_GetNode_Head(data->Q);
- while (node != NULL)
- {
- if (ILibDuktape_HECI_Debug) { printf("** ABORT HECI Ioctl Data [%p]\n", ILibLinkedList_GetDataFromNode(node)); }
- ILibMemory_Free(ILibLinkedList_GetDataFromNode(node));
- node = ILibLinkedList_GetNextNode(node);
- }
- if (ILibDuktape_HECI_Debug) { printf("<== Queue: %p Destroyed in IOCTL Handler ==>\n", (void*)Q); }
- ILibQueue_Destroy(Q);
- return(FALSE);
- }
-
- ILibDuktape_HECI_IoctlHandler_Dispatch(data->chain, data);
-
- if (ILibQueue_GetCount(Q) > 0)
- {
- ILibDuktape_HECI_NextIoctl(Q);
- }
- return(TRUE);
-}
-void ILibDuktape_HECI_NextIoctl(ILibQueue q)
-{
- ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)ILibQueue_PeekQueue(q);
- int res;
- if (data == NULL) { return; } // This line is unnecessary, because this method is only called on a non-empty Queue, but to satisfy Klockwork...
-
- data->bytesReceived = 0;
-
- ResetEvent(data->v.hEvent);
- res = DeviceIoControl(data->device, (DWORD)data->code, data->buffer, (DWORD)data->bufferLen, data->outBuffer, (DWORD)data->outBufferLen, &(data->bytesReceived), &(data->v));
- ILibChain_AddWaitHandle(data->chain, data->v.hEvent, 2000, ILibDuktape_HECI_IoctlHandler, data);
-}
-void __stdcall ILibDuktape_HECI_apc_AddIoctl(ULONG_PTR obj)
-{
- ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)obj;
- ILibQueue_EnQueue(data->Q, data);
- if (ILibQueue_GetCount(data->Q) == 1)
- {
- ILibDuktape_HECI_NextIoctl(data->Q);
- }
-}
-#endif
-#ifdef _POSIX
-void ILibDuktape_HECI_AddIoctl(ILibDuktape_HECI_ioctl_data *data)
-{
- ILibQueue_EnQueue(data->Q, data);
- if (ILibQueue_GetCount(data->Q) == 1)
- {
- ILibForceUnBlockChain(data->chain);
- }
-}
-#endif
-
-duk_ret_t ILibDuktape_HECI_doIoctl(duk_context *ctx)
-{
- int code = duk_require_int(ctx, 0);
- duk_size_t bufferLen = 0;
- char *buffer = duk_is_null(ctx, 1) ? NULL : (char*)Duktape_GetBuffer(ctx, 1, &bufferLen);
- int nargs = duk_get_top(ctx);
- int i;
- ILibQueue Q;
- duk_size_t outBufferLen;
- char *outBuffer;
- int cbx;
-
- if (duk_is_buffer(ctx, 2) || duk_is_buffer_data(ctx, 2))
- {
- outBuffer = (char*)Duktape_GetBuffer(ctx, 2, &outBufferLen);
- cbx = 3;
- }
- else
- {
- outBuffer = NULL;
- outBufferLen = 0;
- cbx = 2;
- }
-
-#ifdef _POSIX
- if (outBuffer == NULL)
- {
- outBuffer = buffer;
- outBufferLen = bufferLen;
- }
- else
- {
- if (bufferLen < outBufferLen) { return(ILibDuktape_Error(ctx, "HECI.doIoctl(): Output Buffer too small")); }
- memcpy_s(outBuffer, outBufferLen, buffer, bufferLen);
- }
-#endif
-
- duk_require_function(ctx, cbx);
- duk_push_this(ctx); // [heci]
- duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [heci][q]
- Q = (ILibQueue)duk_get_pointer(ctx, -1);
- duk_pop(ctx); // [heci]
-
- ILibDuktape_Push_ObjectStash(ctx); // [heci][stash]
- 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]
- if (outBufferLen > 0)
- { // [heci][stash][array][buffer]
- duk_dup(ctx, 2);
- }
- else
- {
- duk_push_null(ctx); // [heci][stash][array][buffer]
- }
-
- duk_put_prop_index(ctx, -2, 1); // [heci][stash][array]
- data->ctx = ctx;
-
- duk_dup(ctx, cbx); // [heci][stash][array][callback]
- duk_put_prop_index(ctx, -2, 2); // [heci][stash][array]
-
-#ifdef WIN32
- duk_get_prop_string(ctx, -3, ILibDuktape_HECI_IoctlWaitHandle); // [heci][stash][array][handle]
- data->v.hEvent = (HANDLE)duk_get_pointer(ctx, -1);
- duk_pop(ctx); // [heci][stash][array]
-#endif
-
- duk_get_prop_string(ctx, -3, ILibDuktape_HECI_Descriptor); // [heci][stash][array][descriptor]
-#ifdef WIN32
- data->device = (HANDLE)duk_get_pointer(ctx, -1);
-#elif defined(_POSIX)
- data->device = duk_get_int(ctx, -1);
-#endif
- duk_pop(ctx); // [heci][stash][array]
- data->chain = Duktape_GetChain(ctx);
- data->Q = Q;
- data->code = code;
- data->outBuffer = outBuffer;
- data->outBufferLen = outBufferLen;
- data->heciObject = duk_get_heapptr(ctx, -3);
- data->bufferLen = bufferLen;
- data->data = duk_get_heapptr(ctx, -1);
- memcpy_s(data->buffer, bufferLen, buffer, bufferLen);
-
- for (i = cbx + 1; i < nargs; ++i)
- {
- duk_dup(ctx, i); // [heci][stash][array][object]
- duk_put_prop_index(ctx, -2, i-1); // [heci][stash][array]
- }
- duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [heci][stash]
-
-
-#ifdef WIN32
- duk_get_prop_string(ctx, -2, ILibDuktape_HECI_ChildProcess); // [heci][stash][childProcess]
- duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager); // [heci][stash][childProcess][manager]
- data->pipeManager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
-
- ILibDuktape_HECI_apc_AddIoctl((ULONG_PTR)data);
-#elif defined(_POSIX)
- ILibDuktape_HECI_AddIoctl(data);
-#endif
-
- return(0);
-}
-
-#ifdef WIN32
-void __stdcall ILibDuktape_HECI_Finalizer2(ULONG_PTR obj)
-{
- ILibQueue Q = (ILibQueue)obj;
-
- if (ILibQueue_IsEmpty(Q) != 0)
- {
- if (ILibDuktape_HECI_Debug) { printf("<== Queue: %p Destroyed in Finalizer ==>\n", (void*)Q); }
- ILibQueue_Destroy(Q);
- }
- else
- {
- void *node = ILibLinkedList_GetNode_Head((void*)Q);
- while (node != NULL)
- {
- ((ILibDuktape_HECI_ioctl_data*)ILibLinkedList_GetDataFromNode(node))->abort = 1;
- node = ILibLinkedList_GetNextNode(node);
- }
- }
-}
-#endif
-
-duk_ret_t ILibDuktape_HECI_Finalizer(duk_context *ctx)
-{
- if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Finalizer()\n"); }
-#ifdef WIN32
- HANDLE h = Duktape_GetPointerProperty(ctx, 0, ILibDuktape_HECI_IoctlWaitHandle);
- if (h != NULL) { CloseHandle(h); }
-#endif
-
- if (duk_has_prop_string(ctx, 0, ILibDuktape_HECI_Q))
- {
-#ifdef WIN32
- 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);
- ILibDuktape_HECI_Finalizer2((ULONG_PTR)Q);
-#else
- duk_get_prop_string(ctx, 0, ILibDuktape_HECI_Q);
- ILibQueue_Destroy((ILibQueue)duk_get_pointer(ctx, -1));
-#endif
- }
-
-#ifdef _POSIX
- if (duk_has_prop_string(ctx, 0, ILibDuktape_HECI_ChainLink))
- {
- duk_get_prop_string(ctx, 0, ILibDuktape_HECI_ChainLink);
- HECI_chainLink *h = (HECI_chainLink*)duk_get_pointer(ctx, -1);
- h->ctx = NULL;
- h->heciObject = NULL;
- if (h->link.ParentChain != NULL) { ILibChain_SafeRemove(h->link.ParentChain, h); }
- }
-#endif
-
- return(0);
-}
-#if !defined(WIN32) && !defined(__APPLE__)
-void ILibDuktape_HECI_PreSelect(void* object, fd_set *readset, fd_set *writeset, fd_set *errorset, int* blocktime)
-{
-
- int result;
- HECI_chainLink *h = (HECI_chainLink*)object;
- //printf("h = %p, descriptor = %d, paused = %d, session = %p\n", (void*)h, h->descriptor, h->paused, (void*)h->session);
-
- if (h->descriptor <= 0) { return; }
- if (h->paused == 0 && h->session != NULL) { FD_SET(h->descriptor, readset); }
- if (h->session != NULL && ILibMemory_CanaryOK(h->session) && ILibQueue_GetCount(h->session->PendingWrites) > 0) { FD_SET(h->descriptor, writeset); }
-
- while (ILibQueue_GetCount(h->Q) > 0 && h->paused == 0)
- {
- ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)ILibQueue_DeQueue(h->Q);
- switch (data->code)
- {
- case 0x00:
- break;
- case 0x01:
- case 0x02:
- case 0x03:
- result = ioctl(h->descriptor, _IOC(_IOC_READ | _IOC_WRITE, 'H', data->code, data->outBufferLen), data->outBuffer);
- data->code = result ? errno : 0;
- ILibDuktape_HECI_IoctlHandler_Dispatch(NULL, data);
- break;
- default:
- break;
- }
- }
-}
-void ILibDuktape_HECI_PostSelect(void* object, int slct, fd_set *readset, fd_set *writeset, fd_set *errorset)
-{
- HECI_chainLink *h = (HECI_chainLink*)object;
- if (h->descriptor <= 0) { return; }
-
- if (FD_ISSET(h->descriptor, readset))
- {
- //printf("session = %p\n", (void*)h->session);
- //printf("Attempting to read: %d bytes from %p\n", h->session->bufferSize, (void*)h->session->buffer);
- int bytesRead = read(h->descriptor, h->session->buffer, h->session->bufferSize);
- if (bytesRead >= 0)
- {
- ILibDuktape_DuplexStream_WriteData(h->session->stream, h->session->buffer, bytesRead);
- }
- else if(h->ctx != NULL && ILibMemory_CanaryOK(h->session))
- {
- ILibDuktape_EventEmitter_SetupEmit(h->ctx, h->session->stream->ParentObject, "error"); // [emit][this][error]
- duk_push_string(h->ctx, "HECI Read Error"); // [emit][this][error][msg]
- duk_pcall_method(h->ctx, 2); duk_pop(h->ctx); // ...
-
- duk_push_heapptr(h->ctx, h->session->stream->ParentObject); // [heci]
- duk_del_prop_string(h->ctx, -1, ILibDuktape_HECI_Descriptor);
- duk_pop(h->ctx); // ...
-
- int td = h->descriptor;
- h->descriptor = -1;
- close(td);
- }
- }
- if (FD_ISSET(h->descriptor, writeset))
- {
- ILibDuktape_HECI_Session_WriteHandler_Process(h->session);
- }
-}
-void ILibDuktape_HECI_Destroy(void *object)
-{
- HECI_chainLink *h = (HECI_chainLink*)object;
- if (h->ctx != NULL && h->heciObject != NULL)
- {
- duk_push_heapptr(h->ctx, h->heciObject); // [heci]
- duk_del_prop_string(h->ctx, -1, ILibDuktape_HECI_ChainLink);
- duk_pop(h->ctx); // ...
- }
- close(h->descriptor);
-}
-#endif
-
-duk_ret_t ILibDuktape_HECI_reset(duk_context *ctx)
-{
- duk_push_this(ctx);
-#ifdef WIN32
- HANDLE h = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor);
- CloseHandle(h);
- h = ILibDuktape_HECI_windowsInit();
- duk_push_pointer(ctx, h);
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Descriptor);
-#endif
- return(0);
-}
-
-void ILibDuktape_HECI_Push(duk_context *ctx, void *chain)
-{
- duk_push_object(ctx); // [HECI]
- ILibDuktape_WriteID(ctx, "heci");
- ILibDuktape_CreateFinalizer(ctx, ILibDuktape_HECI_Finalizer);
-
-#ifdef WIN32
- HANDLE h = ILibDuktape_HECI_windowsInit();
- if (h == NULL) { ILibDuktape_Error(ctx, "Error initializing HECI"); return; }
- duk_push_pointer(ctx, h); // [HECI][HANDLE]
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Descriptor); // [HECI]
-
- if (duk_peval_string(ctx, "require('child_process');") != 0) // [HECI][child_process]
- {
- ILibDuktape_Error(ctx, "Error instantiating dependency 'child_process'");
- return;
- }
-
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_ChildProcess); // [HECI]
- duk_push_pointer(ctx, CreateEvent(NULL, TRUE, FALSE, NULL));
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_IoctlWaitHandle); // [HECI]
-#elif defined(_POSIX) && !defined(__APPLE__)
- int h = ILibDuktape_HECI_linuxInit();
- if (h < 0) { ILibDuktape_Error(ctx, "error initializing HECI"); return; }
- duk_push_int(ctx, h); // [HECI][descriptor]
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Descriptor); // [HECI]
-
- HECI_chainLink *hlink = ILibMemory_Allocate(sizeof(HECI_chainLink), 0, NULL, NULL);
- hlink->link.MetaData = "ILibDuktape_HECI";
- hlink->ctx = ctx;
- hlink->descriptor = h;
- hlink->link.PreSelectHandler = ILibDuktape_HECI_PreSelect;
- hlink->link.PostSelectHandler = ILibDuktape_HECI_PostSelect;
- hlink->link.DestroyHandler = ILibDuktape_HECI_Destroy;
- hlink->Q = ILibQueue_Create();
- duk_push_pointer(ctx, hlink); // [HECI][link]
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_ChainLink); // [HECI]
-
- ILibChain_SafeAdd(Duktape_GetChain(ctx), hlink);
-#endif
- if (chain != NULL) { ILibDuktape_CreateInstanceMethod(ctx, "create", ILibDuktape_HECI_create, 0); }
- ILibDuktape_CreateInstanceMethod(ctx, "doIoctl", ILibDuktape_HECI_doIoctl, DUK_VARARGS);
- ILibDuktape_CreateInstanceMethod(ctx, "disconnect", ILibDuktape_HECI_Session_close, 0);
- ILibDuktape_CreateInstanceMethod(ctx, "reset", ILibDuktape_HECI_reset, 0);
-#if defined(_POSIX) && !defined(__APPLE__)
- duk_push_pointer(ctx, hlink->Q); // [HECI][Q]
-#else
- duk_push_pointer(ctx, ILibQueue_Create()); // [HECI][Q]
-#endif
- duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Q); // [HECI]
- duk_push_object(ctx);
-#ifdef WIN32
- ILibDuktape_CreateReadonlyProperty_int(ctx, "HECI_VERSION", (int)(CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)));
- ILibDuktape_CreateReadonlyProperty_int(ctx, "CLIENT_CONNECT", (int)(CTL_CODE(0x8000, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)));
-#elif defined(_POSIX)
- ILibDuktape_CreateReadonlyProperty_int(ctx, "HECI_VERSION", (int)0x00);
- ILibDuktape_CreateReadonlyProperty_int(ctx, "CLIENT_CONNECT", (int)0x01);
-#endif
-
- ILibDuktape_CreateReadonlyProperty(ctx, "IOCTL");
- duk_push_object(ctx);
- duk_peval_string(ctx, "Buffer.from('DBA4336776047B4EB3AFBCFC29BEE7A7', 'hex');");
- ILibDuktape_CreateReadonlyProperty(ctx, "LME");
- duk_peval_string(ctx, "Buffer.from('2800F812B7B42D4BACA846E0FF65814C', 'hex');");
- ILibDuktape_CreateReadonlyProperty(ctx, "AMT");
- ILibDuktape_CreateReadonlyProperty(ctx, "GUIDS");
-
-} // KLOCKWORK: We are not losing reference to created Event... It is freed in the object finalizer 'ILibDuktape_HECI_Finalizer'
-void ILibDuktape_HECI_Init(duk_context *ctx)
-{
- ILibDuktape_ModSearch_AddHandler(ctx, "heci", ILibDuktape_HECI_Push);
-}
-
-#endif
-
diff --git a/microscript/ILibDuktape_HECI.h b/microscript/ILibDuktape_HECI.h
deleted file mode 100644
index 9a361dc..0000000
--- a/microscript/ILibDuktape_HECI.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-Copyright 2006 - 2018 Intel Corporation
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-#ifndef __DUKTAPEHECI__
-#define __DUKTAPEHECI__
-
-#include "duktape.h"
-
-void ILibDuktape_HECI_Init(duk_context *ctx);
-
-
-#endif
diff --git a/microscript/ILibDuktape_Helpers.h b/microscript/ILibDuktape_Helpers.h
index c314de6..78dbebb 100644
--- a/microscript/ILibDuktape_Helpers.h
+++ b/microscript/ILibDuktape_Helpers.h
@@ -98,6 +98,7 @@ char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *l
#define duk_array_pop(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "pop");duk_swap_top(ctx, -2);duk_call_method(ctx, 0);
#define duk_array_push(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "push");duk_swap_top(ctx, -2);duk_dup(ctx,-3);duk_pcall_method(ctx, 1);duk_pop_2(ctx);
#define duk_array_join(ctx, i, str) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "join");duk_swap_top(ctx, -2);duk_push_string(ctx, str);duk_pcall_method(ctx, 1);
+#define duk_array_unshift(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "unshift");duk_swap_top(ctx, -2);duk_dup(ctx, -3);duk_remove(ctx, -4);duk_pcall_method(ctx, 1);duk_pop(ctx);
#define duk_queue_create(ctx) duk_push_array(ctx)
#define duk_queue_enQueue(ctx, i) duk_array_push(ctx, i)
@@ -105,6 +106,16 @@ char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *l
#define duk_queue_peek(ctx, i) duk_get_prop_index(ctx, i, 0)
#define duk_queue_isEmpty(ctx, i) (duk_get_length(ctx, i)==0)
+#define duk_table_put(ctx, i, key) duk_put_prop_string(ctx, i, key)
+#define duk_table_get(ctx, i, key) duk_get_prop_string(ctx, i, key)
+#define duk_table_get_buffer(ctx, i, key) Duktape_GetBufferProperty(ctx, i, key)
+#define duk_table_keys(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "keys");duk_swap_top(ctx, -2);if(duk_pcall_method(ctx, 0)!=0){duk_pop(ctx);duk_push_null(ctx);}
+#define duk_table_hasKey(ctx, i, key) duk_has_prop_string(ctx, i, key)
+#define duk_table_delKey(ctx, i, key) duk_del_prop_string(ctx, i, key)
+
+#define duk_buffer_slice(ctx, i, start, len) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "slice");duk_swap_top(ctx, -2);duk_push_int(ctx, start);duk_push_int(ctx, len);duk_pcall_method(ctx, 2);duk_remove(ctx, -2);
+#define duk_string_concat(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "concat");duk_swap_top(ctx, -2);duk_dup(ctx, -3);duk_pcall_method(ctx, 1);duk_remove(ctx, -2);
+
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_Polyfills.c b/microscript/ILibDuktape_Polyfills.c
index e308282..e424e80 100644
--- a/microscript/ILibDuktape_Polyfills.c
+++ b/microscript/ILibDuktape_Polyfills.c
@@ -39,6 +39,8 @@ limitations under the License.
#define ILibDuktape_DescriptorEvents_ChainLink "\xFF_DescriptorEvents_ChainLink"
#define ILibDuktape_DescriptorEvents_Table "\xFF_DescriptorEvents_Table"
+#define ILibDuktape_DescriptorEvents_HTable "\xFF_DescriptorEvents_HTable"
+#define ILibDuktape_DescriptorEvents_CURRENT "\xFF_DescriptorEvents_CURRENT"
#define ILibDuktape_DescriptorEvents_FD "\xFF_DescriptorEvents_FD"
#define ILibDuktape_DescriptorEvents_Options "\xFF_DescriptorEvents_Options"
#define ILibDuktape_DescriptorEvents_WaitHandle "\xFF_DescriptorEvents_WindowsWaitHandle"
@@ -1500,16 +1502,26 @@ ILibTransport_DoneState ILibDuktape_Stream_Writable_WriteSink(struct ILibDuktape
{
void *h;
ILibTransport_DoneState retVal = ILibTransport_DoneState_INCOMPLETE;
-
duk_push_this(stream->ctx); // [writable]
+ int bufmode = Duktape_GetIntPropertyValue(stream->ctx, -1, "bufferMode", 0);
duk_get_prop_string(stream->ctx, -1, "_write"); // [writable][_write]
duk_swap_top(stream->ctx, -2); // [_write][this]
if (stream->Reserved == 0)
{
- duk_push_external_buffer(stream->ctx); // [_write][this][extBuffer]
- duk_insert(stream->ctx, -3); // [extBuffer][_write][this]
- duk_config_buffer(stream->ctx, -3, buffer, (duk_size_t)bufferLen);
- duk_push_buffer_object(stream->ctx, -3, 0, (duk_size_t)bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);// [extBuffer][_write][this][buffer]
+ if (bufmode == 0)
+ {
+ // Legacy Mode. We use an external buffer, so a memcpy does not occur. JS must copy memory if it needs to save it
+ duk_push_external_buffer(stream->ctx); // [_write][this][extBuffer]
+ duk_config_buffer(stream->ctx, -1, buffer, (duk_size_t)bufferLen);
+ }
+ else
+ {
+ // Compliant Mode. We copy the buffer into a buffer that will be wholly owned by the recipient
+ char *cb = (char*)duk_push_fixed_buffer(stream->ctx, (duk_size_t)bufferLen); // [_write][this][extBuffer]
+ memcpy_s(cb, (size_t)bufferLen, buffer, (size_t)bufferLen);
+ }
+ duk_push_buffer_object(stream->ctx, -1, 0, (duk_size_t)bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);// [_write][this][extBuffer][buffer]
+ duk_remove(stream->ctx, -2); // [_write][this][buffer]
}
else
{
@@ -1542,7 +1554,6 @@ ILibTransport_DoneState ILibDuktape_Stream_Writable_WriteSink(struct ILibDuktape
duk_push_heap_stash(stream->ctx);
duk_del_prop_string(stream->ctx, -1, Duktape_GetStashKey(h));
duk_pop(stream->ctx);
-
return(retVal);
}
duk_ret_t ILibDuktape_Stream_Writable_EndSink_finish(duk_context *ctx)
@@ -1813,6 +1824,18 @@ duk_ret_t ILibDuktape_Polyfills_Array_peek(duk_context *ctx)
duk_get_prop_index(ctx, -1, (duk_uarridx_t)duk_get_length(ctx, -1) - 1);
return(1);
}
+duk_ret_t ILibDuktape_Polyfills_Object_keys(duk_context *ctx)
+{
+ duk_push_this(ctx); // [obj]
+ duk_push_array(ctx); // [obj][keys]
+ duk_enum(ctx, -2, DUK_ENUM_OWN_PROPERTIES_ONLY); // [obj][keys][enum]
+ while (duk_next(ctx, -1, 0)) // [obj][keys][enum][key]
+ {
+ duk_array_push(ctx, -3); // [obj][keys][enum]
+ }
+ duk_pop(ctx); // [obj][keys]
+ return(1);
+}
void ILibDuktape_Polyfills_object(duk_context *ctx)
{
// Polyfill Object._hashCode()
@@ -1820,6 +1843,8 @@ void ILibDuktape_Polyfills_object(duk_context *ctx)
duk_get_prop_string(ctx, -1, "prototype"); // [g][Object][prototype]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Object_hashCode, 0); // [g][Object][prototype][func]
ILibDuktape_CreateReadonlyProperty(ctx, "_hashCode"); // [g][Object][prototype]
+ duk_push_c_function(ctx, ILibDuktape_Polyfills_Object_keys, 0); // [g][Object][prototype][func]
+ ILibDuktape_CreateReadonlyProperty(ctx, "keys"); // [g][Object][prototype]
duk_pop_2(ctx); // [g]
duk_get_prop_string(ctx, -1, "Array"); // [g][Array]
@@ -2244,6 +2269,17 @@ void ILibDuktape_Polyfills_JS_Init(duk_context *ctx)
duk_pcall_method(ctx, 2); duk_pop(ctx);
free(_identifiers);
+#ifndef _NOHECI
+ char *_heci = ILibMemory_Allocate(57652, 0, NULL, NULL);
+ memcpy_s(_heci + 0, 32944, "LyoNCkNvcHlyaWdodCAyMDIwIEludGVsIENvcnBvcmF0aW9uDQoNCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOw0KeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLg0KWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0DQoNCiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjANCg0KVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQ0KZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywNCldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLg0KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZA0KbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuDQoqLw0KDQp2YXIgR00gPSBudWxsOw0KdmFyIHNldHVwID0gbnVsbDsNCnZhciBrZXJuZWwzMiA9IG51bGw7DQp2YXIgZHVwbGV4ID0gcmVxdWlyZSgnc3RyZWFtJykuRHVwbGV4Ow0KDQoNCmlmIChwcm9jZXNzLnBsYXRmb3JtID09ICd3aW4zMicpDQp7DQogICAgR00gPSByZXF1aXJlKCdfR2VuZXJpY01hcnNoYWwnKTsNCiAgICBzZXR1cCA9IEdNLkNyZWF0ZU5hdGl2ZVByb3h5KCdTZXR1cEFQSS5kbGwnKTsNCiAgICBzZXR1cC5DcmVhdGVNZXRob2QoJ1NldHVwRGlHZXRDbGFzc0RldnNBJyk7DQogICAgc2V0dXAuQ3JlYXRlTWV0aG9kKCdTZXR1cERpRW51bURldmljZUludGVyZmFjZXMnKTsNCiAgICBzZXR1cC5DcmVhdGVNZXRob2QoJ1NldHVwRGlHZXREZXZpY2VJbnRlcmZhY2VEZXRhaWxBJyk7DQogICAgc2V0dXAuQ3JlYXRlTWV0aG9kKCdTZXR1cERpRGVzdHJveURldmljZUluZm9MaXN0Jyk7DQoNCiAgICBrZXJuZWwzMiA9IEdNLkNyZWF0ZU5hdGl2ZVByb3h5KCdLZXJuZWwzMi5kbGwnKTsNCiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0Nsb3NlSGFuZGxlJyk7DQogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdDcmVhdGVFdmVudEEnKTsNCiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0NyZWF0ZUZpbGVBJyk7DQogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdEZXZpY2VJb0NvbnRyb2wnKTsNCiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0dldE92ZXJsYXBwZWRSZXN1bHQnKTsNCiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ1JlYWRGaWxlJyk7DQogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdXcml0ZUZpbGUnKTsNCn0NCg0KdmFyIERJR0NGX0RFRkFVTFQgICAgICAgICAgICAgICA9IDB4MDAwMDAwMDE7ICANCnZhciBESUdDRl9QUkVTRU5UICAgICAgICAgICAgICAgPSAweDAwMDAwMDAyOw0KdmFyIERJR0NGX0FMTENMQVNTRVMgICAgICAgICAgICA9IDB4MDAwMDAwMDQ7DQp2YXIgRElHQ0ZfUFJPRklMRSAgICAgICAgICAgICAgID0gMHgwMDAwMDAwODsNCnZhciBESUdDRl9ERVZJQ0VJTlRFUkZBQ0UgICAgICAgPSAweDAwMDAwMDEwOw0KdmFyIEVSUk9SX0lOU1VGRklDSUVOVF9CVUZGRVIgICA9IDEyMjsgICAgDQp2YXIgR0VORVJJQ19SRUFEICAgICAgICAgICAgICAgID0gMHg4MDAwMDAwMDsNCnZhciBHRU5FUklDX1dSSVRFICAgICAgICAgICAgICAgPSAweDQwMDAwMDAwOw0KdmFyIEZJTEVfU0hBUkVfUkVBRCAgICAgICAgICAgICA9IDB4MDAwMDAwMDE7ICANCnZhciBGSUxFX1NIQVJFX1dSSVRFICAgICAgICAgICAgPSAweDAwMDAwMDAyOyAgDQp2YXIgT1BFTl9FWElTVElORyAgICAgICAgICAgICAgID0gMzsNCnZhciBGSUxFX0ZMQUdfT1ZFUkxBUFBFRCAgICAgICAgPSAweDQwMDAwMDAwOw0KdmFyIEVSUk9SX0lPX1BFTkRJTkcgICAgICAgICAgICA9IDk5NzsNCg0KZnVuY3Rpb24gaGVjaV9jcmVhdGUoKQ0Kew0KICAgIHZhciByZXQgPSBuZXcgZHVwbGV4KA0KICAgIHsNCiAgICAgICAgJ3dyaXRlJzogZnVuY3Rpb24gKGNodW5rLCBmbHVzaCkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKGNodW5rLmxlbmd0aCA+IHRoaXMuTWF4QnVmZmVyU2l6ZSkgeyB0aHJvdyAoJ0J1ZmZlciB0b28gbGFyZ2UnKTsgfQ0KICAgICAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ3dpbjMyJykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBpZiAodGhpcy5fd3JpdGVvdmVybGFwcGVkID09IG51bGwpIHsgdGhyb3cgKCdOb3QgQ29ubmVjdGVkJyk7IH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIHRoaXMuX3BlbmRpbmdXcml0ZXMudW5zaGlmdCh7IGJ1ZmZlcjogY2h1bmssIGZsdXNoOiBmbHVzaCB9KTsNCg0KICAgICAgICAgICAgaWYgKHRoaXMuX3BlbmRpbmdXcml0ZXMubGVuZ3RoID09IDEpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgLy8gS2lja3N0YXJ0IHRoZSB3cml0ZQ0KICAgICAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NXcml0ZSgpOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnd2luMzInKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHJldHVybiAoZmFsc2UpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9LA0KICAgICAgICAnZmluYWwnOiBmdW5jdGlvbiAoZmx1c2gpDQogICAgICAgIHsNCiAgICAgICAgICAgIGZsdXNoKCk7DQogICAgICAgIH0sDQogICAgICAgICdyZWFkJzogZnVuY3Rpb24oc2l6ZSkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKCF0aGlzLl9yZWFkYnVmZmVyKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRidWZmZXIgPSBwcm9jZXNzLnBsYXRmb3JtID09ICd3aW4zMicgPyBHTS5DcmVhdGVWYXJpYWJsZSh0aGlzLk1heEJ1ZmZlclNpemUpIDogQnVmZmVyLmFsbG9jKHRoaXMuTWF4QnVmZmVyU2l6ZSk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmIChwcm9jZXNzLnBsYXRmb3JtID09ICdsaW51eCcpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgdGhpcy5fcHJvY2Vzc1JlYWQoKTsNCiAgICAgICAgICAgICAgICByZXR1cm47DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIHZhciByZXN1bHQgPSBrZXJuZWwzMi5SZWFkRmlsZSh0aGlzLl9kZXNjcmlwdG9yLCB0aGlzLl9yZWFkYnVmZmVyLCB0aGlzLl9yZWFkYnVmZmVyLl9zaXplLCAwLCB0aGlzLl9yZWFkb3ZlcmxhcHBlZCk7DQogICAgICAgICAgICBpZihyZXN1bHQuVmFsICE9IDAgfHwgcmVzdWx0Ll9MYXN0RXJyb3IgPT0gRVJST1JfSU9fUEVORElORykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBpZighdGhpcy5fckRlc2NyaXB0b3JFdmVudCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuX3JEZXNjcmlwdG9yRXZlbnQgPSByZXF1aXJlKCdEZXNjcmlwdG9yRXZlbnRzJykuYWRkRGVzY3JpcHRvcih0aGlzLl9yZWFkb3ZlcmxhcHBlZC5oRXZlbnQsIHsgbWV0YWRhdGE6ICdoZWNpLnNlc3Npb24gW3JlYWRdJyB9KTsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fckRlc2NyaXB0b3JFdmVudC5zZXNzaW9uID0gdGhpczsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fckRlc2NyaXB0b3JFdmVudC5vbignc2lnbmFsZWQnLCBmdW5jdGlvbiAoc3RhdHVzKQ0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICBpZihzdGF0dXMgIT0gJ05PTkUnKQ0KICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzMoJz4+PiBoZWNpLnNlc3Npb24gc2lnbmFsZWQgd2l0aCBzdGF0dXM6ICcgKyBzdGF0dXMpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5wdXNoKG51bGwpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBieXRlc1JlYWQgPSBHTS5DcmVhdGVWYXJpYWJsZSg0KTsNCiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQ7DQogICAgICAgICAgICAgICAgICAgICAgICBpZigocmVzdWx0PWtlcm5lbDMyLkdldE92ZXJsYXBwZWRSZXN1bHQodGhpcy5zZXNzaW9uLl9kZXNjcmlwdG9yLCB0aGlzLnNlc3Npb24uX3JlYWRvdmVybGFwcGVkLCBieXRlc1JlYWQsIDApKS5WYWwgIT0gMCkNCiAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gdGhpcy5zZXNzaW9uLl9yZWFkYnVmZmVyLnRvQnVmZmVyKCkuc2xpY2UoMCwgYnl0ZXNSZWFkLnRvQnVmZmVyKCkucmVhZFVJbnQzMkxFKCkpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzMoYnVmZmVyLmxlbmd0aCArICcgYnl0ZXMgUkVBRCcpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHB1c2hSZXN1bHQgPSB0aGlzLnNlc3Npb24ucHVzaChidWZmZXIpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlc3Npb24uX29wdGlvbnMubm9QaXBlbGluZSAhPSAwICYmIHRoaXMuc2Vzc2lvbi5fcGVuZGluZ1dyaXRlcy5sZW5ndGg+MCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVubG9jayBhIHdyaXRlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzIoJ3BlbmRpbmdXcml0ZUNvdW50OiAnICsgdGhpcy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLmxlbmd0aCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpdGVtID0gdGhpcy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLnBvcCgpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlc3Npb24uX3BlbmRpbmdXcml0ZXMubGVuZ3RoID4gMCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLl9wcm9jZXNzV3JpdGUoKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzIoJ1dyaXRlL0ZsdXNoJyk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLmZsdXNoKCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHVzaFJlc3VsdCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGNhbiByZWFkIG1vcmUsIGJlY2F1c2UgZGF0YSBpcyBzdGlsbCBmbG93aW5nDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBrZXJuZWwzMi5SZWFkRmlsZSh0aGlzLnNlc3Npb24uX2Rlc2NyaXB0b3IsIHRoaXMuc2Vzc2lvbi5fcmVhZGJ1ZmZlciwgdGhpcy5zZXNzaW9uLl9yZWFkYnVmZmVyLl9zaXplLCAwLCB0aGlzLnNlc3Npb24uX3JlYWRvdmVybGFwcGVkKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVzdWx0LlZhbCAhPSAwIHx8IHJlc3VsdC5fTGFzdEVycm9yID09IEVSUk9SX0lPX1BFTkRJTkcpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAodHJ1ZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8xKCdTb21ldHlwZSBvZiBlcnJvcjogJyArIHJlc3VsdC5fTGFzdEVycm9yKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5wdXNoKG51bGwpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzEoJ1JFQURfT1ZFUkxBUFBFRF9FUlJPUjogJyArIHJlc3VsdC5fTGFzdEVycm9yICsgJyBvbiAnICsgdGhpcy5zZXNzaW9uLl9oYXNoQ29kZSgpKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnU29tZSBPdGhlciBFcnJvcjogJyArIHJlc3VsdC5fTGFzdEVycm9yKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH0pOw0KICAgIHJldC5fT2JqZWN0SUQgPSAnaGVjaS5zZXNzaW9uJzsNCiAgICByZXQuYnVmZmVyTW9kZSA9IDE7DQogICAgcmV0Ll9pb2N0bHMgPSBbXTsNCiAgICByZXQuX3BlbmRpbmdXcml0ZXMgPSBbXTsNCiAgICByZXQuaGVjaVBhcmVudCA9IHRoaXM7DQoNCiAgICByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXIuY2FsbChyZXQsIHRydWUpDQogICAgICAgIC5jcmVhdGVFdmVudCgnY29ubmVjdCcpDQogICAgICAgIC5jcmVhdGVFdmVudCgnZXJyb3InKQ0KICAgICAgICAuYWRkTWV0aG9kKCdjb25uZWN0JywgZnVuY3Rpb24gX2Nvbm5lY3QoZ3VpZCwgb3B0aW9ucykNCiAgICAgICAgew0KICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnY29ubmVjdCgpJyk7DQogICAgICAgICAgICB0aGlzLmRvSW9jdGwodGhpcy5oZWNpUGFyZW50LklPQ1RMLkNMSUVOVF9DT05ORUNULCBndWlkLCBCdWZmZXIuYWxsb2MoMTYpLCBmdW5jdGlvbiBfb25jb25uZWN0KHN0YXR1cywgYnVmZmVyLCBvcHQpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYoc3RhdHVzIT0wKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnSEVDSSBDb25uZWN0aW9uIEVycm9yIFsnICsgdGhpcy5MYXN0RXJyb3IgKyAnXScpOw0KICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ2Vycm9yJywgJ0hFQ0kgQ29ubmVjdGlvbiBFcnJvciBbJyArIHRoaXMuTGFzdEVycm9yICsgJ10nKTsNCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBpZihidWZmZXIubGVuZ3RoIDw9NCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIC8vIEludmFsaWQgUmVzcG9uc2UNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0KCdlcnJvcicsICdIRUNJIENvbm5lY3Rpb24gRXJyb3IgW0lOVkFMSUQgUkVTUE9OU0VdJyk7DQogICAgICAgICAgICAgICAgICAgIHJldHVybjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICJNYXhCdWZmZXJTaXplIiwgeyB2YWx1ZTogYnVmZmVyLnJlYWRVSW50MzJMRSgpIH0pOw0KICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMgPSBvcHQ7DQoNCiAgICAgICAgICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnd2luMzInKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZG92ZXJsYXBwZWQgPSBHTS5DcmVhdGVWYXJpYWJsZShHTS5Qb2ludGVyU2l6ZSA9PSA4ID8gMzIgOiAyMCk7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuX3dyaXRlb3ZlcmxhcHBlZCA9IEdNLkNyZWF0ZVZhcmlhYmxlKEdNLlBvaW50ZXJTaXplID09IDggPyAzMiA6IDIwKTsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZG92ZXJsYXBwZWQuaEV2ZW50ID0ga2VybmVsMzIuQ3JlYXRlRXZlbnRBKDAsIDEsIDAsIDApOw0KICAgICAgICAgICAgICAgICAgICB0aGlzLl93cml0ZW92ZXJsYXBwZWQuaEV2ZW50ID0ga2VybmVsMzIuQ3JlYXRlRXZlbnRBKDAsIDEsIDAsIDApOw0KICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkb3ZlcmxhcHBlZC5oRXZlbnQucG9pbnRlckJ1ZmZlcigpLmNvcHkodGhpcy5fcmVhZG92ZXJsYXBwZWQuRGVyZWYoR00uUG9pbnRlclNpemUgPT0gOCA/IDI0IDogMTYsIEdNLlBvaW50ZXJTaXplKS50b0J1ZmZlcigpKTsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fd3JpdGVvdmVybGFwcGVkLmhFdmVudC5wb2ludGVyQnVmZmVyKCkuY29weSh0aGlzLl93cml0ZW92ZXJsYXBwZWQuRGVyZWYoR00uUG9pbnRlclNpemUgPT0gOCA/IDI0IDogMTYsIEdNLlBvaW50ZXJTaXplKS50b0J1ZmZlcigpKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnQ29ubmVjdGVkLCBidWZmZXIgc2l6ZTogJyArIHRoaXMuTWF4QnVmZmVyU2l6ZSk7DQogICAgICAgICAgICAgICAgdGhpcy5fcmVhZCh0aGlzLk1heEJ1ZmZlclNpemUpOw0KICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnY29ubmVjdCcpOw0KICAgICAgICAgICAgfSwgb3B0aW9ucyk7DQogICAgICAgIH0pDQogICAgICAgIC5hZGRNZXRob2QoJ2Rlc2NyaXB0b3JQYXRoJywgZnVuY3Rpb24gX2Rlc2NyaXB0b3JQYXRoKCkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ2xpbnV4JykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBpZiAocmVxdWlyZSgnZnMnKS5leGlzdHNTeW5jKCcvZGV2L21laScpKSB7IHJldHVybiAoJy9kZXYvbWVpJyk7IH0NCiAgICAgICAgICAgICAgICBpZiAocmVxdWlyZSgnZnMnKS5leGlzdHNTeW5jKCcvZGV2L21laTAnKSkgeyByZXR1cm4gKCcvZGV2L21laTAnKTsgfQ0KICAgICAgICAgICAgICAgIHRocm93ICgnSEVDSSBub3Qgc3VwcG9ydGVkJyk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSAhPSAnd2luMzInKSB7IHRocm93ICgnSEVDSSBub3Qgc3VwcG9ydGVkJyk7IH0NCg0KICAgICAgICAgICAgdmFyIHJlc3VsdDsNCiAgICAgICAgICAgIHZhciBpaTsNCiAgICAgICAgICAgIHZhciBkZXZpY2VEZXRhaWw7DQogICAgICAgICAgICB2YXIgYnVmZmVyU2l6ZSA9IEdNLkNyZWF0ZVZhcmlhYmxlKDQpOyAgLy8gRFdPUkQNCiAgICAgICAgICAgIHZhciBoZWNpZ3VpZCA9IEdNLkNyZWF0ZVZhcmlhYmxlKHRoaXMuaGVjaVBhcmVudC5HVUlEUy5IRUNJKTsNCiAgICAgICAgICAgIHZhciBkZXZpY2VJbmZvID0gc2V0dXAuU2V0dXBEaUdldENsYXNzRGV2c0EoaGVjaWd1aWQsIDAsIDAsIERJR0NGX1BSRVNFTlQgfCBESUdDRl9ERVZJQ0VJTlRFUkZBQ0UpOw0KICAgICAgICAgICAgaWYgKGRldmljZUluZm8uVmFsID09IC0xKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzEoJy4uLiBVbmFibGUgdG8gYWNxdWlyZSBbZGV2aWNlSW5mb10nKTsNCiAgICAgICAgICAgICAgICB0aHJvdyAoJ3VuYWJsZSB0byBhY3F1aXJlIFtkZXZpY2VJbmZvXScpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnLi4uIGFjcXVpcmVkIFtkZXZpY2VJbmZvXScpOw0KDQoNCiAgICAgICAgICAgIHZhciBpbnRlcmZhY2VEYXRhID0gR00uQ3JlYXRlVmFyaWFibGUoR00uUG9pbnRlclNpemUgPT0gOCA/IDMyIDogMjgpOw0KICAgICAgICAgICAgaW50ZXJmYWNlRGF0YS50b0J1ZmZlcigpLndyaXRlVUludDMyTEUoaW50ZXJmYWNlRGF0YS5fc2l6ZSwgMCk7DQoNCiAgICAgICAgICAgIGZvciAoaWkgPSAwOyBzZXR1cC5TZXR1cERpRW51bURldmljZUludGVyZmFjZXMoZGV2aWNlSW5mbywgMCwgaGVjaWd1aWQsIGlpLCBpbnRlcmZhY2VEYXRhKS5WYWwgIT0gMDsgKytpaSkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAvLyBGb3VuZCBvdXIgZGV2aWNlIGluc3RhbmNlDQogICAgICAgICAgICAgICAgaWYgKChyZXN1bHQgPSBzZXR1cC5TZXR1cERpR2V0RGV2aWNlSW50ZXJmYWNlRGV0YWlsQShkZXZpY2VJbmZvLCBpbnRlcmZhY2VEYXRhLCAwLCAwLCBidWZmZXJTaXplLCAwKSkuVmFsID09IDApDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Ll9MYXN0RXJyb3IgIT0gRVJST1JfSU5TVUZGSUNJRU5UX0JVRkZFUikNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAvLyBBbGxvY2F0ZSBhIGJpZyBlbm91Z2ggYnVmZmVyIHRvIGdldCBkZXRhaWwgZGF0YQ0KICAgICAgICAgICAgICAgIGRldmljZURldGFpbCA9IEdNLkNyZWF0ZVZhcmlhYmxlKGJ1ZmZlclNpemUudG9CdWZmZXIoKS5yZWFkVUludDMyTEUoKSk7DQogICAgICAgICAgICAgICAgZGV2aWNlRGV0YWlsLnRvQnVmZmVyKCkud3JpdGVVSW50MzJMRShHTS5Qb2ludGVyU2l6ZSA9PSA4ID8gOCA6IDUsIDApOw0KDQogICAgICAgICAgICAgICAgLy8gVHJ5IGFnYWluIHRvIGdldCB0aGUgZGV2aWNlIGludGVyZmFjZSBkZXRhaWwgaW5mbw0KICAgICAgICAgICAgICAgIGlmIChzZXR1cC5TZXR1cERpR2V0RGV2aWNlSW50ZXJmYWNlRGV0YWlsQShkZXZpY2VJbmZvLCBpbnRlcmZhY2VEYXRhLCBkZXZpY2VEZXRhaWwsIGJ1ZmZlclNpemUsIDAsIDApLlZhbCA9PSAwKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgZGV2aWNlRGV0YWlsID0gTlVMTDsNCiAgICAgICAgICAgICAgICAgICAgY29udGludWU7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgc2V0dXAuU2V0dXBEaURlc3Ryb3lEZXZpY2VJbmZvTGlzdChkZXZpY2VJbmZvKTsNCiAgICAgICAgICAgIGlmIChkZXZpY2VEZXRhaWwgPT0gbnVsbCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8xKCcuLi4gZmFpbGVkIHRvIGFjcXVpcmUgW2RldmljZURldGFpbF0nKTsNCiAgICAgICAgICAgICAgICB0aHJvdyAoJ3VuYWJsZSB0byBhY3F1aXJlIFtkZXZpY2VEZXRhaWxdJyk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIHZhciBkZXZQYXRoID0gZGV2aWNlRGV0YWlsLkRlcmVmKDQsIEdNLlBvaW50ZXJTaXplKTsNCiAgICAgICAgICAgIHJldHVybiAoZGV2UGF0aC5TdHJpbmcpOw0KICAgICAgICB9KQ0KICAgICAgICAuYWRkTWV0aG9kKCdjcmVhdGVEZXNjcmlwdG9yJywgZnVuY3Rpb24gX2NyZWF0ZURlc2NyaXB0b3IocGF0aCkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ2xpbnV4JykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICByZXR1cm4gKHJlcXVpcmUoJ2ZzJykub3BlblN5bmMocGF0aCwgcmVxdWlyZSgnZnMnKS5jb25zdGFudHMuT19SRFdSIHwgcmVxdWlyZSgnZnMnKS5jb25zdGFudHMuT19OT05CTE9DSykpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gIT0gJ3dpbjMyJykgeyB0aHJvdyAoJ0hFQ0kgbm90IHN1cHBvcnRlZCcpOyB9DQoNCiAgICAgICAgICAgIHZhciBkZXZQYXRoID0gR00uQ3JlYXRlVmFyaWFibGUo", 16000);
+ memcpy_s(_heci + 16000, 16944, "cGF0aCk7DQogICAgICAgICAgICB2YXIgcmV0ID0ga2VybmVsMzIuQ3JlYXRlRmlsZUEoZGV2UGF0aCwgR0VORVJJQ19SRUFEIHwgR0VORVJJQ19XUklURSwgRklMRV9TSEFSRV9SRUFEIHwgRklMRV9TSEFSRV9XUklURSwgMCwgT1BFTl9FWElTVElORywgRklMRV9GTEFHX09WRVJMQVBQRUQsIDApOw0KICAgICAgICAgICAgaWYgKHJldC5WYWwgPT0gLTEpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnLi4uIGZhaWxlZCB0byBhY3F1aXJlIFtkZXNjcmlwdG9yXScpOw0KICAgICAgICAgICAgICAgIHRocm93ICgnZmFpbGVkIHRvIGFjcXVpcmUgZGVzY3JpcHRvcicpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnLi4uIGFjcXVpcmVkIFtERVNDUklQVE9SXScpOw0KICAgICAgICAgICAgcmV0dXJuIChyZXQpOw0KICAgICAgICB9KTsNCiAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnd2luMzInKQ0KICAgIHsNCiAgICAgICAgcmV0Ll9vdmVybGFwcGVkID0gR00uQ3JlYXRlVmFyaWFibGUoR00uUG9pbnRlclNpemUgPT0gOCA/IDMyIDogMjApOw0KICAgICAgICByZXQuX292ZXJsYXBwZWQuaEV2ZW50ID0ga2VybmVsMzIuQ3JlYXRlRXZlbnRBKDAsIDEsIDAsIDApOw0KDQogICAgICAgIHZhciBvdmVybGFwcGVkX2V2ZW50cHRyID0gcmV0Ll9vdmVybGFwcGVkLkRlcmVmKEdNLlBvaW50ZXJTaXplID09IDggPyAyNCA6IDE2LCBHTS5Qb2ludGVyU2l6ZSkudG9CdWZmZXIoKTsNCiAgICAgICAgcmV0Ll9vdmVybGFwcGVkLmhFdmVudC5wb2ludGVyQnVmZmVyKCkuY29weShvdmVybGFwcGVkX2V2ZW50cHRyKTsNCiAgICB9DQogICAgcmV0LmRpc2Nvbm5lY3QgPSBmdW5jdGlvbiBkaXNjb25uZWN0KCkNCiAgICB7DQogICAgICAgIC8vIENsZWFuIHVwIGFsbCBIYW5kbGVzIGFuZCBEZXNjcmlwdG9ycw0KICAgICAgICBjb25zb2xlLmluZm8xKCdESVNDT05ORUNUIG9uICcgKyB0aGlzLl9oYXNoQ29kZSgpKTsNCiAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ2xpbnV4JykNCiAgICAgICAgew0KICAgICAgICAgICAgaWYodGhpcy5fZGVzY3JpcHRvciAhPSBudWxsKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5yZW1vdmVEZXNjcmlwdG9yKHRoaXMuX2Rlc2NyaXB0b3IpOw0KICAgICAgICAgICAgICAgIHJlcXVpcmUoJ2ZzJykuY2xvc2VTeW5jKHRoaXMuX2Rlc2NyaXB0b3IpOw0KICAgICAgICAgICAgICAgIHRoaXMuX2Rlc2NyaXB0b3IgPSBudWxsOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ3dpbjMyJykNCiAgICAgICAgew0KICAgICAgICAgICAgLy8NCiAgICAgICAgICAgIC8vIGRvSW9jdGwoKSANCiAgICAgICAgICAgIC8vDQogICAgICAgICAgICBpZiAodGhpcy5fZGVzY3JpcHRvckV2ZW50KQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vdmVybGFwcGVkKSB7IHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5yZW1vdmVEZXNjcmlwdG9yKHRoaXMuX292ZXJsYXBwZWQuaEV2ZW50KTsgfQ0KICAgICAgICAgICAgICAgIHRoaXMuX2Rlc2NyaXB0b3JFdmVudCA9IG51bGw7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZiAodGhpcy5fb3ZlcmxhcHBlZCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBrZXJuZWwzMi5DbG9zZUhhbmRsZSh0aGlzLl9vdmVybGFwcGVkLmhFdmVudCk7DQogICAgICAgICAgICAgICAgdGhpcy5fb3ZlcmxhcHBlZCA9IG51bGw7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIC8vDQogICAgICAgICAgICAvLyBSZWFkDQogICAgICAgICAgICAvLw0KICAgICAgICAgICAgaWYgKHRoaXMuX3JEZXNjcmlwdG9yRXZlbnQpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYgKHRoaXMuX3JlYWRvdmVybGFwcGVkKSB7IHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5yZW1vdmVEZXNjcmlwdG9yKHRoaXMuX3JlYWRvdmVybGFwcGVkLmhFdmVudCk7IH0NCiAgICAgICAgICAgICAgICB0aGlzLl9yRGVzY3JpcHRvckV2ZW50ID0gbnVsbDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGlmICh0aGlzLl9yZWFkb3ZlcmxhcHBlZCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBrZXJuZWwzMi5DbG9zZUhhbmRsZSh0aGlzLl9yZWFkb3ZlcmxhcHBlZC5oRXZlbnQpOw0KICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRvdmVybGFwcGVkID0gbnVsbDsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgLy8NCiAgICAgICAgICAgIC8vIFdyaXRlDQogICAgICAgICAgICAvLw0KICAgICAgICAgICAgaWYgKHRoaXMuX3dEZXNjcmlwdG9yRXZlbnQpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYgKHRoaXMuX3dyaXRlb3ZlcmxhcHBlZCkgeyByZXF1aXJlKCdEZXNjcmlwdG9yRXZlbnRzJykucmVtb3ZlRGVzY3JpcHRvcih0aGlzLl93cml0ZW92ZXJsYXBwZWQuaEV2ZW50KTsgfQ0KICAgICAgICAgICAgICAgIHRoaXMuX3dEZXNjcmlwdG9yRXZlbnQgPSBudWxsOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYgKHRoaXMuX3dyaXRlb3ZlcmxhcHBlZCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBrZXJuZWwzMi5DbG9zZUhhbmRsZSh0aGlzLl93cml0ZW92ZXJsYXBwZWQuaEV2ZW50KTsNCiAgICAgICAgICAgICAgICB0aGlzLl93cml0ZW92ZXJsYXBwZWQgPSBudWxsOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAvLw0KICAgICAgICAgICAgLy8gSEVDSQ0KICAgICAgICAgICAgLy8NCiAgICAgICAgICAgIGlmICh0aGlzLl9kZXNjcmlwdG9yKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIGtlcm5lbDMyLkNsb3NlSGFuZGxlKHRoaXMuX2Rlc2NyaXB0b3IpOw0KICAgICAgICAgICAgICAgIHRoaXMuX2Rlc2NyaXB0b3IgPSBudWxsOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfTsNCiAgICByZXQuZG9Jb2N0bCA9IGZ1bmN0aW9uIGRvSW9jdGwoY29kZSwgaW5wdXRCdWZmZXIsIG91dHB1dEJ1ZmZlciwgY2FsbGJhY2spDQogICAgew0KICAgICAgICBpZiAodHlwZW9mIChjYWxsYmFjaykgIT0gJ2Z1bmN0aW9uJykgeyB0aHJvdyAoJ0NhbGxiYWNrIG5vdCBzcGVjaWZpZWQnKTsgfQ0KDQogICAgICAgIHZhciBpOw0KICAgICAgICB2YXIgcGFybXMgPSBbXTsNCiAgICAgICAgZm9yIChpID0gNDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7ICsraSkNCiAgICAgICAgew0KICAgICAgICAgICAgcGFybXMucHVzaChhcmd1bWVudHNbaV0pOw0KICAgICAgICB9DQoNCg0KICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnbGludXgnKQ0KICAgICAgICB7DQogICAgICAgICAgICBpZiAob3V0cHV0QnVmZmVyLmxlbmd0aCA8IGlucHV0QnVmZmVyLmxlbmd0aCkgeyB0aHJvdyAoJ291dHB1dCBidWZmZXIgaXMgdG9vIHNtYWxsJyk7IH0NCiAgICAgICAgICAgIG91dHB1dEJ1ZmZlci5maWxsKDApOw0KICAgICAgICAgICAgaW5wdXRCdWZmZXIuY29weShvdXRwdXRCdWZmZXIpOw0KICAgICAgICAgICAgaWYgKHRoaXMuX2Rlc2NyaXB0b3IgPT0gbnVsbCkgeyB0aGlzLl9kZXNjcmlwdG9yID0gdGhpcy5jcmVhdGVEZXNjcmlwdG9yKHRoaXMuZGVzY3JpcHRvclBhdGgoKSk7IH0NCiAgICAgICAgICAgIHZhciByZXQgPSByZXF1aXJlKCdpb2N0bCcpKHRoaXMuX2Rlc2NyaXB0b3IsIGNvZGUsIG91dHB1dEJ1ZmZlcik7DQogICAgICAgICAgICBwYXJtcy51bnNoaWZ0KG91dHB1dEJ1ZmZlcik7DQogICAgICAgICAgICBwYXJtcy51bnNoaWZ0KHJldCk7DQogICAgICAgICAgICBjYWxsYmFjay5hcHBseSh0aGlzLCBwYXJtcyk7DQogICAgICAgICAgICByZXR1cm47DQogICAgICAgIH0NCg0KICAgICAgICB0aGlzLl9pb2N0bHMudW5zaGlmdCh7IGNvZGU6IGNvZGUsIGlucHV0OiBpbnB1dEJ1ZmZlciwgb3V0cHV0OiBvdXRwdXRCdWZmZXIsIGNhbGxiYWNrOiBjYWxsYmFjaywgcGFybXM6IHBhcm1zIH0pOw0KICAgICAgICBpZih0aGlzLl9pb2N0bHMubGVuZ3RoID09IDEpDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIEZpcnN0IElPQ1RMLCBzbyB3ZSBuZWVkIHRvIHNlbmQgdGhlIGZpcnN0IG9uZQ0KICAgICAgICAgICAgdGhpcy5fc2VuZCh0aGlzLl9pb2N0bHMucGVlaygpKTsNCiAgICAgICAgfQ0KICAgIH07DQoNCiAgICByZXQuX3NlbmQgPSBmdW5jdGlvbiBfc2VuZChvcHRpb25zKQ0KICAgIHsNCiAgICAgICAgaWYodGhpcy5fZGVzY3JpcHRvciA9PSBudWxsKSANCiAgICAgICAgew0KICAgICAgICAgICAgdGhpcy5fZGVzY3JpcHRvciA9IHRoaXMuY3JlYXRlRGVzY3JpcHRvcih0aGlzLmRlc2NyaXB0b3JQYXRoKCkpOyANCiAgICAgICAgICAgIHRoaXMuX2Rlc2NyaXB0b3JFdmVudCA9IHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5hZGREZXNjcmlwdG9yKHRoaXMuX292ZXJsYXBwZWQuaEV2ZW50LCB7bWV0YWRhdGE6ICdoZWNpJ30pOw0KICAgICAgICAgICAgdGhpcy5fZGVzY3JpcHRvckV2ZW50LnNlc3Npb24gPSB0aGlzOw0KICAgICAgICAgICAgdGhpcy5fZGVzY3JpcHRvckV2ZW50Lm9uKCdzaWduYWxlZCcsIGZ1bmN0aW9uKHN0YXR1cykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMuc2Vzc2lvbi5faW9jdGxzLnBvcCgpOw0KICAgICAgICAgICAgICAgIGlmKHN0YXR1cyA9PSAnTk9ORScpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICB2YXIgYnl0ZXNSZWFkID0gR00uQ3JlYXRlVmFyaWFibGUoNCk7DQogICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBrZXJuZWwzMi5HZXRPdmVybGFwcGVkUmVzdWx0KHRoaXMuc2Vzc2lvbi5fZGVzY3JpcHRvciwgdGhpcy5zZXNzaW9uLl9vdmVybGFwcGVkLCBieXRlc1JlYWQsIDApOw0KICAgICAgICAgICAgICAgICAgICBpZihyZXN1bHQuVmFsICE9IDApDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvdXQgPSBkYXRhLm91dHB1dDsNCiAgICAgICAgICAgICAgICAgICAgICAgIHRyeQ0KICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dC5zbGljZSgwLGJ5dGVzUmVhZC50b0J1ZmZlcigpLnJlYWRVSW50MzJMRSgpKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGNhdGNoKGUpDQogICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0ID0gbnVsbDsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucGFybXMudW5zaGlmdChvdXQpOw0KICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5wYXJtcy51bnNoaWZ0KDApOw0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLkxhc3RFcnJvciA9ICdOT05FJzsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucGFybXMudW5zaGlmdChudWxsKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucGFybXMudW5zaGlmdCgxKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5MYXN0RXJyb3IgPSAnT1ZFUkxBUFBFRF9FUlJPUjogJyArIHJlc3VsdC5fTGFzdEVycm9yOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIGRhdGEucGFybXMudW5zaGlmdChudWxsKTsNCiAgICAgICAgICAgICAgICAgICAgZGF0YS5wYXJtcy51bnNoaWZ0KDEpOw0KICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uTGFzdEVycm9yID0gc3RhdHVzOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB0cnkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIGRhdGEuY2FsbGJhY2suYXBwbHkodGhpcy5zZXNzaW9uLCBkYXRhLnBhcm1zKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgY2F0Y2godWUpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLmVtaXQoJ3VuY2F1Z2h0RXhjZXB0aW9uJywgdWUpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBpZih0aGlzLnNlc3Npb24uX2lvY3Rscy5sZW5ndGggPiAwKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgLy8gU3RpbGwgbW9yZSBJT0NUTHMgdG8gc2VuZA0KICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uX3NlbmQodGhpcy5zZXNzaW9uLl9pb2N0bHMucGVlaygpKTsNCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICh0cnVlKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9KTsNCiAgICAgICAgfQ0KICAgICAgICBrZXJuZWwzMi5EZXZpY2VJb0NvbnRyb2wodGhpcy5fZGVzY3JpcHRvciwgb3B0aW9ucy5jb2RlLCBHTS5DcmVhdGVWYXJpYWJsZShvcHRpb25zLmlucHV0KSwgb3B0aW9ucy5pbnB1dC5sZW5ndGgsIEdNLkNyZWF0ZVZhcmlhYmxlKG9wdGlvbnMub3V0cHV0KSwgb3B0aW9ucy5vdXRwdXQubGVuZ3RoLCAwLCB0aGlzLl9vdmVybGFwcGVkKTsNCiAgICB9Ow0KICAgIHJldC5fcHJvY2Vzc1dyaXRlID0gZnVuY3Rpb24gX3Byb2Nlc3NXcml0ZSgpDQogICAgew0KICAgICAgICB2YXIgY2h1bmsgPSB0aGlzLl9wZW5kaW5nV3JpdGVzLnBlZWsoKTsNCiAgICAgICAgY29uc29sZS5pbmZvMygnX1dSSVRJTkc6ICcgKyBjaHVuay5idWZmZXIubGVuZ3RoICsgJyBieXRlcycgKyAnIG9uICcgKyB0aGlzLl9oYXNoQ29kZSgpKTsNCg0KICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnd2luMzInKQ0KICAgICAgICB7DQogICAgICAgICAgICB2YXIgcmVzdWx0ID0ga2VybmVsMzIuV3JpdGVGaWxlKHRoaXMuX2Rlc2NyaXB0b3IsIEdNLkNyZWF0ZVZhcmlhYmxlKGNodW5rLmJ1ZmZlciksIGNodW5rLmJ1ZmZlci5sZW5ndGgsIDAsIHRoaXMuX3dyaXRlb3ZlcmxhcHBlZCk7DQogICAgICAgICAgICBpZiAocmVzdWx0LlZhbCAhPSAwIHx8IHJlc3VsdC5fTGFzdEVycm9yID09IEVSUk9SX0lPX1BFTkRJTkcpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYgKCF0aGlzLl93RGVzY3JpcHRvckV2ZW50KQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fd0Rlc2NyaXB0b3JFdmVudCA9IHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5hZGREZXNjcmlwdG9yKHRoaXMuX3dyaXRlb3ZlcmxhcHBlZC5oRXZlbnQsIHsgbWV0YWRhdGE6ICdoZWNpLnNlc3Npb24gW3dyaXRlXScgfSk7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuX3dEZXNjcmlwdG9yRXZlbnQuc2Vzc2lvbiA9IHRoaXM7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuX3dEZXNjcmlwdG9yRXZlbnQub24oJ3NpZ25hbGVkJywgdGhpcy5fcHJvY2Vzc1dyaXRlX3NpZ25hbGVkKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnV3JpdGUgRXJyb3I6ICcgKyByZXN1bHQuX0xhc3RFcnJvcik7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICByZXF1aXJlKCdmcycpLndyaXRlKHRoaXMuX2Rlc2NyaXB0b3IsIGNodW5rLmJ1ZmZlciwgdGhpcy5fcHJvY2Vzc1dyaXRlX2xpbnV4X3NpZ25hbGVkLCB7IG1ldGFkYXRhOiAnaGVjaS5zZXNzaW9uJywgc2Vzc2lvbjogdGhpcyB9KTsNCiAgICB9Ow0KICAgIHJldC5fcHJvY2Vzc1dyaXRlX2xpbnV4X3NpZ25hbGVkID0gZnVuY3Rpb24gX3Byb2Nlc3NXcml0ZV9saW51eF9zaWduYWxlZChzdGF0dXMsIGJ5dGVzV3JpdHRlbiwgYnVmZmVyLCBvcHRpb25zKQ0KICAgIHsNCiAgICAgICAgaWYoc3RhdHVzID09IDApDQogICAgICAgIHsNCiAgICAgICAgICAgIGNvbnNvbGUuaW5mbzMoYnl0ZXNXcml0dGVuICsgJyBieXRlcyB3cml0dGVuJyk7DQogICAgICAgICAgICBjb25zb2xlLmluZm8zKCdub1BpcGVsaW5lID0gJyArIG9wdGlvbnMuc2Vzc2lvbi5fb3B0aW9ucy5ub1BpcGVsaW5lLCBvcHRpb25zLnNlc3Npb24uX3BlbmRpbmdXcml0ZXMubGVuZ3RoKTsNCiAgICAgICAgICAgIGlmIChvcHRpb25zLnNlc3Npb24uX29wdGlvbnMubm9QaXBlbGluZSA9PSBudWxsIHx8IG9wdGlvbnMuc2Vzc2lvbi5fb3B0aW9ucy5ub1BpcGVsaW5lID09IGZhbHNlKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHZhciBpdGVtID0gb3B0aW9ucy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLnBvcCgpOw0KICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNlc3Npb24uX3BlbmRpbmdXcml0ZXMubGVuZ3RoID4gMCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2Vzc2lvbi5fcHJvY2Vzc1dyaXRlKCk7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzMoJ1dyaXRlL0ZsdXNoJyk7DQogICAgICAgICAgICAgICAgICAgIGl0ZW0uZmx1c2goKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9Ow0KICAgIHJldC5fcHJvY2Vzc1dyaXRlX3NpZ25hbGVkID0gZnVuY3Rpb24gX3Byb2Nlc3NXcml0ZV9zaWduYWxlZChzdGF0dXMpDQogICAgew0KICAgICAgICBjb25zb2xlLmluZm8zKCdXcml0ZSBTaWduYWxlZDogJyArIHN0YXR1cyk7DQogICAgICAgIGlmKHN0YXR1cyA9PSAnTk9ORScpDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIE5vIEVycm9ycw0KICAgICAgICAgICAgdmFyIGJ5dGVzV3JpdHRlbiA9IEdNLkNyZWF0ZVZhcmlhYmxlKDQpOw0KICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGtlcm5lbDMyLkdldE92ZXJsYXBwZWRSZXN1bHQodGhpcy5zZXNzaW9uLl9kZXNjcmlwdG9yLCB0aGlzLnNlc3Npb24uX3dyaXRlb3ZlcmxhcHBlZCwgYnl0ZXNXcml0dGVuLCAwKTsNCiAgICAgICAgICAgIGlmKHJlc3VsdC5WYWwgIT0gMCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8zKGJ5dGVzV3JpdHRlbi50b0J1ZmZlcigpLnJlYWRVSW50MzJMRSgpICsgJyBieXRlcyB3cml0dGVuJyk7DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMygnbm9QaXBlbGluZSA9ICcgKyB0aGlzLnNlc3Npb24uX29wdGlvbnMubm9QaXBlbGluZSwgdGhpcy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLmxlbmd0aCk7DQogICAgICAgICAgICAgICAgaWYodGhpcy5zZXNzaW9uLl9vcHRpb25zLm5vUGlwZWxpbmU9PW51bGwgfHwgdGhpcy5zZXNzaW9uLl9vcHRpb25zLm5vUGlwZWxpbmUgPT0gZmFsc2UpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IHRoaXMuc2Vzc2lvbi5fcGVuZGluZ1dyaXRlcy5wb3AoKTsNCiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5fcGVuZGluZ1dyaXRlcy5sZW5ndGggPiAwKQ0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uX3Byb2Nlc3NXcml0ZSgpOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMygnV3JpdGUvRmx1c2gnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uZmx1c2goKTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gKHRydWUpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH07DQogICAgcmV0Ll9wcm9jZXNzUmVhZF9yZWFkU2V0X3NpbmsgPSBmdW5jdGlvbiBfcHJvY2Vzc1JlYWRfcmVhZFNldF9zaW5rKHN0YXR1cywgYnl0ZXNSZWFkLCBidWZmZXIsIG9wdGlvbnMpDQogICAgew0KICAgICAgICBpZiAoc3RhdHVzICE9IDApIHsgb3B0aW9ucy5zZXNzaW9uLnB1c2gobnVsbCk7IHJldHVybjsgfQ0KICAgICAgICBjb25zb2xlLmluZm8zKGJ5dGVzUmVhZCArICcgYnl0ZXMgcmVhZCcpOw0KDQogICAgICAgIGJ1ZmZlciA9IGJ1ZmZlci5zbGljZSgwLCBieXRlc1JlYWQpOw0KICAgICAgICB2YXIgcHVzaFJlc3VsdCA9IG9wdGlvbnMuc2Vzc2lvbi5wdXNoKGJ1ZmZlcik7DQogICAgICAgIGlmIChvcHRpb25zLnNlc3Npb24uX29wdGlvbnMubm9QaXBlbGluZSAhPSAwICYmIG9wdGlvbnMuc2Vzc2lvbi5fcGVuZGluZ1dyaXRlcy5sZW5ndGggPiAwKQ0KICAgICAgICB7DQogICAgICAgICAgICAvLyBVbmxvY2sgYSB3cml0ZQ0KICAgICAgICAgICAgY29uc29sZS5pbmZvMygncGVuZGluZ1dyaXRlQ291bnQ6ICcgKyBvcHRpb25zLnNlc3Npb24uX3BlbmRpbmdXcml0ZXMubGVuZ3RoKTsNCiAgICAgICAgICAgIHZhciBpdGVtID0gb3B0aW9ucy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLnBvcCgpOw0KDQogICAgICAgICAgICBpZiAob3B0aW9ucy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLmxlbmd0aCA+IDApDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgb3B0aW9ucy5zZXNzaW9uLl9wcm9jZXNzV3JpdGUoKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8zKCdXcml0ZS9GbHVzaCcpOw0KICAgICAgICAgICAgICAgIGl0ZW0uZmx1c2goKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChwdXNoUmVzdWx0KQ0KICAgICAgICB7DQogICAgICAgICAgICAvLyBXZSBjYW4gcmVhZCBtb3JlLCBiZWNhdXNlIGRhdGEgaXMgc3RpbGwgZmxvd2luZw0KICAgICAgICAgICAgb3B0aW9ucy5zZXNzaW9uLl9wcm9jZXNzUmVhZCgpOw0KICAgICAgICB9DQogICAgfTsNCiAgICByZXQuX3Byb2Nlc3NSZWFkID0gZnVuY3Rpb24gX3Byb2Nlc3NSZWFkKCkNCiAgICB7DQogICAgICAgIGlmICh0aGlzLl9kZXNjcmlwdG9yID09IG51bGwpIHsgcmV0dXJuOyB9DQogICAgICAgIHJlcXVpcmUoJ2ZzJykucmVhZCh0aGlzLl9kZXNjcmlwdG9yLCB7IG1ldGFkYXRhOiAnaGVjaS5zZXNzaW9uJywgYnVmZmVyOiB0aGlzLl9yZWFkYnVmZmVyLCBzZXNzaW9uOiB0aGlzIH0sIHRoaXMuX3Byb2Nlc3NSZWFkX3JlYWRTZXRfc2luayk7DQogICAgfTsNCiAgICByZXQub25jZSgnficsIGZ1bmN0aW9uICgpIHsgdGhpcy5kaXNjb25uZWN0KCk7IH0pOw0KICAgIHJldHVybiAocmV0KTsNCn0NCg0KdmFyIGlvY3RsID0ge307DQppZihwcm9jZXNzLnBsYXRmb3JtID09ICd3aW4zMicpDQp7DQogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGlvY3RsLCAnSEVDSV9WRVJTSU9OJywgeyB2YWx1ZTogMHg4MDAwRTAwMCB9KTsNCiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaW9jdGwsICdDTElFTlRfQ09OTkVDVCcsIHsgdmFsdWU6IDB4ODAwMEUwMDQgfSk7DQp9DQppZihwcm9jZXNzLnBsYXRmb3JtID09ICdsaW51eCcpDQp7DQogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGlvY3RsLCAnSEVDSV9WRVJTSU9OJywgeyB2YWx1ZTogMHgwMCB9KTsNCiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaW9jdGwsICdDTElFTlRfQ09OTkVDVCcsIHsgdmFsdWU6IDB4MDEgfSk7DQp9DQoNCnZhciBndWlkcyA9IHt9Ow0KT2JqZWN0LmRlZmluZVByb3BlcnR5KGd1aWRzLCAnQU1UJywgeyB2YWx1ZTogQnVmZmVyLmZyb20oJzI4MDBGODEyQjdCNDJENEJBQ0E4NDZF", 16000);
+ memcpy_s(_heci + 32000, 944, "MEZGNjU4MTRDJywgJ2hleCcpIH0pOw0KT2JqZWN0LmRlZmluZVByb3BlcnR5KGd1aWRzLCAnTE1FJywgeyB2YWx1ZTogQnVmZmVyLmZyb20oJ0RCQTQzMzY3NzYwNDdCNEVCM0FGQkNGQzI5QkVFN0E3JywgJ2hleCcpIH0pOw0KaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ3dpbjMyJykNCnsNCiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZ3VpZHMsICdIRUNJJywgeyB2YWx1ZTogQnVmZmVyLmZyb20oJzM0RkZEMUUyNTgzNEE5NDk4OERBOEU2OTE1Q0U5QkU1JywgJ2hleCcpIH0pOw0KfQ0KDQoNCm1vZHVsZS5leHBvcnRzID0geyBfT2JqZWN0SUQ6ICdoZWNpJywgSU9DVEw6IGlvY3RsLCBHVUlEUzogZ3VpZHMsIGNyZWF0ZTogaGVjaV9jcmVhdGUgfTsNCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGUuZXhwb3J0cywgInN1cHBvcnRlZCIsIHsNCiAgICBnZXQ6IGZ1bmN0aW9uICgpDQogICAgew0KICAgICAgICB0cnkNCiAgICAgICAgew0KICAgICAgICAgICAgdmFyIHAgPSB0aGlzLmNyZWF0ZSgpLmRlc2NyaXB0b3JQYXRoKCk7DQogICAgICAgICAgICB2YXIgZCA9IHRoaXMuY3JlYXRlKCkuY3JlYXRlRGVzY3JpcHRvcihwKTsNCiAgICAgICAgICAgIHJldHVybih0cnVlKTsNCiAgICAgICAgfQ0KICAgICAgICBjYXRjaChlKQ0KICAgICAgICB7DQogICAgICAgICAgICByZXR1cm4gKGZhbHNlKTsNCiAgICAgICAgfQ0KICAgIH0NCn0pOw==", 944);
+ ILibBase64DecodeEx((unsigned char*)_heci, 32944, (unsigned char*)_heci + 32944);
+ duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "addModule"); duk_swap_top(ctx, -2); duk_push_string(ctx, "heci"); duk_push_string(ctx, _heci + 32944);
+ duk_pcall_method(ctx, 2); duk_pop(ctx);
+ free(_heci);
+#endif
+
#ifdef __APPLE__
duk_peval_string_noresult(ctx, "addModule('mac-powerutil', Buffer.from('LyoKQ29weXJpZ2h0IDIwMjAgSW50ZWwgQ29ycG9yYXRpb24KCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQpkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLApXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZApsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKi8KCmZ1bmN0aW9uIHBvd2VydXRpbCgpCnsKICAgIHRoaXMuX09iamVjdElEID0gJ21hYy1wb3dlcnV0aWwnOwoKICAgIHRoaXMuc2xlZXAgPSBmdW5jdGlvbiBzbGVlcCgpCiAgICB7DQogICAgICAgIHZhciBjaGlsZDsNCiAgICAgICAgc3dpdGNoIChwcm9jZXNzLnBsYXRmb3JtKQ0KICAgICAgICB7DQogICAgICAgICAgICBjYXNlICdkYXJ3aW4nOg0KICAgICAgICAgICAgICAgIGNoaWxkID0gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWNGaWxlKCcvYmluL3NoJywgWydzaCddKTsKICAgICAgICAgICAgICAgIGNoaWxkLnN0ZG91dC5zdHIgPSAnJzsgY2hpbGQuc3Rkb3V0Lm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7IHRoaXMuc3RyICs9IGNodW5rLnRvU3RyaW5nKCk7IH0pOwogICAgICAgICAgICAgICAgY2hpbGQuc3RkZXJyLnN0ciA9ICcnOyBjaGlsZC5zdGRlcnIub24oJ2RhdGEnLCBmdW5jdGlvbiAoY2h1bmspIHsgdGhpcy5zdHIgKz0gY2h1bmsudG9TdHJpbmcoKTsgfSk7CiAgICAgICAgICAgICAgICBjaGlsZC5zdGRpbi53cml0ZSgnb3Nhc2NyaXB0IC1lIFwndGVsbCBhcHBsaWNhdGlvbiAiU3lzdGVtIEV2ZW50cyIgdG8gc2xlZXBcJ1xuZXhpdFxuJyk7CiAgICAgICAgICAgICAgICBjaGlsZC53YWl0RXhpdCgpOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgZGVmYXVsdDoNCiAgICAgICAgICAgICAgICB0aHJvdyAoJ3NsZWVwKCkgbm90IGltcGxlbWVudGVkIG9uIHRoaXMgcGxhdGZvcm0nKTsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KICAgIH0KICAgIHRoaXMucmVzdGFydCA9IGZ1bmN0aW9uIHJlc3RhcnQoKQogICAgew0KICAgICAgICB2YXIgY2hpbGQ7DQogICAgICAgIHN3aXRjaChwcm9jZXNzLnBsYXRmb3JtKQ0KICAgICAgICB7DQogICAgICAgICAgICBjYXNlICdkYXJ3aW4nOg0KICAgICAgICAgICAgICAgIGNoaWxkID0gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWNGaWxlKCcvYmluL3NoJywgWydzaCddKTsKICAgICAgICAgICAgICAgIGNoaWxkLnN0ZG91dC5zdHIgPSAnJzsgY2hpbGQuc3Rkb3V0Lm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7IHRoaXMuc3RyICs9IGNodW5rLnRvU3RyaW5nKCk7IH0pOwogICAgICAgICAgICAgICAgY2hpbGQuc3RkZXJyLnN0ciA9ICcnOyBjaGlsZC5zdGRlcnIub24oJ2RhdGEnLCBmdW5jdGlvbiAoY2h1bmspIHsgdGhpcy5zdHIgKz0gY2h1bmsudG9TdHJpbmcoKTsgfSk7CiAgICAgICAgICAgICAgICBjaGlsZC5zdGRpbi53cml0ZSgnc2h1dGRvd24gLXIgbm93XG4nKTsKICAgICAgICAgICAgICAgIGNoaWxkLndhaXRFeGl0KCk7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBkZWZhdWx0Og0KICAgICAgICAgICAgICAgIHRocm93ICgncmVzdGFydCgpIG5vdCBpbXBsZW1lbnRlZCBvbiB0aGlzIHBsYXRmb3JtJyk7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCiAgICB9CiAgICB0aGlzLnNodXRkb3duID0gZnVuY3Rpb24gc2h1dGRvd24oKQogICAgew0KICAgICAgICB2YXIgY2hpbGQ7DQogICAgICAgIHN3aXRjaCAocHJvY2Vzcy5wbGF0Zm9ybSkNCiAgICAgICAgew0KICAgICAgICAgICAgY2FzZSAnZGFyd2luJzoNCiAgICAgICAgICAgICAgICBjaGlsZCA9IHJlcXVpcmUoJ2NoaWxkX3Byb2Nlc3MnKS5leGVjRmlsZSgnL2Jpbi9zaCcsIFsnc2gnXSk7CiAgICAgICAgICAgICAgICBjaGlsZC5zdGRvdXQuc3RyID0gJyc7IGNoaWxkLnN0ZG91dC5vbignZGF0YScsIGZ1bmN0aW9uIChjaHVuaykgeyB0aGlzLnN0ciArPSBjaHVuay50b1N0cmluZygpOyB9KTsKICAgICAgICAgICAgICAgIGNoaWxkLnN0ZGVyci5zdHIgPSAnJzsgY2hpbGQuc3RkZXJyLm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7IHRoaXMuc3RyICs9IGNodW5rLnRvU3RyaW5nKCk7IH0pOwogICAgICAgICAgICAgICAgY2hpbGQuc3RkaW4ud3JpdGUoJ3NodXRkb3duIC1oIG5vd1xuJyk7CiAgICAgICAgICAgICAgICBjaGlsZC53YWl0RXhpdCgpOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgZGVmYXVsdDoNCiAgICAgICAgICAgICAgICB0aHJvdyAoJ3NodXRkb3duKCkgbm90IGltcGxlbWVudGVkIG9uIHRoaXMgcGxhdGZvcm0nKTsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KICAgIH0KfQoKbW9kdWxlLmV4cG9ydHMgPSBuZXcgcG93ZXJ1dGlsKCk7', 'base64').toString());");
#endif
@@ -2468,57 +2504,143 @@ void ILibDuktape_DescriptorEvents_PostSelect(void* object, int slct, fd_set *rea
}
duk_ret_t ILibDuktape_DescriptorEvents_Remove(duk_context *ctx)
{
+#ifdef WIN32
+ if (duk_is_object(ctx, 0) && duk_has_prop_string(ctx, 0, "_ptr"))
+ {
+ // Windows Wait Handle
+ HANDLE h = (HANDLE)Duktape_GetPointerProperty(ctx, 0, "_ptr");
+ duk_push_this(ctx); // [obj]
+ duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_HTable); // [obj][table]
+ ILibChain_RemoveWaitHandle(duk_ctx_chain(ctx), h);
+ duk_push_sprintf(ctx, "%p", h); duk_del_prop(ctx, -2); // [obj][table]
+ if (Duktape_GetPointerProperty(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT) == h)
+ {
+ duk_del_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT);
+ }
+ return(0);
+ }
+#endif
if (!duk_is_number(ctx, 0)) { return(ILibDuktape_Error(ctx, "Invalid Descriptor")); }
ILibForceUnBlockChain(Duktape_GetChain(ctx));
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Table); // [obj][table]
duk_dup(ctx, 0); // [obj][table][key]
- duk_del_prop(ctx, -2); // [obj][table]
+ if (!duk_is_null_or_undefined(ctx, 1) && duk_is_object(ctx, 1))
+ {
+ duk_get_prop(ctx, -2); // [obj][table][value]
+ if (duk_is_null_or_undefined(ctx, -1)) { return(0); }
+ duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Options); //..[table][value][options]
+ if (duk_has_prop_string(ctx, 1, "readset")) { duk_push_false(ctx); duk_put_prop_string(ctx, -2, "readset"); }
+ if (duk_has_prop_string(ctx, 1, "writeset")) { duk_push_false(ctx); duk_put_prop_string(ctx, -2, "writeset"); }
+ if (duk_has_prop_string(ctx, 1, "errorset")) { duk_push_false(ctx); duk_put_prop_string(ctx, -2, "errorset"); }
+ if( Duktape_GetBooleanProperty(ctx, -1, "readset", 0) == 0 &&
+ Duktape_GetBooleanProperty(ctx, -1, "writeset", 0) == 0 &&
+ Duktape_GetBooleanProperty(ctx, -1, "errorset", 0) == 0)
+ {
+ // No FD_SET watchers, so we can remove the entire object
+ duk_pop_2(ctx); // [obj][table]
+ duk_dup(ctx, 0); // [obj][table][key]
+ duk_del_prop(ctx, -2); // [obj][table]
+ }
+ }
+ else
+ {
+ // Remove All FD_SET watchers for this FD
+ duk_del_prop(ctx, -2); // [obj][table]
+ }
return(0);
}
#ifdef WIN32
-void ILibDuktape_DescriptorEvents_WaitHandle_EventThread(void *chain, void *user)
+char *DescriptorEvents_Status[] = { "NONE", "INVALID_HANDLE", "TIMEOUT", "REMOVED", "EXITING", "ERROR" };
+BOOL ILibDuktape_DescriptorEvents_WaitHandleSink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, void* user)
{
- if (!ILibMemory_CanaryOK((void*)user)) { return; }
- ILibDuktape_DescriptorEvents_WindowsWaitHandle *v = (ILibDuktape_DescriptorEvents_WindowsWaitHandle*)user;
+ BOOL ret = FALSE;
+ duk_context *ctx = (duk_context*)((void**)user)[0];
+
+ int top = duk_get_top(ctx);
+ duk_push_heapptr(ctx, ((void**)user)[1]); // [events]
+ duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_HTable); // [events][table]
+ duk_push_sprintf(ctx, "%p", h); // [events][table][key]
+ duk_get_prop(ctx, -2); // [events][table][val]
+ if (!duk_is_null_or_undefined(ctx, -1))
+ {
+ void *hptr = duk_get_heapptr(ctx, -1);
+ if (status != ILibWaitHandle_ErrorStatus_NONE) { duk_push_sprintf(ctx, "%p", h); duk_del_prop(ctx, -3); }
+ duk_push_pointer(ctx, h); duk_put_prop_string(ctx, -3, ILibDuktape_DescriptorEvents_CURRENT);
+ ILibDuktape_EventEmitter_SetupEmit(ctx, hptr, "signaled"); // [events][table][val][emit][this][signaled]
+ duk_push_string(ctx, DescriptorEvents_Status[(int)status]); // [events][table][val][emit][this][signaled][status]
+ if (duk_pcall_method(ctx, 2) == 0) // [events][table][val][undef]
+ {
+ ILibDuktape_EventEmitter_GetEmitReturn(ctx, hptr, "signaled"); // [events][table][val][undef][ret]
+ if (duk_is_boolean(ctx, -1) && duk_get_boolean(ctx, -1) != 0)
+ {
+ ret = TRUE;
+ }
+ }
+ duk_set_top(ctx, top);
+ duk_push_heapptr(ctx, ((void**)user)[1]); // [events]
+ duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_HTable); // [events][table]
- UnregisterWait(v->waitHandle); v->waitHandle = NULL;
- ILibDuktape_EventEmitter_SetupEmit(v->ctx, v->object, "signaled"); // [emit][this][signaled]
- if (duk_pcall_method(v->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(v->ctx, "WaitHandleAPC Error "); }
- duk_pop(v->ctx);
-}
-void __stdcall ILibDuktape_DescriptorEvents_WaitHandleSignaled(void *user, BOOLEAN TimerOrWaitFired)
-{
- if (!ILibMemory_CanaryOK(user)) { return; }
- ILibDuktape_DescriptorEvents_WindowsWaitHandle *v = (ILibDuktape_DescriptorEvents_WindowsWaitHandle*)user;
- Duktape_RunOnEventLoop(v->chain, duk_ctx_nonce(v->ctx), v->ctx, ILibDuktape_DescriptorEvents_WaitHandle_EventThread, NULL, user);
+ if (ret == FALSE && Duktape_GetPointerProperty(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT) == h)
+ {
+ duk_push_sprintf(ctx, "%p", h); // [events][table][key]
+ duk_del_prop(ctx, -2); // [events][table]
+ }
+ duk_del_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT); // [events][table]
+ }
+ duk_set_top(ctx, top);
+
+ return(ret);
}
#endif
duk_ret_t ILibDuktape_DescriptorEvents_Add(duk_context *ctx)
{
+ ILibDuktape_EventEmitter *e;
#ifdef WIN32
if (duk_is_object(ctx, 0) && duk_has_prop_string(ctx, 0, "_ptr"))
{
+ // Adding a Windows Wait Handle
HANDLE h = (HANDLE)Duktape_GetPointerProperty(ctx, 0, "_ptr");
if (h != NULL)
{
- duk_push_object(ctx); // [value]
- ILibDuktape_DescriptorEvents_WindowsWaitHandle *v = (ILibDuktape_DescriptorEvents_WindowsWaitHandle*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_DescriptorEvents_WindowsWaitHandle));
- duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_WaitHandle);
-
- ILibDuktape_EventEmitter *e = ILibDuktape_EventEmitter_Create(ctx);
- ILibDuktape_EventEmitter_CreateEventEx(e, "signaled");
- v->ctx = ctx;
- v->object = duk_get_heapptr(ctx, -1);
- v->chain = Duktape_GetChain(ctx);
- v->eventThread = ILibChain_GetMicrostackThreadHandle(v->chain);
- if (RegisterWaitForSingleObject(&(v->waitHandle), h, ILibDuktape_DescriptorEvents_WaitHandleSignaled, (void*)v, INFINITE, WT_EXECUTEINPERSISTENTTHREAD | WT_EXECUTEONLYONCE) == 0)
+ // Normal Add Wait Handle
+ char *metadata = "DescriptorEvents";
+ int timeout = -1;
+ duk_push_this(ctx); // [events]
+ ILibChain_Link *link = (ILibChain_Link*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_DescriptorEvents_ChainLink);
+ duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_HTable); // [events][table]
+ if (Duktape_GetPointerProperty(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT) == h)
{
- return(ILibDuktape_Error(ctx, "Error(%d) Calling RegisterWaitForSingleObject() ", GetLastError()));
+ // We are adding a wait handle from the event handler for this same signal, so remove this attribute,
+ // so the signaler doesn't remove the object we are about to put in.
+ duk_del_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT);
}
+ duk_push_object(ctx); // [events][table][value]
+ duk_push_sprintf(ctx, "%p", h); // [events][table][value][key]
+ duk_dup(ctx, -2); // [events][table][value][key][value]
+ duk_dup(ctx, 0);
+ duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_WaitHandle); // [events][table][value][key][value]
+ if (duk_is_object(ctx, 1)) { duk_dup(ctx, 1); }
+ else { duk_push_object(ctx); } // [events][table][value][key][value][options]
+ if (duk_has_prop_string(ctx, -1, "metadata"))
+ {
+ duk_push_string(ctx, "DescriptorEvents, "); // [events][table][value][key][value][options][str1]
+ duk_get_prop_string(ctx, -2, "metadata"); // [events][table][value][key][value][options][str1][str2]
+ duk_string_concat(ctx, -2); // [events][table][value][key][value][options][str1][newstr]
+ duk_remove(ctx, -2); // [events][table][value][key][value][options][newstr]
+ metadata = (char*)duk_get_string(ctx, -1);
+ duk_put_prop_string(ctx, -2, "metadata"); // [events][table][value][key][value][options]
+ }
+ timeout = Duktape_GetIntPropertyValue(ctx, -1, "timeout", -1);
+ duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_Options); // [events][table][value][key][value]
+ duk_put_prop(ctx, -4); // [events][table][value]
+ e = ILibDuktape_EventEmitter_Create(ctx);
+ ILibDuktape_EventEmitter_CreateEventEx(e, "signaled");
+ ILibChain_AddWaitHandleEx(duk_ctx_chain(ctx), h, timeout, ILibDuktape_DescriptorEvents_WaitHandleSink, link->ExtraMemoryPtr, metadata);
return(1);
}
+ return(ILibDuktape_Error(ctx, "Invalid Parameter"));
}
#endif
@@ -2527,17 +2649,39 @@ duk_ret_t ILibDuktape_DescriptorEvents_Add(duk_context *ctx)
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Table); // [obj][table]
+ duk_dup(ctx, 0); // [obj][table][key]
+ if (duk_has_prop(ctx, -2)) // [obj][table]
+ {
+ // There's already a watcher, so let's just merge the FD_SETS
+ duk_dup(ctx, 0); // [obj][table][key]
+ duk_get_prop(ctx, -2); // [obj][table][value]
+ duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Options); //..[table][value][options]
+ if (Duktape_GetBooleanProperty(ctx, 1, "readset", 0) != 0) { duk_push_true(ctx); duk_put_prop_string(ctx, -2, "readset"); }
+ if (Duktape_GetBooleanProperty(ctx, 1, "writeset", 0) != 0) { duk_push_true(ctx); duk_put_prop_string(ctx, -2, "writeset"); }
+ if (Duktape_GetBooleanProperty(ctx, 1, "errorset", 0) != 0) { duk_push_true(ctx); duk_put_prop_string(ctx, -2, "errorset"); }
+ duk_pop(ctx); // [obj][table][value]
+ return(1);
+ }
+
duk_push_object(ctx); // [obj][table][value]
duk_dup(ctx, 0); // [obj][table][value][key]
duk_dup(ctx, -2); // [obj][table][value][key][value]
- ILibDuktape_EventEmitter *e = ILibDuktape_EventEmitter_Create(ctx);
+ e = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEventEx(e, "readset");
ILibDuktape_EventEmitter_CreateEventEx(e, "writeset");
ILibDuktape_EventEmitter_CreateEventEx(e, "errorset");
duk_dup(ctx, 0); // [obj][table][value][key][value][FD]
duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_FD); // [obj][table][value][key][value]
- duk_dup(ctx, 1); duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_Options);
-
+ duk_dup(ctx, 1); // [obj][table][value][key][value][options]
+ duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_Options); // [obj][table][value][key][value]
+ char* metadata = Duktape_GetStringPropertyValue(ctx, -1, "metadata", NULL);
+ if (metadata != NULL)
+ {
+ duk_push_string(ctx, "DescriptorEvents, "); // [obj][table][value][key][value][str1]
+ duk_push_string(ctx, metadata); // [obj][table][value][key][value][str1][str2]
+ duk_string_concat(ctx, -2); // [obj][table][value][key][value][newStr]
+ duk_put_prop_string(ctx, -2, "metadata"); // [obj][table][value][key][value]
+ }
duk_put_prop(ctx, -4); // [obj][table][value]
return(1);
@@ -2604,22 +2748,51 @@ duk_ret_t ILibDuktape_DescriptorEvents_GetCount(duk_context *ctx)
#endif
return(1);
}
+char* ILibDuktape_DescriptorEvents_Query(void* chain, void *object, int fd, size_t *dataLen)
+{
+ char *retVal = ((ILibChain_Link*)object)->MetaData;
+ *dataLen = strnlen_s(retVal, 1024);
+
+ duk_context *ctx = (duk_context*)((void**)((ILibChain_Link*)object)->ExtraMemoryPtr)[0];
+ void *h = ((void**)((ILibChain_Link*)object)->ExtraMemoryPtr)[1];
+ if (h == NULL || ctx == NULL || !duk_ctx_is_alive(ctx)) { return(retVal); }
+ int top = duk_get_top(ctx);
+
+ duk_push_heapptr(ctx, h); // [events]
+ duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Table); // [events][table]
+ duk_push_int(ctx, fd); // [events][table][key]
+ if (duk_has_prop(ctx, -2) != 0) // [events][table]
+ {
+ duk_push_int(ctx, fd); duk_get_prop(ctx, -2); // [events][table][val]
+ duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Options); // [events][table][val][options]
+ if (!duk_is_null_or_undefined(ctx, -1))
+ {
+ retVal = Duktape_GetStringPropertyValueEx(ctx, -1, "metadata", retVal, dataLen);
+ }
+ }
+
+ duk_set_top(ctx, top);
+ return(retVal);
+}
void ILibDuktape_DescriptorEvents_Push(duk_context *ctx, void *chain)
{
ILibChain_Link *link = (ILibChain_Link*)ILibChain_Link_Allocate(sizeof(ILibChain_Link), 2 * sizeof(void*));
- link->MetaData = "ILibDuktape_DescriptorEvents";
+ link->MetaData = "DescriptorEvents";
link->PreSelectHandler = ILibDuktape_DescriptorEvents_PreSelect;
link->PostSelectHandler = ILibDuktape_DescriptorEvents_PostSelect;
+ link->QueryHandler = ILibDuktape_DescriptorEvents_Query;
duk_push_object(ctx);
duk_push_pointer(ctx, link); duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_ChainLink);
duk_push_object(ctx); duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_Table);
+ duk_push_object(ctx); duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_HTable);
+
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_DescriptorEvents_Finalizer);
((void**)link->ExtraMemoryPtr)[0] = ctx;
((void**)link->ExtraMemoryPtr)[1] = duk_get_heapptr(ctx, -1);
ILibDuktape_CreateInstanceMethod(ctx, "addDescriptor", ILibDuktape_DescriptorEvents_Add, 2);
- ILibDuktape_CreateInstanceMethod(ctx, "removeDescriptor", ILibDuktape_DescriptorEvents_Remove, 1);
+ ILibDuktape_CreateInstanceMethod(ctx, "removeDescriptor", ILibDuktape_DescriptorEvents_Remove, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "getDescriptorCount", ILibDuktape_DescriptorEvents_GetCount, 0);
ILibAddToChain(chain, link);
@@ -2656,6 +2829,23 @@ duk_ret_t ILibDuktape_Polyfills_isBuffer(duk_context *ctx)
duk_push_boolean(ctx, duk_is_buffer_data(ctx, 0));
return(1);
}
+#if defined(_POSIX) && !defined(__APPLE__) && !defined(_FREEBSD)
+duk_ret_t ILibDuktape_ioctl_func(duk_context *ctx)
+{
+ int fd = (int)duk_require_int(ctx, 0);
+ int code = (int)duk_require_int(ctx, 1);
+ duk_size_t outBufferLen = 0;
+ char *outBuffer = Duktape_GetBuffer(ctx, 2, &outBufferLen);
+
+ duk_push_int(ctx, ioctl(fd, _IOC(_IOC_READ | _IOC_WRITE, 'H', code, outBufferLen), outBuffer) ? errno : 0);
+ return(1);
+}
+void ILibDuktape_ioctl_Push(duk_context *ctx, void *chain)
+{
+ duk_push_c_function(ctx, ILibDuktape_ioctl_func, DUK_VARARGS);
+ ILibDuktape_WriteID(ctx, "ioctl");
+}
+#endif
void ILibDuktape_uuidv4_Push(duk_context *ctx, void *chain)
{
duk_push_object(ctx);
@@ -2693,6 +2883,9 @@ void ILibDuktape_Polyfills_Init(duk_context *ctx)
ILibDuktape_ModSearch_AddHandler(ctx, "ChainViewer", ILibDuktape_ChainViewer_Push);
ILibDuktape_ModSearch_AddHandler(ctx, "DescriptorEvents", ILibDuktape_DescriptorEvents_Push);
ILibDuktape_ModSearch_AddHandler(ctx, "uuid/v4", ILibDuktape_uuidv4_Push);
+#if defined(_POSIX) && !defined(__APPLE__) && !defined(_FREEBSD)
+ ILibDuktape_ModSearch_AddHandler(ctx, "ioctl", ILibDuktape_ioctl_Push);
+#endif
// Global Polyfills
diff --git a/microscript/ILibDuktape_ScriptContainer.c b/microscript/ILibDuktape_ScriptContainer.c
index 8db2749..0db6643 100644
--- a/microscript/ILibDuktape_ScriptContainer.c
+++ b/microscript/ILibDuktape_ScriptContainer.c
@@ -72,7 +72,6 @@ limitations under the License.
#include "ILibDuktape_SHA256.h"
#include "ILibDuktape_EncryptionStream.h"
#include "ILibDuktape_ChildProcess.h"
-#include "ILibDuktape_HECI.h"
#include "ILibDuktape_Debugger.h"
#include "ILibDuktape_Commit.h"
@@ -2377,9 +2376,6 @@ duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx3(duk_conte
if ((securityFlags & SCRIPT_ENGINE_NO_PROCESS_SPAWNING) == 0)
{
ILibDuktape_ChildProcess_Init(ctx);
-#ifndef _NOHECI
- ILibDuktape_HECI_Init(ctx);
-#endif
}
if ((securityFlags & SCRIPT_ENGINE_NO_FILE_SYSTEM_ACCESS) == 0) { ILibDuktape_fs_init(ctx); }
diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c
index b4fbd2d..1d57be8 100644
--- a/microscript/ILibDuktape_fs.c
+++ b/microscript/ILibDuktape_fs.c
@@ -21,6 +21,8 @@ limitations under the License.
#include
#include
#include
+#include
+#include
#endif
#include "microstack/ILibParsers.h"
@@ -66,6 +68,9 @@ limitations under the License.
#define FS_NOTIFY_DISPATCH_PTR "\xFF_FSWatcher_NotifyDispatchPtr"
#define FS_CHAIN_PTR "\xFF_FSWatcher_ChainPtr"
#define FS_WATCH_PATH "\xFF_FSWatcher_Path"
+#define FS_EVENT_R_DESCRIPTORS "\xFF_FSEventReadDescriptors"
+#define FS_EVENT_W_DESCRIPTORS "\xFF_FSEventWriteDescriptors"
+#define FS_EVENT_DESCRIPTORS_IO "\xFF_FSEventDescriptors_IO"
#if defined(_POSIX) && !defined(__APPLE__)
typedef struct ILibDuktape_fs_linuxWatcher
@@ -197,6 +202,17 @@ FILE* ILibDuktape_fs_getFilePtr(duk_context *ctx, int fd)
duk_ret_t ILibDuktape_fs_closeSync(duk_context *ctx)
{
int fd = duk_require_int(ctx, 0);
+
+ if (fd < 65535)
+ {
+#ifdef WIN32
+ _close(fd);
+#else
+ close(fd);
+#endif
+ return(0);
+ }
+
FILE *f;
char *key = ILibScratchPad;
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%d", fd);
@@ -263,21 +279,44 @@ duk_ret_t ILibDuktape_fs_openSync(duk_context *ctx)
#else
char *path = ILibDuktape_fs_fixLinuxPath((char*)duk_require_string(ctx, 0));
#endif
- char *flags = (char*)duk_require_string(ctx, 1);
- int retVal = -1;
-
- if (nargs < 2) { return(ILibDuktape_Error(ctx, "Too few arguments")); }
-
- retVal = ILibDuktape_fs_openSyncEx(ctx, path, flags, NULL);
- if (retVal > 0)
+ if (duk_is_string(ctx, 1))
{
- duk_push_int(ctx, retVal);
- return 1;
+ char *flags = (char*)duk_require_string(ctx, 1);
+ int retVal = -1;
+
+ if (nargs < 2) { return(ILibDuktape_Error(ctx, "Too few arguments")); }
+
+ retVal = ILibDuktape_fs_openSyncEx(ctx, path, flags, NULL);
+ if (retVal > 0)
+ {
+ duk_push_int(ctx, retVal);
+ return 1;
+ }
+ else
+ {
+ return(ILibDuktape_Error(ctx, "fs.openSync(): Error opening '%s'", path));
+ }
}
- else
+ int flags = (int)duk_require_int(ctx, 1);
+#ifdef WIN32
+ int fd = -1;
+ if (_wsopen_s(&fd, (wchar_t*)ILibDuktape_String_UTF8ToWide(ctx, path), flags, 0, 0) != 0)
{
- return(ILibDuktape_Error(ctx, "fs.openSync(): Error opening '%s'", path));
+ return(ILibDuktape_Error(ctx, "openSync() Error: %d ", errno));
}
+ duk_push_int(ctx, fd);
+#else
+ int fd = open(path, flags);
+ duk_push_int(ctx, fd);
+#ifdef _POSIX
+ if (fd >= 0 && (flags & O_NONBLOCK) == O_NONBLOCK)
+ {
+ flags = fcntl(fd, F_GETFL, 0);
+ fcntl(fd, F_SETFL, O_NONBLOCK | flags);
+ }
+#endif
+#endif
+ return(1);
}
duk_ret_t ILibDuktape_fs_readSync(duk_context *ctx)
{
@@ -303,6 +342,329 @@ duk_ret_t ILibDuktape_fs_readSync(duk_context *ctx)
return(ILibDuktape_Error(ctx, "FS I/O Error"));
}
+duk_ret_t ILibDuktape_fs_read_readsetSink(duk_context *ctx)
+{
+ int fd = duk_require_int(ctx, 0);
+ duk_push_this(ctx); // [DescriptorEvents]
+ duk_get_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO); // [DescriptorEvents][pending]
+ duk_array_pop(ctx, -1); // [DescriptorEvents][pending][options]
+
+ duk_size_t bufferLen;
+ char *buffer = Duktape_GetBufferPropertyEx(ctx, -1, "buffer", &bufferLen);
+ duk_size_t offset = (duk_size_t)Duktape_GetIntPropertyValue(ctx, -1, "offset", 0);
+ duk_size_t length = (duk_size_t)Duktape_GetIntPropertyValue(ctx, -1, "length", (int)bufferLen);
+#ifdef WIN32
+ int bytesRead = _read(fd, buffer + offset, (unsigned int)length);
+#else
+ int bytesRead = read(fd, buffer + offset, length);
+#endif
+ int status = bytesRead < 0 ? errno : 0;
+
+ duk_get_prop_string(ctx, -1, "callback"); // [DescriptorEvents][pending][options][callback]
+ duk_eval_string(ctx, "require('fs');"); // ..............[pending][options][callback][this]
+ duk_push_int(ctx, status); // ..............[pending][options][callback][this][err/status]
+ duk_push_int(ctx, bytesRead); // ..............[pending][options][callback][this][err/status][bytesRead]
+ duk_get_prop_string(ctx, -5, "buffer"); // ..............[pending][options][callback][this][err/status][bytesRead][buffer]
+ duk_dup(ctx, -6); // ..............[pending][options][callback][this][err/status][bytesRead][buffer][options]
+ if (duk_pcall_method(ctx, 4) != 0) // [DescriptorEvents][pending][options][val]
+ {
+ ILibDuktape_Process_UncaughtExceptionEx(ctx, "fs.read() Callback Error: %s ", duk_safe_to_string(ctx, -1));
+ }
+ duk_pop_2(ctx); // [DescriptorEvents][pending]
+ if (duk_get_length(ctx, -1) == 0)
+ {
+ // No more pending read I/O operations, so we can cleanup the DescriptorEvents
+ duk_eval_string(ctx, "require('DescriptorEvents');"); // .....[DescriptorEvents]
+ duk_get_prop_string(ctx, -1, "removeDescriptor"); // .....[DescriptorEvents][removeDescriptor]
+ duk_swap_top(ctx, -2); // .....[removeDescriptor][this]
+ duk_push_int(ctx, fd); // .....[removeDescriptor][this][fd]
+ duk_push_object(ctx); // .....[removeDescriptor][this][fd][options]
+ duk_push_true(ctx); duk_put_prop_string(ctx, -2, "readset");//..[removeDescriptor][this][fd][options]
+ duk_pcall_method(ctx, 2); duk_pop(ctx); // [DescriptorEvents][pending]
+
+ duk_eval_string(ctx, "require('fs');"); // [DescriptorEvents][pending][FS]
+ duk_get_prop_string(ctx, -1,FS_EVENT_R_DESCRIPTORS);// [DescriptorEvents][pending][FS][table]
+ duk_del_prop_index(ctx, -1, fd);
+ }
+ return(0);
+}
+duk_ret_t ILibDuktape_fs_write_writeset_sink(duk_context *ctx)
+{
+ int fd = (int)duk_require_int(ctx, 0);
+ duk_push_this(ctx); // [events]
+ duk_get_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO); // [events][pending]
+ duk_size_t bufferLen;
+ char *buffer = Duktape_GetBufferPropertyEx(ctx, -1, "buffer", &bufferLen);
+ int performCleanup = 0;
+#ifdef WIN32
+ int bytesWritten = _write(fd, buffer, (unsigned int)bufferLen);
+#else
+ int bytesWritten = write(fd, buffer, bufferLen);
+#endif
+ if (bytesWritten == bufferLen)
+ {
+ // Complete
+ duk_del_prop_string(ctx, -2, FS_EVENT_DESCRIPTORS_IO);
+ duk_get_prop_string(ctx, -1, "callback"); // [events][pending][callback]
+ duk_eval_string(ctx, "require('fs');"); // [events][pending][callback][this]
+ duk_push_int(ctx, 0); // [events][pending][callback][this][status]
+ duk_get_prop_string(ctx, -5, "original"); // [events][pending][callback][this][status][buffer]
+ duk_get_length(ctx, -1); // [events][pending][callback][this][status][buffer][length]
+ duk_swap_top(ctx, -2); // [events][pending][callback][this][status][bytesWritten][buffer]
+ duk_get_prop_string(ctx, -6, "opt"); // [events][pending][callback][this][status][bytesWritten][buffer][options]
+ if (duk_pcall_method(ctx, 4) != 0) // [events][pending][ret]
+ {
+ ILibDuktape_Process_UncaughtExceptionEx(ctx, "fs.write() Callback Error: %s ", duk_safe_to_string(ctx, -1));
+ }
+ duk_pop_2(ctx); // [events]
+ if (!duk_has_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO))
+ {
+ performCleanup = 1;
+ }
+ }
+ else
+ {
+ if (bytesWritten > 0) // [events][pending]
+ {
+ duk_get_prop_string(ctx, -1, "buffer"); // [events][pending][buffer]
+ duk_buffer_slice(ctx, -1, bytesWritten, (int)bufferLen - bytesWritten); // ....][buffer][sliced]
+ duk_put_prop_string(ctx, -3, "buffer"); // [events][pending][oldBuffer]
+ }
+ else
+ {
+ int e = errno;
+ if (e != EAGAIN && e != EWOULDBLOCK && e != EINTR) // [events][pending]
+ {
+ // Error occured
+ duk_del_prop_string(ctx, -2, FS_EVENT_DESCRIPTORS_IO);
+ performCleanup = 1;
+
+ duk_get_prop_string(ctx, -1, "callback"); // [events][pending][callback]
+ duk_eval_string(ctx, "require('fs');"); // [events][pending][callback][this]
+ duk_push_int(ctx, e); // [events][pending][callback][this][status]
+ duk_get_prop_string(ctx, -5, "original"); // [events][pending][callback][this][status][buffer]
+ duk_push_int(ctx, 0); // [events][pending][callback][this][status][buffer][written]
+ duk_swap_top(ctx, -2); // [events][pending][callback][this][status][bytesWritten][buffer]
+ duk_get_prop_string(ctx, -6, "opt"); // [events][pending][callback][this][status][bytesWritten][buffer][options]
+ if (duk_pcall_method(ctx, 4) != 0) // [events][pending][ret]
+ {
+ ILibDuktape_Process_UncaughtExceptionEx(ctx, "fs.write() Callback Error: %s ", duk_safe_to_string(ctx, -1));
+ }
+ }
+ }
+ }
+ if (performCleanup != 0)
+ {
+ // No more pending writes, so we can do some cleanup
+ duk_eval_string(ctx, "require('fs');"); // ... [fs]
+ duk_get_prop_string(ctx, -1, FS_EVENT_W_DESCRIPTORS); // ... [fs][table]
+ duk_del_prop_index(ctx, -1, fd); // ... [fs][table]
+
+ // And we can also unhook ourselves
+ duk_eval_string(ctx, "require('EventDescriptors');"); // ... [eventdescriptors]
+ duk_get_prop_string(ctx, -1, "removeDescriptor"); // ... [eventdescriptors][remove]
+ duk_swap_top(ctx, -2); // ... [remove][this]
+ duk_push_int(ctx, fd); // ... [remove][this][fd]
+ duk_push_object(ctx); // ... [remove][this][fd][options]
+ duk_push_true(ctx); duk_put_prop_string(ctx, -2, "writeset");//[remove][this][fd][options]
+ duk_call_method(ctx, 2); // ... [ret]
+ }
+ return(0);
+}
+duk_ret_t ILibDuktape_fs_write(duk_context *ctx)
+{
+ int fd = (int)duk_require_int(ctx, 0);
+ duk_size_t bufferLen;
+ char *buffer = Duktape_GetBuffer(ctx, 1, &bufferLen);
+ int cbx = 2;
+ int offset = 0, length = (int)bufferLen, e;
+ //int position = -1;
+
+ if (duk_is_number(ctx, 2)) { offset = (int)duk_require_int(ctx, 2); cbx++; }
+ if (duk_is_number(ctx, 3)) { length = (int)duk_require_int(ctx, 3); cbx++; }
+ if (duk_is_number(ctx, 4))
+ {
+ //position = (int)duk_require_int(ctx, 4);
+ cbx++;
+ }
+ if (!duk_is_function(ctx, cbx)) { return(ILibDuktape_Error(ctx, "Invalid Parameters")); }
+
+#ifdef WIN32
+ int bytesWritten = _write(fd, buffer + offset, length);
+#else
+ int bytesWritten = write(fd, buffer + offset, length);
+#endif
+ if (bytesWritten == length)
+ {
+ // Completed
+ duk_require_function(ctx, cbx);
+ duk_dup(ctx, cbx); // [func]
+ duk_push_this(ctx); // [func][this]
+ duk_push_int(ctx, 0); // [func][this][ERR]
+ duk_push_int(ctx, bytesWritten); // [func][this][ERR][bytesWritten]
+ duk_dup(ctx, 1); // [func][this][ERR][bytesWritten][buffer]
+ duk_dup(ctx, cbx + 1); // [func][this][ERR][bytesWritten][buffer][options]
+ duk_call_method(ctx, 4);
+ return(0);
+ }
+ if (bytesWritten > 0 || (e = errno) == EAGAIN || e == EWOULDBLOCK || e == EINTR)
+ {
+ // Partial Write
+ duk_push_this(ctx); // [fs]
+ duk_get_prop_string(ctx, -1, FS_EVENT_W_DESCRIPTORS); // [fs][table]
+ if (!duk_has_prop_index(ctx, -1, fd))
+ {
+ duk_eval_string(ctx, "require('DescriptorEvents');"); // [fs][table][DescriptorEvents]
+ duk_get_prop_string(ctx, -1, "addDescriptor"); // [fs][table][DescriptorEvents][add]
+ duk_swap_top(ctx, -2); // [fs][table][add][this]
+ duk_push_int(ctx, fd); // [fs][table][add][this][fd]
+ duk_push_object(ctx); // [fs][table][add][this][fd][options]
+ duk_push_true(ctx); duk_put_prop_string(ctx, -2, "writeset"); // ...[add][this][fd][options]
+ if (duk_is_object(ctx, cbx + 1) && duk_has_prop_string(ctx, cbx + 1, "metadata"))
+ {
+ duk_push_string(ctx, "fs.write(), "); // [fs][table][add][this][fd][options][str1]
+ duk_get_prop_string(ctx, cbx + 1, "metadata"); // [fs][table][add][this][fd][options][str1][str2]
+ duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [fs][table][add][this][fd][options][metadata]
+ }
+ else
+ {
+ duk_push_string(ctx, "fs.write()"); // [fs][table][add][this][fd][options][metadata]
+ }
+ duk_put_prop_string(ctx, -2, "metadata"); // [fs][table][add][this][fd][options]
+ duk_call_method(ctx, 2); // [fs][table][events]
+ ILibDuktape_EventEmitter_SetupOn(ctx, duk_get_heapptr(ctx, -1), "writeset"); // [on][this][writeset]
+ duk_push_c_function(ctx, ILibDuktape_fs_write_writeset_sink, DUK_VARARGS); // [on][this][writeset][func]
+ duk_call_method(ctx, 2); duk_pop(ctx); // [fs][table][events] .............................
+ duk_put_prop_index(ctx, -2, fd); // [fs][table]
+ }
+ duk_get_prop_index(ctx, -1, fd); // [fs][table][events]
+ duk_push_object(ctx); // [fs][table][events][pending]
+ if (duk_is_object(ctx, cbx + 1)) { duk_dup(ctx, cbx + 1); duk_put_prop_string(ctx, -2, "opt"); }
+ duk_dup(ctx, 1); // [fs][table][events][pending][buffer]
+ duk_buffer_slice(ctx, -1, offset + length, length - offset);// [fs][table][events][pending][buffer][sliced]
+ duk_dup(ctx, -1); // [fs][table][events][pending][buffer][sliced][dup]
+ duk_put_prop_string(ctx, -4, "buffer"); // [fs][table][events][pending][buffer][sliced]
+ duk_put_prop_string(ctx, -3, "original"); // [fs][table][events][pending][buffer]
+ duk_pop(ctx); // [fs][table][events][pending]
+ duk_dup(ctx, cbx); duk_put_prop_string(ctx, -2, "callback");// [fs][table][events][pending]
+ duk_put_prop_string(ctx, -2, FS_EVENT_DESCRIPTORS_IO); // [fs][table][events]
+ return(0);
+ }
+
+ // ERROR
+ duk_require_function(ctx, cbx);
+ duk_dup(ctx, cbx); // [func]
+ duk_push_this(ctx); // [func][this]
+ duk_push_int(ctx, e); // [func][this][ERR]
+ duk_push_int(ctx, bytesWritten); // [func][this][ERR][bytesWritten]
+ duk_dup(ctx, 1); // [func][this][ERR][bytesWritten][buffer]
+ duk_dup(ctx, cbx + 1); // [func][this][ERR][bytesWritten][buffer][options]
+ duk_call_method(ctx, 4);
+ return(0);
+}
+duk_ret_t ILibDuktape_fs_read(duk_context *ctx)
+{
+ int top = duk_get_top(ctx);
+ if (top > 2 && (!duk_is_function(ctx, 2)))
+ {
+ // Simplify flow, by converting to an options object
+ duk_push_this(ctx); // [fs]
+ duk_get_prop_string(ctx, -1, "read"); // [fs][read]
+ duk_swap_top(ctx, -2); // [read][this]
+ duk_dup(ctx, 0); // [read][this][fd]
+ duk_push_object(ctx); // [read][this][fd][options]
+ duk_dup(ctx, 1); duk_put_prop_string(ctx, -2, "buffer");
+ duk_dup(ctx, 2); duk_put_prop_string(ctx, -2, "offset");
+ duk_dup(ctx, 3); duk_put_prop_string(ctx, -2, "length");
+ duk_dup(ctx, 4); duk_put_prop_string(ctx, -2, "position");
+ duk_dup(ctx, 5); // [read][this][fd][options][callback]
+ duk_call_method(ctx, 3);
+ return(1);
+ }
+ if (top == 2 && duk_is_function(ctx, 1))
+ {
+ // Simplify flow, by converting to a default options object
+ duk_push_this(ctx); // [fs]
+ duk_get_prop_string(ctx, -1, "read"); // [fs][read]
+ duk_swap_top(ctx, -2); // [read][this]
+ duk_dup(ctx, 0); // [read][this][fd]
+ duk_push_object(ctx); // [read][this][fd][options]
+ duk_push_fixed_buffer(ctx, 16384); // [read][this][fd][options][buffer]
+ duk_push_buffer_object(ctx, -1, 0, 16384, DUK_BUFOBJ_NODEJS_BUFFER);
+ duk_remove(ctx, -2); // [read][this][fd][options][buffer]
+ duk_put_prop_string(ctx, -2, "buffer"); // [read][this][fd][options]
+ duk_push_int(ctx, 0); duk_put_prop_string(ctx, -2, "offset");
+ duk_push_int(ctx, 16384); duk_put_prop_string(ctx, -2, "length");
+ duk_push_null(ctx); duk_put_prop_string(ctx, -2, "position");
+ duk_dup(ctx, 1); // [read][this][fd][options][callback]
+ duk_call_method(ctx, 3);
+ return(1);
+ }
+ if (!(duk_is_number(ctx, 0) && duk_is_object(ctx, 1) && duk_is_function(ctx, 2))) { return(ILibDuktape_Error(ctx, "Invalid Parameters")); }
+ int fd = (int)duk_require_int(ctx, 0);
+
+ // First, we'll attempt to read, and see if it completes or is pending
+ duk_size_t bufferLen;
+ char *buffer = Duktape_GetBufferPropertyEx(ctx, 1, "buffer", &bufferLen);
+ duk_size_t offset = (duk_size_t)Duktape_GetIntPropertyValue(ctx, 1, "offset", 0);
+ duk_size_t length = (duk_size_t)Duktape_GetIntPropertyValue(ctx, 1, "length", (int)bufferLen);
+#ifdef WIN32
+ int bytesRead = _read(fd, buffer + offset, (unsigned int)length);
+#else
+ int bytesRead = read(fd, buffer + offset, length);
+#endif
+ if (bytesRead >= 0 || (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR))
+ {
+ // Completed
+ int errStatus = bytesRead >= 0 ? 0 : errno;
+ duk_dup(ctx, 2); // [func]
+ duk_push_this(ctx); // [func][this]
+ duk_push_int(ctx, errStatus); // [func][this][err/status]
+ duk_push_int(ctx, bytesRead); // [func][this][err/status][bytesRead]
+ duk_get_prop_string(ctx, 1, "buffer"); // [func][this][err/status][bytesRead][buffer]
+ duk_dup(ctx, 3); // [func][this][err/status][bytesRead][buffer][options]
+ duk_call_method(ctx, 4);
+ return(0);
+ }
+
+ //
+ // Setup the EventDescriptor listener, because the read did not complete
+ //
+ duk_push_this(ctx); // [fs]
+ duk_get_prop_string(ctx, -1, FS_EVENT_R_DESCRIPTORS); // [fs][table]
+ if (!duk_has_prop_index(ctx, -1, fd))
+ {
+ duk_eval_string(ctx, "require('DescriptorEvents');"); // [fs][table][DE]
+ duk_get_prop_string(ctx, -1, "addDescriptor"); // [fs][table][DE][addDescriptor]
+ duk_swap_top(ctx, -2); // [fs][table][addDescriptor][this]
+ duk_push_int(ctx, fd); // [fs][table][addDescriptor][this][fd]
+ duk_push_object(ctx); // [fs][table][addDescriptor][this][fd][options]
+ duk_push_true(ctx); duk_put_prop_string(ctx, -2, "readset");
+ if (duk_has_prop_string(ctx, 1, "metadata"))
+ {
+ duk_push_string(ctx, "fs.read(), "); // [fs][table][addDescriptor][this][fd][options][str]
+ duk_get_prop_string(ctx, 1, "metadata"); // [fs][table][addDescriptor][this][fd][options][str][str2]
+ duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [fs][table][addDescriptor][this][fd][options][metadata]
+ duk_put_prop_string(ctx, -2, "metadata"); // [fs][table][addDescriptor][this][fd][options]
+ }
+ else
+ {
+ duk_push_string(ctx, "fs.read()"); duk_put_prop_string(ctx, -2, "metadata");
+ }
+ duk_call_method(ctx, 2); // [fs][table][descriptorEvent]
+ ILibDuktape_EventEmitter_SetupOn(ctx, duk_get_heapptr(ctx, -1), "readset"); // ........[on][this][readset]
+ duk_push_c_function(ctx, ILibDuktape_fs_read_readsetSink, DUK_VARARGS); // ........[on][this][readset][func]
+ duk_call_method(ctx, 2); duk_pop(ctx); // [fs][table][descriptorEvent]
+ duk_push_array(ctx); duk_put_prop_string(ctx, -2, FS_EVENT_DESCRIPTORS_IO);
+ duk_put_prop_index(ctx, -2, fd); // [fs][table]
+ }
+ duk_get_prop_index(ctx, -1, fd); // [fs][table][desriptorEvent]
+ duk_get_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO); // [fs][table][desriptorEvent][pending]
+ duk_dup(ctx, 1); // [fs][table][desriptorEvent][pending][options]
+ duk_dup(ctx, 2); duk_put_prop_string(ctx, -2, "callback"); // [fs][table][desriptorEvent][pending][options]
+ duk_array_unshift(ctx, -2); // [fs][table][desriptorEvent][pending]
+ return(0);
+}
duk_ret_t ILibDuktape_fs_writeSync(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
@@ -1061,7 +1423,6 @@ duk_ret_t ILibDuktape_fs_watcher_finalizer(duk_context *ctx)
void ILibDuktape_fs_notifyDispatcher_QueryEx(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
ILibDuktape_fs_watcherData *data = (ILibDuktape_fs_watcherData*)Data;
- int fd = (int)(uintptr_t)Key1;
duk_push_heapptr(data->ctx, user); // [array]
duk_push_heapptr(data->ctx, data->object); // [array][watcher]
duk_get_prop_string(data->ctx, -1, FS_WATCH_PATH); // [array][watcher][path]
@@ -1644,16 +2005,23 @@ void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain)
duk_push_pointer(ctx, chain); // [fs][chain]
duk_put_prop_string(ctx, -2, FS_CHAIN_PTR); // [fs]
- duk_push_int(ctx, 0); // [fs][nextFD]
+ duk_push_int(ctx, 65535); // [fs][nextFD]
duk_put_prop_string(ctx, -2, FS_NextFD); // [fs]
duk_push_object(ctx); // [fs][descriptors]
duk_put_prop_string(ctx, -2, FS_FDS); // [fs]
+ duk_push_object(ctx);
+ duk_put_prop_string(ctx, -2, FS_EVENT_R_DESCRIPTORS);
+ duk_push_object(ctx);
+ duk_put_prop_string(ctx, -2, FS_EVENT_W_DESCRIPTORS);
+
ILibDuktape_CreateInstanceMethod(ctx, "closeSync", ILibDuktape_fs_closeSync, 1);
ILibDuktape_CreateInstanceMethod(ctx, "openSync", ILibDuktape_fs_openSync, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "readSync", ILibDuktape_fs_readSync, 5);
ILibDuktape_CreateInstanceMethod(ctx, "writeSync", ILibDuktape_fs_writeSync, DUK_VARARGS);
+ ILibDuktape_CreateInstanceMethod(ctx, "read", ILibDuktape_fs_read, DUK_VARARGS);
+ ILibDuktape_CreateInstanceMethod(ctx, "write", ILibDuktape_fs_write, DUK_VARARGS);
#ifdef WIN32
ILibDuktape_CreateInstanceMethod(ctx, "_readdirSync", ILibDuktape_fs_readdirSync, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "_statSync", ILibDuktape_fs_statSync, 1);
@@ -1678,6 +2046,18 @@ void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain)
ILibDuktape_CreateInstanceMethod(ctx, "mkdirSync", ILibDuktape_fs_mkdirSync, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "rmdirSync", ILibDuktape_fs_rmdirSync, 1);
+ duk_push_object(ctx);
+#ifdef WIN32
+ duk_push_int(ctx, _O_RDONLY); duk_put_prop_string(ctx, -2, "O_RDONLY");
+ duk_push_int(ctx, _O_WRONLY); duk_put_prop_string(ctx, -2, "O_WRONLY");
+ duk_push_int(ctx, _O_RDWR); duk_put_prop_string(ctx, -2, "O_RDWR");
+#else
+ duk_push_int(ctx, O_RDONLY); duk_put_prop_string(ctx, -2, "O_RDONLY");
+ duk_push_int(ctx, O_WRONLY); duk_put_prop_string(ctx, -2, "O_WRONLY");
+ duk_push_int(ctx, O_RDWR); duk_put_prop_string(ctx, -2, "O_RDWR");
+ duk_push_int(ctx, O_NONBLOCK); duk_put_prop_string(ctx, -2, "O_NONBLOCK");
+#endif
+ duk_put_prop_string(ctx, -2, "constants");
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_fs_Finalizer);
diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c
index 4ebe3d4..0c4313c 100644
--- a/microscript/ILibDuktape_net.c
+++ b/microscript/ILibDuktape_net.c
@@ -122,6 +122,7 @@ typedef struct ILibDuktape_net_WindowsIPC
#define ILibDuktape_SERVER2LISTENOPTIONS "\xFF_ServerToListenOptions"
#define ILibDuktape_TLSSocket2SecureContext "\xFF_TLSSocket2SecureContext"
#define ILibDuktape_IPAddress_SockAddr "\xFF_IPAddress_SockAddr"
+#define ILibDuktape_net_server_metadata "\xFF_net_server_metadata"
extern void ILibAsyncServerSocket_RemoveFromChain(ILibAsyncServerSocket_ServerModule serverModule);
@@ -1012,6 +1013,12 @@ void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void *
ILibChain_WaitHandle_DestroySavedState(winIPC->mChain, winIPC->reservedState);
winIPC->reservedState = NULL;
}
+ else
+ {
+ // We probably aren't paused, so we need to remove our wait handles
+ if (winIPC->read_overlapped.hEvent != NULL) { ILibChain_RemoveWaitHandle(winIPC->mChain, winIPC->read_overlapped.hEvent); }
+ if (winIPC->write_overlapped.hEvent != NULL) { ILibChain_RemoveWaitHandle(winIPC->mChain, winIPC->write_overlapped.hEvent); }
+ }
if (winIPC->mPipeHandle != NULL)
{
if (winIPC->mServer != NULL) { DisconnectNamedPipe(winIPC->mPipeHandle); }
@@ -1263,8 +1270,10 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx)
return(ILibDuktape_Error(ctx, "Error Creating Named Pipe: %s", ipc));
}
//printf("ConnectNamedPipe(%s)\n", ipc);
+ duk_push_sprintf(ctx, "net.ipcServer [listen: %s]", ipc);
ConnectNamedPipe(winIPC->mPipeHandle, &winIPC->overlapped);
- ILibChain_AddWaitHandleEx(duk_ctx_chain(ctx), winIPC->overlapped.hEvent, -1, ILibDuktape_net_server_IPC_ConnectSink, winIPC, "net.ipcServer [listen]");
+ ILibChain_AddWaitHandleEx(duk_ctx_chain(ctx), winIPC->overlapped.hEvent, -1, ILibDuktape_net_server_IPC_ConnectSink, winIPC, (char*)duk_get_string(ctx, -1));
+ duk_pop(ctx);
if (pIPC_SA != NULL) { LocalFree(IPC_ACL); }
return(1);
@@ -1326,7 +1335,21 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx)
#endif
duk_push_this(ctx);
- if (server->server != NULL) { ILibChain_Link_SetMetadata(server->server, Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "net.Server")); }
+ if (server->server != NULL)
+ {
+ duk_get_prop_string(ctx, -1, ILibDuktape_OBJID); // [server][str]
+ if (duk_has_prop_string(ctx, -2, ILibDuktape_net_server_metadata))
+ {
+ duk_push_string(ctx, ", "); // [server][str][newVal]
+ duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [server][str]
+ duk_get_prop_string(ctx, -2, ILibDuktape_net_server_metadata); // [server][str][metadata]
+ duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [server][metadata]
+ duk_dup(ctx, -1); // [server][metadata][clone]
+ duk_put_prop_string(ctx, -3, ILibDuktape_net_server_metadata); // [server][metadata]
+ }
+ ILibChain_Link_SetMetadata(server->server, (char*)duk_get_string(ctx, -1));
+ duk_pop(ctx);
+ }
return 1;
}
@@ -1466,6 +1489,11 @@ duk_ret_t ILibDuktape_net_createServer_metadata(duk_context *ctx)
memcpy_s(tmp2, ILibMemory_Size(tmp2), tmp, ILibMemory_Size(tmp2) - 1);
ILibChain_Link_SetMetadata(server->server, tmp2);
}
+ else
+ {
+ duk_dup(ctx, 0); // [server][string]
+ duk_put_prop_string(ctx, -2, ILibDuktape_net_server_metadata);
+ }
return(0);
}
diff --git a/microstack/ILibParsers.c b/microstack/ILibParsers.c
index d8aa27a..89da431 100644
--- a/microstack/ILibParsers.c
+++ b/microstack/ILibParsers.c
@@ -2079,9 +2079,16 @@ int ILibChain_WindowsSelect(void *chain, fd_set *readset, fd_set *writeset, fd_s
// TIMEOUT occured
if (((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler != NULL)
{
- ((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler(chain, waitList[i], ILibWaitHandle_ErrorStatus_TIMEOUT, ((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->user);
+ if (((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler(chain, waitList[i], ILibWaitHandle_ErrorStatus_TIMEOUT, ((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->user) == FALSE)
+ {
+ ILibLinkedList_Remove(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->node);
+ }
}
- ILibLinkedList_Remove(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->node);
+ else
+ {
+ ILibLinkedList_Remove(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->node);
+ }
+
waitList[i] = NULL;
waitList[ILibChain_HandleInfoIndex(i)] = NULL;
}
@@ -3432,6 +3439,7 @@ void ILibChain_AddWaitHandleEx(void *chain, HANDLE h, int msTIMEOUT, ILibChain_W
info->expiration.tv_usec += ((msTIMEOUT % 1000) * 1000);
}
}
+ ILibMemory_Free(metadata);
}
void __stdcall ILibChain_RemoveWaitHandle_APC(ULONG_PTR u)
{
diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c
index c174274..2051a25 100644
--- a/microstack/ILibProcessPipe.c
+++ b/microstack/ILibProcessPipe.c
@@ -184,7 +184,6 @@ char * ILibProcessPipe_Manager_OnQuery(void *chain, void *object, int fd, size_t
{
ILibProcessPipe_Manager_Object *man = (ILibProcessPipe_Manager_Object*)object;
char *ret = ((ILibChain_Link*)object)->MetaData;
- int i;
*dataLen = strnlen_s(((ILibChain_Link*)object)->MetaData, 1024);
void *node = ILibLinkedList_GetNode_Search(man->ActivePipes, ILibProcessPipe_Manager_OnQuery_comparer, (void*)(uintptr_t)fd);
diff --git a/modules/amt-lme.js b/modules/amt-lme.js
index c5263ae..bea0098 100644
--- a/modules/amt-lme.js
+++ b/modules/amt-lme.js
@@ -117,6 +117,7 @@ function lme_heci(options) {
emitterUtils.createEvent('notify');
emitterUtils.createEvent('bind');
+ this.on('newListener', function (name, func) { if (name == 'connect' && this._LME._connected == true) { func.call(this);} });
if ((options != null) && (options.debug == true)) { lme_port_offset = -100; } // LMS debug mode
var heci = require('heci');
@@ -124,10 +125,14 @@ function lme_heci(options) {
this._ObjectID = "lme";
this._LME = heci.create();
+ this._LME._connected = false;
+ this._LME.descriptorMetadata = "amt-lme";
this._LME._binded = {};
this._LME.LMS = this;
this._LME.on('error', function (e) { this.LMS.emit('error', e); });
- this._LME.on('connect', function () {
+ this._LME.on('connect', function ()
+ {
+ this._connected = true;
this.on('data', function (chunk) {
// this = HECI
var cmd = chunk.readUInt8(0);
@@ -173,6 +178,7 @@ function lme_heci(options) {
try {
// Bind a new server socket if not already present
this[name][port] = require('net').createServer();
+ this[name][port].descriptorMetadata = 'amt-lme (port: ' + port + ')';
this[name][port].HECI = this;
if (lme_port_offset == 0) {
this[name][port].listen({ port: port, host: '127.0.0.1' }); // Normal mode
diff --git a/modules/amt-mei.js b/modules/amt-mei.js
index 3a724e1..304ac35 100644
--- a/modules/amt-mei.js
+++ b/modules/amt-mei.js
@@ -27,6 +27,7 @@ function amt_heci() {
this._setupPTHI = function _setupPTHI()
{
this._amt = heci.create();
+ this._amt.descriptorMetadata = "amt-pthi";
this._amt.BiosVersionLen = 65;
this._amt.UnicodeStringLen = 20;
@@ -397,20 +398,25 @@ function amt_heci() {
fn.apply(this, opt);
}, callback, optional);
}
- this.getProtocolVersion = function getProtocolVersion(callback) {
+ this.getProtocolVersion = function getProtocolVersion(callback)
+ {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { opt.push(arguments[i]); }
- heci.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) {
+ if (!this._tmpSession) { this._tmpSession = heci.create(); this._tmpSession.parent = this;}
+ this._tmpSession.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt)
+ {
if (status == 0) {
var result = buffer.readUInt8(0).toString() + '.' + buffer.readUInt8(1).toString() + '.' + buffer.readUInt8(2).toString() + '.' + buffer.readUInt16BE(3).toString();
opt.unshift(result);
fn.apply(self, opt);
}
- else {
+ else
+ {
opt.unshift(null);
fn.apply(self, opt);
}
+
}, this, callback, optional);
}
}
diff --git a/modules/heci.js b/modules/heci.js
new file mode 100644
index 0000000..2ff0590
--- /dev/null
+++ b/modules/heci.js
@@ -0,0 +1,606 @@
+/*
+Copyright 2020 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+var GM = null;
+var setup = null;
+var kernel32 = null;
+var duplex = require('stream').Duplex;
+
+
+if (process.platform == 'win32')
+{
+ GM = require('_GenericMarshal');
+ setup = GM.CreateNativeProxy('SetupAPI.dll');
+ setup.CreateMethod('SetupDiGetClassDevsA');
+ setup.CreateMethod('SetupDiEnumDeviceInterfaces');
+ setup.CreateMethod('SetupDiGetDeviceInterfaceDetailA');
+ setup.CreateMethod('SetupDiDestroyDeviceInfoList');
+
+ kernel32 = GM.CreateNativeProxy('Kernel32.dll');
+ kernel32.CreateMethod('CloseHandle');
+ kernel32.CreateMethod('CreateEventA');
+ kernel32.CreateMethod('CreateFileA');
+ kernel32.CreateMethod('DeviceIoControl');
+ kernel32.CreateMethod('GetOverlappedResult');
+ kernel32.CreateMethod('ReadFile');
+ kernel32.CreateMethod('WriteFile');
+}
+
+var DIGCF_DEFAULT = 0x00000001;
+var DIGCF_PRESENT = 0x00000002;
+var DIGCF_ALLCLASSES = 0x00000004;
+var DIGCF_PROFILE = 0x00000008;
+var DIGCF_DEVICEINTERFACE = 0x00000010;
+var ERROR_INSUFFICIENT_BUFFER = 122;
+var GENERIC_READ = 0x80000000;
+var GENERIC_WRITE = 0x40000000;
+var FILE_SHARE_READ = 0x00000001;
+var FILE_SHARE_WRITE = 0x00000002;
+var OPEN_EXISTING = 3;
+var FILE_FLAG_OVERLAPPED = 0x40000000;
+var ERROR_IO_PENDING = 997;
+
+function heci_create()
+{
+ var ret = new duplex(
+ {
+ 'write': function (chunk, flush)
+ {
+ if (chunk.length > this.MaxBufferSize) { throw ('Buffer too large'); }
+ if (process.platform == 'win32')
+ {
+ if (this._writeoverlapped == null) { throw ('Not Connected'); }
+ }
+ this._pendingWrites.unshift({ buffer: chunk, flush: flush });
+
+ if (this._pendingWrites.length == 1)
+ {
+ // Kickstart the write
+ this._processWrite();
+ }
+
+ if (process.platform == 'win32')
+ {
+ return (false);
+ }
+ },
+ 'final': function (flush)
+ {
+ flush();
+ },
+ 'read': function(size)
+ {
+ if (!this._readbuffer)
+ {
+ this._readbuffer = process.platform == 'win32' ? GM.CreateVariable(this.MaxBufferSize) : Buffer.alloc(this.MaxBufferSize);
+ }
+
+ if (process.platform == 'linux')
+ {
+ this._processRead();
+ return;
+ }
+
+ var result = kernel32.ReadFile(this._descriptor, this._readbuffer, this._readbuffer._size, 0, this._readoverlapped);
+ if(result.Val != 0 || result._LastError == ERROR_IO_PENDING)
+ {
+ if(!this._rDescriptorEvent)
+ {
+ this._rDescriptorEvent = require('DescriptorEvents').addDescriptor(this._readoverlapped.hEvent, { metadata: 'heci.session [read]' });
+ this._rDescriptorEvent.session = this;
+ this._rDescriptorEvent.on('signaled', function (status)
+ {
+ if(status != 'NONE')
+ {
+ console.info3('>>> heci.session signaled with status: ' + status);
+ this.session.push(null);
+ return;
+ }
+ var bytesRead = GM.CreateVariable(4);
+ var result;
+ if((result=kernel32.GetOverlappedResult(this.session._descriptor, this.session._readoverlapped, bytesRead, 0)).Val != 0)
+ {
+ var buffer = this.session._readbuffer.toBuffer().slice(0, bytesRead.toBuffer().readUInt32LE());
+ console.info3(buffer.length + ' bytes READ');
+
+ var pushResult = this.session.push(buffer);
+ if (this.session._options.noPipeline != 0 && this.session._pendingWrites.length>0)
+ {
+ // Unlock a write
+ console.info2('pendingWriteCount: ' + this.session._pendingWrites.length);
+ var item = this.session._pendingWrites.pop();
+
+ if (this.session._pendingWrites.length > 0)
+ {
+ this.session._processWrite();
+ }
+ else
+ {
+ console.info2('Write/Flush');
+ item.flush();
+ }
+ }
+
+ if (pushResult)
+ {
+ // We can read more, because data is still flowing
+ var result = kernel32.ReadFile(this.session._descriptor, this.session._readbuffer, this.session._readbuffer._size, 0, this.session._readoverlapped);
+ if(result.Val != 0 || result._LastError == ERROR_IO_PENDING)
+ {
+ return (true);
+ }
+ else
+ {
+ console.info1('Sometype of error: ' + result._LastError);
+ this.session.push(null);
+ }
+ }
+ }
+ else
+ {
+ console.info1('READ_OVERLAPPED_ERROR: ' + result._LastError + ' on ' + this.session._hashCode());
+ }
+
+ });
+ }
+ }
+ else
+ {
+ console.info1('Some Other Error: ' + result._LastError);
+ }
+ }
+ });
+ ret._ObjectID = 'heci.session';
+ ret.bufferMode = 1;
+ ret._ioctls = [];
+ ret._pendingWrites = [];
+ ret.heciParent = this;
+
+ require('events').EventEmitter.call(ret, true)
+ .createEvent('connect')
+ .createEvent('error')
+ .addMethod('connect', function _connect(guid, options)
+ {
+ console.info1('connect()');
+ this.doIoctl(this.heciParent.IOCTL.CLIENT_CONNECT, guid, Buffer.alloc(16), function _onconnect(status, buffer, opt)
+ {
+ if(status!=0)
+ {
+ console.info1('HECI Connection Error [' + this.LastError + ']');
+ this.emit('error', 'HECI Connection Error [' + this.LastError + ']');
+ return;
+ }
+ if(buffer.length <=4)
+ {
+ // Invalid Response
+ this.emit('error', 'HECI Connection Error [INVALID RESPONSE]');
+ return;
+ }
+ Object.defineProperty(this, "MaxBufferSize", { value: buffer.readUInt32LE() });
+ this._options = opt;
+
+ if (process.platform == 'win32')
+ {
+ this._readoverlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20);
+ this._writeoverlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20);
+ this._readoverlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0);
+ this._writeoverlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0);
+ this._readoverlapped.hEvent.pointerBuffer().copy(this._readoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer());
+ this._writeoverlapped.hEvent.pointerBuffer().copy(this._writeoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer());
+ }
+ console.info1('Connected, buffer size: ' + this.MaxBufferSize);
+ this._read(this.MaxBufferSize);
+ this.emit('connect');
+ }, options);
+ })
+ .addMethod('descriptorPath', function _descriptorPath()
+ {
+ if (process.platform == 'linux')
+ {
+ if (require('fs').existsSync('/dev/mei')) { return ('/dev/mei'); }
+ if (require('fs').existsSync('/dev/mei0')) { return ('/dev/mei0'); }
+ throw ('HECI not supported');
+ }
+ if (process.platform != 'win32') { throw ('HECI not supported'); }
+
+ var result;
+ var ii;
+ var deviceDetail;
+ var bufferSize = GM.CreateVariable(4); // DWORD
+ var heciguid = GM.CreateVariable(this.heciParent.GUIDS.HECI);
+ var deviceInfo = setup.SetupDiGetClassDevsA(heciguid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ if (deviceInfo.Val == -1)
+ {
+ console.info1('... Unable to acquire [deviceInfo]');
+ throw ('unable to acquire [deviceInfo]');
+ }
+ console.info1('... acquired [deviceInfo]');
+
+
+ var interfaceData = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 28);
+ interfaceData.toBuffer().writeUInt32LE(interfaceData._size, 0);
+
+ for (ii = 0; setup.SetupDiEnumDeviceInterfaces(deviceInfo, 0, heciguid, ii, interfaceData).Val != 0; ++ii)
+ {
+ // Found our device instance
+ if ((result = setup.SetupDiGetDeviceInterfaceDetailA(deviceInfo, interfaceData, 0, 0, bufferSize, 0)).Val == 0)
+ {
+ if (result._LastError != ERROR_INSUFFICIENT_BUFFER)
+ {
+ continue;
+ }
+ }
+
+ // Allocate a big enough buffer to get detail data
+ deviceDetail = GM.CreateVariable(bufferSize.toBuffer().readUInt32LE());
+ deviceDetail.toBuffer().writeUInt32LE(GM.PointerSize == 8 ? 8 : 5, 0);
+
+ // Try again to get the device interface detail info
+ if (setup.SetupDiGetDeviceInterfaceDetailA(deviceInfo, interfaceData, deviceDetail, bufferSize, 0, 0).Val == 0)
+ {
+ deviceDetail = NULL;
+ continue;
+ }
+ break;
+ }
+ setup.SetupDiDestroyDeviceInfoList(deviceInfo);
+ if (deviceDetail == null)
+ {
+ console.info1('... failed to acquire [deviceDetail]');
+ throw ('unable to acquire [deviceDetail]');
+ }
+
+ var devPath = deviceDetail.Deref(4, GM.PointerSize);
+ return (devPath.String);
+ })
+ .addMethod('createDescriptor', function _createDescriptor(path)
+ {
+ if (process.platform == 'linux')
+ {
+ return (require('fs').openSync(path, require('fs').constants.O_RDWR | require('fs').constants.O_NONBLOCK));
+ }
+ if (process.platform != 'win32') { throw ('HECI not supported'); }
+
+ var devPath = GM.CreateVariable(path);
+ var ret = kernel32.CreateFileA(devPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+ if (ret.Val == -1)
+ {
+ console.info1('... failed to acquire [descriptor]');
+ throw ('failed to acquire descriptor');
+ }
+ console.info1('... acquired [DESCRIPTOR]');
+ return (ret);
+ });
+ if (process.platform == 'win32')
+ {
+ ret._overlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20);
+ ret._overlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0);
+
+ var overlapped_eventptr = ret._overlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer();
+ ret._overlapped.hEvent.pointerBuffer().copy(overlapped_eventptr);
+ }
+ ret.disconnect = function disconnect()
+ {
+ // Clean up all Handles and Descriptors
+ console.info1('DISCONNECT on ' + this._hashCode());
+ if (process.platform == 'linux')
+ {
+ if(this._descriptor != null)
+ {
+ require('DescriptorEvents').removeDescriptor(this._descriptor);
+ require('fs').closeSync(this._descriptor);
+ this._descriptor = null;
+ }
+ }
+
+ if (process.platform == 'win32')
+ {
+ //
+ // doIoctl()
+ //
+ if (this._descriptorEvent)
+ {
+ if (this._overlapped) { require('DescriptorEvents').removeDescriptor(this._overlapped.hEvent); }
+ this._descriptorEvent = null;
+ }
+ if (this._overlapped)
+ {
+ kernel32.CloseHandle(this._overlapped.hEvent);
+ this._overlapped = null;
+ }
+
+ //
+ // Read
+ //
+ if (this._rDescriptorEvent)
+ {
+ if (this._readoverlapped) { require('DescriptorEvents').removeDescriptor(this._readoverlapped.hEvent); }
+ this._rDescriptorEvent = null;
+ }
+ if (this._readoverlapped)
+ {
+ kernel32.CloseHandle(this._readoverlapped.hEvent);
+ this._readoverlapped = null;
+ }
+
+ //
+ // Write
+ //
+ if (this._wDescriptorEvent)
+ {
+ if (this._writeoverlapped) { require('DescriptorEvents').removeDescriptor(this._writeoverlapped.hEvent); }
+ this._wDescriptorEvent = null;
+ }
+ if (this._writeoverlapped)
+ {
+ kernel32.CloseHandle(this._writeoverlapped.hEvent);
+ this._writeoverlapped = null;
+ }
+
+ //
+ // HECI
+ //
+ if (this._descriptor)
+ {
+ kernel32.CloseHandle(this._descriptor);
+ this._descriptor = null;
+ }
+ }
+ };
+ ret.doIoctl = function doIoctl(code, inputBuffer, outputBuffer, callback)
+ {
+ if (typeof (callback) != 'function') { throw ('Callback not specified'); }
+
+ var i;
+ var parms = [];
+ for (i = 4; i < arguments.length; ++i)
+ {
+ parms.push(arguments[i]);
+ }
+
+
+ if (process.platform == 'linux')
+ {
+ if (outputBuffer.length < inputBuffer.length) { throw ('output buffer is too small'); }
+ outputBuffer.fill(0);
+ inputBuffer.copy(outputBuffer);
+ if (this._descriptor == null) { this._descriptor = this.createDescriptor(this.descriptorPath()); }
+ var ret = require('ioctl')(this._descriptor, code, outputBuffer);
+ parms.unshift(outputBuffer);
+ parms.unshift(ret);
+ callback.apply(this, parms);
+ return;
+ }
+
+ this._ioctls.unshift({ code: code, input: inputBuffer, output: outputBuffer, callback: callback, parms: parms });
+ if(this._ioctls.length == 1)
+ {
+ // First IOCTL, so we need to send the first one
+ this._send(this._ioctls.peek());
+ }
+ };
+
+ ret._send = function _send(options)
+ {
+ if(this._descriptor == null)
+ {
+ this._descriptor = this.createDescriptor(this.descriptorPath());
+ this._descriptorEvent = require('DescriptorEvents').addDescriptor(this._overlapped.hEvent, {metadata: 'heci'});
+ this._descriptorEvent.session = this;
+ this._descriptorEvent.on('signaled', function(status)
+ {
+ var data = this.session._ioctls.pop();
+ if(status == 'NONE')
+ {
+ var bytesRead = GM.CreateVariable(4);
+ var result = kernel32.GetOverlappedResult(this.session._descriptor, this.session._overlapped, bytesRead, 0);
+ if(result.Val != 0)
+ {
+ var out = data.output;
+ try
+ {
+ out.slice(0,bytesRead.toBuffer().readUInt32LE());
+ }
+ catch(e)
+ {
+ out = null;
+ }
+ data.parms.unshift(out);
+ data.parms.unshift(0);
+ this.session.LastError = 'NONE';
+ }
+ else
+ {
+ data.parms.unshift(null);
+ data.parms.unshift(1);
+ this.session.LastError = 'OVERLAPPED_ERROR: ' + result._LastError;
+ }
+ }
+ else
+ {
+ data.parms.unshift(null);
+ data.parms.unshift(1);
+ this.session.LastError = status;
+ }
+ try
+ {
+ data.callback.apply(this.session, data.parms);
+ }
+ catch(ue)
+ {
+ process.emit('uncaughtException', ue);
+ }
+ if(this.session._ioctls.length > 0)
+ {
+ // Still more IOCTLs to send
+ this.session._send(this.session._ioctls.peek());
+ return (true);
+ }
+ });
+ }
+ kernel32.DeviceIoControl(this._descriptor, options.code, GM.CreateVariable(options.input), options.input.length, GM.CreateVariable(options.output), options.output.length, 0, this._overlapped);
+ };
+ ret._processWrite = function _processWrite()
+ {
+ var chunk = this._pendingWrites.peek();
+ console.info3('_WRITING: ' + chunk.buffer.length + ' bytes' + ' on ' + this._hashCode());
+
+ if (process.platform == 'win32')
+ {
+ var result = kernel32.WriteFile(this._descriptor, GM.CreateVariable(chunk.buffer), chunk.buffer.length, 0, this._writeoverlapped);
+ if (result.Val != 0 || result._LastError == ERROR_IO_PENDING)
+ {
+ if (!this._wDescriptorEvent)
+ {
+ this._wDescriptorEvent = require('DescriptorEvents').addDescriptor(this._writeoverlapped.hEvent, { metadata: 'heci.session [write]' });
+ this._wDescriptorEvent.session = this;
+ this._wDescriptorEvent.on('signaled', this._processWrite_signaled);
+ }
+ }
+ else
+ {
+ console.info1('Write Error: ' + result._LastError);
+ }
+ }
+
+ require('fs').write(this._descriptor, chunk.buffer, this._processWrite_linux_signaled, { metadata: 'heci.session', session: this });
+ };
+ ret._processWrite_linux_signaled = function _processWrite_linux_signaled(status, bytesWritten, buffer, options)
+ {
+ if(status == 0)
+ {
+ console.info3(bytesWritten + ' bytes written');
+ console.info3('noPipeline = ' + options.session._options.noPipeline, options.session._pendingWrites.length);
+ if (options.session._options.noPipeline == null || options.session._options.noPipeline == false)
+ {
+ var item = options.session._pendingWrites.pop();
+ if (options.session._pendingWrites.length > 0)
+ {
+ options.session._processWrite();
+ }
+ else
+ {
+ console.info3('Write/Flush');
+ item.flush();
+ }
+ }
+ }
+ };
+ ret._processWrite_signaled = function _processWrite_signaled(status)
+ {
+ console.info3('Write Signaled: ' + status);
+ if(status == 'NONE')
+ {
+ // No Errors
+ var bytesWritten = GM.CreateVariable(4);
+ var result = kernel32.GetOverlappedResult(this.session._descriptor, this.session._writeoverlapped, bytesWritten, 0);
+ if(result.Val != 0)
+ {
+ console.info3(bytesWritten.toBuffer().readUInt32LE() + ' bytes written');
+ console.info3('noPipeline = ' + this.session._options.noPipeline, this.session._pendingWrites.length);
+ if(this.session._options.noPipeline==null || this.session._options.noPipeline == false)
+ {
+ var item = this.session._pendingWrites.pop();
+ if (this.session._pendingWrites.length > 0)
+ {
+ this.session._processWrite();
+ }
+ else
+ {
+ console.info3('Write/Flush');
+ item.flush();
+ }
+ return (true);
+ }
+ }
+ }
+ };
+ ret._processRead_readSet_sink = function _processRead_readSet_sink(status, bytesRead, buffer, options)
+ {
+ if (status != 0) { options.session.push(null); return; }
+ console.info3(bytesRead + ' bytes read');
+
+ buffer = buffer.slice(0, bytesRead);
+ var pushResult = options.session.push(buffer);
+ if (options.session._options.noPipeline != 0 && options.session._pendingWrites.length > 0)
+ {
+ // Unlock a write
+ console.info3('pendingWriteCount: ' + options.session._pendingWrites.length);
+ var item = options.session._pendingWrites.pop();
+
+ if (options.session._pendingWrites.length > 0)
+ {
+ options.session._processWrite();
+ }
+ else
+ {
+ console.info3('Write/Flush');
+ item.flush();
+ }
+ }
+
+ if (pushResult)
+ {
+ // We can read more, because data is still flowing
+ options.session._processRead();
+ }
+ };
+ ret._processRead = function _processRead()
+ {
+ if (this._descriptor == null) { return; }
+ require('fs').read(this._descriptor, { metadata: 'heci.session', buffer: this._readbuffer, session: this }, this._processRead_readSet_sink);
+ };
+ ret.once('~', function () { this.disconnect(); });
+ return (ret);
+}
+
+var ioctl = {};
+if(process.platform == 'win32')
+{
+ Object.defineProperty(ioctl, 'HECI_VERSION', { value: 0x8000E000 });
+ Object.defineProperty(ioctl, 'CLIENT_CONNECT', { value: 0x8000E004 });
+}
+if(process.platform == 'linux')
+{
+ Object.defineProperty(ioctl, 'HECI_VERSION', { value: 0x00 });
+ Object.defineProperty(ioctl, 'CLIENT_CONNECT', { value: 0x01 });
+}
+
+var guids = {};
+Object.defineProperty(guids, 'AMT', { value: Buffer.from('2800F812B7B42D4BACA846E0FF65814C', 'hex') });
+Object.defineProperty(guids, 'LME', { value: Buffer.from('DBA4336776047B4EB3AFBCFC29BEE7A7', 'hex') });
+if (process.platform == 'win32')
+{
+ Object.defineProperty(guids, 'HECI', { value: Buffer.from('34FFD1E25834A94988DA8E6915CE9BE5', 'hex') });
+}
+
+
+module.exports = { _ObjectID: 'heci', IOCTL: ioctl, GUIDS: guids, create: heci_create };
+Object.defineProperty(module.exports, "supported", {
+ get: function ()
+ {
+ try
+ {
+ var p = this.create().descriptorPath();
+ var d = this.create().createDescriptor(p);
+ return(true);
+ }
+ catch(e)
+ {
+ return (false);
+ }
+ }
+});
\ No newline at end of file