1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-24 04:04:31 +00:00

Much improved, better stability, lots of fixes

This commit is contained in:
Ylian Saint-Hilaire
2018-01-12 11:50:04 -08:00
parent becf71557f
commit 508646044e
69 changed files with 11803 additions and 4088 deletions

View File

@@ -29,7 +29,7 @@ limitations under the License.
#include <crtdbg.h>
#endif
#define ILibDuktape_ModSearch_ModuleFile "0xFF"
#define ILibDuktape_ModSearch_ModuleFile (void*)0xFF
int ILibDuktape_ModSearch_AddModule(duk_context *ctx, char *id, char *module, int moduleLen)
{

View File

@@ -9,7 +9,6 @@
#include "ILibDuktape_WritableStream.h"
#include "ILibDuktape_EventEmitter.h"
#define ILibDuktape_ChildProcess_Manager "\xFF_ChildProcess_Manager"
#define ILibDuktape_ChildProcess_Process "\xFF_ChildProcess_Process"
#define ILibDuktape_ChildProcess_MemBuf "\xFF_ChildProcess_MemBuf"
@@ -122,14 +121,23 @@ ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUS
ILibDuktape_CreateInstanceMethod(ctx, "kill", ILibDuktape_ChildProcess_Kill, 0);
duk_push_object(ctx);
ILibDuktape_WriteID(ctx, "childProcess.stdout");
duk_dup(ctx, -2);
ILibDuktape_CreateReadonlyProperty(ctx, "parent");
retVal->stdOut = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdOut_OnPause, ILibDuktape_ChildProcess_SubProcess_StdOut_OnResume, retVal);
ILibDuktape_CreateReadonlyProperty(ctx, "stdout");
duk_push_object(ctx);
ILibDuktape_WriteID(ctx, "childProcess.stderr");
duk_dup(ctx, -2);
ILibDuktape_CreateReadonlyProperty(ctx, "parent");
retVal->stdErr = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdErr_OnPause, ILibDuktape_ChildProcess_SubProcess_StdErr_OnResume, retVal);
ILibDuktape_CreateReadonlyProperty(ctx, "stderr");
duk_push_object(ctx);
ILibDuktape_WriteID(ctx, "childProcess.stdin");
duk_dup(ctx, -2);
ILibDuktape_CreateReadonlyProperty(ctx, "parent");
retVal->stdIn = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdIn_WriteHandler, ILibDuktape_ChildProcess_SubProcess_StdIn_EndHandler, retVal);
ILibDuktape_CreateReadonlyProperty(ctx, "stdin");
@@ -163,12 +171,13 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
int i, x;
void *callback = NULL;
ILibProcessPipe_Process p = NULL;
ILibProcessPipe_SpawnTypes spawnType = ILibProcessPipe_SpawnTypes_DEFAULT;
for (i = 0; i < nargs; ++i)
{
if (duk_is_array(ctx, i) != 0)
{
int arrLen = duk_get_length(ctx, i);
int arrLen = (int)duk_get_length(ctx, i);
#ifdef WIN32
args = (char**)_alloca((arrLen + 1) * sizeof(char*));
#else
@@ -185,6 +194,11 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
{
callback = duk_get_heapptr(ctx, i);
}
else if (duk_is_object(ctx, i))
{
// Options
spawnType = (ILibProcessPipe_SpawnTypes)Duktape_GetIntPropertyValue(ctx, i, "type", (int)ILibProcessPipe_SpawnTypes_DEFAULT);
}
}
#ifdef WIN32
@@ -206,7 +220,7 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
}
#endif
p = ILibProcessPipe_Manager_SpawnProcess(manager, target, args);
p = ILibProcessPipe_Manager_SpawnProcessEx2(manager, target, args, spawnType, 0);
if (p == NULL)
{
return(ILibDuktape_Error(ctx, "child_process.execFile(): Could not exec [%s]", target));
@@ -222,6 +236,16 @@ void ILibDuktape_ChildProcess_PUSH(duk_context *ctx, void *chain)
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ChildProcess_Manager_Finalizer);
ILibDuktape_CreateInstanceMethod(ctx, "execFile", ILibDuktape_ChildProcess_execFile, DUK_VARARGS);
duk_push_object(ctx);
duk_push_int(ctx, 0);
duk_put_prop_string(ctx, -2, "DEFAULT");
duk_push_int(ctx, 1);
duk_put_prop_string(ctx, -2, "USER");
duk_push_int(ctx, 2);
duk_put_prop_string(ctx, -2, "WINLOGON");
duk_push_int(ctx, 3);
duk_put_prop_string(ctx, -2, "TERM");
duk_put_prop_string(ctx, -2, "SpawnTypes");
}
void ILibDuktape_ChildProcess_Init(duk_context *ctx)
{

View File

@@ -2,6 +2,7 @@
#define __ILIBDUKTAPE_CHILDPROCESS__
#include "duktape.h"
#define ILibDuktape_ChildProcess_Manager "\xFF_ChildProcess_Manager"
void ILibDuktape_ChildProcess_Init(duk_context *ctx);

View File

@@ -376,6 +376,29 @@ duk_ret_t ILibDuktape_DGram_setTTL(duk_context *ctx)
{
return ILibDuktape_Error(ctx, "Not implemented");
}
duk_ret_t ILibDuktape_DGram_setMulticastInterface(duk_context *ctx)
{
ILibDuktape_DGRAM_DATA *ptrs = ILibDuktape_DGram_GetPTR(ctx);
struct sockaddr_in addr;
char *str = (char*)duk_require_string(ctx, 0);
memset(&addr, 0, sizeof(struct sockaddr_in));
ILibInet_pton(AF_INET, str, &(addr.sin_addr));
ILibAsyncUDPSocket_SetMulticastInterface(ptrs->mSocket, (struct sockaddr*)&addr);
return(0);
}
duk_ret_t ILibDuktape_Dgram_socket_close(duk_context *ctx)
{
if (duk_get_top(ctx) > 0 && duk_is_function(ctx, 0)) { ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter_GetEmitter_fromThis(ctx), "close", duk_require_heapptr(ctx, 0)); }
duk_push_this(ctx); // [socket]
duk_get_prop_string(ctx, -1, ILibDuktape_DGRAM_SOCKET_NATIVE); // [socket][ptr]
ILibDuktape_DGRAM_DATA *data = (ILibDuktape_DGRAM_DATA*)Duktape_GetBuffer(ctx, -1, NULL);
ILibAsyncSocket_Disconnect(data->mSocket);
return(0);
}
duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
{
ILibDuktape_DGRAM_Config config = ILibDuktape_DGRAM_Config_NONE;
@@ -397,6 +420,7 @@ duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
/**************************************************************************************/
duk_push_object(ctx); // [socket]
ILibDuktape_WriteID(ctx, "dgram.socket");
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Dgram_Finalizer);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_DGRAM_DATA)); // [socket][native]
ptrs = (ILibDuktape_DGRAM_DATA*)Duktape_GetBuffer(ctx, -1, NULL);
@@ -420,10 +444,13 @@ duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
ILibDuktape_CreateInstanceMethodWithStringProperty(ctx, ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE, "add", "addMembership", ILibDuktape_DGram_multicastMembership, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithStringProperty(ctx, ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE, "remove", "dropMembership", ILibDuktape_DGram_multicastMembership, DUK_VARARGS);
ILibDuktape_CreateProperty_InstanceMethod(ctx, "close", ILibDuktape_Dgram_socket_close, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "send", ILibDuktape_DGram_send, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "setBroadcast", ILibDuktape_DGram_setBroadcast, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastLoopback", ILibDuktape_DGram_setMulticastLoopback, 1);
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastTTL", ILibDuktape_DGram_setMulticastTTL, 1);
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastInterface", ILibDuktape_DGram_setMulticastInterface, 1);
ILibDuktape_CreateInstanceMethod(ctx, "setTTL", ILibDuktape_DGram_setTTL, 1);
return 1;

View File

@@ -18,6 +18,7 @@ limitations under the License.
#include "ILibDuktape_Helpers.h"
#include "ILibDuktape_DuplexStream.h"
#define ILibDuktape_Transform_Data "\xFF_Transform_Data"
#ifdef __DOXY__
/*!
@@ -53,7 +54,19 @@ void ILibDuktape_DuplexStream_OnEnd(struct ILibDuktape_WritableStream *stream, v
if (ds->OnEnd != NULL) { ((ILibDuktape_DuplexStream_EndHandler)ds->OnEnd)(ds, ds->user); }
}
ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_Init(duk_context * ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, void * user)
int ILibDuktape_DuplexStream_OnUnshift(ILibDuktape_readableStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_DuplexStream *ds = (ILibDuktape_DuplexStream*)user;
if (ds->unshiftHandler == NULL)
{
return(0);
}
else
{
return(((ILibDuktape_DuplexStream_UnshiftHandler)ds->unshiftHandler)(ds, unshiftBytes, ds->user));
}
}
ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_InitEx(duk_context * ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, ILibDuktape_DuplexStream_UnshiftHandler UnshiftHandler, void * user)
{
ILibDuktape_DuplexStream *retVal;
@@ -63,12 +76,94 @@ ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_Init(duk_context * ctx, ILib
memset(retVal, 0, sizeof(ILibDuktape_DuplexStream));
retVal->user = user;
retVal->readableStream = ILibDuktape_InitReadableStream(ctx, ILibDuktape_DuplexStream_OnPause, ILibDuktape_DuplexStream_OnResume, retVal);
retVal->readableStream = ILibDuktape_ReadableStream_InitEx(ctx, ILibDuktape_DuplexStream_OnPause, ILibDuktape_DuplexStream_OnResume, UnshiftHandler != NULL ? ILibDuktape_DuplexStream_OnUnshift : NULL, retVal);
retVal->writableStream = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_DuplexStream_OnWrite, ILibDuktape_DuplexStream_OnEnd, retVal);
retVal->OnEnd = EndHandler;
retVal->OnWrite = WriteHandler;
retVal->OnPause = PauseHandler;
retVal->OnResume = ResumeHandler;
retVal->ParentObject = duk_get_heapptr(ctx, -1);
retVal->unshiftHandler = UnshiftHandler;
return retVal;
}
ILibTransport_DoneState ILibDuktape_Transform_WriteSink(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
TF->writerEnded = stream->endBytes;
TF->On_NativeTransform(TF, TF->source->Reserved, stream->endBytes, buffer, bufferLen, TF->user);
return(TF->target->paused == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE);
}
void ILibDuktape_Transform_EndSink(struct ILibDuktape_WritableStream *stream, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
if (TF->writerEnded == 0)
{
TF->writerEnded = -1;
TF->On_NativeTransform(TF, 0, -1, NULL, 0, TF->user);
}
ILibDuktape_readableStream_WriteEnd(TF->target);
}
void ILibDuktape_Transform_PauseSink(struct ILibDuktape_readableStream *sender, void *user)
{
UNREFERENCED_PARAMETER(sender);
UNREFERENCED_PARAMETER(user);
// NO-OP, because it is handled in the WriteSink
}
void ILibDuktape_Transform_ResumeSink(struct ILibDuktape_readableStream *sender, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
ILibDuktape_WritableStream_Ready(TF->source);
}
void ILibDuktape_Transform_ReaderPipeHook(struct ILibDuktape_readableStream *sender, void *wstream, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
TF->readerIsPiped = 1;
if (TF->On_NativePipedSink != NULL) { TF->On_NativePipedSink(TF, TF->user); }
}
int ILibDuktape_Transform_UnshiftSink(struct ILibDuktape_readableStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
return(TF->On_NativeUnshift(TF, unshiftBytes, TF->user));
}
ILibDuktape_Transform* ILibDuktape_Transform_InitEx(duk_context *ctx, ILibDuktape_TransformStream_TransformHandler transformHandler, ILibDuktape_TransformStream_UnShiftHandler unshiftHandler, ILibDuktape_TransformStream_TargetPipedHandler pipedHandler, void *user)
{
ILibDuktape_Transform *TF;
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_Transform)); // [buffer]
TF = (ILibDuktape_Transform*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_Transform_Data); // ...
TF->source = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_Transform_WriteSink, ILibDuktape_Transform_EndSink, TF);
if (unshiftHandler != NULL)
{
TF->target = ILibDuktape_ReadableStream_InitEx(ctx, ILibDuktape_Transform_PauseSink, ILibDuktape_Transform_ResumeSink, ILibDuktape_Transform_UnshiftSink, TF);
}
else
{
TF->target = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_Transform_PauseSink, ILibDuktape_Transform_ResumeSink, TF);
}
TF->target->PipeHookHandler = ILibDuktape_Transform_ReaderPipeHook;
TF->On_NativePipedSink = pipedHandler;
TF->On_NativeTransform = transformHandler;
TF->On_NativeUnshift = unshiftHandler;
TF->user = user;
return(TF);
}
ILibDuktape_WritableStream *ILibDuktape_DuplexStream_GetNativeWritable(duk_context *ctx, void *stream)
{
ILibDuktape_WritableStream *retVal = NULL;
duk_push_heapptr(ctx, stream); // [stream]
if (duk_has_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS))
{
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS); // [stream][ws]
retVal = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL);
if (retVal->JSCreated) { retVal = NULL; }
duk_pop(ctx); // [stream]
}
duk_pop(ctx); // ...
return(retVal);
}

View File

@@ -28,6 +28,7 @@ typedef struct ILibDuktape_DuplexStream
{
ILibDuktape_readableStream *readableStream;
ILibDuktape_WritableStream *writableStream;
void *unshiftHandler;
void *user;
void *ParentObject;
void *OnWrite;
@@ -36,9 +37,34 @@ typedef struct ILibDuktape_DuplexStream
void *OnResume;
}ILibDuktape_DuplexStream;
struct ILibDuktape_Transform;
typedef void(*ILibDuktape_TransformStream_TransformHandler)(struct ILibDuktape_Transform *sender, int Reserved, int flush, char *buffer, int bufferLen, void *user);
typedef void(*ILibDuktape_TransformStream_TargetPipedHandler)(struct ILibDuktape_Transform *sender, void *user);
typedef int(*ILibDuktape_TransformStream_UnShiftHandler)(struct ILibDuktape_Transform *sender, int unshiftBytes, void *user);
typedef struct ILibDuktape_Transform
{
duk_context *ctx;
ILibDuktape_WritableStream *source;
ILibDuktape_readableStream *target;
int readerIsPiped;
int writerEnded;
ILibDuktape_TransformStream_UnShiftHandler On_NativeUnshift;
ILibDuktape_TransformStream_TransformHandler On_NativeTransform;
ILibDuktape_TransformStream_TargetPipedHandler On_NativePipedSink;
void *user;
}ILibDuktape_Transform;
ILibDuktape_Transform* ILibDuktape_Transform_InitEx(duk_context *ctx, ILibDuktape_TransformStream_TransformHandler transformHandler, ILibDuktape_TransformStream_UnShiftHandler unshiftHandler, ILibDuktape_TransformStream_TargetPipedHandler pipedHandler, void *user);
#define ILibDuktape_Transform_Init(ctx, transformHandler, pipedHandler, user) ILibDuktape_Transform_InitEx(ctx, transformHandler, NULL, pipedHandler, user)
typedef ILibTransport_DoneState(*ILibDuktape_DuplexStream_WriteHandler)(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user);
typedef void(*ILibDuktape_DuplexStream_EndHandler)(ILibDuktape_DuplexStream *stream, void *user);
typedef void(*ILibDuktape_DuplexStream_PauseResumeHandler)(ILibDuktape_DuplexStream *sender, void *user);
typedef int(*ILibDuktape_DuplexStream_UnshiftHandler)(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user);
#define ILibDuktape_DuplexStream_Ready(duplexStream) ILibDuktape_WritableStream_Ready((duplexStream)->writableStream)
#define ILibDuktape_DuplexStream_WriteData(duplexStream, buffer, bufferLen) ILibDuktape_readableStream_WriteData((duplexStream)->readableStream, buffer, bufferLen)
@@ -46,7 +72,7 @@ typedef void(*ILibDuktape_DuplexStream_PauseResumeHandler)(ILibDuktape_DuplexStr
#define ILibDuktape_DuplexStream_WriteEnd(duplexStream) ILibDuktape_readableStream_WriteEnd((duplexStream)->readableStream)
#define ILibDuktape_DuplexStream_Closed(duplexStream) ILibDuktape_readableStream_Closed((duplexStream)->readableStream)
ILibDuktape_DuplexStream* ILibDuktape_DuplexStream_Init(duk_context *ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, void *user);
ILibDuktape_DuplexStream* ILibDuktape_DuplexStream_InitEx(duk_context *ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, ILibDuktape_DuplexStream_UnshiftHandler UnshiftHandler, void *user);
#define ILibDuktape_DuplexStream_Init(ctx, WriteHandler, EndHandler, PauseHandler, ResumeHandler, user) ILibDuktape_DuplexStream_InitEx(ctx, WriteHandler, EndHandler, PauseHandler, ResumeHandler, NULL, user)
ILibDuktape_WritableStream *ILibDuktape_DuplexStream_GetNativeWritable(duk_context *ctx, void *stream);
#endif

View File

@@ -31,11 +31,13 @@ int ILibDuktape_EventEmitter_AddEventHeapptr(ILibDuktape_EventEmitter *emitter,
int ILibDuktape_EventEmitter_AddSink(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_Handler handler); // Add Native Event Handler
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler 'once'
int ILibDuktape_EventEmitter_AddOnceEx(ILibDuktape_EventEmitter *emitter, char *eventName, duk_c_function func, duk_idx_t funcArgs);
int ILibDuktape_EventEmitter_AddOnceEx2(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func, duk_idx_t funcArgs);
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler
int ILibDuktape_EventEmitter_AddOnceEx3(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func);
#define ILibDuktape_EventEmitter_AddOnceEx2(ctx, idx, eventName, func, argCount) ILibDuktape_EventEmitter_AddOnceEx3(ctx, idx, eventName, func)
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);
void ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_HookHandler handler);
void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSourceIndex, char *sourceEventName, duk_idx_t eventTargetIndex, char *targetEventName);
#endif

View File

@@ -41,6 +41,8 @@ limitations under the License.
#include <dlfcn.h>
#endif
#define ILibDuktape_GenericMarshal_VariableType "\xFF_GenericMarshal_VarType"
typedef PTRSIZE(APICALLTYPE *R0)();
typedef PTRSIZE(APICALLTYPE *R1)(PTRSIZE V1);
typedef PTRSIZE(APICALLTYPE *R2)(PTRSIZE V1, PTRSIZE V2);
@@ -52,6 +54,17 @@ typedef PTRSIZE(APICALLTYPE *R7)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4,
typedef PTRSIZE(APICALLTYPE *R8)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8);
typedef PTRSIZE(APICALLTYPE *R9)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9);
typedef PTRSIZE(APICALLTYPE *R10)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10);
typedef PTRSIZE(APICALLTYPE *R11)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11);
typedef PTRSIZE(APICALLTYPE *R12)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12);
typedef PTRSIZE(APICALLTYPE *R13)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13);
typedef PTRSIZE(APICALLTYPE *R14)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14);
typedef PTRSIZE(APICALLTYPE *R15)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15);
typedef PTRSIZE(APICALLTYPE *R16)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16);
typedef PTRSIZE(APICALLTYPE *R17)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17);
typedef PTRSIZE(APICALLTYPE *R18)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17, PTRSIZE V18);
typedef PTRSIZE(APICALLTYPE *R19)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17, PTRSIZE V18, PTRSIZE V19);
typedef PTRSIZE(APICALLTYPE *R20)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17, PTRSIZE V18, PTRSIZE V19, PTRSIZE V20);
typedef struct Duktape_GenericMarshal_Proxy
{
@@ -175,7 +188,6 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_SET(duk_context *ctx)
{
void *ptr;
int size;
int value = duk_require_int(ctx, 0);
duk_push_this(ctx); // [var]
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
@@ -183,18 +195,32 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_SET(duk_context *ctx)
duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
size = duk_to_int(ctx, -1);
switch (size)
if (duk_is_number(ctx, 0))
{
switch (size)
{
case 2:
((unsigned short*)ptr)[0] = (unsigned short)value;
((unsigned short*)ptr)[0] = (unsigned short)duk_require_int(ctx, 0);
break;
case 4:
((unsigned int*)ptr)[0] = (unsigned int)value;
((unsigned int*)ptr)[0] = (unsigned int)duk_require_int(ctx, 0);
break;
default:
duk_push_string(ctx, "UNSUPPORTED VAL SIZE");
duk_push_string(ctx, "UNSUPPORTED VAL SIZE, with integral type");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
}
else if (duk_is_object(ctx, 0) && duk_has_prop_string(ctx, 0, ILibDuktape_GenericMarshal_VariableType))
{
((void**)ptr)[0] = Duktape_GetPointerProperty(ctx, 0, "_ptr");
duk_push_this(ctx); // [var]
duk_dup(ctx, 0); // [var][var]
duk_put_prop_string(ctx, -2, "\xFF_ref");
}
else
{
return(ILibDuktape_Error(ctx, "Invalid Parameter"));
}
return 0;
}
@@ -292,6 +318,18 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_SetEx(duk_context *ctx)
}
return 0;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_toBuffer(duk_context *ctx)
{
duk_push_this(ctx); // [variable]
void *buffer = Duktape_GetPointerProperty(ctx, -1, "_ptr");
int bufferLen = Duktape_GetIntPropertyValue(ctx, -1, "_size", 0);
duk_push_external_buffer(ctx); // [variable][ext]
duk_config_buffer(ctx, -1, buffer, (duk_size_t)bufferLen);
duk_push_buffer_object(ctx, -1, 0, (duk_size_t)bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int size)
{
duk_push_object(ctx); // [var]
@@ -299,7 +337,8 @@ void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int s
duk_put_prop_string(ctx, -2, "_ptr"); // [var]
duk_push_int(ctx, size); // [var][size]
duk_put_prop_string(ctx, -2, "_size"); // [var]
duk_push_true(ctx);
duk_put_prop_string(ctx, -2, ILibDuktape_GenericMarshal_VariableType);
ILibDuktape_CreateEventWithGetterAndSetterEx(ctx, "Val", ILibDuktape_GenericMarshal_Variable_Val_GET, ILibDuktape_GenericMarshal_Variable_Val_SET);
ILibDuktape_CreateEventWithGetterAndSetterWithIntMetaData(ctx, "_VarSize", 4, "IntVal", ILibDuktape_GenericMarshal_Variable_GetEx, ILibDuktape_GenericMarshal_Variable_SetEx);
@@ -310,6 +349,8 @@ void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int s
ILibDuktape_CreateEventWithGetter(ctx, "AnsiString", ILibDuktape_GenericMarshal_Variable_Val_ASTRING);
ILibDuktape_CreateEventWithGetter(ctx, "HexString", ILibDuktape_GenericMarshal_Variable_Val_HSTRING);
ILibDuktape_CreateEventWithGetter(ctx, "HexString2", ILibDuktape_GenericMarshal_Variable_Val_HSTRING2);
ILibDuktape_CreateInstanceMethod(ctx, "toBuffer", ILibDuktape_GenericMarshal_Variable_toBuffer, 0);
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_Finalizer(duk_context *ctx)
{
@@ -330,9 +371,30 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_Finalizer(duk_context *ctx)
duk_ret_t ILibDuktape_GenericMarshal_CreateVariable(duk_context *ctx)
{
char* ptr;
int size = duk_require_int(ctx, 0);
int size;
char *str = NULL;
duk_size_t strLen;
if (duk_is_number(ctx, 0))
{
size = duk_require_int(ctx, 0);
}
else if(duk_is_string(ctx, 0))
{
str = Duktape_GetBuffer(ctx, 0, &strLen);
size = (int)strLen + 1;
}
else
{
return(ILibDuktape_Error(ctx, "_GenericMarshal.CreateVariable(): Invalid Parameter"));
}
ptr = (char*)ILibMemory_Allocate(size, 0, NULL, NULL);
if (str != NULL)
{
memcpy_s(ptr, size, str, strLen);
ptr[strLen] = 0;
}
ILibDuktape_GenericMarshal_Variable_PUSH(ctx, ptr, size); // [var]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_GenericMarshal_Variable_Finalizer);
@@ -567,8 +629,9 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx)
void *fptr = NULL;
int parms = duk_get_top(ctx);
int i;
PTRSIZE vars[10];
int retVal = -1;
if (parms > 20) { return(ILibDuktape_Error(ctx, "Too many parameters")); }
PTRSIZE *vars = ILibMemory_AllocateA(sizeof(PTRSIZE)*parms);
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "_address"); // [func][addr]
@@ -639,6 +702,36 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx)
case 10:
retVal = (int)((R10)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9]);
break;
case 11:
retVal = (int)((R11)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10]);
break;
case 12:
retVal = (int)((R12)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11]);
break;
case 13:
retVal = (int)((R13)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12]);
break;
case 14:
retVal = (int)((R14)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13]);
break;
case 15:
retVal = (int)((R15)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14]);
break;
case 16:
retVal = (int)((R16)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15]);
break;
case 17:
retVal = (int)((R17)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16]);
break;
case 18:
retVal = (int)((R18)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16], vars[17]);
break;
case 19:
retVal = (int)((R19)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16], vars[17], vars[18]);
break;
case 20:
retVal = (int)((R20)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16], vars[17], vars[18], vars[19]);
break;
default:
duk_push_string(ctx, "INVALID NUMBER OF PARAMETERS, MAX of 10");
duk_throw(ctx);
@@ -726,6 +819,7 @@ duk_ret_t ILibDuktape_GenericMarshal_CreateVariableEx(duk_context *ctx)
return 1;
}
void ILibDuktape_GenericMarshal_Push(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [obj]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
#ifndef __DUKTAPEHECI__
#define __DUKTAPEHECI__
#include "duktape.h"
void ILibDuktape_HECI_Init(duk_context *ctx);
#endif

View File

@@ -245,6 +245,15 @@ void ILibDuktape_CreateEventWithGetter(duk_context *ctx, char *propName, duk_c_f
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetterAndCustomProperty(duk_context *ctx, char *customPropName, char *propName, duk_c_function getterMethod)
{
duk_push_string(ctx, propName); // [obj][customProp][prop]
duk_push_c_function(ctx, getterMethod, 1); // [obj][customProp][prop][getFunc]
duk_dup(ctx, -3); // [obj][customProp][prop][getFunc][customProp]
duk_put_prop_string(ctx, -2, customPropName); // [obj][customProp][prop][getFunc]
duk_remove(ctx, -3); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetterAndSetterEx(duk_context *ctx, char *propName, duk_c_function getterMethod, duk_c_function setterMethod)
{
@@ -597,3 +606,127 @@ void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size)
return(retVal);
}
void *ILibDuktape_Memory_AllocEx(duk_context *ctx, duk_idx_t index, duk_size_t size)
{
char *retVal = NULL;
duk_dup(ctx, index); // [object]
ILibDuktape_Push_ObjectStash(ctx); // [object][stash]
duk_push_fixed_buffer(ctx, size); // [object][stash][buffer]
retVal = (char*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(retVal)); // [object][stash]
duk_pop_2(ctx); // ...
return(retVal);
}
void ILibDuktape_ValidatePointer(void *chain, void *ptr)
{
ILibHashtable_Put(ILibChain_GetBaseHashtable(chain), ptr, NULL, 0, (void*)0xFFFF);
}
void ILibDuktape_InValidatePointer(void *chain, void *ptr)
{
ILibHashtable_Remove(ILibChain_GetBaseHashtable(chain), ptr, NULL, 0);
}
int ILibDuktape_IsPointerValid(void *chain, void *ptr)
{
return(ILibHashtable_Get(ILibChain_GetBaseHashtable(chain), ptr, NULL, 0) == NULL ? 0 : 1);
}
void ILibDuktape_PointerValidation_Finalizer(duk_context *ctx, void *obj)
{
void *chain = Duktape_GetChain(ctx);
ILibDuktape_InValidatePointer(chain, obj);
}
void ILibDuktape_PointerValidation_Init(duk_context *ctx)
{
void *chain = Duktape_GetChain(ctx);
if (!ILibDuktape_IsPointerValid(chain, duk_get_heapptr(ctx, -1)))
{
// Not set up yet, so set it up
ILibDuktape_ValidatePointer(chain, duk_get_heapptr(ctx, -1));
ILibDuktape_CreateIndependentFinalizer(ctx, ILibDuktape_PointerValidation_Finalizer);
}
}
duk_ret_t ILibDuktape_Immediate_Sink(duk_context *ctx)
{
ILibDuktape_ImmediateHandler userCallback = (ILibDuktape_ImmediateHandler)duk_get_pointer(ctx, 0);
void **args = NULL;
int argsLen, i;
duk_push_this(ctx); // [immediate]
duk_dup(ctx, 1); // [immediate][array]
if ((argsLen = (int)duk_get_length(ctx, -1)) > 0)
{
args = ILibMemory_AllocateA(sizeof(void*)*argsLen);
for (i = 0; i < argsLen; ++i)
{
duk_get_prop_index(ctx, -1, i); // [immediate][array][arg]
args[i] = duk_get_pointer(ctx, -1);
duk_pop(ctx); // [immediate][array]
}
}
duk_push_heap_stash(ctx); // [immediate][array][stash]
duk_del_prop_string(ctx, -1, Duktape_GetStashKey(duk_get_heapptr(ctx, -3)));
if (userCallback != NULL) { userCallback(ctx, args, argsLen); }
return(0);
}
void ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback)
{
int i = 0;
duk_push_global_object(ctx); // [g]
duk_get_prop_string(ctx, -1, "setImmediate"); // [g][setImmediate]
duk_swap_top(ctx, -2); // [setImmediate][this]
duk_push_c_function(ctx, ILibDuktape_Immediate_Sink, DUK_VARARGS); // [setImmediate][this][func]
duk_push_pointer(ctx, callback); // [setImmediate][this][func][userFunc]
duk_push_array(ctx); // [setImmediate][this][func][userFunc][array]
while (args[i] != NULL && i < argsLen)
{
duk_get_prop_string(ctx, -1, "push"); // [setImmediate][this][func][userFunc][array][push]
duk_dup(ctx, -2); // [setImmediate][this][func][userFunc][array][push][this]
duk_push_pointer(ctx, args[i]); // [setImmediate][this][func][userFunc][array][push][this][val]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Immediate => Array.push(): "); }
duk_pop(ctx); // [setImmediate][this][func][userFunc][array]
++i;
}
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Immediate => immediate(): "); duk_pop(ctx); return; }
// [immediate]
duk_push_heap_stash(ctx); // [immediate][stash]
duk_swap_top(ctx, -2); // [stash][immediate]
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1)));// [stash]
duk_pop(ctx); // ...
}
void ILibDuktape_CreateInstanceMethodWithProperties(duk_context *ctx, char *funcName, duk_c_function funcImpl, duk_idx_t numArgs, unsigned int propertyCount, ...)
{
unsigned int i;
char *name;
duk_idx_t valueIndex;
duk_push_c_function(ctx, funcImpl, numArgs); // [func]
va_list vlist;
va_start(vlist, propertyCount);
for (i = 0; i < propertyCount; ++i)
{
name = va_arg(vlist, char*);
valueIndex = va_arg(vlist, duk_idx_t);
duk_dup(ctx, valueIndex); // [func][value]
duk_put_prop_string(ctx, -2, name); // [func]
}
va_end(vlist);
while (propertyCount-- > 0) { duk_remove(ctx, -2); }
duk_put_prop_string(ctx, -2, funcName);
}
duk_idx_t duk_push_int_ex(duk_context *ctx, duk_int_t val)
{
return(duk_push_int(ctx, val), duk_get_top_index(ctx));
}

View File

@@ -32,6 +32,10 @@ typedef void(*ILibDuktape_HelperEvent)(duk_context *ctx, void *user);
#define ILibDuktape_MeshAgent_Cert_Server "\xFF_selftlscert"
#define CONTEXT_GUID_BUFFER "_CONTEXT_GUID"
#define ILibDuktape_Context_Chain "\xFF_chainptr"
#define ILibDuktape_OBJID "_ObjectID"
#define ILibDuktape_CR2HTTP "\xFF_CR2HTTP"
#define ILibDuktape_CR2Options "\xFF_CR2Options"
char* Duktape_GetContextGuidHex(duk_context *ctx);
void *Duktape_GetChain(duk_context *ctx);
@@ -62,6 +66,7 @@ int ILibDuktape_Process_GetExitCode(duk_context *ctx);
void ILibDuktape_CreateEventWithGetter(duk_context *ctx, char *propName, duk_c_function getterMethod);
void ILibDuktape_CreateEventWithGetterEx(duk_context *ctx, char *propName, void *heapptr);
void ILibDuktape_CreateEventWithGetterAndCustomProperty(duk_context *ctx, char *customPropName, char *propName, duk_c_function getterMethod);
void ILibDuktape_CreateEventWithSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr);
void ILibDuktape_CreateEventWithSetterEx(duk_context *ctx, char *propName, duk_c_function setterMethod);
void ILibDuktape_CreateEventWithGetterAndSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr, duk_c_function getterMethod);
@@ -74,6 +79,9 @@ void ILibDuktape_CreateEventWithGetterAndSetterWithMetaData(duk_context *ctx, ch
#define ILibDuktape_CreateInstanceMethodWithBooleanProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_boolean(context, propValue);duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
#define ILibDuktape_CreateInstanceMethodWithIntProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_int(context, propValue);duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
#define ILibDuktape_CreateInstanceMethodWithNumberProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_number(context, (propValue));duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
void ILibDuktape_CreateInstanceMethodWithProperties(duk_context *ctx, char *funcName, duk_c_function funcImpl, duk_idx_t numArgs, unsigned int propertyCount, ...);
duk_idx_t duk_push_int_ex(duk_context *ctx, duk_int_t val);
void ILibDuktape_CreateProperty_InstanceMethod(duk_context *ctx, char *methodName, duk_c_function impl, duk_idx_t argCount);
void ILibDuktape_CreateProperty_InstanceMethodEx(duk_context *ctx, char *methodName, void *funcHeapPtr);
void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName);
@@ -81,8 +89,21 @@ void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName);
#define ILibDuktape_CreateFinalizer(context, funcImpl) duk_push_c_function(context, funcImpl, 1); duk_set_finalizer(context, -2);
void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size);
void *ILibDuktape_Memory_AllocEx(duk_context *ctx, duk_idx_t index, duk_size_t size);
void ILibDuktape_Helper_AddHeapFinalizer(duk_context *ctx, ILibDuktape_HelperEvent handler, void *user);
void ILibDuktape_Push_ObjectStash(duk_context *ctx);
void ILibDuktape_PointerValidation_Init(duk_context *ctx);
void ILibDuktape_ValidatePointer(void *chain, void *ptr);
void ILibDuktape_InValidatePointer(void *chain, void *ptr);
int ILibDuktape_IsPointerValid(void *chain, void *ptr);
#define ILibDuktape_ValidateHeapPointer(ctx, objIdx) ILibDuktape_ValidatePointer(Duktape_GetChain(ctx), duk_get_heapptr(ctx, objIdx))
#define ILibDuktape_InValidateHeapPointer(ctx, objIdx) ILibDuktape_InValidatePointer(Duktape_GetChain(ctx), duk_get_heapptr(ctx, objIdx))
typedef void(*ILibDuktape_ImmediateHandler)(duk_context *ctx, void ** args, int argsLen);
void ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback);
#define ILibDuktape_WriteID(ctx, id) duk_push_string(ctx, id);duk_put_prop_string(ctx, -2, ILibDuktape_OBJID)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -81,6 +81,7 @@ duk_ret_t ILibDuktape_MemoryStream_buffer(duk_context *ctx)
duk_push_external_buffer(ctx);
duk_config_buffer(ctx, -1, ms->buffer, ms->bufferLen);
duk_push_buffer_object(ctx, -1, 0, ms->bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
@@ -93,6 +94,43 @@ duk_ret_t ILibDuktape_MemoryStream_Finalizer(duk_context *ctx)
return(0);
}
duk_ret_t ILibDuktape_MemoryStream_writeBE(duk_context *ctx)
{
duk_push_current_function(ctx);
int size = Duktape_GetIntPropertyValue(ctx, -1, "size", 0);
char buffer[16];
int value = duk_require_int(ctx, 0);
switch (size)
{
case 1:
buffer[0] = (char)value;
break;
case 2:
((unsigned short*)buffer)[0] = htons((unsigned short)value);
break;
case 4:
((unsigned int*)buffer)[0] = htonl((unsigned int)value);
break;
default:
break;
}
if (size > 0)
{
duk_push_this(ctx); // [ms]
duk_get_prop_string(ctx, -1, "write"); // [ms][write]
duk_swap_top(ctx, -2); // [write][this]
duk_push_external_buffer(ctx); // [write][this][buffer]
duk_config_buffer(ctx, -1, buffer, size);
duk_call_method(ctx, 1); // [retVal]
return(1);
}
else
{
return(ILibDuktape_Error(ctx, "MemoryStream.writeBE() Unknown Error"));
}
}
duk_ret_t ILibDuktape_MemoryStream_new(duk_context *ctx)
{
int initial = duk_get_top(ctx) > 0 ? duk_require_int(ctx, 0) : 4096;
@@ -110,6 +148,11 @@ duk_ret_t ILibDuktape_MemoryStream_new(duk_context *ctx)
ms->s = ILibDuktape_DuplexStream_Init(ctx, ILibDuktape_MemoryStream_OnWrite, ILibDuktape_MemoryStream_OnEnd, NULL, NULL, ms);
ILibDuktape_CreateEventWithGetter(ctx, "buffer", ILibDuktape_MemoryStream_buffer);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_MemoryStream_Finalizer);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "size", 4, "writeUInt32BE", ILibDuktape_MemoryStream_writeBE, 1);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "size", 2, "writeUInt16BE", ILibDuktape_MemoryStream_writeBE, 1);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "size", 1, "writeUInt8", ILibDuktape_MemoryStream_writeBE, 1);
return(1);
}
void ILibDuktape_MemoryStream_PUSH(duk_context *ctx, void *chain)

View File

@@ -108,14 +108,14 @@ void ILibDuktape_NetworkMonitor_EventSink(ILibIPAddressMonitor sender, void *use
}
duk_ret_t ILibDuktape_NetworkMonitor_Finalizer(duk_context *ctx)
{
if (ILibIsChainBeingDestroyed(Duktape_GetChain(ctx)) != 0) { return(0); }
duk_get_prop_string(ctx, 0, ILibDuktape_NetworkMonitor_PTR);
ILibDuktape_NetworkMonitor *nm = (ILibDuktape_NetworkMonitor*)Duktape_GetBuffer(ctx, -1, NULL);
ILibChain_SafeRemoveEx(Duktape_GetChain(ctx), nm->addressMonitor);
if (nm->addressTable != NULL) { ILibHashtable_Destroy(nm->addressTable); }
if (ILibIsChainBeingDestroyed(Duktape_GetChain(ctx)) != 0) { return(0); }
ILibChain_SafeRemoveEx(Duktape_GetChain(ctx), nm->addressMonitor);
return(0);
}
void ILibDuktape_NetworkMonitor_PUSH(duk_context *ctx, void *chain)

View File

@@ -1,11 +1,15 @@
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_DuplexStream.h"
#include "ILibDuktape_EventEmitter.h"
#include "../microstack/ILibParsers.h"
#include "../microstack/ILibCrypto.h"
#define ILibDuktape_Timer_Ptrs "\xFF_DuktapeTimer_PTRS"
#define ILibDuktape_Queue_Ptr "\xFF_Queue"
duk_ret_t ILibDuktape_Pollyfills_Buffer_slice(duk_context *ctx)
{
@@ -63,6 +67,13 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_toString(duk_context *ctx)
util_tohex(buffer, (int)bufferLen, tmpBuffer);
duk_push_string(ctx, tmpBuffer);
}
else if (strcmp(cType, "hex:") == 0)
{
duk_push_fixed_buffer(ctx, 1 + (bufferLen * 3));
tmpBuffer = Duktape_GetBuffer(ctx, -1, NULL);
util_tohex2(buffer, (int)bufferLen, tmpBuffer);
duk_push_string(ctx, tmpBuffer);
}
else
{
duk_push_string(ctx, "buffer.toString(): Unrecognized parameter");
@@ -84,11 +95,10 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_from(duk_context *ctx)
if (nargs == 1)
{
str = (char*)duk_get_lstring(ctx, 0, &strlength);
duk_push_fixed_buffer(ctx, strlength + 1);
duk_push_fixed_buffer(ctx, strlength);
buffer = Duktape_GetBuffer(ctx, -1, NULL);
memcpy_s(buffer, strlength + 1, str, strlength);
buffer[strlength] = 0;
duk_push_buffer_object(ctx, -1, 0, strlength+1, DUK_BUFOBJ_ARRAYBUFFER);
memcpy_s(buffer, strlength, str, strlength);
duk_push_buffer_object(ctx, -1, 0, strlength, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
else if(!(nargs == 2 && duk_is_string(ctx, 0) && duk_is_string(ctx, 1)))
@@ -107,14 +117,14 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_from(duk_context *ctx)
duk_push_fixed_buffer(ctx, ILibBase64DecodeLength((int)strlength));
buffer = Duktape_GetBuffer(ctx, -1, NULL);
bufferLen = ILibBase64Decode((unsigned char*)str, (int)strlength, (unsigned char**)&buffer);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_ARRAYBUFFER);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
}
else if (strcmp(encoding, "hex") == 0)
{
duk_push_fixed_buffer(ctx, strlength / 2);
buffer = Duktape_GetBuffer(ctx, -1, NULL);
bufferLen = util_hexToBuf(str, (int)strlength, buffer);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_ARRAYBUFFER);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
}
else
{
@@ -136,31 +146,55 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_readInt32BE(duk_context *ctx)
duk_push_int(ctx, ntohl(((int*)(buffer + offset))[0]));
return(1);
}
duk_ret_t ILibDuktape_Polyfills_Buffer_alloc(duk_context *ctx)
{
int sz = duk_require_int(ctx, 0);
duk_push_fixed_buffer(ctx, sz);
char *buffer = Duktape_GetBuffer(ctx, -1, NULL);
memset(buffer, 0, sz);
duk_push_buffer_object(ctx, -1, 0, sz, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
void ILibDuktape_Polyfills_Buffer(duk_context *ctx)
{
// Polyfill 'Buffer.slice'
duk_get_prop_string(ctx, -1, "Duktape"); // [g][Duktape]
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Duktape][Buffer]
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Pollyfills_Buffer_slice, DUK_VARARGS); // [g][Duktape][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "slice"); // [g][Duktape][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_readInt32BE, DUK_VARARGS);
duk_put_prop_string(ctx, -2, "readInt32BE");
duk_pop_3(ctx); // [g]
duk_get_prop_string(ctx, -1, "Duktape"); // [g][Duktape]
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Duktape][Buffer]
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Pollyfills_Buffer_slice, DUK_VARARGS); // [g][Duktape][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "slice"); // [g][Duktape][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_readInt32BE, DUK_VARARGS);// [g][Duktape][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "readInt32BE"); // [g][Duktape][Buffer][prototype]
duk_pop_3(ctx); // [g]
// Polyfill 'Buffer.toString()
duk_get_prop_string(ctx, -1, "Duktape"); // [g][Duktape]
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Duktape][Buffer]
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_toString, DUK_VARARGS);// [g][Duktape][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "toString"); // [g][Duktape][Buffer][prototype]
duk_pop_3(ctx); // [g]
duk_get_prop_string(ctx, -1, "Duktape"); // [g][Duktape]
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Duktape][Buffer]
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_toString, DUK_VARARGS); // [g][Duktape][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "toString"); // [g][Duktape][Buffer][prototype]
duk_pop_3(ctx); // [g]
// Polyfill Buffer.from()
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_from, DUK_VARARGS); // [g][Buffer][func]
duk_put_prop_string(ctx, -2, "from"); // [g][Buffer]
duk_pop(ctx);
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_from, DUK_VARARGS); // [g][Buffer][func]
duk_put_prop_string(ctx, -2, "from"); // [g][Buffer]
duk_pop(ctx); // [g]
// Polyfill Buffer.alloc() for Node Buffers)
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_alloc, DUK_VARARGS); // [g][Buffer][func]
duk_put_prop_string(ctx, -2, "alloc"); // [g][Buffer]
duk_pop(ctx); // [g]
// Polyfill Buffer.toString() for Node Buffers
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
duk_get_prop_string(ctx, -1, "prototype"); // [g][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_toString, DUK_VARARGS); // [g][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "toString"); // [g][Buffer][prototype]
duk_pop_2(ctx); // [g]
}
duk_ret_t ILibDuktape_Polyfills_String_startsWith(duk_context *ctx)
{
@@ -379,6 +413,7 @@ void ILibDuktape_Polyfills_timer_elapsed(void *obj)
{
ILibDuktape_Timer *ptrs = (ILibDuktape_Timer*)obj;
int argCount, i;
duk_context *ctx = ptrs->ctx;
if (ptrs->timerType == ILibDuktape_Timer_Type_INTERVAL)
{
@@ -397,7 +432,7 @@ void ILibDuktape_Polyfills_timer_elapsed(void *obj)
}
duk_pop(ptrs->ctx); // [func][this][...arg...]
if (duk_pcall_method(ptrs->ctx, argCount) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "timers.onElapsed() callback handler"); }
duk_pop(ptrs->ctx); // ...
duk_pop(ctx); // ...
}
duk_ret_t ILibDuktape_Polyfills_timer_set(duk_context *ctx)
{
@@ -490,8 +525,245 @@ duk_ret_t ILibDuktape_Polyfills_addModule(duk_context *ctx)
}
return(0);
}
duk_ret_t ILibDuktape_Queue_Finalizer(duk_context *ctx)
{
duk_get_prop_string(ctx, 0, ILibDuktape_Queue_Ptr);
ILibQueue_Destroy((ILibQueue)duk_get_pointer(ctx, -1));
return(0);
}
duk_ret_t ILibDuktape_Queue_EnQueue(duk_context *ctx)
{
ILibQueue Q;
int i;
int nargs = duk_get_top(ctx);
duk_push_this(ctx); // [queue]
duk_get_prop_string(ctx, -1, ILibDuktape_Queue_Ptr); // [queue][ptr]
Q = (ILibQueue)duk_get_pointer(ctx, -1);
duk_pop(ctx); // [queue]
ILibDuktape_Push_ObjectStash(ctx); // [queue][stash]
duk_push_array(ctx); // [queue][stash][array]
for (i = 0; i < nargs; ++i)
{
duk_dup(ctx, i); // [queue][stash][array][arg]
duk_put_prop_index(ctx, -2, i); // [queue][stash][array]
}
ILibQueue_EnQueue(Q, duk_get_heapptr(ctx, -1));
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [queue][stash]
return(0);
}
duk_ret_t ILibDuktape_Queue_DeQueue(duk_context *ctx)
{
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "peek");
int peek = duk_get_int(ctx, -1);
duk_push_this(ctx); // [Q]
duk_get_prop_string(ctx, -1, ILibDuktape_Queue_Ptr); // [Q][ptr]
ILibQueue Q = (ILibQueue)duk_get_pointer(ctx, -1);
void *h = peek == 0 ? ILibQueue_DeQueue(Q) : ILibQueue_PeekQueue(Q);
if (h == NULL) { return(ILibDuktape_Error(ctx, "Queue is empty")); }
duk_pop(ctx); // [Q]
ILibDuktape_Push_ObjectStash(ctx); // [Q][stash]
duk_push_heapptr(ctx, h); // [Q][stash][array]
int length = (int)duk_get_length(ctx, -1);
int i;
for (i = 0; i < length; ++i)
{
duk_get_prop_index(ctx, -i - 1, i); // [Q][stash][array][args]
}
if (peek == 0) { duk_del_prop_string(ctx, -length - 2, Duktape_GetStashKey(h)); }
return(length);
}
duk_ret_t ILibDuktape_Queue_new(duk_context *ctx)
{
duk_push_object(ctx); // [queue]
duk_push_pointer(ctx, ILibQueue_Create()); // [queue][ptr]
duk_put_prop_string(ctx, -2, ILibDuktape_Queue_Ptr); // [queue]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Queue_Finalizer);
ILibDuktape_CreateInstanceMethod(ctx, "enQueue", ILibDuktape_Queue_EnQueue, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "peek", 0, "deQueue", ILibDuktape_Queue_DeQueue, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "peek", 1, "peekQueue", ILibDuktape_Queue_DeQueue, DUK_VARARGS);
return(1);
}
void ILibDuktape_Queue_Push(duk_context *ctx, void* chain)
{
duk_push_c_function(ctx, ILibDuktape_Queue_new, 0);
}
typedef struct ILibDuktape_DynamicBuffer_data
{
int start;
int end;
int unshiftBytes;
char *buffer;
int bufferLen;
}ILibDuktape_DynamicBuffer_data;
typedef struct ILibDuktape_DynamicBuffer_ContextSwitchData
{
void *chain;
void *heapptr;
ILibDuktape_DuplexStream *stream;
ILibDuktape_DynamicBuffer_data *data;
int bufferLen;
char buffer[];
}ILibDuktape_DynamicBuffer_ContextSwitchData;
ILibTransport_DoneState ILibDuktape_DynamicBuffer_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user);
void ILibDuktape_DynamicBuffer_WriteSink_ChainThread(void *chain, void *user)
{
ILibDuktape_DynamicBuffer_ContextSwitchData *data = (ILibDuktape_DynamicBuffer_ContextSwitchData*)user;
if (ILibDuktape_IsPointerValid(chain, data->heapptr) != 0)
{
ILibDuktape_DynamicBuffer_WriteSink(data->stream, data->buffer, data->bufferLen, data->data);
ILibDuktape_DuplexStream_Ready(data->stream);
}
free(user);
}
ILibTransport_DoneState ILibDuktape_DynamicBuffer_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_DynamicBuffer_data *data = (ILibDuktape_DynamicBuffer_data*)user;
if (ILibIsRunningOnChainThread(stream->readableStream->chain) == 0)
{
ILibDuktape_DynamicBuffer_ContextSwitchData *tmp = (ILibDuktape_DynamicBuffer_ContextSwitchData*)ILibMemory_Allocate(sizeof(ILibDuktape_DynamicBuffer_ContextSwitchData) + bufferLen, 0, NULL, NULL);
tmp->chain = stream->readableStream->chain;
tmp->heapptr = stream->ParentObject;
tmp->stream = stream;
tmp->data = data;
tmp->bufferLen = bufferLen;
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
ILibChain_RunOnMicrostackThread(tmp->chain, ILibDuktape_DynamicBuffer_WriteSink_ChainThread, tmp);
return(ILibTransport_DoneState_INCOMPLETE);
}
if ((data->bufferLen - data->start - data->end) < bufferLen)
{
if (data->end > 0)
{
// Move the buffer first
memmove_s(data->buffer, data->bufferLen, data->buffer + data->start, data->end);
data->start = 0;
}
if ((data->bufferLen - data->end) < bufferLen)
{
// Need to resize buffer first
int tmpSize = data->bufferLen;
while ((tmpSize - data->end) < bufferLen)
{
tmpSize += 4096;
}
data->buffer = (char*)realloc(data->buffer, tmpSize);
data->bufferLen = tmpSize;
}
}
memcpy_s(data->buffer + data->start + data->end, data->bufferLen - data->start - data->end, buffer, bufferLen);
data->end += bufferLen;
int unshifted = 0;
do
{
duk_push_heapptr(stream->readableStream->ctx, stream->ParentObject); // [ds]
duk_get_prop_string(stream->readableStream->ctx, -1, "emit"); // [ds][emit]
duk_swap_top(stream->readableStream->ctx, -2); // [emit][this]
duk_push_string(stream->readableStream->ctx, "readable"); // [emit][this][readable]
if (duk_pcall_method(stream->readableStream->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(stream->readableStream->ctx, "DynamicBuffer.WriteSink => readable(): "); }
duk_pop(stream->readableStream->ctx); // ...
ILibDuktape_DuplexStream_WriteData(stream, data->buffer + data->start, data->end);
if (data->unshiftBytes == 0)
{
// All the data was consumed
data->start = data->end = 0;
}
else
{
unshifted = (data->end - data->unshiftBytes);
if (unshifted > 0)
{
data->start += unshifted;
data->end = data->unshiftBytes;
data->unshiftBytes = 0;
}
}
} while (unshifted != 0);
return(ILibTransport_DoneState_COMPLETE);
}
void ILibDuktape_DynamicBuffer_EndSink(ILibDuktape_DuplexStream *stream, void *user)
{
ILibDuktape_DuplexStream_WriteEnd(stream);
}
duk_ret_t ILibDuktape_DynamicBuffer_Finalizer(duk_context *ctx)
{
ILibDuktape_InValidateHeapPointer(ctx, 0);
duk_get_prop_string(ctx, 0, "\xFF_buffer");
ILibDuktape_DynamicBuffer_data *data = (ILibDuktape_DynamicBuffer_data*)Duktape_GetBuffer(ctx, -1, NULL);
free(data->buffer);
return(0);
}
int ILibDuktape_DynamicBuffer_unshift(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_DynamicBuffer_data *data = (ILibDuktape_DynamicBuffer_data*)user;
data->unshiftBytes = unshiftBytes;
return(unshiftBytes);
}
duk_ret_t ILibDuktape_DynamicBuffer_read(duk_context *ctx)
{
ILibDuktape_DynamicBuffer_data *data;
duk_push_this(ctx); // [DynamicBuffer]
duk_get_prop_string(ctx, -1, "\xFF_buffer"); // [DynamicBuffer][buffer]
data = (ILibDuktape_DynamicBuffer_data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_push_external_buffer(ctx); // [DynamicBuffer][buffer][extBuffer]
duk_config_buffer(ctx, -1, data->buffer + data->start, data->bufferLen - (data->start + data->end));
duk_push_buffer_object(ctx, -1, 0, data->bufferLen - (data->start + data->end), DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
duk_ret_t ILibDuktape_DynamicBuffer_new(duk_context *ctx)
{
ILibDuktape_DynamicBuffer_data *data;
int initSize = 4096;
if (duk_get_top(ctx) != 0)
{
initSize = duk_require_int(ctx, 0);
}
duk_push_object(ctx); // [stream]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_DynamicBuffer_data));
data = (ILibDuktape_DynamicBuffer_data*)Duktape_GetBuffer(ctx, -1, NULL);
memset(data, 0, sizeof(ILibDuktape_DynamicBuffer_data));
duk_put_prop_string(ctx, -2, "\xFF_buffer");
data->bufferLen = initSize;
data->buffer = (char*)malloc(initSize);
ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_DynamicBuffer_WriteSink, ILibDuktape_DynamicBuffer_EndSink, NULL, NULL, ILibDuktape_DynamicBuffer_unshift, data);
ILibDuktape_EventEmitter_CreateEventEx(ILibDuktape_EventEmitter_GetEmitter(ctx, -1), "readable");
ILibDuktape_CreateInstanceMethod(ctx, "read", ILibDuktape_DynamicBuffer_read, DUK_VARARGS);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_DynamicBuffer_Finalizer);
ILibDuktape_ValidateHeapPointer(ctx, -1);
return(1);
}
void ILibDuktape_DynamicBuffer_Push(duk_context *ctx, void *chain)
{
duk_push_c_function(ctx, ILibDuktape_DynamicBuffer_new, DUK_VARARGS);
}
void ILibDuktape_Polyfills_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "queue", ILibDuktape_Queue_Push);
ILibDuktape_ModSearch_AddHandler(ctx, "DynamicBuffer", ILibDuktape_DynamicBuffer_Push);
// Global Polyfills
duk_push_global_object(ctx); // [g]

View File

@@ -25,6 +25,7 @@ limitations under the License.
#define ILibDuktape_readableStream_WritePipes "\xFF_WritePipes"
#define ILibDuktape_readableStream_WritePipes_PTRBUFFER "\xFF_WritePipesPtrBuffer"
#define ILibDuktape_readableStream_WritePipes_Stream "\xFF_WritePipes_Stream"
#define ILibDuktape_readableStream_PipeArray "\xFF_RS_PipeArray"
#ifdef __DOXY__
/*!
@@ -124,40 +125,48 @@ void ILibDuktape_readableStream_WriteData_buffer(ILibDuktape_readableStream *str
}
tmp->Next = buffered;
}
if (stream->paused == 0)
{
stream->paused = 1;
stream->PauseHandler(stream, stream->user);
}
}
void ILibDuktape_readableStream_WriteData_OnData_ChainThread(void *chain, void *user)
{
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
ILibDuktape_readableStream_bufferedData *data = (ILibDuktape_readableStream_bufferedData*)user;
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)data->Next;
stream->paused = 0;
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (stream->extBuffer_Reserved == 0)
if (data->Reserved == 0)
{
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][buffer]
duk_config_buffer(stream->ctx, -1, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
duk_push_external_buffer(stream->ctx); // [ext]
duk_config_buffer(stream->ctx, -1, data->buffer, data->bufferLen);
}
duk_push_heapptr(stream->ctx, stream->OnData); // [ext][func]
duk_push_heapptr(stream->ctx, stream->object); // [ext][func][this]
if (data->Reserved == 0)
{
duk_push_buffer_object(stream->ctx, -3, 0, data->bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [ext][func][this][buffer]
}
else
{
duk_push_lstring(stream->ctx, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
duk_push_lstring(stream->ctx, data->buffer, data->bufferLen); // [ext][func][this][buffer/string]
}
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
if (duk_pcall_method(stream->ctx, 1) != 0) // [...][retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
if (data->Reserved == 0)
{
duk_pop_2(stream->ctx); // ...
}
else
{
duk_pop(stream->ctx); // ...
}
free(data);
if (stream->paused == 0 && stream->ResumeHandler != NULL) { stream->ResumeHandler(stream, stream->user); }
}
void ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStream *ws, void *user)
int ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStream *ws, void *user)
{
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
int unpipeInProgress = 0;
#ifdef WIN32
if(InterlockedDecrement(&(stream->pipe_pendingCount)) == 0)
#elif defined(__ATOMIC_SEQ_CST)
@@ -169,243 +178,220 @@ void ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStrea
if(stream->pipe_pendingCount == 0)
#endif
{
if (stream->ResumeHandler != NULL) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
sem_wait(&(stream->pipeLock));
stream->pipeInProgress = 0;
unpipeInProgress = stream->unpipeInProgress;
sem_post(&(stream->pipeLock));
if (unpipeInProgress == 0 && stream->ResumeHandler != NULL && stream->paused != 0) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
return(1);
}
return(0);
}
duk_ret_t ILibDuktape_readableStream_WriteData_Flush_JS(duk_context *ctx)
duk_ret_t ILibDuktape_readableStream_WriteDataEx_Flush(duk_context *ctx)
{
ILibDuktape_readableStream *stream;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "readable");
stream = (ILibDuktape_readableStream*)duk_get_pointer(ctx, -1);
duk_get_prop_string(ctx, -1, "\xFF_STREAM");
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)duk_to_pointer(ctx, -1);
ILibDuktape_readableStream_WriteData_Flush(NULL, stream);
return 0;
return(0);
}
void ILibDuktape_readableStream_WriteData_ChainThread(void *chain, void *user)
int ILibDuktape_readableStream_WriteDataEx_Chain_Dispatch(ILibDuktape_readableStream *stream, void *ws, char *buffer, int bufferLen)
{
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
ILibDuktape_readableStream_nextWriteablePipe *w;
int jsCount = 0;
int retVal = 0;
duk_push_external_buffer(stream->ctx); // [ext]
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
duk_push_heapptr(stream->ctx, ws); // [ext][ws]
duk_get_prop_string(stream->ctx, -1, "write"); // [ext][ws][write]
duk_swap_top(stream->ctx, -2); // [ext][write][this]
duk_push_buffer_object(stream->ctx, -3, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [ext][write][this][buffer]
duk_push_c_function(stream->ctx, ILibDuktape_readableStream_WriteDataEx_Flush, DUK_VARARGS);// [ext][write][this][buffer][flush]
duk_push_pointer(stream->ctx, stream); // [ext][write][this][buffer][flush][ptr]
duk_put_prop_string(stream->ctx, -2, "\xFF_STREAM"); // [ext][write][this][buffer][flush]
if (duk_pcall_method(stream->ctx, 2) != 0) // [ext][...]
{
ILibDuktape_Process_UncaughtExceptionEx(stream->ctx, "readable.write(): Error Piping ");
if (ILibDuktape_readableStream_WriteData_Flush(NULL, stream)) { retVal = 2; }
}
retVal = duk_to_boolean(stream->ctx, -1) ? 1 : 0;
duk_pop_2(stream->ctx);
sem_wait(&(stream->pipeLock));
w = stream->nextWriteable;
stream->pipe_pendingCount = 0;
return(retVal);
}
void ILibDuktape_readableStream_WriteDataEx_Chain(void *chain, void *user)
{
ILibDuktape_readableStream_bufferedData *data = (ILibDuktape_readableStream_bufferedData*)user;
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)data->Next;
ILibDuktape_readableStream_nextWriteablePipe *w = stream->nextWriteable;
while (w != NULL)
{
if (w->nativeWritable != NULL || w->writableStream != NULL) { stream->pipe_pendingCount++; }
w = w->next;
}
w = stream->nextWriteable;
while (w != NULL)
{
if (w->nativeWritable != NULL)
if (w->writableStream != NULL && w->nativeWritable == NULL)
{
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
switch (ws->WriteSink(ws, stream->extBuffer_buffer, stream->extBuffer_bufferLen, ws->WriteSink_User))
{
case ILibTransport_DoneState_INCOMPLETE:
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
ws->OnWriteFlushEx_User = stream;
break;
case ILibTransport_DoneState_COMPLETE:
ws->OnWriteFlushEx = NULL;
ws->OnWriteFlushEx_User = NULL;
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
case ILibTransport_DoneState_ERROR:
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
}
}
else if(w->writableStream != NULL)
{
duk_push_heapptr(stream->ctx, w->writableStream); // [stream]
duk_get_prop_string(stream->ctx, -1, "write"); // [stream][func]
duk_swap_top(stream->ctx, -2); // [func][this]
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][chunk]
duk_config_buffer(stream->ctx, -1, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
duk_push_c_function(stream->ctx, ILibDuktape_readableStream_WriteData_Flush_JS, DUK_VARARGS); // [func][this][chunk][callback]
duk_push_pointer(stream->ctx, stream); // [func][this][chunk][callback][user]
duk_put_prop_string(stream->ctx, -2, "readable"); // [func][this][chunk][callback]
if (duk_pcall_method(stream->ctx, 2) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
else
{
jsCount += duk_get_int(stream->ctx, -1);
}
duk_pop(stream->ctx);
if (ILibDuktape_readableStream_WriteDataEx_Chain_Dispatch(stream, w->writableStream, data->buffer, data->bufferLen) == 2) { break; }
}
w = w->next;
}
if (stream->paused != 0 && stream->pipe_pendingCount == 0)
{
sem_post(&(stream->pipeLock));
if (stream->ResumeHandler != NULL) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
}
else
{
sem_post(&(stream->pipeLock));
}
free(data);
}
int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, int streamReserved, char* buffer, int bufferLen)
{
ILibDuktape_readableStream_nextWriteablePipe *w;
int nonNativeCount = 0;
int nativeCount = 0;
int dispatchedNonNative = 0;
int noContinue = 0;
int dispatched = 0;
int needPause = 0;
if (stream == NULL) { return(1); }
if (stream->paused != 0)
{
ILibDuktape_readableStream_WriteData_buffer(stream, streamReserved, buffer, bufferLen);
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
return(stream->paused);
}
if (stream->bypassValue == 0 || stream->bypassValue != streamReserved)
{
sem_wait(&(stream->pipeLock));
stream->pipeInProgress = 1;
sem_post(&(stream->pipeLock));
w = stream->nextWriteable;
stream->pipe_pendingCount = 0;
while (w != NULL)
{
++stream->pipe_pendingCount;
w = w->next;
}
dispatched = stream->pipe_pendingCount;
w = stream->nextWriteable;
while (w != NULL)
{
if (w->nativeWritable == 0) { ++nonNativeCount; }
else { ++nativeCount; }
w = w->next;
}
w = stream->nextWriteable;
if (w != NULL)
{
if (nonNativeCount > 0)
if (w->nativeWritable != NULL)
{
// There are piped Pure JavaScript objects... We must context switch to Microstack Thread
stream->extBuffer_Reserved = streamReserved;
stream->extBuffer_buffer = buffer;
stream->extBuffer_bufferLen = bufferLen;
sem_post(&(stream->pipeLock));
if (stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_ChainThread, stream);
return(stream->paused);
}
else
{
// All piped objects are native, so we can blast out a send
stream->pipe_pendingCount = nativeCount;
while (w != NULL)
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
ws->Reserved = streamReserved;
switch (ws->WriteSink(ws, buffer, bufferLen, ws->WriteSink_User))
{
if (w->nativeWritable != NULL)
{
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
ws->Reserved = streamReserved;
switch (ws->WriteSink(ws, buffer, bufferLen, ws->WriteSink_User))
{
case ILibTransport_DoneState_INCOMPLETE:
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
ws->OnWriteFlushEx_User = stream;
break;
case ILibTransport_DoneState_COMPLETE:
ws->OnWriteFlushEx = NULL;
ws->OnWriteFlushEx_User = NULL;
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
case ILibTransport_DoneState_ERROR:
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
}
}
w = w->next;
case ILibTransport_DoneState_INCOMPLETE:
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
ws->OnWriteFlushEx_User = stream;
needPause = 1;
break;
case ILibTransport_DoneState_COMPLETE:
ws->OnWriteFlushEx = NULL;
ws->OnWriteFlushEx_User = NULL;
if (ILibDuktape_readableStream_WriteData_Flush(ws, stream)) { noContinue = 1; }
break;
case ILibTransport_DoneState_ERROR:
if (ILibDuktape_readableStream_WriteData_Flush(ws, stream)) { noContinue = 1; }
break;
}
if (stream->pipe_pendingCount == 0)
if (noContinue != 0) { break; }
}
else if (w->writableStream != NULL && dispatchedNonNative == 0)
{
if (ILibIsRunningOnChainThread(stream->chain) == 0)
{
sem_post(&(stream->pipeLock));
return(stream->paused);
ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, 0, NULL, NULL);
tmp->Next = (ILibDuktape_readableStream_bufferedData*)stream;
tmp->Reserved = streamReserved;
tmp->bufferLen = bufferLen;
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
dispatchedNonNative = 1;
needPause = 1;
ILibChain_RunOnMicrostackThreadEx(stream->chain, ILibDuktape_readableStream_WriteDataEx_Chain, tmp);
}
else
{
sem_post(&(stream->pipeLock));
if (stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
return(stream->paused);
// We're running on the Chain Thread, so we can directly dispatch into JS
switch (ILibDuktape_readableStream_WriteDataEx_Chain_Dispatch(stream, w->writableStream, buffer, bufferLen))
{
case 1: // Need to Pause
needPause = 1;
break;
case 2: // Complete
noContinue = 1;
break;
default: // NOP
break;
}
}
}
}
else
{
sem_post(&(stream->pipeLock));
if (noContinue != 0) { break; }
w = w->next;
}
}
if (stream->OnData != NULL)
if (dispatched == 0)
{
if (ILibIsRunningOnChainThread(stream->chain))
sem_wait(&(stream->pipeLock));
stream->pipeInProgress = 0;
sem_post(&(stream->pipeLock));
if (stream->OnData != NULL)
{
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (streamReserved == 0)
if (ILibIsRunningOnChainThread(stream->chain))
{
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][buffer]
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
if (streamReserved == 0)
{
duk_push_external_buffer(stream->ctx); // [extBuffer]
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
}
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (streamReserved == 0)
{
duk_push_buffer_object(stream->ctx, -3, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [extBuffer][func][this][nodeBuffer]
}
else
{
duk_push_lstring(stream->ctx, buffer, bufferLen); // [func][this][string]
}
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
if (streamReserved == 0)
{
duk_pop_2(stream->ctx);
}
else
{
duk_pop(stream->ctx); // ...
}
}
else
{
duk_push_lstring(stream->ctx, buffer, bufferLen); // [func][this][string]
// Need to PAUSE, and context switch to Chain Thread, so we can dispatch into JavaScript
ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, 0, NULL, NULL);
tmp->bufferLen = bufferLen;
tmp->Reserved = streamReserved;
tmp->Next = (ILibDuktape_readableStream_bufferedData*)stream;
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
needPause = 1;
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, tmp);
}
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
}
else
else if (stream->PauseHandler != NULL && stream->OnEnd == NULL)
{
// Need to PAUSE, and context switch to Chain Thread, so we can dispatch into JavaScript
sem_wait(&(stream->pipeLock));
stream->extBuffer_Reserved = streamReserved;
stream->extBuffer_buffer = buffer;
stream->extBuffer_bufferLen = bufferLen;
sem_post(&(stream->pipeLock));
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, stream);
// If we get here, it means we are writing data, but nobody is going to be receiving it...
// So we need to buffer the data, so when we are resumed later, we can retry
needPause = 1;
ILibDuktape_readableStream_WriteData_buffer(stream, streamReserved, buffer, bufferLen);
}
else if (stream->OnEnd != NULL)
{
return 0;
}
}
else if(stream->PauseHandler != NULL && stream->OnEnd == NULL)
if (needPause)
{
// If we get here, it means we are writing data, but nobody is going to be receiving it...
// So we need to buffer the data, so when we are resumed later, we can retry
ILibDuktape_readableStream_WriteData_buffer(stream, streamReserved, buffer, bufferLen);
}
else if (stream->OnEnd != NULL)
{
return 0;
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
}
return(stream->paused);
}
@@ -426,7 +412,24 @@ int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream)
{
ILibDuktape_readableStream_nextWriteablePipe *next;
if (stream->OnEnd != NULL)
if (stream->noPropagateEnd == 0 && stream->nextWriteable != NULL)
{
next = stream->nextWriteable;
while (next != NULL)
{
duk_push_heapptr(stream->ctx, next->writableStream); // [stream]
duk_get_prop_string(stream->ctx, -1, "end"); // [stream][func]
duk_swap_top(stream->ctx, -2); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
next = next->next;
retVal = 0;
}
}
else if (stream->OnEnd != NULL)
{
duk_context *x = stream->ctx;
duk_push_heapptr(stream->ctx, stream->OnEnd); // [func]
@@ -438,29 +441,15 @@ int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream)
duk_pop(x); // ...
retVal = 0;
}
next = stream->nextWriteable;
while (next != NULL)
{
duk_push_heapptr(stream->ctx, next->writableStream); // [stream]
duk_get_prop_string(stream->ctx, -1, "end"); // [stream][func]
duk_swap_top(stream->ctx, -2); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
next = next->next;
retVal = 0;
}
}
return retVal;
}
void ILibDuktape_readableStream_Closed(ILibDuktape_readableStream *stream)
{
ILibDuktape_readableStream_WriteEnd(stream);
if (stream->OnClose != NULL)
{
duk_push_heapptr(stream->ctx, stream->OnEnd); // [func]
duk_push_heapptr(stream->ctx, stream->OnClose); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
{
@@ -479,7 +468,14 @@ duk_ret_t ILibDuktape_readableStream_pause(duk_context *ctx)
ptr = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [stream]
if (ptr->PauseHandler != NULL) { ptr->paused = 1; ptr->PauseHandler(ptr, ptr->user); }
if (ptr->PauseHandler != NULL)
{
ptr->paused = 1; ptr->PauseHandler(ptr, ptr->user);
}
else
{
return(ILibDuktape_Error(ctx, "Pause Not Supported"));
}
return 1;
}
@@ -523,151 +519,240 @@ duk_ret_t ILibDuktape_readableStream_resume(duk_context *ctx)
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
ptr = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [stream]
if (ptr->ResumeHandler == NULL) { return(ILibDuktape_Error(ctx, "Resume not supported")); }
if (ILibDuktape_readableStream_resume_flush(ptr) == 0 && ptr->ResumeHandler != NULL) { ptr->paused = 0; ptr->ResumeHandler(ptr, ptr->user); }
return 1;
}
void ILibDuktape_readableStream_pipe_resumeFromTimer(void *obj)
void ILibDuktape_ReadableStream_pipe_ResumeLater(duk_context *ctx, void **args, int argsLen)
{
ILibDuktape_readableStream* ptr = (ILibDuktape_readableStream*)((void**)obj)[0];
if (ILibDuktape_readableStream_resume_flush(ptr) == 0 && ptr->ResumeHandler != NULL) { ptr->paused = 0; ptr->ResumeHandler(ptr, ptr->user); }
free(obj);
ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)args[0];
if (ILibDuktape_readableStream_resume_flush(rs) == 0 && rs->ResumeHandler != NULL) { rs->paused = 0; rs->ResumeHandler(rs, rs->user); }
if (rs->PipeHookHandler != NULL) { rs->PipeHookHandler(rs, args[1], rs->user); }
}
void ILibDuktape_readableStream_pipe_resumeFromTimer2(void *obj)
void ILibDuktape_readableStream_pipe_later(duk_context *ctx, void **args, int argsLen)
{
free(obj);
duk_push_heapptr(ctx, args[0]); // [readable]
duk_get_prop_string(ctx, -1, "pipe"); // [readable][pipe]
duk_swap_top(ctx, -2); // [pipe][this]
duk_push_heapptr(ctx, args[1]); // [pipe][this][writable]
if (argsLen > 2) { duk_push_heapptr(ctx, args[2]); } // [pipe][this][writable][options]
if (duk_pcall_method(ctx, argsLen - 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "readableStream.pipeLater(): "); }
duk_pop(ctx); // ...
}
duk_ret_t ILibDuktape_readableStream_pipe(duk_context *ctx)
{
ILibDuktape_readableStream *rstream;
ILibDuktape_readableStream_nextWriteablePipe *w;
ILibDuktape_readableStream_nextWriteablePipe *w, *tmp;
int nargs = duk_get_top(ctx);
duk_push_this(ctx); // [readable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
rstream = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable]
duk_pop_2(ctx); // ...
if (nargs > 1 && duk_is_object(ctx, 1))
sem_wait(&(rstream->pipeLock));
if (rstream->pipeInProgress != 0)
{
rstream->bypassValue = Duktape_GetIntPropertyValue(ctx, 1, "dataTypeSkip", 0);
}
// We must YIELD and try again later, becuase there is an active dispatch going on
duk_push_this(ctx);
ILibDuktape_Immediate(ctx, (void*[]) { duk_get_heapptr(ctx, -1), duk_get_heapptr(ctx, 0), nargs > 1 ? duk_get_heapptr(ctx, 1) : NULL }, 1 + nargs, ILibDuktape_readableStream_pipe_later);
duk_push_object(ctx); // [readable][nextWriteable]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream_nextWriteablePipe)); // [readable][nextWriteable][ptrBuffer]
w = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
memset(w, 0, sizeof(ILibDuktape_readableStream_nextWriteablePipe));
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes_PTRBUFFER); // [readable][nextWriteable]
if (duk_has_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes))
{
// There are already associated pipes
duk_get_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable][nextWriteable][prevWriteable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_WritePipes_PTRBUFFER); // [readable][nextWriteable][prevWriteable][ptr]
w->next = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable][nextWriteable][prevWriteable]
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable][nextWriteable]
}
duk_dup(ctx, 0); // [readable][nextWriteable][stream]
if (duk_has_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS))
{
// This is one of our writable stream implementation... So we can keep everything native
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS); // [readable][nextWriteable][stream][buffer]
w->nativeWritable = Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable][nextWriteable][stream]
}
w->writableStream = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes_Stream); // [readable][nextWriteable]
rstream->nextWriteable = w;
// Save to the readableStream
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable]
duk_dup(ctx, 0); // [readable][writable]
if (duk_has_prop_string(ctx, -1, "emit"))
{
duk_push_string(ctx, "emit"); // [readable][writable][key]
duk_push_string(ctx, "pipe"); // [readable][writable][key][eventName]
duk_dup(ctx, -4); // [readable][writable][key][eventName][readable]
if (duk_pcall_prop(ctx, -4, 2) != 0) // [readable][writable][retVal/err]
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop_2(ctx); // [readable]
duk_dup(ctx, 0);
sem_post(&(rstream->pipeLock));
return(1);
}
else
{
duk_pop(ctx);
}
if (rstream->paused != 0)
{
void *chain = Duktape_GetChain(ctx);
if (chain != NULL)
// No Active Dispatch, so while we hold this lock, we can setup/add the pipe
duk_push_heapptr(ctx, rstream->pipeArray); // [pipeArray]
duk_get_prop_string(ctx, -1, "push"); // [pipeArray][push]
duk_swap_top(ctx, -2); // [push][this]
duk_dup(ctx, 0); // [push][this][dest]
ILibDuktape_Push_ObjectStash(ctx); // [push][this][dest][stash]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream_nextWriteablePipe)); // [push][this][dest][stash][buffer]
w = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [push][this][dest][stash]
duk_pop(ctx); // [push][this][dest]
duk_call_method(ctx, 1); duk_pop(ctx); // ...
memset(w, 0, sizeof(ILibDuktape_readableStream_nextWriteablePipe));
w->writableStream = duk_get_heapptr(ctx, 0);
if (duk_has_prop_string(ctx, 0, ILibDuktape_WritableStream_WSPTRS))
{
// We are paused, so we should yield and resume... We yield, so in case the user tries to chain multiple pipes, it will chain first
void **tmp = (void**)ILibMemory_Allocate(sizeof(void*), 0, NULL, NULL);
tmp[0] = rstream;
ILibLifeTime_AddEx(ILibGetBaseTimer(chain), tmp, 0, ILibDuktape_readableStream_pipe_resumeFromTimer, ILibDuktape_readableStream_pipe_resumeFromTimer2);
// This is one of our writable stream implementation... So we can keep everything native
duk_get_prop_string(ctx, 0, ILibDuktape_WritableStream_WSPTRS); // [wrsPTR]
w->nativeWritable = Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // ...
// If JSCreate is non-zero, it means this is actually a JS Stream, not a native one
if (((int*)w->nativeWritable)[0] != 0) { w->nativeWritable = NULL; }
}
// Now lets lets add this entry to the end of the list, so it can be dispatched without invoking into JS to access the array
if (rstream->nextWriteable == NULL)
{
rstream->nextWriteable = w;
}
else
{
// Oops
duk_push_string(ctx, "ILibParsers_Duktape *MISSING*");
duk_throw(ctx);
return(DUK_RET_ERROR);
tmp = rstream->nextWriteable;
while (tmp->next != NULL) { tmp = tmp->next; }
tmp->next = w;
w->previous = tmp;
}
}
if (nargs > 1 && duk_is_object(ctx, 1))
{
rstream->bypassValue = Duktape_GetIntPropertyValue(ctx, 1, "dataTypeSkip", 0);
rstream->noPropagateEnd = Duktape_GetBooleanProperty(ctx, 1, "end", 1) == 0 ? 1 : 0;
}
sem_post(&(rstream->pipeLock));
if (rstream->PipeHookHandler != NULL) { rstream->PipeHookHandler(rstream, rstream->user); }
// Now we need to emit a 'pipe' event on the writable that we just attached
duk_push_heapptr(ctx, w->writableStream); // [dest]
duk_get_prop_string(ctx, -1, "emit"); // [dest][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "pipe"); // [emit][this][pipe]
duk_push_this(ctx); // [emit][this][pipe][readable]
duk_call_method(ctx, 2); duk_pop(ctx); // ...
if (rstream->paused != 0)
{
// We are paused, so we should yield and resume... We yield, so in case the user tries to chain multiple pipes, it will chain first
ILibDuktape_Immediate(ctx, (void*[]) { rstream, duk_get_heapptr(ctx, 0) }, 1, ILibDuktape_ReadableStream_pipe_ResumeLater);
}
else
{
if (rstream->PipeHookHandler != NULL) { rstream->PipeHookHandler(rstream, duk_get_heapptr(ctx, 0), rstream->user); }
}
duk_dup(ctx, 0);
return 1;
}
void ILibDuktape_readableStream_unpipe_later(duk_context *ctx, void ** args, int argsLen)
{
ILibDuktape_readableStream *data;
ILibDuktape_readableStream_nextWriteablePipe *w;
int i;
duk_size_t arrayLen;
duk_push_heapptr(ctx, args[0]); // [readable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
data = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop_2(ctx); // ...
sem_wait(&(data->pipeLock));
if (data->pipeInProgress != 0)
{
// We must yield, and try again, because there's an active dispatch going on
ILibDuktape_Immediate(ctx, (void*[]) { args[0], args[1] }, argsLen, ILibDuktape_readableStream_unpipe_later);
sem_post(&(data->pipeLock));
return;
}
else
{
i = 0;
w = data->nextWriteable;
if (argsLen > 1)
{
// Specific stream was specified in 'unpipe'
while (w != NULL)
{
if (w->writableStream == args[1])
{
// Emit the 'unpipe' event
duk_push_heapptr(ctx, args[1]); // [ws]
duk_get_prop_string(ctx, -1, "emit"); // [ws][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "unpipe"); // [emit][this][unpipe]
duk_push_heapptr(ctx, args[0]); // [emit][this][unpipe][readable]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "readable.unpipe(): "); }
duk_pop(ctx); // ...
if (w->previous != NULL)
{
w->previous->next = w->next;
}
else
{
data->nextWriteable = w->next;
}
duk_push_heapptr(ctx, data->pipeArray); // [array]
arrayLen = duk_get_length(ctx, -1);
for (i = 0; i < (int)arrayLen; ++i)
{
duk_get_prop_index(ctx, -1, i); // [array][ws]
ILibDuktape_Push_ObjectStash(ctx); // [array][ws][stash]
if (duk_has_prop_string(ctx, -1, Duktape_GetStashKey(args[1])))
{
// Removing the entry from the Array
duk_pop_2(ctx); // [array]
duk_get_prop_string(ctx, -1, "splice"); // [array][splice]
duk_swap_top(ctx, -2); // [splice][this]
duk_push_int(ctx, i); // [splice][this][i]
duk_push_int(ctx, 1); // [splice][this][i][1]
duk_call_method(ctx, 2); // [undefined]
duk_pop(ctx); // ...
break;
}
duk_pop_2(ctx); // [array]
}
duk_pop(ctx); // ...
break;
}
w = w->next;
}
}
else
{
// 'unpipe' all pipes
w = data->nextWriteable;
while (w != NULL)
{
duk_push_heapptr(ctx, w->writableStream); // [ws]
duk_get_prop_string(ctx, -1, "emit"); // [ws][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "unpipe"); // [emit][this][unpipe]
duk_push_heapptr(ctx, args[0]); // [emit][this][unpipe][readable]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "readable.unpipe(): "); }
duk_pop(ctx); // ...
w = w->next;
}
data->nextWriteable = NULL;
duk_push_heapptr(ctx, args[0]); // [readable]
duk_del_prop_string(ctx, -1, ILibDuktape_readableStream_PipeArray);
duk_push_array(ctx); // [readable][array]
data->pipeArray = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_PipeArray); // [readable]
duk_pop(ctx); // ...
}
}
data->unpipeInProgress = 0;
sem_post(&(data->pipeLock));
}
duk_ret_t ILibDuktape_readableStream_unpipe(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
ILibDuktape_readableStream *data;
ILibDuktape_readableStream_nextWriteablePipe *w, *prev;
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
duk_push_this(ctx); // [readable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
data = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable]
if (nargs == 0)
{
duk_del_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes);
data->nextWriteable = NULL;
}
else if (data->nextWriteable != NULL)
{
w = data->nextWriteable;
prev = NULL;
while (w != NULL)
{
if (w->writableStream == duk_get_heapptr(ctx, 0))
{
memset(w, 0, 2 * sizeof(void*));
if (data->nextWriteable == w)
{
//printf("Unpiping object: %p\n", (void*)w);
data->nextWriteable = w->next;
break;
}
else
{
prev->next = w->next;
break;
}
}
else
{
prev = w;
w = w->next;
}
}
}
sem_wait(&(data->pipeLock));
data->unpipeInProgress = 1;
sem_post(&(data->pipeLock));
// We need to pause first
duk_push_this(ctx); // [readable]
duk_get_prop_string(ctx, -1, "pause"); // [readable][pause]
duk_dup(ctx, -2); // [readable][pause][this]
duk_call_method(ctx, 0); duk_pop(ctx); // [readable]
// We must yield, and do this on the next event loop, because we can't unpipe if we're called from a pipe'ed call
ILibDuktape_Immediate(ctx, (void*[]) { duk_get_heapptr(ctx, -1), nargs == 1 ? duk_get_heapptr(ctx, 0) : NULL }, nargs + 1, ILibDuktape_readableStream_unpipe_later);
return 0;
}
duk_ret_t ILibDuktape_readableStream_isPaused(duk_context *ctx)
@@ -710,11 +795,31 @@ void ILibDuktape_ReadableStream_PipeLockFinalizer(duk_context *ctx, void *stream
sem_destroy(&(ptrs->pipeLock));
duk_pop_2(ctx);
}
ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, void *user)
duk_ret_t ILibDuktape_ReadableStream_unshift(duk_context *ctx)
{
ILibDuktape_readableStream *rs;
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
rs = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
if (rs->UnshiftHandler == NULL)
{
return(ILibDuktape_Error(ctx, "readable.unshift(): Not Implemented"));
}
else
{
duk_size_t bufferLen;
Duktape_GetBuffer(ctx, 0, &bufferLen);
duk_push_int(ctx, rs->UnshiftHandler(rs, (int)bufferLen, rs->user));
return(1);
}
}
ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, ILibDuktape_readableStream_UnShiftHandler OnUnshift, void *user)
{
ILibDuktape_readableStream *retVal;
ILibDuktape_EventEmitter *emitter;
ILibDuktape_PointerValidation_Init(ctx);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream)); // [obj][buffer]
duk_dup(ctx, -1); // [obj][buffer][buffer]
duk_put_prop_string(ctx, -3, ILibDuktape_readableStream_RSPTRS); // [obj][buffer]
@@ -722,9 +827,10 @@ ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILi
memset(retVal, 0, sizeof(ILibDuktape_readableStream));
duk_pop(ctx); // [obj]
duk_push_external_buffer(ctx); // [obj][extBuffer]
retVal->extBuffer = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, "_extBuffer"); // [obj]
duk_push_array(ctx); // [obj][array]
retVal->pipeArray = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_PipeArray); // [obj]
retVal->ctx = ctx;
retVal->chain = Duktape_GetChain(ctx);
@@ -732,6 +838,7 @@ ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILi
retVal->user = user;
retVal->PauseHandler = OnPause;
retVal->ResumeHandler = OnResume;
retVal->UnshiftHandler = OnUnshift;
sem_init(&(retVal->pipeLock), 0, 1);
ILibDuktape_CreateIndependentFinalizer(ctx, ILibDuktape_ReadableStream_PipeLockFinalizer);
@@ -743,7 +850,8 @@ ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILi
ILibDuktape_CreateInstanceMethod(ctx, "pause", ILibDuktape_readableStream_pause, 0);
ILibDuktape_CreateInstanceMethod(ctx, "resume", ILibDuktape_readableStream_resume, 0);
ILibDuktape_CreateEventWithGetter(ctx, "pipe", ILibDuktape_readableStream_pipe_getter);
ILibDuktape_CreateInstanceMethod(ctx, "unpipe", ILibDuktape_readableStream_unpipe, DUK_VARARGS);
ILibDuktape_CreateProperty_InstanceMethod(ctx, "unpipe", ILibDuktape_readableStream_unpipe, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "isPaused", ILibDuktape_readableStream_isPaused, 0);
ILibDuktape_CreateInstanceMethod(ctx, "unshift", ILibDuktape_ReadableStream_unshift, 1);
return retVal;
}

View File

@@ -24,12 +24,14 @@ limitations under the License.
struct ILibDuktape_readableStream;
typedef void(*ILibDuktape_readableStream_PauseResumeHandler)(struct ILibDuktape_readableStream *sender, void *user);
typedef void(*ILibDuktape_readableStream_MethodHookHandler)(struct ILibDuktape_readableStream *sender, void *user);
typedef void(*ILibDuktape_readableStream_MethodHookHandler)(struct ILibDuktape_readableStream *sender, void *writableStream, void *user);
typedef int(*ILibDuktape_readableStream_UnShiftHandler)(struct ILibDuktape_readableStream *sender, int unshiftBytes, void *user);
typedef struct ILibDuktape_readableStream_nextWriteablePipe
{
void *writableStream;
void *nativeWritable;
struct ILibDuktape_readableStream_nextWriteablePipe *next;
struct ILibDuktape_readableStream_nextWriteablePipe *previous, *next;
}ILibDuktape_readableStream_nextWriteablePipe;
typedef struct ILibDuktape_readableStream
@@ -40,11 +42,9 @@ typedef struct ILibDuktape_readableStream
void *OnClose;
void *OnData;
void *OnEnd;
void *extBuffer;
char *extBuffer_buffer;
int extBuffer_bufferLen, extBuffer_Reserved;
void *user;
void *pipeArray;
ILibDuktape_readableStream_nextWriteablePipe *nextWriteable;
sem_t pipeLock;
#if defined(WIN32)
@@ -54,16 +54,21 @@ typedef struct ILibDuktape_readableStream
#else
int pipe_pendingCount; // No Atomic Built-ins... Use a Mutex
#endif
int pipeInProgress;
int unpipeInProgress;
int bypassValue;
int noPropagateEnd;
int paused;
void *paused_data;
ILibDuktape_readableStream_PauseResumeHandler PauseHandler;
ILibDuktape_readableStream_PauseResumeHandler ResumeHandler;
ILibDuktape_readableStream_MethodHookHandler PipeHookHandler;
ILibDuktape_readableStream_UnShiftHandler UnshiftHandler;
}ILibDuktape_readableStream;
ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, void *user);
#define ILibDuktape_ReadableStream_Init(ctx, OnPause, OnResume, user) ILibDuktape_InitReadableStream(ctx, OnPause, OnResume, user)
ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, ILibDuktape_readableStream_UnShiftHandler OnUnshift, void *user);
#define ILibDuktape_InitReadableStream(ctx, OnPause, OnResume, user) ILibDuktape_ReadableStream_InitEx(ctx, OnPause, OnResume, NULL, user)
#define ILibDuktape_ReadableStream_Init(ctx, OnPause, OnResume, user) ILibDuktape_ReadableStream_InitEx(ctx, OnPause, OnResume, NULL, user)
#define ILibDuktape_readableStream_SetPauseResumeHandlers(stream, PauseFunc, ResumeFunc, userObj) ((ILibDuktape_readableStream*)stream)->PauseHandler = PauseFunc; ((ILibDuktape_readableStream*)stream)->ResumeHandler = ResumeFunc; ((ILibDuktape_readableStream*)stream)->user = userObj;
int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, int streamReserved, char* buffer, int bufferLen);

View File

@@ -40,7 +40,6 @@ limitations under the License.
#include "ILibDuktape_EventEmitter.h"
#include "ILibDuktape_Helpers.h"
#include "../microstack/ILibParsers.h"
#include "../microstack/ILibProcessPipe.h"
#include "../microstack/ILibRemoteLogging.h"
#include "../microstack/ILibCrypto.h"
@@ -49,7 +48,6 @@ limitations under the License.
#include "ILibDuktape_WebRTC.h"
#include "ILibDuktape_Dgram.h"
#include "ILibDuktape_GenericMarshal.h"
#include "ILibDuktape_ProcessPipe.h"
#include "ILibDuktape_fs.h"
#include "ILibDuktape_Polyfills.h"
#include "ILibDuktape_SimpleDataStore.h"
@@ -58,6 +56,7 @@ limitations under the License.
#include "ILibDuktape_SHA256.h"
#include "ILibDuktape_EncryptionStream.h"
#include "ILibDuktape_ChildProcess.h"
#include "ILibDuktape_HECI.h"
#ifdef _POSIX
extern char **environ;
@@ -198,11 +197,11 @@ void ILibDuktape_ScriptContainer_CheckEmbedded(char **argv, char **script, int *
if (ILibString_EndsWith(argv[0], -1, ".exe", 4) == 0)
{
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s.exe", argv[0]);
tmpFile = fopen(ILibScratchPad, "rb");
fopen_s(&tmpFile, ILibScratchPad, "rb");
}
else
{
tmpFile = fopen(argv[0], "rb");
fopen_s(&tmpFile, argv[0], "rb");
}
#else
tmpFile = fopen(argv[0], "rb");
@@ -290,15 +289,23 @@ duk_ret_t ILibDuktape_ScriptContainer_Process_Argv0(duk_context *ctx)
// Polyfill process object:
duk_ret_t ILibDuktape_ScriptContainer_Process_Argv(duk_context *ctx)
{
duk_push_current_function(ctx);
int readOnly = Duktape_GetIntPropertyValue(ctx, -1, "readOnly", 0);
duk_push_this(ctx); // [process]
if (duk_has_prop_string(ctx, -1, ILibDuktape_ScriptContainer_Process_ArgArray))
{
duk_get_prop_string(ctx, -1, ILibDuktape_ScriptContainer_Process_ArgArray); // [process][array]
duk_dup(ctx, -1); // [process][array][array]
if (readOnly != 0) { duk_dup(ctx, -1); } // [process][array][array]
}
else
{
duk_push_array(ctx); // [process][array]
if (readOnly == 0)
{
duk_dup(ctx, -1); // [process][array][array]
duk_put_prop_string(ctx, -3, ILibDuktape_ScriptContainer_Process_ArgArray); // [process][array]
}
}
return 1;
}
@@ -404,7 +411,10 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
ILibDuktape_EventEmitter_CreateEventEx(emitter, "uncaughtException");
ILibDuktape_CreateEventWithGetter(ctx, "argv0", ILibDuktape_ScriptContainer_Process_Argv0);
ILibDuktape_CreateEventWithGetter(ctx, "argv", ILibDuktape_ScriptContainer_Process_Argv);
duk_push_int(ctx, 1);
ILibDuktape_CreateEventWithGetterAndCustomProperty(ctx, "readOnly", "argv", ILibDuktape_ScriptContainer_Process_Argv);
duk_push_int(ctx, 0);
ILibDuktape_CreateEventWithGetterAndCustomProperty(ctx, "readOnly", "_argv", ILibDuktape_ScriptContainer_Process_Argv);
duk_put_prop_string(ctx, -2, "process"); // [g]
duk_pop(ctx); // ...
@@ -762,7 +772,7 @@ void ILibDuktape_ScriptContainer_OS_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "os", ILibDuktape_ScriptContainer_OS_Push);
}
extern void ILibDuktape_HttpStream_Init(duk_context *ctx);
duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(SCRIPT_ENGINE_SECURITY_FLAGS securityFlags, unsigned int executionTimeout, void *chain, char **argList, ILibSimpleDataStore *db, char *exePath, ILibProcessPipe_Manager pipeManager, ILibDuktape_HelperEvent exitHandler, void *exitUser)
{
duk_context *ctx = duk_create_heap(ILibDuktape_ScriptContainer_Engine_malloc, ILibDuktape_ScriptContainer_Engine_realloc, ILibDuktape_ScriptContainer_Engine_free, NULL, ILibDuktape_ScriptContainer_Engine_fatal);
@@ -800,12 +810,19 @@ duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(SCRIPT_ENG
if ((securityFlags & SCRIPT_ENGINE_NO_NETWORK_ACCESS) == 0)
{
ILibDuktape_WebRTC_Init(ctx); // WebRTC library (browser api)
ILibDuktape_http_init(ctx, chain); // HTTP library (node api)
ILibDuktape_http_init(ctx, chain); // HTTP-Digest library (node api)
ILibDuktape_net_init(ctx, chain); // Network library (node api)
ILibDuktape_DGram_Init(ctx); // Datagram Sockets
ILibDuktape_HttpStream_Init(ctx); // HTTP Library (node api)
}
if ((securityFlags & SCRIPT_ENGINE_NO_GENERIC_MARSHAL_ACCESS) == 0) { ILibDuktape_GenericMarshal_init(ctx); }
if ((securityFlags & SCRIPT_ENGINE_NO_PROCESS_SPAWNING) == 0) { ILibDuktape_ProcessPipe_Init(ctx, chain); ILibDuktape_ChildProcess_Init(ctx); }
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); }

View File

@@ -0,0 +1,561 @@
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_DuplexStream.h"
#include "ILibDuktape_EventEmitter.h"
#ifndef MICROSTACK_NOTLS
#include <openssl/err.h>
#include <openssl/ssl.h>
#endif
#include "../microstack/ILibCrypto.h"
#define ILibDuktape_TlsStream_Ptr "\xFF_ILibDuktape_TLSSTREAM_PTR"
#define ILibDuktape_TlsStream2Cert "\xFF_TLS_CERT"
#define MEMORYCHUNKSIZE 4096
int ILibDuktape_TlsStream_ctx2stream = -1;
typedef struct ILibDuktape_TlsStream_Data
{
duk_context *ctx;
void *tlsObject;
void *chain;
int isClient;
ILibDuktape_EventEmitter *emitter;
char *decryptedBuffer;
int decryptedBuffer_mallocSize;
int decryptedBuffer_beginPointer;
int decryptedBuffer_endPointer;
int decryptedBuffer_unshiftedBytes;
int decryptedBuffer_maxSize;
int rejectUnauthorized;
void *OnVerify;
void *OnServerSNI;
int ProcessEncryptedBuffer_Active;
SSL* ssl;
SSL_CTX *ssl_ctx;
BIO *readBio, *writeBio;
BUF_MEM *readBioBuffer, *writeBioBuffer;
int TLSHandshakeCompleted;
ILibDuktape_DuplexStream *clear;
ILibDuktape_DuplexStream *encrypted;
int encrypted_unshiftBytes;
}ILibDuktape_TlsStream_Data;
void ILibDuktape_TlsStream_X509_PUSH(duk_context *ctx, X509* cert)
{
char hash[UTIL_SHA384_HASHSIZE];
char fingerprint[150];
util_keyhash2(cert, hash);
util_tohex2(hash, UTIL_SHA384_HASHSIZE, fingerprint);
duk_push_object(ctx); // [cert]
duk_push_string(ctx, fingerprint); // [cert][fingerprint]
duk_put_prop_string(ctx, -2, "fingerprint"); // [cert]
}
ILibTransport_DoneState ILibDuktape_TlsStream_ProcessEncryptedBuffer(ILibDuktape_TlsStream_Data *tlsdata)
{
int j, first = 1;
if (tlsdata->ProcessEncryptedBuffer_Active == 0)
{
tlsdata->ProcessEncryptedBuffer_Active = 1;
tlsdata->encrypted_unshiftBytes = 0;
BIO_clear_retry_flags(tlsdata->writeBio);
while ((j = (int)tlsdata->writeBioBuffer->length) > 0 && tlsdata->encrypted->readableStream->paused == 0)
{
if (first == 1)
{
first = 0;
}
else
{
tlsdata->encrypted_unshiftBytes = 0;
BIO_clear_retry_flags(tlsdata->writeBio);
}
do
{
ILibDuktape_DuplexStream_WriteData(tlsdata->encrypted, tlsdata->writeBioBuffer->data, (int)tlsdata->writeBioBuffer->length);
} while (tlsdata->encrypted_unshiftBytes > 0);
if (tlsdata->encrypted_unshiftBytes == 0)
{
tlsdata->writeBioBuffer->data += (int)tlsdata->writeBioBuffer->length;
tlsdata->writeBioBuffer->length = 0;
}
}
tlsdata->ProcessEncryptedBuffer_Active = 0;
return(tlsdata->writeBioBuffer->length > 0 ? ILibTransport_DoneState_INCOMPLETE : ILibTransport_DoneState_COMPLETE);
}
else
{
return(ILibTransport_DoneState_ERROR);
}
}
ILibTransport_DoneState ILibDuktape_TlsStream_Clear_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
SSL_write(data->ssl, buffer, bufferLen);
return(ILibDuktape_TlsStream_ProcessEncryptedBuffer(data));
}
void ILibDuktape_TlsStream_Clear_EndSink(ILibDuktape_DuplexStream *stream, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (ILibIsRunningOnChainThread(data->chain) != 0 && data->encrypted->writableStream->pipedReadable != NULL)
{
duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [stream]
duk_get_prop_string(data->ctx, -1, "end"); // [stream][end]
duk_swap_top(data->ctx, -2); // [end][this]
if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.unencrypted.end(): Error dispatching 'end' upstream "); }
duk_pop(data->ctx); // ...
}
}
void ILibDuktape_TlsStream_Clear_PauseSink_Chain(void *chain, void *user)
{
if (chain != NULL && !ILibDuktape_IsPointerValid(chain, user)) { return; }
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [readable]
duk_get_prop_string(data->ctx, -1, "pause"); // [readable][pause]
duk_swap_top(data->ctx, -2); // [pause][this]
if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.Decrypted.pause(): Error pausing upstream object "); };
duk_pop(data->ctx); // ...
}
void ILibDuktape_TlsStream_Clear_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (data->encrypted->writableStream->pipedReadable_native != NULL && data->encrypted->writableStream->pipedReadable_native->PauseHandler != NULL)
{
data->encrypted->writableStream->pipedReadable_native->paused = 1;
data->encrypted->writableStream->pipedReadable_native->PauseHandler(data->encrypted->writableStream->pipedReadable_native, data->encrypted->writableStream->pipedReadable_native->user);
}
else if (data->encrypted->writableStream->pipedReadable != NULL)
{
if (ILibIsRunningOnChainThread(data->chain) != 0)
{
ILibDuktape_TlsStream_Clear_PauseSink_Chain(NULL, data);
}
else
{
// We're on the wrong thread to resume the upstream object
ILibChain_RunOnMicrostackThreadEx(data->chain, ILibDuktape_TlsStream_Clear_PauseSink_Chain, data);
}
}
}
void ILibDuktape_TlsStream_Clear_ResumeSink_Chain(void *chain, void *user)
{
if (chain != NULL && !ILibDuktape_IsPointerValid(chain, user)) { return; }
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [readable]
duk_get_prop_string(data->ctx, -1, "resume"); // [readable][resume]
duk_swap_top(data->ctx, -2); // [resume][this]
if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.Decrypted.resume(): Error resuming upstream object "); };
duk_pop(data->ctx); // ...
}
void ILibDuktape_TlsStream_Clear_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (data->encrypted->writableStream->pipedReadable_native != NULL && data->encrypted->writableStream->pipedReadable_native->ResumeHandler != NULL)
{
data->encrypted->writableStream->pipedReadable_native->paused = 0;
data->encrypted->writableStream->pipedReadable_native->ResumeHandler(data->encrypted->writableStream->pipedReadable_native, data->encrypted->writableStream->pipedReadable_native->user);
}
else if (data->encrypted->writableStream->pipedReadable != NULL)
{
if (ILibIsRunningOnChainThread(data->chain) != 0)
{
ILibDuktape_TlsStream_Clear_ResumeSink_Chain(NULL, data);
}
else
{
// We're on the wrong thread to resume the upstream object
ILibChain_RunOnMicrostackThreadEx(data->chain, ILibDuktape_TlsStream_Clear_ResumeSink_Chain, data);
}
}
}
int ILibDuktape_TlsStream_Clear_UnshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (unshiftBytes == data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer)
{
data->decryptedBuffer_unshiftedBytes = -1;
}
else
{
data->decryptedBuffer_beginPointer = data->decryptedBuffer_endPointer - unshiftBytes;
data->decryptedBuffer_unshiftedBytes = unshiftBytes;
}
return(unshiftBytes);
}
ILibTransport_DoneState ILibDuktape_TlsStream_Encrypted_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
int j;
//int len = BIO_write(data->writeBio, buffer, bufferLen);
BIO_write(SSL_get_rbio(data->ssl), buffer, bufferLen);
int sslerror;
if (data->TLSHandshakeCompleted == 0)
{
switch ((sslerror = SSL_do_handshake(data->ssl)))
{
case 0:
// Handshake Failed!
while ((sslerror = ERR_get_error()) != 0)
{
ERR_error_string_n(sslerror, ILibScratchPad, sizeof(ILibScratchPad));
}
// TODO: We should probably do something
break;
case 1:
data->TLSHandshakeCompleted = 1;
if (ILibIsRunningOnChainThread(data->chain) != 0)
{
// We're on the Duktape Thread
duk_push_heapptr(data->ctx, data->tlsObject); // [TLS]
duk_get_prop_string(data->ctx, -1, "emit"); // [TLS][emit]
duk_swap_top(data->ctx, -2); // [emit][this]
duk_push_string(data->ctx, "connect"); // [emit][this][connect]
if (duk_pcall_method(data->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.connect(): "); }
duk_pop(data->ctx); // ...
}
else
{
// Need to context switch to the Duktape Thread
}
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
break;
default:
// SSL_WANT_READ most likely
sslerror = SSL_get_error(data->ssl, sslerror);
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
break;
}
return(ILibTransport_DoneState_COMPLETE);
}
else
{
while ((j = SSL_read(data->ssl, data->decryptedBuffer + data->decryptedBuffer_endPointer, data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer)) > 0)
{
// We got new TLS Data
if (j > 0)
{
data->decryptedBuffer_endPointer += j;
if (data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer == 0)
{
data->decryptedBuffer_mallocSize = (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE < data->decryptedBuffer_maxSize) ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : (data->decryptedBuffer_maxSize == 0 ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : data->decryptedBuffer_maxSize);
if((data->decryptedBuffer = (char*)realloc(data->decryptedBuffer, data->decryptedBuffer_mallocSize)) == NULL) ILIBCRITICALEXIT(254);
}
}
}
if (j < 0)
{
sslerror = SSL_get_error(data->ssl, j);
if (data->writeBioBuffer->length > 0)
{
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
}
}
}
//
// Event data up the stack, to process any data that is available
//
do
{
data->decryptedBuffer_unshiftedBytes = 0;
ILibDuktape_DuplexStream_WriteData(data->clear, data->decryptedBuffer + data->decryptedBuffer_beginPointer, data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer);
} while (data->decryptedBuffer_unshiftedBytes > 0);
if (data->decryptedBuffer_unshiftedBytes == 0) { data->decryptedBuffer_beginPointer = data->decryptedBuffer_endPointer = 0; }
//
// Check to see if we need to move any data, to maximize buffer space
//
if (data->decryptedBuffer_beginPointer != 0)
{
//
// We can save some cycles by moving the data back to the top
// of the buffer, instead of just allocating more memory.
//
char *temp = data->decryptedBuffer + data->decryptedBuffer_beginPointer;
memmove_s(data->decryptedBuffer, data->decryptedBuffer_mallocSize, temp, data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer);
data->decryptedBuffer_endPointer -= data->decryptedBuffer_beginPointer;
data->decryptedBuffer_beginPointer = 0;
}
//
// Check to see if we should grow the buffer
//
if (data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer < 1024 && (data->decryptedBuffer_maxSize == 0 || data->decryptedBuffer_mallocSize < data->decryptedBuffer_maxSize))
{
data->decryptedBuffer_mallocSize = (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE < data->decryptedBuffer_maxSize) ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : (data->decryptedBuffer_maxSize == 0 ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : data->decryptedBuffer_maxSize);
if ((data->decryptedBuffer = (char*)realloc(data->decryptedBuffer, data->decryptedBuffer_mallocSize)) == NULL) ILIBCRITICALEXIT(254);
}
return(data->clear->readableStream->paused == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE);
}
void ILibDuktape_TlsStream_Encrypted_EndSink(ILibDuktape_DuplexStream *stream, void *user)
{
}
void ILibDuktape_TlsStream_Encrypted_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
{
// Don't need to do anythign, becuase the 'ILibDuktape_TlsStream_ProcessEncryptedBuffer' will exit the processing loop when paused
}
void ILibDuktape_TlsStream_Encrypted_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
}
int ILibDuktape_TlsStream_Encrypted_UnshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (unshiftBytes == data->writeBioBuffer->length)
{
data->encrypted_unshiftBytes = -1;
}
else
{
data->writeBioBuffer->data += ((int)data->writeBioBuffer->length - unshiftBytes);
data->writeBioBuffer->length = unshiftBytes;
}
return(unshiftBytes);
}
int ILibDuktape_TlsStream_verify(int preverify_ok, X509_STORE_CTX *ctx)
{
STACK_OF(X509) *certChain = X509_STORE_CTX_get_chain(ctx);
SSL *ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)SSL_get_ex_data(ssl, ILibDuktape_TlsStream_ctx2stream);
int i;
int retVal = 0;
if (data->rejectUnauthorized != 0) { return(preverify_ok); }
if (data->OnVerify == NULL) { return 1; }
duk_push_heapptr(data->ctx, data->OnVerify); // [func]
duk_push_heapptr(data->ctx, data->emitter->object); // [func][this]
duk_push_array(data->ctx); // [func][this][certs]
for (i = 0; i < sk_X509_num(certChain); ++i)
{
ILibDuktape_TlsStream_X509_PUSH(data->ctx, sk_X509_value(certChain, i)); // [func][this][certs][cert]
duk_put_prop_index(data->ctx, -2, i); // [func][this][certs]
}
retVal = duk_pcall_method(data->ctx, 1) == 0 ? 1 : 0; // [undefined]
duk_pop(data->ctx); // ...
return retVal;
}
duk_ret_t ILibDuktape_TlsStream_Finalizer(duk_context *ctx)
{
void *chain = Duktape_GetChain(ctx);
duk_get_prop_string(ctx, 0, ILibDuktape_TlsStream_Ptr);
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)Duktape_GetBuffer(ctx, -1, NULL);
struct util_cert *cert = NULL;
if (data->ssl != NULL) { SSL_free(data->ssl); }
if (data->ssl_ctx != NULL) { SSL_CTX_free(data->ssl_ctx); }
if (data->decryptedBuffer != NULL) { free(data->decryptedBuffer); }
if (duk_has_prop_string(ctx, 0, ILibDuktape_TlsStream2Cert))
{
duk_get_prop_string(ctx, 0, ILibDuktape_TlsStream2Cert);
cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
util_freecert(cert);
}
ILibDuktape_InValidatePointer(chain, data);
return(0);
}
duk_ret_t ILibDuktape_TlsStream_serverSNI_cb(duk_context *ctx)
{
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "\xFF_ptr");
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)duk_get_pointer(ctx, -1);
if (duk_has_prop_string(ctx, 1, "pfx") && duk_has_prop_string(ctx, 1, "passphrase"))
{
char *passphrase = Duktape_GetStringPropertyValue(ctx, 1, "passphrase", "");
char *pfx;
duk_size_t pfxLen;
duk_get_prop_string(ctx, 1, "pfx");
pfx = (char*)Duktape_GetBuffer(ctx, -1, &pfxLen);
duk_push_heapptr(ctx, data->tlsObject); // [TLS]
duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [TLS][cert]
struct util_cert *cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
if (util_from_p12(pfx, (int)pfxLen, passphrase, cert) == 0) { return(ILibDuktape_Error(ctx, "Error Reading Certificate")); }
SSL_CTX *newCTX = SSL_CTX_new(SSLv23_server_method());
SSL_CTX_set_options(newCTX, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
SSL_CTX_set_verify(newCTX, SSL_VERIFY_CLIENT_ONCE, ILibDuktape_TlsStream_verify); /* Ask for authentication */
SSL_CTX_use_certificate(newCTX, cert->x509);
SSL_CTX_use_PrivateKey(newCTX, cert->pkey);
SSL_set_SSL_CTX(data->ssl, newCTX);
duk_get_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS][cert][oldCert]
util_freecert((struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL));
duk_pop(ctx); // [TLS][cert]
duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS]
SSL_CTX_free(data->ssl_ctx);
data->ssl_ctx = newCTX;
}
return(0);
}
static int ILibDuktape_TlsStream_serverSNI_callback(SSL *s, int *ad, void *arg)
{
const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)SSL_get_ex_data(s, ILibDuktape_TlsStream_ctx2stream);
int retVal = SSL_TLSEXT_ERR_OK;
duk_push_heapptr(data->ctx, data->OnServerSNI); // [func]
duk_push_heapptr(data->ctx, data->tlsObject); // [func][this]
duk_push_string(data->ctx, servername); // [func][this][servername]
duk_push_c_function(data->ctx, ILibDuktape_TlsStream_serverSNI_cb, 2); // [func][this][servername][cb]
duk_push_pointer(data->ctx, data); // [func][this][servername][cb][ptr]
duk_put_prop_string(data->ctx, -2, "\xFF_ptr"); // [func][this][servername][cb]
if (duk_pcall_method(data->ctx, 2) != 0)
{
ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.serverSNI(): Error dispatching callback ");
retVal = SSL_TLSEXT_ERR_NOACK;
}
duk_pop(data->ctx); // ...
return(retVal);
}
duk_ret_t ILibDuktape_TlsStream_create(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *sniHost = NULL;
void *chain = Duktape_GetChain(ctx);
int status, requestCert;
duk_push_current_function(ctx);
int isClient = Duktape_GetIntPropertyValue(ctx, -1, "isClient", 0);
ILibDuktape_TlsStream_Data *data;
duk_push_object(ctx); // [TLS]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_TlsStream_Finalizer);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_TlsStream_Data)); // [TLS][struct]
data = (ILibDuktape_TlsStream_Data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream_Ptr); // [TLS]
memset(data, 0, sizeof(ILibDuktape_TlsStream_Data));
ILibDuktape_ValidatePointer(chain, data);
data->emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEventEx(data->emitter, "connect");
data->tlsObject = duk_get_heapptr(ctx, -1);
data->decryptedBuffer_mallocSize = MEMORYCHUNKSIZE;
data->decryptedBuffer = (char*)ILibMemory_Allocate(data->decryptedBuffer_mallocSize, 0, NULL, NULL);
data->rejectUnauthorized = Duktape_GetIntPropertyValue(ctx, 0, "rejectUnauthorized", 1);
requestCert = Duktape_GetIntPropertyValue(ctx, 0, "requestCert", 0);
data->OnVerify = Duktape_GetHeapptrProperty(ctx, 0, isClient != 0 ? "checkServerIdentity" : "checkClientIdentity");
duk_push_object(ctx); // [TLS][clear]
ILibDuktape_WriteID(ctx, "TlsStream.decrypted");
data->clear = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_TlsStream_Clear_WriteSink, ILibDuktape_TlsStream_Clear_EndSink,
ILibDuktape_TlsStream_Clear_PauseSink, ILibDuktape_TlsStream_Clear_ResumeSink, ILibDuktape_TlsStream_Clear_UnshiftSink, data);
ILibDuktape_CreateReadonlyProperty(ctx, "clear"); // [TLS]
duk_push_object(ctx); // [TLS][encrypted]
ILibDuktape_WriteID(ctx, "TlsStream.encrypted");
data->encrypted = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_TlsStream_Encrypted_WriteSink, ILibDuktape_TlsStream_Encrypted_EndSink,
ILibDuktape_TlsStream_Encrypted_PauseSink, ILibDuktape_TlsStream_Encrypted_ResumeSink, ILibDuktape_TlsStream_Encrypted_UnshiftSink, data);
ILibDuktape_CreateReadonlyProperty(ctx, "encrypted"); // [TLS]
data->ctx = ctx;
data->chain = Duktape_GetChain(ctx);
data->ssl_ctx = isClient != 0 ? SSL_CTX_new(SSLv23_client_method()) : SSL_CTX_new(SSLv23_server_method());
SSL_CTX_set_options(data->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
if (isClient != 0 || requestCert != 0) { SSL_CTX_set_verify(data->ssl_ctx, isClient != 0 ? SSL_VERIFY_PEER : SSL_VERIFY_CLIENT_ONCE, ILibDuktape_TlsStream_verify); /* Ask for authentication */ }
if (nargs > 0 && duk_is_object(ctx, 0))
{
sniHost = Duktape_GetStringPropertyValue(ctx, 0, "host", NULL);
data->OnServerSNI = Duktape_GetHeapptrProperty(ctx, 0, "SNICallback");
if (duk_has_prop_string(ctx, 0, "pfx") && duk_has_prop_string(ctx, 0, "passphrase"))
{
// PFX certificate was passed in thru Options
char *pfx, *passphrase;
duk_size_t pfxLen, passphraseLen;
duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [TLS][buff]
struct util_cert *cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS]
duk_get_prop_string(ctx, 0, "pfx"); // [pfx]
duk_get_prop_string(ctx, 0, "passphrase"); // [pfx][passphrase]
pfx = (char*)Duktape_GetBuffer(ctx, -2, &pfxLen);
passphrase = (char*)Duktape_GetBuffer(ctx, -1, &passphraseLen);
if (util_from_p12(pfx, (int)pfxLen, passphrase, cert) == 0) { return(ILibDuktape_Error(ctx, "Error Reading Certificate")); }
SSL_CTX_use_certificate(data->ssl_ctx, cert->x509);
SSL_CTX_use_PrivateKey(data->ssl_ctx, cert->pkey);
duk_pop_2(ctx);
}
}
data->ssl = SSL_new(data->ssl_ctx);
data->TLSHandshakeCompleted = 0;
data->readBio = BIO_new(BIO_s_mem());
data->writeBio = BIO_new(BIO_s_mem());
BIO_get_mem_ptr(data->readBio, &(data->readBioBuffer));
BIO_get_mem_ptr(data->writeBio, &(data->writeBioBuffer));
BIO_set_mem_eof_return(data->readBio, -1);
BIO_set_mem_eof_return(data->writeBio, -1);
data->readBioBuffer->length = 0;
SSL_set_bio(data->ssl, data->readBio, data->writeBio);
if (ILibDuktape_TlsStream_ctx2stream < 0)
{
ILibDuktape_TlsStream_ctx2stream = SSL_get_ex_new_index(0, "ILibDuktape_TlsStream index", NULL, NULL, NULL);
}
SSL_set_ex_data(data->ssl, ILibDuktape_TlsStream_ctx2stream, data);
if (isClient != 0)
{
if (sniHost != NULL) { SSL_set_tlsext_host_name(data->ssl, sniHost); }
SSL_set_connect_state(data->ssl);
status = SSL_do_handshake(data->ssl);
if (status <= 0) { status = SSL_get_error(data->ssl, status); }
if (status == SSL_ERROR_WANT_READ)
{
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
// We're going to drop out now, becuase we need to check for received data
}
}
else
{
if (data->OnServerSNI != NULL)
{
SSL_CTX_set_tlsext_servername_callback(data->ssl_ctx, ILibDuktape_TlsStream_serverSNI_callback);
}
SSL_set_accept_state(data->ssl); // Setup server SSL state
}
return(1);
}
void ILibDuktape_TlsStream_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isClient", 1, "createClient", ILibDuktape_TlsStream_create, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isClient", 0, "createServer", ILibDuktape_TlsStream_create, DUK_VARARGS);
}
void ILibDuktape_TlsStream_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "TlsStream", ILibDuktape_TlsStream_PUSH);
}

