1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2026-01-07 11:03:55 +00:00

Many improvements.

This commit is contained in:
Ylian Saint-Hilaire
2018-02-11 21:11:58 -08:00
parent 508646044e
commit 4b5c77b4fd
127 changed files with 51725 additions and 35030 deletions

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
@@ -7,6 +23,7 @@
#include "ILibDuktape_EventEmitter.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktape_Polyfills.h"
#define ILibDuktape_EventEmitter_MaxEventNameLen 255
#define ILibDuktape_EventEmitter_Data "\xFF_EventEmitter_Data"
@@ -127,39 +144,19 @@ void ILibDuktape_EventEmitter_FinalizerEx(ILibHashtable sender, void *Key1, char
duk_pop_2(data->ctx); // ...
}
}
duk_ret_t ILibDuktape_EventEmitter_Finalizer(duk_context *ctx)
int ILibDuktape_EventEmitter_HasListeners(ILibDuktape_EventEmitter *emitter, char *eventName)
{
ILibDuktape_EventEmitter *data;
duk_get_prop_string(ctx, 0, ILibDuktape_EventEmitter_Data);
data = (ILibDuktape_EventEmitter*)Duktape_GetBuffer(ctx, -1, NULL);
// Check to see if this is the process object going away
if (ILibDuktape_GetProcessObject(ctx) == data->object)
int retVal = 0;
if (emitter->eventTable != NULL)
{
// We need to dispatch the 'exit' event
int exitCode = 0;
duk_push_heapptr(data->ctx, data->object); // [process]
if (duk_has_prop_string(data->ctx, -1, "\xFF_ExitCode"))
ILibLinkedList eventList = ILibHashtable_Get(emitter->eventTable, NULL, eventName, (int)strnlen_s(eventName, 255));
if (eventList != NULL)
{
duk_get_prop_string(data->ctx, -1, "\xFF_ExitCode"); // [process][exitCode]
exitCode = duk_get_int(data->ctx, -1);
duk_pop(data->ctx); // [process]
retVal = ILibLinkedList_GetCount(eventList);
}
duk_get_prop_string(data->ctx, -1, "emit"); // [process][emit]
duk_swap_top(data->ctx, -2); // [emit][this]
duk_push_string(data->ctx, "exit"); // [emit][this][eventName/exit]
duk_push_int(data->ctx, exitCode); // [emit][this][eventName/exit][exitCode]
duk_pcall_method(data->ctx, 2);
duk_pop(data->ctx);
}
// We need to clear the Native Dispatcher, while destroying the Hashtable
ILibHashtable_DestroyEx(data->eventTable, ILibDuktape_EventEmitter_FinalizerEx, data);
memset(data, 0, sizeof(ILibDuktape_EventEmitter));
return 0;
return(retVal);
}
duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
{
@@ -170,25 +167,24 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
void *self;
int nargs = duk_get_top(ctx);
ILibDuktape_EventEmitter *data;
void *node, *nextNode, *func, *dispatcher;
int i, j, count;
void **hptr;
void *node, *nextNode, *func;
int i, j;
void **emitList;
char *objid;
duk_push_this(ctx);
duk_push_this(ctx); // [this]
objid = Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown");
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject); // [this][tmp]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_Data); // [this][tmp][data]
data = (ILibDuktape_EventEmitter*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop_2(ctx); // [this]
self = duk_get_heapptr(ctx, -1);
duk_pop(ctx); // ...
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); }
dispatcher = ILibHashtable_Get(data->eventTable, ILibDuktape_EventEmitter_SetterFunc, name, (int)nameLen);
if (dispatcher == NULL) { return ILibDuktape_Error(ctx, "EventEmitter.emit(): Internal Error with event '%s'", name); }
if (eventList == NULL) { return ILibDuktape_Error(ctx, "EventEmitter.emit(): Event '%s' not found on object '%s'", name, objid); }
// Copy the list, so we can enumerate with local memory, so the list can be manipulated while we are dispatching
#ifdef WIN32
@@ -213,22 +209,6 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
}
emitList[i] = NULL;
// If no more listeners, we can set the hptr to NULL
if (ILibLinkedList_GetCount(eventList) == 0)
{
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = NULL;
duk_pop(ctx); // [dispatcher][hptrList]
}
duk_pop_2(ctx); // ...
}
// Now that we have all the housekeeping stuff out of the way, we can actually dispatch our events
i = 0;
while ((func = emitList[i++]) != NULL)
@@ -241,13 +221,27 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
}
if (duk_pcall_method(ctx, nargs - 1) != 0)
{
return(ILibDuktape_Error(ctx, "EventEmitter.emit(): Event dispatch for '%s' threw an exception: %s", name, duk_safe_to_string(ctx, -1)));
return(ILibDuktape_Error(ctx, "EventEmitter.emit(): Event dispatch for '%s' on '%s' threw an exception: %s", name, objid, duk_safe_to_string(ctx, -1)));
}
duk_pop(ctx); // ...
}
duk_push_boolean(ctx, i > 1 ? 1 : 0);
return(1);
}
int ILibDuktape_EventEmitter_PrependOnce(duk_context *ctx, duk_idx_t i, char *eventName, duk_c_function func)
{
int retVal = 1;
duk_dup(ctx, i); // [this]
duk_get_prop_string(ctx, -1, "prependOnceListener"); // [this][prependOnce]
duk_swap_top(ctx, -2); // [prependOnce][this]
duk_push_string(ctx, eventName); // [prependOnce][this][eventName]
duk_push_c_function(ctx, func, DUK_VARARGS); // [prependOnce][this][eventName][func]
if (duk_pcall_method(ctx, 2) != 0) { retVal = 0; }
duk_pop(ctx); // ...
return(retVal);
}
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr)
{
int retVal = 1;
@@ -315,8 +309,9 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
void *callback = duk_require_heapptr(ctx, 1);
ILibDuktape_EventEmitter *data;
int once;
void *eventList, *node, *dispatcher, **hptr;
int i, count, prepend;
void *eventList, *node;
int prepend;
ILibDuktape_EventEmitter_HookHandler hookHandler = NULL;
duk_push_current_function(ctx);
once = Duktape_GetIntPropertyValue(ctx, -1, "once", 0);
@@ -333,8 +328,7 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
{
return(ILibDuktape_Error(ctx, "EventEmitter.on(): Event '%s' not found", propName));
}
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)); }
hookHandler = ILibHashtable_Get(data->eventTable, ILibDuktape_EventEmitter_Hook, propName, (int)propNameLen);
node = prepend ? ILibLinkedList_AddHead(eventList, callback) : ILibLinkedList_AddTail(eventList, callback);
((int*)ILibLinkedList_GetExtendedMemory(node))[0] = once;
@@ -344,17 +338,7 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
duk_push_heapptr(ctx, callback);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(callback)); // Save the callback to the tmp object, so it won't get GC'ed
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = dispatcher;
duk_pop(ctx); // [dispatcher][hptrList]
}
if (hookHandler != NULL) { hookHandler(data, propName, callback); }
return 0;
}
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_GetEmitter_fromThis(duk_context *ctx)
@@ -406,36 +390,69 @@ duk_ret_t ILibDuktape_EventEmitter_removeAllListeners(duk_context *ctx)
duk_size_t eventNameLen;
char *eventName = Duktape_GetBuffer(ctx, 0, &eventNameLen);
ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_GetEmitter_fromThis(ctx);
void *eventList, *dispatcher;
int count, i;
void **hptr;
void *eventList;
if (emitter != NULL)
{
eventList = ILibHashtable_Get(emitter->eventTable, NULL, eventName, (int)eventNameLen);
if (eventList == NULL) { return(ILibDuktape_Error(ctx, "EventEmitter.removeAllListeners(): Event '%s' not found", eventName)); }
dispatcher = ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, (int)eventNameLen);
if (dispatcher == NULL) { return(ILibDuktape_Error(ctx, "EventEmitter.removeAllListeners(): Internal error with Event '%s'", eventName)); }
// NULL was passed, we'll need to clear all listeners.
// Start by setting the Native Dispatcher to NULL, so it appears there are no subscribers
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = NULL;
duk_pop(ctx); // [dispatcher][hptrList]
}
ILibLinkedList_Clear(eventList);
emitter->totalListeners[0] = 0;
}
return(0);
}
void ILibDuktape_EventEmitter_EmbeddedFinalizer2(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
if (Key1 == NULL)
{
char *name = (char*)ILibMemory_AllocateA(Key2Len + 1);
name[Key2Len] = 0;
memcpy_s(name, Key2Len + 1, Key2, Key2Len);
printf("%s ", name);
}
}
duk_ret_t ILibDuktape_EventEmitter_EmbeddedFinalizer(duk_context *ctx)
{
ILibDuktape_EventEmitter_SetupEmit(ctx, duk_get_heapptr(ctx, 0), "~"); // [emit][this][~]
duk_dup(ctx, 0); // [emit][this][~][self]
if (g_displayFinalizerMessages)
{
printf("+-+- Finalizer Event for: %s [%p] -+-+\n", Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "UNKNOWN"), duk_get_heapptr(ctx, -1));
if (strcmp(Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "UNKNOWN"), "UNKNOWN") == 0)
{
ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_GetEmitter(ctx, -1);
if (emitter != NULL)
{
printf("UNKNOWN: Listeners=%d\n", ILibDuktape_EventEmitter_HasListeners(emitter, "~"));
duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY); // [enumerator]
while (duk_next(ctx, -1, 1))
{
printf("Key: %s, Val: %s\n", duk_get_string(ctx, -2), duk_get_string(ctx, -1));// [enumerator][key][val]
duk_pop_2(ctx); // [enumerator]
}
duk_pop(ctx); // ...
printf("Event Names: ");
if (emitter->eventTable != NULL) { ILibHashtable_Enumerate(emitter->eventTable, ILibDuktape_EventEmitter_EmbeddedFinalizer2, NULL); }
printf("\n");
}
}
}
if (duk_pcall_method(ctx, 2) != 0)
{
ILibDuktape_Process_UncaughtExceptionEx(ctx, "Error in Finalizer: [Invalid C function means you forgot to return 0] ");
}
ILibDuktape_EventEmitter *data = ILibDuktape_EventEmitter_GetEmitter(ctx, 0);
if (data == NULL) { return(ILibDuktape_Error(ctx, "Internal Error")); } // This is deadcode, will never occur, but is here because Klockwork thinks this could happen
// We need to clear the Native Dispatcher, while destroying the Hashtable
ILibHashtable_DestroyEx(data->eventTable, ILibDuktape_EventEmitter_FinalizerEx, data);
memset(data, 0, sizeof(ILibDuktape_EventEmitter));
return(0);
}
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
{
ILibDuktape_EventEmitter *retVal;
@@ -456,10 +473,8 @@ ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
retVal->tmpObject = duk_get_heapptr(ctx, -2);
duk_put_prop_string(ctx, -2, ILibDuktape_EventEmitter_Data); // [emitterTmp]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_EventEmitter_Finalizer);
duk_put_prop_string(ctx, -2, ILibDuktape_EventEmitter_TempObject); // [...parent...]
retVal->ctx = ctx;
retVal->object = duk_get_heapptr(ctx, -1);
retVal->eventTable = ILibHashtable_Create();
@@ -489,6 +504,10 @@ ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
}
duk_pop(ctx);
ILibDuktape_EventEmitter_CreateEventEx(retVal, "~");
duk_push_c_function(ctx, ILibDuktape_EventEmitter_EmbeddedFinalizer, 1);
duk_set_finalizer(ctx, -2);
return retVal;
}
@@ -505,15 +524,10 @@ duk_ret_t ILibDuktape_EventEmitter_SetEvent(duk_context *ctx)
duk_size_t propNameLen;
ILibDuktape_EventEmitter *data;
ILibLinkedList eventList = NULL;
void **hptr;
void *dispatcher;
int i, count;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "name"); // [func][name]
duk_get_prop_string(ctx, -1, "eventName"); // [func][name]
propName = (char*)duk_get_lstring(ctx, -1, &propNameLen);
duk_get_prop_string(ctx, -2, ILibDuktape_EventEmitter_DispatcherFunc); // [func][name][dispatcher]
dispatcher = duk_get_heapptr(ctx, -1);
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject); // [this][tmp]
@@ -526,142 +540,20 @@ duk_ret_t ILibDuktape_EventEmitter_SetEvent(duk_context *ctx)
if (duk_is_null_or_undefined(ctx, 0))
{
// NULL was passed, we'll need to clear all listeners.
// Start by setting the Native Dispatcher to NULL, so it appears there are no subscribers
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = NULL;
duk_pop(ctx); // [dispatcher][hptrList]
}
ILibLinkedList_Clear(eventList);
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, "removeAllListeners"); // [obj][removeAll]
duk_swap_top(ctx, -2); // [removeAll][this]
duk_push_string(ctx, propName); // [removeAll][this][name]
duk_call_method(ctx, 1); duk_pop(ctx);
}
else
{
void *callback = duk_require_heapptr(ctx, 0);
ILibDuktape_EventEmitter_HookHandler hookHandler = ILibHashtable_Get(data->eventTable, ILibDuktape_EventEmitter_Hook, propName, (int)propNameLen);
ILibLinkedList_AddTail(eventList, callback);
duk_push_heapptr(ctx, data->tmpObject);
duk_push_heapptr(ctx, callback);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(callback)); // Save callback to tmpObject so it won't get GC'ed
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = dispatcher; // Set this, so from Native, it looks like there is a subscriber.
duk_pop(ctx); // [dispatcher][hptrList]
}
if (hookHandler != NULL)
{
hookHandler(data, propName, callback);
}
ILibDuktape_EventEmitter_AddOn(data, propName, duk_get_heapptr(ctx, 0));
}
return 0;
}
duk_ret_t ILibDuktape_EventEmitter_Dispatcher(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
void *self;
int i;
char *name;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "name"); // [func][name]
name = (char*)duk_get_string(ctx, -1);
duk_get_prop_string(ctx, -2, "this"); // [func][name][this]
self = duk_get_heapptr(ctx, -1);
duk_get_prop_string(ctx, -1, "emit"); // [func][name][this][emitter]
//-------------------------------------------------------------------------------------------------
duk_push_heapptr(ctx, self); // [emitter][this]
duk_push_string(ctx, name); // [emitter][this][name]
for (i = 0; i < nargs; ++i)
{
duk_dup(ctx, i); // [emitter][this][name][...args...]
}
duk_call_method(ctx, nargs + 1); // Exception will bubble up.
return 0;
}
duk_ret_t ILibDuktape_EventEmitter_NativeDispatch(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *name;
ILibDuktape_EventEmitter_Handler handler;
void *args;
int i = 0;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "name"); // [func][name]
name = (char*)duk_get_string(ctx, -1);
duk_get_prop_string(ctx, -2, "handler"); // [func][name][handler]
handler = (ILibDuktape_EventEmitter_Handler)duk_get_pointer(ctx, -1);
duk_push_array(ctx); // [func][name][handler][args]
args = duk_get_heapptr(ctx, -1);
for (i = 0; i < nargs; ++i)
{
duk_dup(ctx, i); // [func][name][handler][args][...arg...]
duk_put_prop_index(ctx, -2, i); // [func][name][handler][args]
}
duk_push_this(ctx);
handler(ctx, duk_get_heapptr(ctx, -1), name, args);
return 0;
}
int ILibDuktape_EventEmitter_AddSink(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_Handler handler)
{
ILibLinkedList eventList;
void *func;
duk_push_heapptr(emitter->ctx, emitter->tmpObject); // [tmp]
duk_push_c_function(emitter->ctx, ILibDuktape_EventEmitter_NativeDispatch, DUK_VARARGS); // [tmp][dispatch]
duk_push_string(emitter->ctx, eventName); // [tmp][dispatch][name]
duk_put_prop_string(emitter->ctx, -2, "name"); // [tmp][dispatch]
duk_push_pointer(emitter->ctx, handler); // [tmp][dispatch][nativePtr]
duk_put_prop_string(emitter->ctx, -2, "handler"); // [tmp][dispatch]
func = duk_get_heapptr(emitter->ctx, -1);
eventList = ILibHashtable_Get(emitter->eventTable, NULL, eventName, (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen));
if (eventList == NULL) { return 1; }
((int*)ILibLinkedList_GetExtendedMemory(ILibLinkedList_AddTail(eventList, func)))[0] = 2;
emitter->totalListeners[0]++;
duk_put_prop_string(emitter->ctx, -2, Duktape_GetStashKey(func)); // [tmp]
duk_pop(emitter->ctx); // ...
return 0;
}
void ILibDuktape_EventEmitter_RemoveAllEx(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
ILibDuktape_EventEmitter *data = (ILibDuktape_EventEmitter*)user;
if (Key1 == ILibDuktape_EventEmitter_SetterFunc)
{
// If this is not NULL, this is the JavaScript Setter Func
memcpy_s(ILibScratchPad, sizeof(ILibScratchPad), Key2, Key2Len);
ILibScratchPad[Key2Len] = 0;
duk_push_heapptr(data->ctx, Data); // [Setter]
duk_del_prop_string(data->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST);
duk_push_array(data->ctx); // [Setter][list]
duk_put_prop_string(data->ctx, -2, ILibDuktape_EventEmitter_HPTR_LIST); // [Setter]
duk_pop(data->ctx); // ...
}
}
void ILibDuktape_EventEmitter_RemoveAllListeners(ILibDuktape_EventEmitter *emitter, char *eventName)
{
duk_push_heapptr(emitter->ctx, emitter->object); // [this]
@@ -671,125 +563,45 @@ void ILibDuktape_EventEmitter_RemoveAllListeners(ILibDuktape_EventEmitter *emitt
if (duk_pcall_method(emitter->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(emitter->ctx, "EventEmitter.removeAllListeners(): "); }
duk_pop(emitter->ctx); // ...
}
void ILibDuktape_EventEmitter_RemoveAll(ILibDuktape_EventEmitter *emitter)
void ILibDuktape_EventEmitter_GetEventCountSink(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
if (emitter->eventTable != NULL) { ILibHashtable_Enumerate(emitter->eventTable, ILibDuktape_EventEmitter_RemoveAllEx, emitter); }
}
void ILibDuktape_EventEmitter_RemoveEventHeapptr(ILibDuktape_EventEmitter *emitter, char *eventName, void **heapptr)
{
int i, count;
void *dispatcher = NULL;
int eventNameLen = (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen);
if ((dispatcher = ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, eventNameLen)) != NULL)
int *count = (int*)user;
if (Key1 == NULL)
{
// This event already exists... Let's hook up the hptr to the existing dispatcher
duk_push_heapptr(emitter->ctx, dispatcher); // [dispatcher]
if (heapptr != NULL)
{
duk_get_prop_string(emitter->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(emitter->ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(emitter->ctx, -1, i); // [dispatcher][hptrList][hptr]
if (duk_get_pointer(emitter->ctx, -1) == heapptr)
{
duk_pop(emitter->ctx); // [dispatcher][hptrList]
duk_del_prop_index(emitter->ctx, -1, i);
break;
}
duk_pop(emitter->ctx); // [dispatcher][hptrList]
}
duk_pop(emitter->ctx); // [dispatcher]
}
else
{
duk_del_prop_string(emitter->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher]
duk_push_array(emitter->ctx); // [dispatcher][hptrList]
duk_put_prop_string(emitter->ctx, -2, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher]
}
duk_pop(emitter->ctx); // ...
++(*count);
}
}
int ILibDuktape_EventEmitter_AddEventHeapptr(ILibDuktape_EventEmitter *emitter, char *eventName, void **heapptr)
int ILibDuktape_EventEmitter_GetEventCount(ILibDuktape_EventEmitter *emitter)
{
ILibLinkedList eventList = NULL;
void *dispatcher = NULL;
int eventNameLen = (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen);
if ((dispatcher = ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, eventNameLen)) != NULL)
{
// This event already exists... Let's hook up the hptr to the existing dispatcher
duk_push_heapptr(emitter->ctx, dispatcher); // [dispatcher]
duk_get_prop_string(emitter->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
duk_push_pointer(emitter->ctx, heapptr); // [dispatcher][hptrList][hptr]
duk_put_prop_index(emitter->ctx, -2, (duk_uarridx_t)duk_get_length(emitter->ctx, -2)); // [dispatcher][hptrList]
duk_pop_2(emitter->ctx); // ...
int retVal = 0;
if (emitter->eventTable != NULL) { ILibHashtable_Enumerate(emitter->eventTable, ILibDuktape_EventEmitter_GetEventCountSink, &retVal); }
return(retVal);
}
// Now lets check if there was already a subscriber
if ((eventList = ILibHashtable_Get(emitter->eventTable, NULL, eventName, eventNameLen)) != NULL && ILibLinkedList_GetCount(eventList) > 0)
{
*heapptr = dispatcher;
}
return 0;
}
return 1;
}
void ILibDuktape_EventEmitter_CreateEventEx(ILibDuktape_EventEmitter *emitter, char *eventName)
{
void **heapptr;
duk_push_heapptr(emitter->ctx, emitter->tmpObject); // [emitter]
duk_push_object(emitter->ctx); // [emitter][tmp]
duk_push_fixed_buffer(emitter->ctx, sizeof(void*)); // [emitter][tmp][buffer]
heapptr = (void**)Duktape_GetBuffer(emitter->ctx, -1, NULL);
memset((void*)heapptr, 0, sizeof(void*));
duk_put_prop_string(emitter->ctx, -2, "\xFF_buffer"); // [emitter][tmp]
duk_put_prop_string(emitter->ctx, -2, Duktape_GetStashKey(duk_get_heapptr(emitter->ctx, -1))); // [emitter]
duk_pop(emitter->ctx); // ...
ILibDuktape_EventEmitter_CreateEvent(emitter, eventName, heapptr);
}
void ILibDuktape_EventEmitter_CreateEvent(ILibDuktape_EventEmitter *emitter, char *eventName, void **hptr)
{
void *dispatcher = NULL;
int eventNameLen = (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen);
if ((dispatcher = ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, eventNameLen)) != NULL)
if (ILibHashtable_Get(emitter->eventTable, NULL, eventName, eventNameLen) != NULL)
{
// This event already exists... Let's hook up the hptr to the existing dispatcher
duk_push_heapptr(emitter->ctx, dispatcher); // [dispatcher]
duk_get_prop_string(emitter->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
duk_push_pointer(emitter->ctx, hptr); // [dispatcher][hptrList][hptr]
duk_put_prop_index(emitter->ctx, -2, (duk_uarridx_t)duk_get_length(emitter->ctx, -2)); // [dispatcher][hptrList]
duk_pop_2(emitter->ctx); // ...
// This event already exists...
return;
}
duk_push_heapptr(emitter->ctx, emitter->object); // [obj]
// Create the Property Setter
duk_push_string(emitter->ctx, eventName); // [obj][prop]
duk_push_c_function(emitter->ctx, ILibDuktape_EventEmitter_SetEvent, 1); // [obj][prop][setFunc]
duk_push_string(emitter->ctx, eventName); // [obj][prop][setFunc][name]
duk_put_prop_string(emitter->ctx, -2, "name"); // [obj][prop][setFunc]
// Set some custom properties into the setter func, so we can access it later
duk_push_c_function(emitter->ctx, ILibDuktape_EventEmitter_Dispatcher, DUK_VARARGS); // [obj][prop][setFunc][dispatcher]
dispatcher = duk_get_heapptr(emitter->ctx, -1);
duk_push_heapptr(emitter->ctx, emitter->object); // [obj][prop][setFunc][dispatcher][this]
duk_put_prop_string(emitter->ctx, -2, "this"); // [obj][prop][setFunc][dispatcher]
duk_push_string(emitter->ctx, eventName); // [obj][prop][setFunc][dispatcher][name]
duk_put_prop_string(emitter->ctx, -2, "name"); // [obj][prop][setFunc][dispatcher]
duk_push_array(emitter->ctx); // [obj][prop][setFunc][dispatcher][hptrList]
duk_push_pointer(emitter->ctx, hptr); // [obj][prop][setFunc][dispatcher][hptrList][hptr]
duk_put_prop_index(emitter->ctx, -2, 0); // [obj][prop][setFunc][dispatcher][hptrList]
duk_put_prop_string(emitter->ctx, -2, ILibDuktape_EventEmitter_HPTR_LIST); // [obj][prop][setFunc][dispatcher]
duk_put_prop_string(emitter->ctx, -2, ILibDuktape_EventEmitter_DispatcherFunc); // [obj][prop][setFunc]
duk_put_prop_string(emitter->ctx, -2, "eventName"); // [obj][prop][setFunc]
duk_def_prop(emitter->ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_SETTER); // [obj]
duk_pop(emitter->ctx); // ...
ILibHashtable_Put(emitter->eventTable, NULL, eventName, eventNameLen, ILibLinkedList_CreateEx(sizeof(int)));
ILibHashtable_Put(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, eventNameLen, dispatcher);
}
void *ILibDuktape_EventEmitter_GetDispatcher(ILibDuktape_EventEmitter *emitter, char *eventName)
{
return ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen));
@@ -798,16 +610,13 @@ duk_ret_t ILibDuktape_EventEmitter_Inherits_createEvent(duk_context *ctx)
{
char *name = (char*)duk_require_string(ctx, 0);
ILibDuktape_EventEmitter *emitter;
void **hptr;
duk_push_this(ctx); // [emitterUtils]
duk_get_prop_string(ctx, -1, "emitter"); // [emitterUtils][ptr]
emitter = (ILibDuktape_EventEmitter*)duk_get_pointer(ctx, -1);
duk_pop(ctx); // [emitterUtils]
duk_push_fixed_buffer(ctx, sizeof(void*)); // [emitterUtils][buffer]
hptr = (void**)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, name); // [emitterUtils]
ILibDuktape_EventEmitter_CreateEvent(emitter, name, hptr);
ILibDuktape_EventEmitter_CreateEventEx(emitter, name);
return 0;
}
duk_ret_t ILibDuktape_EventEmitter_Inherits_addMethod(duk_context *ctx)
@@ -878,8 +687,22 @@ duk_ret_t ILibDuktape_EventEmitter_ForwardEvent_Sink(duk_context *ctx)
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);
}
duk_ret_t ILibDuktape_EventEmitter_ForwardEvent_Finalizer(duk_context *ctx)
{
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "fptr"); // [func][fptr]
duk_get_prop_string(ctx, -1, "targetObject"); // [func][fptr][target]
duk_del_prop_string(ctx, -2, "targetObject");
if (g_displayFinalizerMessages) { printf("EventEmitter.Forwarder[%s]: Deleted reference to [%s] RC=%d\n", Duktape_GetStringPropertyValue(ctx, -3, "targetName", "UNKNOWN"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "UNKNOWN"), ILibDuktape_GetReferenceCount(ctx, -1) - 1); }
duk_pop_n(ctx, 3);
if (g_displayFinalizerMessages) { duk_eval_string(ctx, "_debugGC();"); duk_pop(ctx); }
return(0);
}
void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSourceIndex, char *sourceEventName, duk_idx_t eventTargetIndex, char *targetEventName)
{
void *fptr;
void *target;
duk_dup(ctx, eventTargetIndex); // [targetObject]
target = duk_get_heapptr(ctx, -1);
@@ -889,12 +712,26 @@ void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSour
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]
fptr = duk_get_heapptr(ctx, -1);
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); // ...
duk_dup(ctx, eventSourceIndex); // [sourceObject]
duk_get_prop_string(ctx, -1, "prependOnceListener"); // [sourceObject][prependOnce]
duk_swap_top(ctx, -2); // [prependOnce][this]
duk_push_string(ctx, "~"); // [prependOnce][this]['~']
duk_push_c_function(ctx, ILibDuktape_EventEmitter_ForwardEvent_Finalizer, DUK_VARARGS); // [prependOnce][this]['~'][func]
duk_push_heapptr(ctx, fptr); // [prependOnce][this]['~'][func][fptr]
duk_put_prop_string(ctx, -2, "fptr"); // [prependOnce][this]['~'][func]
duk_push_string(ctx, targetEventName); // [prependOnce][this]['~'][func][name]
duk_put_prop_string(ctx, -2, "targetName"); // [prependOnce][this]['~'][func]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "EventEmitter_ForwardEvent_SetFinalizer(): "); }
duk_pop(ctx); // ...
}
int ILibDuktape_EventEmitter_AddOnEx(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func)
{