View File

@@ -235,6 +235,7 @@ duk_ret_t ILibDuktape_WritableStream_End(duk_context *ctx)
duk_dup(ctx, 2); // [stream][flush]
duk_put_prop_string(ctx, -2, "_Finish"); // [stream]
}
stream->endBytes = (int)bufferLen;
if (stream->WriteSink(stream, buffer, (int)bufferLen, stream->WriteSink_User) == ILibTransport_DoneState_INCOMPLETE)
{
// Incomplete, wait for SendOK
@@ -265,11 +266,40 @@ duk_ret_t ILibDuktape_WritableStream_End_Getter(duk_context *ctx)
duk_push_c_function(ctx, ILibDuktape_WritableStream_End, DUK_VARARGS);
return 1;
}
duk_ret_t ILibDuktape_WritableStream_UnPipeSink(duk_context *ctx)
{
duk_dup(ctx, 0);
duk_push_this(ctx);
//printf("UNPIPE: [%s] => X => [%s]\n", Duktape_GetStringPropertyValue(ctx, -2, ILibDuktape_OBJID, "unknown"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown"));
return(0);
}
duk_ret_t ILibDuktape_WritableStream_PipeSink(duk_context *ctx)
{
ILibDuktape_WritableStream *ws;
duk_push_this(ctx); // [writable]
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS);
ws = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL);
if (duk_has_prop_string(ctx, 0, "\xFF_ReadableStream_PTRS"))
{
duk_get_prop_string(ctx, 0, "\xFF_ReadableStream_PTRS"); // [writable][rs]
ws->pipedReadable_native = (struct ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
}
ws->pipedReadable = duk_get_heapptr(ctx, 0);
duk_dup(ctx, 0);
duk_push_this(ctx);
//printf("PIPE: [%s] => [%s]\n", Duktape_GetStringPropertyValue(ctx, -2, ILibDuktape_OBJID, "unknown"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown"));
return(0);
}
ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, ILibDuktape_WritableStream_WriteHandler WriteHandler, ILibDuktape_WritableStream_EndHandler EndHandler, void *user)
{
ILibDuktape_WritableStream *retVal;
ILibDuktape_EventEmitter *emitter;
ILibDuktape_PointerValidation_Init(ctx);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_WritableStream)); // [obj][buffer]
retVal = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL); // [obj][buffer]
memset(retVal, 0, sizeof(ILibDuktape_WritableStream));
@@ -283,7 +313,8 @@ ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, IL
retVal->WriteSink_User = user;
emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEvent(emitter, "pipe", &(retVal->OnPipe));
ILibDuktape_EventEmitter_CreateEventEx(emitter, "pipe");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "unpipe");
ILibDuktape_EventEmitter_CreateEvent(emitter, "drain", &(retVal->OnDrain));
ILibDuktape_EventEmitter_CreateEvent(emitter, "finish", &(retVal->OnFinish));
ILibDuktape_EventEmitter_CreateEvent(emitter, "error", &(retVal->OnError));
@@ -291,5 +322,7 @@ ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, IL
ILibDuktape_CreateInstanceMethod(ctx, "write", ILibDuktape_WritableStream_Write, DUK_VARARGS);
ILibDuktape_CreateEventWithGetter(ctx, "end", ILibDuktape_WritableStream_End_Getter);
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "pipe", ILibDuktape_WritableStream_PipeSink);
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "unpipe", ILibDuktape_WritableStream_UnPipeSink);
return retVal;
}

View File

@@ -23,16 +23,19 @@ limitations under the License.
struct ILibDuktape_WritableStream;
typedef ILibTransport_DoneState(*ILibDuktape_WritableStream_WriteHandler)(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user);
typedef void(*ILibDuktape_WritableStream_EndHandler)(struct ILibDuktape_WritableStream *stream, void *user);
typedef void(*ILibDuktape_WriteableStream_WriteFlushNative)(struct ILibDuktape_WritableStream *stream, void *user);
typedef int(*ILibDuktape_WriteableStream_WriteFlushNative)(struct ILibDuktape_WritableStream *stream, void *user);
typedef void(*ILibDuktape_WritableStream_PipeHandler)(struct ILibDuktape_WritableStream *stream, void *readableSource, void *user);
struct ILibDuktape_readableStream;
typedef struct ILibDuktape_WritableStream
{
int JSCreated;
duk_context *ctx;
void *obj;
void *OnDrain;
void *OnWriteFlush;
void *OnPipe;
ILibDuktape_WriteableStream_WriteFlushNative OnWriteFlushEx;
void *OnWriteFlushEx_User;
@@ -42,8 +45,12 @@ typedef struct ILibDuktape_WritableStream
ILibDuktape_WritableStream_WriteHandler WriteSink;
ILibDuktape_WritableStream_EndHandler EndSink;
ILibDuktape_WritableStream_PipeHandler PipeSink;
void *pipedReadable;
struct ILibDuktape_readableStream* pipedReadable_native;
void *WriteSink_User;
int endBytes;
int Reserved;
} ILibDuktape_WritableStream;

View File

@@ -1229,6 +1229,7 @@ duk_ret_t ILibDuktape_fs_readFileSync(duk_context *ctx)
duk_push_fixed_buffer(ctx, (duk_size_t)fileLen);
ignore_result(fread(Duktape_GetBuffer(ctx, -1, NULL), 1, (size_t)fileLen, f));
fclose(f);
duk_push_buffer_object(ctx, -1, 0, (duk_size_t)fileLen, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,7 @@ limitations under the License.
#include "microstack/ILibParsers.h"
#define ILibDuktape_SOCKET2OPTIONS "\xFF_NET_SOCKET2OPTIONS"
void ILibDuktape_net_init(duk_context *ctx, void *chain);
typedef struct ILibDuktape_globalTunnel_data

View File

@@ -182,7 +182,7 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
duk_pop_2(ctx); // [this]
self = duk_get_heapptr(ctx, -1);
if (data->eventTable == NULL) { return 0; } // This probably means the finalizer was already run on the eventEmitter
if (data->eventTable == NULL) { duk_push_false(ctx); return(1); } // This probably means the finalizer was already run on the eventEmitter
eventList = ILibHashtable_Get(data->eventTable, NULL, name, (int)nameLen);
if (eventList == NULL) { return ILibDuktape_Error(ctx, "EventEmitter.emit(): Event '%s' not found", name); }
@@ -245,8 +245,8 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
}
duk_pop(ctx); // ...
}
return 0;
duk_push_boolean(ctx, i > 1 ? 1 : 0);
return(1);
}
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr)
{
@@ -261,13 +261,13 @@ int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *ev
return retVal;
}
int ILibDuktape_EventEmitter_AddOnceEx2(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func, duk_idx_t funcArgs)
int ILibDuktape_EventEmitter_AddOnceEx3(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func)
{
int retVal = 1;
duk_dup(ctx, idx); // [obj]
ILibDuktape_Push_ObjectStash(ctx); // [obj][stash]
duk_push_c_function(ctx, func, funcArgs); // [obj][stash][func]
duk_push_c_function(ctx, func, DUK_VARARGS); // [obj][stash][func]
duk_dup(ctx, -1); // [obj][stash][func][func]
duk_put_prop_string(ctx, -3, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [obj][stash][func]
duk_get_prop_string(ctx, -3, "once"); // [obj][stash][func][once]
@@ -316,10 +316,12 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
ILibDuktape_EventEmitter *data;
int once;
void *eventList, *node, *dispatcher, **hptr;
int i, count;
int i, count, prepend;
duk_push_current_function(ctx);
once = Duktape_GetIntPropertyValue(ctx, -1, "once", 0);
prepend = Duktape_GetIntPropertyValue(ctx, -1, "prepend", 0);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject);
@@ -334,7 +336,7 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
dispatcher = ILibHashtable_Get(data->eventTable, ILibDuktape_EventEmitter_SetterFunc, propName, (int)propNameLen);
if (dispatcher == NULL) { return(ILibDuktape_Error(ctx, "EventEmitter.on(): Internal error with Event '%s'", propName)); }
node = ILibLinkedList_AddTail(eventList, callback);
node = prepend ? ILibLinkedList_AddHead(eventList, callback) : ILibLinkedList_AddTail(eventList, callback);
((int*)ILibLinkedList_GetExtendedMemory(node))[0] = once;
data->totalListeners[0]++;
@@ -462,8 +464,11 @@ ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
retVal->object = duk_get_heapptr(ctx, -1);
retVal->eventTable = ILibHashtable_Create();
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "once", 1, "once", ILibDuktape_EventEmitter_on, 2);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "once", 0, "on", ILibDuktape_EventEmitter_on, 2);
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "once", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 1), "prepend", duk_push_int_ex(ctx, 0));
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "on", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 0), "prepend", duk_push_int_ex(ctx, 0));
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "prependOnceListener", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 1), "prepend", duk_push_int_ex(ctx, 1));
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "prependListener", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 0), "prepend", duk_push_int_ex(ctx, 1));
ILibDuktape_CreateInstanceMethod(ctx, "removeListener", ILibDuktape_EventEmitter_removeListener, 2);
ILibDuktape_CreateInstanceMethod(ctx, "removeAllListeners", ILibDuktape_EventEmitter_removeAllListeners, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "emit", ILibDuktape_EventEmitter_emit, DUK_VARARGS);
@@ -816,6 +821,15 @@ duk_ret_t ILibDuktape_EventEmitter_Inherits_addMethod(duk_context *ctx)
ILibDuktape_CreateProperty_InstanceMethodEx(ctx, (char*)duk_require_string(ctx, 0), duk_require_heapptr(ctx, 1));
return(0);
}
duk_ret_t ILibDuktape_EventEmitter_EmitterUtils_Finalizer(duk_context *ctx)
{
duk_get_prop_string(ctx, 0, "\xFF_MainObject"); // [obj]
duk_get_prop_string(ctx, -1, "emit"); // [obj][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "~"); // [emit][this][~]
duk_call_method(ctx, 1);
return(0);
}
duk_ret_t ILibDuktape_EventEmitter_Inherits(duk_context *ctx)
{
ILibDuktape_EventEmitter *emitter;
@@ -823,12 +837,16 @@ duk_ret_t ILibDuktape_EventEmitter_Inherits(duk_context *ctx)
duk_dup(ctx, 0); // [target]
emitter = ILibDuktape_EventEmitter_Create(ctx);
duk_push_object(ctx); // [target][emitterUtils]
duk_dup(ctx, -2); // [target][emitterUtils][target]
duk_put_prop_string(ctx, -2, "\xFF_MainObject"); // [target][emitterUtils]
duk_dup(ctx, -1); // [target][emitterUtils][dup]
duk_put_prop_string(ctx, -3, "\xFF_emitterUtils"); // [target][emitterUtils]
duk_push_pointer(ctx, emitter); // [target][emitterUtils][ptr]
duk_put_prop_string(ctx, -2, "emitter"); // [target][emitterUtils]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_EventEmitter_EmitterUtils_Finalizer);
ILibDuktape_CreateInstanceMethod(ctx, "createEvent", ILibDuktape_EventEmitter_Inherits_createEvent, 1);
ILibDuktape_CreateInstanceMethod(ctx, "addMethod", ILibDuktape_EventEmitter_Inherits_addMethod, 2);
ILibDuktape_EventEmitter_CreateEventEx(emitter, "~");
return 1;
}
void ILibDuktape_EventEmitter_PUSH(duk_context *ctx, void *chain)
@@ -840,3 +858,54 @@ void ILibDuktape_EventEmitter_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "events", ILibDuktape_EventEmitter_PUSH);
}
duk_ret_t ILibDuktape_EventEmitter_ForwardEvent_Sink(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
int i;
char *name;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "targetObject"); // [func][obj]
duk_get_prop_string(ctx, -1, "emit"); // [func][obj][emit]
duk_swap_top(ctx, -2); // [func][emit][this]
duk_get_prop_string(ctx, -3, "targetName"); // [func][emit][this][name]
name = (char*)duk_get_string(ctx, -1);
for (i = 0; i < nargs; ++i)
{
duk_dup(ctx, i); // [func][emit][this][name][...args...]
}
if (duk_pcall_method(ctx, 1 + nargs) != 0) { return(ILibDuktape_Error(ctx, "EventEmitter.ForwardEvent() [%s]: %s", name, duk_safe_to_string(ctx, -1))); }
return(0);
}
void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSourceIndex, char *sourceEventName, duk_idx_t eventTargetIndex, char *targetEventName)
{
void *target;
duk_dup(ctx, eventTargetIndex); // [targetObject]
target = duk_get_heapptr(ctx, -1);
duk_pop(ctx); // ...
duk_dup(ctx, eventSourceIndex); // [sourceObject]
duk_get_prop_string(ctx, -1, "on"); // [sourceObject][on]
duk_swap_top(ctx, -2); // [on][this]
duk_push_string(ctx, sourceEventName); // [on][this][name]
duk_push_c_function(ctx, ILibDuktape_EventEmitter_ForwardEvent_Sink, DUK_VARARGS); // [on][this][name][sink]
duk_push_heapptr(ctx, target); // [on][this][name][sink][targetObject]
duk_put_prop_string(ctx, -2, "targetObject"); // [on][this][name][sink]
duk_push_string(ctx, targetEventName); // [on][this][name][sink][targetName]
duk_put_prop_string(ctx, -2, "targetName"); // [on][this][name][sink]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "EventEmitter_ForwardEvent(): "); }
duk_pop(ctx); // ...
}
int ILibDuktape_EventEmitter_AddOnEx(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func)
{
int retVal = 1;
duk_dup(ctx, idx); // [object]
duk_get_prop_string(ctx, -1, "on"); // [object][on]
duk_swap_top(ctx, -2); // [on][this]
duk_push_string(ctx, eventName); // [on][this][name]
duk_push_c_function(ctx, func, DUK_VARARGS); // [on][this][name][func]
if (duk_pcall_method(ctx, 2) != 0) { retVal = 0; }
duk_pop(ctx); // ...
return(retVal);
}