1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-06 00:13:33 +00:00
Files
MeshAgent/microscript/ILibDuktape_Helpers.c
Bryan Roe 9682464cb6 1. fixed #def issue
2. Added Virtual Machine  detection
2020-04-24 16:06:59 -07:00

1179 lines
42 KiB
C

/*
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.
*/
#ifdef WIN32
#include <WinSock2.h>
#include <WS2tcpip.h>
#endif
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
#include "duktape.h"
#include "microstack/ILibParsers.h"
#include "ILibDuktape_Helpers.h"
#include "microstack/ILibCrypto.h"
#include "ILibDuktape_EventEmitter.h"
char stash_key[32];
struct sockaddr_in6 duktape_internalAddress;
#define ILibDuktape_EventEmitter_Table "\xFF_EventEmitterTable"
#define ILibDuktape_Process_ExitCode "\xFF_ExitCode"
#define ILibDuktape_Memory_AllocTable "\xFF_MemoryAllocTable"
#define ILibDuktape_ObjectStashKey "\xFF_ObjectStashKey"
#define ILibDuktape_UncaughtException_NativeHandler "\xFF_UncaughtNativeHandler"
#define ILibDuktape_UncaughtException_NativeUser "\xFF_UncaughtNativeUser"
typedef struct Duktape_EventLoopDispatchData
{
duk_context *ctx;
uintptr_t nonce;
Duktape_EventLoopDispatch handler;
Duktape_EventLoopDispatch abortHandler;
ILibDuktape_ContextData *ctxd;
void *chain;
void *user;
}Duktape_EventLoopDispatchData;
void Duktape_RunOnEventLoop_AbortSink(void *chain, void *user)
{
Duktape_EventLoopDispatchData *tmp = (Duktape_EventLoopDispatchData*)user;
if (tmp->abortHandler == (Duktape_EventLoopDispatch)(uintptr_t)0x01)
{
if (tmp->user != NULL) { free(tmp->user); }
}
else if(tmp->abortHandler != NULL)
{
tmp->abortHandler(chain, tmp->user);
}
ILibMemory_Free(tmp);
}
void Duktape_RunOnEventLoop_Sink(void *chain, void *user)
{
Duktape_EventLoopDispatchData *tmp = (Duktape_EventLoopDispatchData*)user;
if (duk_ctx_is_alive(tmp->ctx) && duk_ctx_is_valid(tmp->nonce, tmp->ctx))
{
// duk_context matches the intended context
if (tmp->handler != NULL) { tmp->handler(chain, tmp->user); }
}
else
{
// duk_context does not match the intended context
Duktape_RunOnEventLoop_AbortSink(chain, user);
return;
}
ILibMemory_Free(tmp);
}
#ifdef WIN32
void __stdcall Duktape_RunOnEventLoop_SanityCheck(ULONG_PTR u)
{
if (!ILibMemory_CanaryOK((void*)u)) { return; }
Duktape_EventLoopDispatchData* d = (Duktape_EventLoopDispatchData*)((void**)u)[2];
if (ILibMemory_CanaryOK(d) && ILibMemory_CanaryOK(d->ctxd))
{
if ((d->ctxd->flags & duk_destroy_heap_in_progress) == duk_destroy_heap_in_progress)
{
if (d->abortHandler != NULL) { d->abortHandler(d->chain, d->user); }
}
}
}
#endif
void Duktape_RunOnEventLoop(void *chain, uintptr_t nonce, duk_context *ctx, Duktape_EventLoopDispatch handler, Duktape_EventLoopDispatch abortHandler, void *user)
{
Duktape_EventLoopDispatchData* tmp = (Duktape_EventLoopDispatchData*)ILibMemory_SmartAllocate(sizeof(Duktape_EventLoopDispatchData));
tmp->ctx = ctx;
tmp->nonce = nonce;
tmp->handler = handler;
tmp->abortHandler = abortHandler;
tmp->user = user;
tmp->ctxd = duk_ctx_context_data(ctx);
tmp->chain = chain;
#ifdef WIN32
void *tobj = ILibChain_RunOnMicrostackThreadEx3(chain, Duktape_RunOnEventLoop_Sink, Duktape_RunOnEventLoop_AbortSink, tmp);
QueueUserAPC((PAPCFUNC)Duktape_RunOnEventLoop_SanityCheck, ILibChain_GetMicrostackThreadHandle(chain), (ULONG_PTR)tobj);
#else
ILibChain_RunOnMicrostackThreadEx3(chain, Duktape_RunOnEventLoop_Sink, Duktape_RunOnEventLoop_AbortSink, tmp);
#endif
}
int ILibDuktape_GetReferenceCount(duk_context *ctx, duk_idx_t i)
{
int retVal = -1;
duk_inspect_value(ctx, i);
retVal = Duktape_GetIntPropertyValue(ctx, -1, "refc", -1);
duk_pop(ctx);
return(retVal-1);
}
void ILibDuktape_Push_ObjectStash(duk_context *ctx)
{
if (duk_has_prop_string(ctx, -1, ILibDuktape_ObjectStashKey))
{
duk_get_prop_string(ctx, -1, ILibDuktape_ObjectStashKey); // [obj][stash]
}
else
{
duk_push_object(ctx); // [obj][stash]
duk_dup(ctx, -1); // [obj][stash][stash]
duk_put_prop_string(ctx, -3, ILibDuktape_ObjectStashKey); // [obj][stash]
}
}
#ifdef _POSIX
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-value"
#endif
duk_ret_t ILibDuktape_Error(duk_context *ctx, char *format, ...)
{
char dest[4096];
int len = 0;
va_list argptr;
va_start(argptr, format);
len += vsnprintf(dest + len, sizeof(dest) - len, format, argptr);
va_end(argptr);
duk_push_string(ctx, dest);
duk_throw(ctx);
return DUK_RET_ERROR;
}
#ifdef _POSIX
#pragma GCC diagnostic pop
#endif
int Duktape_GetBooleanProperty(duk_context *ctx, duk_idx_t i, char *propertyName, int defaultValue)
{
int retVal = defaultValue;
if (duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
retVal = (int)duk_get_boolean(ctx, -1);
duk_pop(ctx);
}
return retVal;
}
void *Duktape_GetHeapptrProperty(duk_context *ctx, duk_idx_t i, char* propertyName)
{
void *retVal = NULL;
if (duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
retVal = duk_get_heapptr(ctx, -1);
duk_pop(ctx);
}
return retVal;
}
void *Duktape_GetBufferPropertyEx(duk_context *ctx, duk_idx_t i, char* propertyName, duk_size_t* bufferLen)
{
void *retVal = NULL;
if (bufferLen != NULL) { *bufferLen = 0; }
if (duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName); // [prop]
retVal = (void*)Duktape_GetBuffer(ctx, -1, bufferLen);
duk_pop(ctx); // ...
}
return(retVal);
}
void *Duktape_Duplicate_GetBufferPropertyEx(duk_context *ctx, duk_idx_t i, char* propertyName, duk_size_t* bufferLen)
{
duk_size_t sourceLen = 0;
void *retVal = NULL, *source;
if (bufferLen != NULL) { *bufferLen = 0; }
source = Duktape_GetBufferPropertyEx(ctx, i, propertyName, &sourceLen);
if (sourceLen > 0)
{
retVal = ILibMemory_SmartAllocate(sourceLen);
memcpy_s(retVal, sourceLen, source, sourceLen);
if (bufferLen != NULL) { *bufferLen = sourceLen; }
}
return(retVal);
}
void *Duktape_GetPointerProperty(duk_context *ctx, duk_idx_t i, char* propertyName)
{
void *retVal = NULL;
if (duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
retVal = duk_to_pointer(ctx, -1);
duk_pop(ctx);
}
return retVal;
}
char* Duktape_GetStringPropertyValueEx(duk_context *ctx, duk_idx_t i, char* propertyName, char* defaultValue, duk_size_t *len)
{
char *retVal = defaultValue;
if (ctx != NULL && duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
retVal = (char*)duk_get_lstring(ctx, -1, len);
duk_pop(ctx);
}
else
{
if (len != NULL) { *len = (defaultValue == NULL) ? 0 : strnlen_s(defaultValue, sizeof(ILibScratchPad)); }
}
return retVal;
}
char* Duktape_Duplicate_GetStringPropertyValueEx(duk_context *ctx, duk_idx_t i, char* propertyName, char* defaultValue, duk_size_t *len)
{
char *ret = NULL;
if (len != NULL) { *len = 0; }
duk_size_t sourceLen = 0;
char *source = Duktape_GetStringPropertyValueEx(ctx, i, propertyName, defaultValue, &sourceLen);
if (sourceLen > 0)
{
if (len != NULL) { *len = sourceLen; }
ret = (char*)ILibMemory_SmartAllocate(sourceLen + 1);
memcpy_s(ret, sourceLen, source, sourceLen);
}
return(ret);
}
char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *len)
{
char *ret = NULL;
duk_size_t srcLen = 0;
char* src = (char*)duk_get_lstring(ctx, i, &srcLen);
if (len != NULL) { *len = srcLen; }
if (srcLen > 0)
{
ret = ILibMemory_SmartAllocate(srcLen);
memcpy_s(ret, srcLen, src, srcLen);
}
return(ret);
}
int Duktape_GetIntPropertyValue(duk_context *ctx, duk_idx_t i, char* propertyName, int defaultValue)
{
int retVal = defaultValue;
if (ctx!=NULL && duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
if (!duk_is_null_or_undefined(ctx, -1))
{
retVal = duk_to_int(ctx, -1);
}
duk_pop(ctx);
}
return retVal;
}
void Duktape_CreateEnum(duk_context *ctx, char* enumName, char **fieldNames, int *fieldValues, int numFields)
{
duk_push_global_object(ctx);
Duktape_CreateEnumEx(ctx, fieldNames, fieldValues, numFields);
duk_put_prop_string(ctx, -2, enumName);
duk_pop(ctx);
}
void Duktape_CreateEnumEx(duk_context *ctx, char** fieldNames, int * fieldValues, int numFields)
{
int i;
duk_push_object(ctx); // [obj]
for (i = 0; i < numFields; ++i)
{
duk_push_int(ctx, fieldValues[i]); // [obj][val]
duk_put_prop_string(ctx, -2, fieldNames[i]); // [obj]
}
}
char *Duktape_GetStashKey(void* value)
{
sprintf_s(stash_key, sizeof(stash_key), "%p", value);
return((char*)stash_key);
}
char* Duktape_GetBuffer(duk_context *ctx, duk_idx_t i, duk_size_t *bufLen)
{
char *retVal = NULL;
duk_size_t len = 0;
if (bufLen != NULL) { *bufLen = 0; }
if (duk_is_string(ctx, i))
{
retVal = (char*)duk_get_lstring(ctx, i, bufLen);
}
else if (duk_is_buffer(ctx, i))
{
retVal = (char*)duk_require_buffer(ctx, i, &len);
if (ILibMemory_CanaryOK(ILibMemory_FromRaw(retVal)) && ILibMemory_RawSize(ILibMemory_FromRaw(retVal)) == len)
{
retVal = ILibMemory_FromRaw(retVal);
if (bufLen != NULL) { *bufLen = ILibMemory_Size(retVal); }
}
else if (bufLen != NULL)
{
*bufLen = len;
}
}
else if(duk_is_buffer_data(ctx, i))
{
retVal = (char*)duk_require_buffer_data(ctx, i, &len);
if (ILibMemory_CanaryOK(ILibMemory_FromRaw(retVal)) && ILibMemory_RawSize(ILibMemory_FromRaw(retVal)) == len)
{
retVal = ILibMemory_FromRaw(retVal);
if (bufLen != NULL) { *bufLen = ILibMemory_Size(retVal); }
}
else if (bufLen != NULL)
{
*bufLen = len;
}
}
else if (duk_is_object(ctx, i))
{
duk_json_encode(ctx, i);
retVal = (char*)duk_get_lstring(ctx, i, bufLen);
}
else if (duk_is_null_or_undefined(ctx, i))
{
retVal = NULL;
}
else
{
ILibDuktape_Error(ctx, "Duktape_GetBuffer(): Unknown parameter");
}
return retVal;
}
struct sockaddr_in6* Duktape_IPAddress4_FromString(char* address, unsigned short port)
{
memset(&duktape_internalAddress, 0, sizeof(struct sockaddr_in6));
duktape_internalAddress.sin6_family = AF_INET;
duktape_internalAddress.sin6_port = htons(port);
ILibInet_pton(AF_INET, address, &(((struct sockaddr_in*)&duktape_internalAddress)->sin_addr));
return(&duktape_internalAddress);
}
struct sockaddr_in6* Duktape_IPAddress6_FromString(char* address, unsigned short port)
{
memset(&duktape_internalAddress, 0, sizeof(struct sockaddr_in6));
duktape_internalAddress.sin6_family = AF_INET6;
duktape_internalAddress.sin6_port = htons(port);
ILibInet_pton(AF_INET6, address, &(duktape_internalAddress.sin6_addr));
return(&duktape_internalAddress);
}
void ILibDuktape_IPV4AddressToOptions(duk_context *ctx, int addr)
{
struct sockaddr_in6 in6;
memset(&in6, 0, sizeof(struct sockaddr_in6));
in6.sin6_family = AF_INET;
((struct sockaddr_in*)&in6)->sin_addr.s_addr = addr;
ILibDuktape_SockAddrToOptions(ctx, &in6);
}
void ILibDuktape_SockAddrToOptions(duk_context *ctx, struct sockaddr_in6 *addr)
{
char *str = ILibInet_ntop2((struct sockaddr*)addr, ILibScratchPad, sizeof(ILibScratchPad));
unsigned short port = ntohs(addr->sin6_port);
duk_push_object(ctx); // [options]
duk_push_string(ctx, str); // [options][host]
duk_put_prop_string(ctx, -2, "host"); // [options]
duk_push_int(ctx, (int)port); // [options][port]
duk_put_prop_string(ctx, -2, "port"); // [options]
}
duk_ret_t ILibDuktape_CreateEventWithSetter_SetterSink(duk_context *ctx)
{
void **ptr;
char *name;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "_ptr"); // [func][ptr]
ptr = (void**)duk_to_pointer(ctx, -1); // [func][ptr]
duk_get_prop_string(ctx, -2, "_pname"); // [func][ptr][pname]
name = (char*)duk_to_string(ctx, -1); // [func][ptr][pname]
duk_push_this(ctx); // [obj]
duk_dup(ctx, 0); // [obj][handler]
duk_put_prop_string(ctx, -2, name); // [obj]
*ptr = !duk_is_null_or_undefined(ctx, 0) ? duk_require_heapptr(ctx, 0) : NULL;
return 0;
}
duk_ret_t ILibDuktape_CreateEventWithGetterExSink(duk_context *ctx)
{
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "\xFF_return");
return 1;
}
void ILibDuktape_CreateEventWithGetterEx(duk_context *ctx, char *propName, void *heapptr)
{
duk_push_string(ctx, propName); // [obj][prop]
duk_push_c_function(ctx, ILibDuktape_CreateEventWithGetterExSink, 1); // [obj][prop][func] // [obj][prop][getFunc]
duk_push_heapptr(ctx, heapptr); // [obj][prop][func][ptr]
duk_put_prop_string(ctx, -2, "\xFF_return"); // [obj][prop][func]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetter(duk_context *ctx, char *propName, duk_c_function getterMethod)
{
duk_push_string(ctx, propName); // [obj][prop]
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)
{
duk_push_string(ctx, propName); // [obj][prop]
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][getFunc]
duk_push_c_function(ctx, setterMethod, 1); // [obj][prop][getFunc][setFunc]
duk_def_prop(ctx, -4, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetterAndSetterWithMetaData(duk_context *ctx, char* metaDataPropName, duk_idx_t metaDataPropIndex, char *propName, duk_c_function getterMethod, duk_c_function setterMethod)
{
duk_dup(ctx, metaDataPropIndex); // [obj][metaData]
if (metaDataPropIndex < 0)
{
duk_remove(ctx, metaDataPropIndex - 1);
}
duk_push_string(ctx, propName); // [obj][metaData][prop]
duk_swap_top(ctx, -2); // [obj][prop][metaData]
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][metaData][getFunc]
duk_swap_top(ctx, -2); // [obj][prop][getFunc][metaData]
duk_dup(ctx, -1); // [obj][prop][getFunc][metaData][metaData]
duk_put_prop_string(ctx, -3, metaDataPropName); // [obj][prop][getFunc][metaData]
duk_push_c_function(ctx, setterMethod, 1); // [obj][prop][getFunc][metaData][setFunc]
duk_swap_top(ctx, -2); // [obj][prop][getFunc][setFunc][metaData]
duk_put_prop_string(ctx, -2, metaDataPropName); // [obj][prop][getFunc][setFunc]
duk_def_prop(ctx, -4, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetterAndSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr, duk_c_function getterMethod)
{
duk_push_string(ctx, propName); // [obj][prop]
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][getFunc]
duk_push_c_function(ctx, ILibDuktape_CreateEventWithSetter_SetterSink, 1); // [obj][prop][getFunc][setFunc]
duk_push_pointer(ctx, hptr); // [obj][prop][getFunc][setFunc][ptr]
duk_put_prop_string(ctx, -2, "_ptr"); // [obj][prop][getFunc][setFunc]
duk_push_string(ctx, propNamePtr); // [obj][prop][getFunc][setFunc][name]
duk_put_prop_string(ctx, -2, "_pname"); // [obj][prop][getFunc][setFunc]
duk_def_prop(ctx, -4, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
void ILibDuktape_CreateEventWithSetterEx(duk_context *ctx, char *propName, duk_c_function setterMethod)
{
duk_push_string(ctx, propName); // [obj][prop]
duk_push_c_function(ctx, setterMethod, 1); // [obj][prop][setFunc]
duk_push_string(ctx, propName); // [obj][prop][setFunc][name]
duk_put_prop_string(ctx, -2, "propName"); // [obj][prop][setFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
void ILibDuktape_CreateEventWithSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr)
{
duk_push_string(ctx, propName); // [obj][setter]
duk_push_c_function(ctx, ILibDuktape_CreateEventWithSetter_SetterSink, 1); // [obj][setter][func]
duk_push_pointer(ctx, hptr); // [obj][setter][func][ptr]
duk_put_prop_string(ctx, -2, "_ptr"); // [obj][setter][func]
duk_push_string(ctx, propNamePtr); // [obj][setter][func][name]
duk_put_prop_string(ctx, -2, "_pname"); // [obj][setter][func]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
duk_ret_t ILibDuktape_Helper_AddHeapFinalizerSink(duk_context *ctx)
{
ILibDuktape_HelperEvent handler;
void *user;
duk_dup(ctx, 0); // [obj]
duk_get_prop_string(ctx, -1, "handler"); // [obj][handler]
handler = (ILibDuktape_HelperEvent)duk_get_pointer(ctx, -1);
duk_get_prop_string(ctx, -2, "user"); // [obj][handler][user]
user = duk_get_pointer(ctx, -1);
if (handler != NULL) { handler(ctx, user); }
return 0;
}
void ILibDuktape_Helper_AddHeapFinalizer(duk_context *ctx, ILibDuktape_HelperEvent handler, void *user)
{
char *key = Duktape_GetStashKey(user != NULL ? user : (void*)handler);
duk_push_heap_stash(ctx); // [g]
duk_push_object(ctx); // [g][obj]
ILibDuktape_WriteID(ctx, "Mesh.ScriptContainer.heapFinalizer");
duk_push_pointer(ctx, user); // [g][obj][user]
duk_put_prop_string(ctx, -2, "user"); // [g][obj]
duk_push_pointer(ctx, handler); // [g][obj][handler]
duk_put_prop_string(ctx, -2, "handler");// [g][obj]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Helper_AddHeapFinalizerSink);
duk_put_prop_string(ctx, -2, key); // [g]
duk_pop(ctx); // ...
}
int ILibDuktape_Process_GetExitCode(duk_context *ctx)
{
int retVal = 0;
duk_push_global_object(ctx); // [g]
if (duk_has_prop_string(ctx, -1, "process"))
{
duk_get_prop_string(ctx, -1, "process"); // [g][process]
if (duk_has_prop_string(ctx, -1, ILibDuktape_Process_ExitCode))
{
duk_get_prop_string(ctx, -1, ILibDuktape_Process_ExitCode); // [g][process][code]
retVal = (int)duk_get_int(ctx, -1);
duk_pop(ctx); // [g][process]
}
duk_pop(ctx); // [g]
}
duk_pop(ctx); // ...
return(retVal);
}
void *ILibDuktape_GetProcessObject(duk_context *ctx)
{
void *retVal = NULL;
duk_push_global_object(ctx); // [g]
if (duk_has_prop_string(ctx, -1, "process"))
{
duk_get_prop_string(ctx, -1, "process"); // [g][process]
retVal = duk_get_heapptr(ctx, -1);
duk_pop(ctx); // [g]
}
duk_pop(ctx); // ...
return retVal;
}
duk_ret_t ILibDuktape_SetNativeUncaughtExceptionSink(duk_context *ctx)
{
duk_push_current_function(ctx);
ILibDuktape_NativeUncaughtExceptionHandler handler = (ILibDuktape_NativeUncaughtExceptionHandler)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_UncaughtException_NativeHandler);
void *user = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_UncaughtException_NativeUser);
if (handler != NULL)
{
handler(ctx, (char*)duk_safe_to_string(ctx, 0), user);
}
return(0);
}
void ILibDuktape_SetNativeUncaughtExceptionHandler(duk_context * ctx, ILibDuktape_NativeUncaughtExceptionHandler handler, void * user)
{
void *j = ILibDuktape_GetProcessObject(ctx);
if (j != NULL)
{
duk_push_heapptr(ctx, j); // [process]
duk_get_prop_string(ctx, -1, "on"); // [process][on]
duk_swap_top(ctx, -2); // [on][this]
duk_push_string(ctx, "uncaughtException"); // [on][this][exception]
duk_push_c_function(ctx, ILibDuktape_SetNativeUncaughtExceptionSink, DUK_VARARGS); // [on][this][exception][func]
duk_push_pointer(ctx, handler); // [on][this][exception][func][handler]
duk_put_prop_string(ctx, -2, ILibDuktape_UncaughtException_NativeHandler); // [on][this][exception][func]
duk_push_pointer(ctx, user);
duk_put_prop_string(ctx, -2, ILibDuktape_UncaughtException_NativeUser); // [on][this][exception][func]
duk_pcall_method(ctx, 2); duk_pop(ctx); // ...
// This is only used when we dump the core, so we can re-set these events
duk_push_heapptr(ctx, j); // [process]
duk_push_pointer(ctx, handler); // [process][handler]
duk_put_prop_string(ctx, -2, ILibDuktape_NativeUncaughtExceptionPtr); // [process]
duk_push_pointer(ctx, user); // [process][user]
duk_put_prop_string(ctx, -2, ILibDuktape_NativeUncaughtExceptionUserPtr); // [process]
duk_pop(ctx); // ...
}
}
duk_ret_t ILibDuktape_Process_UncaughtExceptionExGetter(duk_context *ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "\xFF_customMessage");
return 1;
}
void ILibDuktape_Process_UncaughtExceptionEx(duk_context *ctx, char *format, ...)
{
if (ctx == NULL) { return; }
char dest[4096];
int len = 0;
va_list argptr;
duk_size_t errmsgLen;
char *errmsg = (char*)duk_safe_to_lstring(ctx, -1, &errmsgLen);
void *j = ILibDuktape_GetProcessObject(ctx);
ILibDuktape_EventEmitter *emitter;
if (ILibString_IndexOf(errmsg, (int)errmsgLen, "Process.exit() forced script termination", 40) >= 0) { return; }
duk_push_heapptr(ctx, j); // [process]
emitter = ILibDuktape_EventEmitter_GetEmitter_fromCurrent(ctx);
duk_pop(ctx); // ...
va_start(argptr, format);
len += vsnprintf(dest + len, sizeof(dest) - len, format, argptr);
va_end(argptr);
if (errmsgLen + len < sizeof(dest))
{
len += sprintf_s(dest + len, sizeof(dest) - len, " => %s", errmsg);
}
if (emitter != NULL)
{
duk_push_heapptr(emitter->ctx, emitter->object); // [process]
duk_get_prop_string(emitter->ctx, -1, "emit"); // [process][emit]
duk_swap_top(emitter->ctx, -2); // [emit][this]
duk_push_string(emitter->ctx, "uncaughtException"); // [emit][this][eventName]
duk_push_error_object(emitter->ctx, DUK_ERR_ERROR, "%s", dest);
duk_pcall_method(emitter->ctx, 2);
duk_pop(emitter->ctx); // ...
}
}
// Error MUST be at top of stack when calling this method
void ILibDuktape_Process_UncaughtException(duk_context *ctx)
{
if (ctx != NULL) { ILibDuktape_Process_UncaughtExceptionEx(ctx, ""); }
}
char* Duktape_GetContextGuidHex(duk_context *ctx, void *db)
{
char *retVal = NULL;
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, "\xFF_ScriptContainerSettings_DB"))
{
duk_get_prop_string(ctx, -1, "\xFF_ScriptContainerSettings_DB"); // [stash][db]
if (duk_get_pointer(ctx, -1) != NULL && duk_get_pointer(ctx, -1) == db) { retVal = "0"; }
duk_pop(ctx); // [stash]
}
duk_pop(ctx); // ...
return retVal;
}
ILibDuktape_ContextData* ILibDuktape_GetContextData(duk_context *ctx)
{
duk_memory_functions mfuncs;
memset(&mfuncs, 0, sizeof(duk_memory_functions));
duk_get_memory_functions(ctx, &mfuncs);
return((ILibDuktape_ContextData*)mfuncs.udata);
}
void Duktape_SafeDestroyHeap(duk_context *ctx)
{
ILibDuktape_ContextData *ctxd = duk_ctx_context_data(ctx);
ctxd->flags |= duk_destroy_heap_in_progress;
duk_destroy_heap(ctx);
if (ILibLinkedList_GetCount(ctxd->threads) > 0)
{
#ifdef WIN32
HANDLE* threadList = (HANDLE*)ILibMemory_SmartAllocate(sizeof(HANDLE) * ILibLinkedList_GetCount(ctxd->threads));
int i = 0;
void *node;
while ((node = ILibLinkedList_GetNode_Head(ctxd->threads)) != NULL)
{
threadList[i++] = ILibLinkedList_GetDataFromNode(node);
ILibLinkedList_Remove(node);
}
while (WaitForMultipleObjectsEx(i, threadList, TRUE, 5000, TRUE) == WAIT_IO_COMPLETION);
ILibMemory_Free(threadList);
#else
int rv;
struct timespec ts;
void *node;
void *thr;
ILibThread_ms2ts(5000, &ts);
while ((node = ILibLinkedList_GetNode_Head(ctxd->threads)) != NULL)
{
thr = ILibLinkedList_GetDataFromNode(node);
if ((rv = ILibThread_TimedJoinEx(thr, &ts)) != 0)
{
break;
}
ILibLinkedList_Remove(node);
}
#endif
}
ILibLinkedList_Destroy(ctxd->threads);
ILibMemory_Free(ctxd);
}
void *Duktape_GetChain(duk_context *ctx)
{
void *ret = duk_ctx_chain(ctx);
return(ret);
}
duk_ret_t ILibDuktape_ExternalEventEmitter(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *name = (char*)duk_require_string(ctx, 0);
void **hptr;
int i;
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_Table); // [obj][table]
if (!duk_has_prop_string(ctx, -1, name))
{
return(ILibDuktape_Error(ctx, "ExternalEventEmitter(): Event '%s' not found", name));
}
duk_get_prop_string(ctx, -1, name); // [obj][table][ptr]
hptr = (void**)duk_get_pointer(ctx, -1);
if (*hptr != NULL)
{
duk_push_heapptr(ctx, *hptr); // [func]
duk_push_this(ctx); // [func][this]
for (i = 1; i < nargs; ++i)
{
duk_dup(ctx, i); // [func][this][...]
}
if (duk_pcall_method(ctx, nargs - 1) != 0) { ILibDuktape_Process_UncaughtException(ctx); }
duk_pop(ctx); // ...
}
return 0;
}
duk_ret_t ILibDuktape_IndependentFinalizer_Dispatch(duk_context *ctx)
{
ILibDuktape_IndependentFinalizerHandler handler;
duk_get_prop_string(ctx, 0, "ptr");
duk_get_prop_string(ctx, 0, "parent");
handler = (ILibDuktape_IndependentFinalizerHandler)duk_get_pointer(ctx, -2);
handler(ctx, duk_get_heapptr(ctx, -1));
return 0;
}
void ILibDuktape_CreateFinalizerEx(duk_context *ctx, duk_c_function func, int singleton)
{
ILibDuktape_EventEmitter *e = ILibDuktape_EventEmitter_Create(ctx);
if (singleton != 0) { ILibDuktape_EventEmitter_RemoveAllListeners(e, "~"); }
ILibDuktape_EventEmitter_PrependOnce(ctx, -1, "~", func);
}
duk_ret_t ILibDuktape_CreateProperty_InstanceMethod_Sink(duk_context *ctx)
{
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "actualFunc"); // [func][actualFunc]
return 1;
}
void ILibDuktape_CreateProperty_InstanceMethodEx(duk_context *ctx, char *methodName, void *funcHeapPtr)
{
duk_push_string(ctx, methodName); // [obj][prop]
duk_push_c_function(ctx, ILibDuktape_CreateProperty_InstanceMethod_Sink, 1); // [obj][prop][getFunc]
duk_push_heapptr(ctx, funcHeapPtr); // [obj][prop][getFunc][func]
duk_put_prop_string(ctx, -2, "actualFunc"); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void ILibDuktape_CreateProperty_InstanceMethod(duk_context *ctx, char *methodName, duk_c_function impl, duk_idx_t argCount)
{
duk_push_string(ctx, methodName); // [obj][prop]
duk_push_c_function(ctx, ILibDuktape_CreateProperty_InstanceMethod_Sink, 1); // [obj][prop][getFunc]
duk_push_c_function(ctx, impl, argCount); // [obj][prop][getFunc][func]
duk_put_prop_string(ctx, -2, "actualFunc"); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
duk_ret_t ILibDuktape_ReadonlyProperty_Get(duk_context *ctx)
{
duk_push_current_function(ctx); // [getFunc]
duk_get_prop_string(ctx, -1, "\xFF_PropValue"); // [getFunc][value]
return 1;
}
void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName)
{ // [obj][value]
duk_push_string(ctx, propName); // [obj][value][prop]
duk_swap_top(ctx, -2); // [obj][prop][value]
duk_push_c_function(ctx, ILibDuktape_ReadonlyProperty_Get, 1); // [obj][prop][value][getFunc]
duk_swap_top(ctx, -2); // [obj][prop][getFunc][value]
duk_put_prop_string(ctx, -2, "\xFF_PropValue"); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size)
{
void *retVal = NULL;
duk_push_heap_stash(ctx); // [s]
if (!duk_has_prop_string(ctx, -1, ILibDuktape_Memory_AllocTable))
{
duk_push_object(ctx); // [s][table]
duk_dup(ctx, -1); // [s][table][table]
duk_put_prop_string(ctx, -3, ILibDuktape_Memory_AllocTable); // [s][table]
}
else
{
duk_get_prop_string(ctx, -1, ILibDuktape_Memory_AllocTable); // [s][table]
}
duk_push_fixed_buffer(ctx, size); // [s][table][buffer]
retVal = Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(retVal)); // [s][table]
duk_pop_2(ctx);
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);
}
duk_ret_t ILibDuktape_Timeout_Sink(duk_context *ctx)
{
ILibDuktape_TimeoutHandler userCallback = (ILibDuktape_TimeoutHandler)duk_get_pointer(ctx, 0);
void **args = NULL;
int argsLen, i;
duk_push_this(ctx); // [timeout]
duk_dup(ctx, 1); // [timeout][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); // [timeout][array][arg]
args[i] = duk_get_pointer(ctx, -1);
duk_pop(ctx); // [timeout][array]
}
}
if (userCallback != NULL) { userCallback(ctx, args, argsLen); }
return(0);
}
void* ILibDuktape_Timeout(duk_context *ctx, void **args, int argsLen, int delay, ILibDuktape_TimeoutHandler callback)
{
void *retval = NULL;
int i = 0;
duk_push_global_object(ctx); // [g]
duk_get_prop_string(ctx, -1, "setTimeout"); // [g][setTimeout]
duk_swap_top(ctx, -2); // [setTimeout][this]
duk_push_c_function(ctx, ILibDuktape_Timeout_Sink, DUK_VARARGS); // [setTimeout][this][func]
duk_push_int(ctx, delay); // [setTimeout][this][func][delay]
duk_push_pointer(ctx, callback); // [setTimeout][this][func][delay][userFunc]
duk_push_array(ctx); // [setTimeout][this][func][delay][userFunc][array]
while (i < argsLen && args[i] != NULL)
{
duk_get_prop_string(ctx, -1, "push"); // [setInterval][this][func][delay][userFunc][array][push]
duk_dup(ctx, -2); // [setInterval][this][func][delay][userFunc][array][push][this]
duk_push_pointer(ctx, args[i]); // [setInterval][this][func][delay][userFunc][array][push][this][val]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Timeout => Array.push(): "); }
duk_pop(ctx); // [setInterval][this][func][delay][userFunc][array]
++i;
}
if (duk_pcall_method(ctx, 4) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Timeout => timeout(): "); duk_pop(ctx); return(NULL); }
retval = duk_get_heapptr(ctx, -1); // [timeout]
return(retval);
}
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]
}
}
if (userCallback != NULL) { userCallback(ctx, args, argsLen); }
duk_push_heap_stash(ctx); // [stash]
duk_push_this(ctx); // [stash][immediate]
duk_del_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1)));
return(0);
}
void* ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback)
{
void *retval = NULL;
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(NULL); }
retval = duk_get_heapptr(ctx, -1); // [immediate]
duk_push_heap_stash(ctx); // [immediate][stash]
duk_swap_top(ctx, -2); // [stash][immediate]
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(retval)); // [stash]
duk_pop(ctx); // ...
return(retval);
}
duk_ret_t ILibDuktape_Interval_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]
}
}
if (userCallback != NULL) { userCallback(ctx, args, argsLen); }
return(0);
}
void* ILibDuktape_Interval(duk_context *ctx, void **args, int argsLen, int delay, ILibDuktape_IntervalHandler callback)
{
void *retval = NULL;
int i = 0;
duk_push_global_object(ctx); // [g]
duk_get_prop_string(ctx, -1, "setInterval"); // [g][setInterval]
duk_swap_top(ctx, -2); // [setInterval][this]
duk_push_c_function(ctx, ILibDuktape_Interval_Sink, DUK_VARARGS); // [setInterval][this][func]
duk_push_int(ctx, delay); // [setInterval][this][func][delay]
duk_push_pointer(ctx, callback); // [setInterval][this][func][delay][userFunc]
duk_push_array(ctx); // [setInterval][this][func][delay][userFunc][array]
while (args[i] != NULL && i < argsLen)
{
duk_get_prop_string(ctx, -1, "push"); // [setInterval][this][func][delay][userFunc][array][push]
duk_dup(ctx, -2); // [setInterval][this][func][delay][userFunc][array][push][this]
duk_push_pointer(ctx, args[i]); // [setInterval][this][func][delay][userFunc][array][push][this][val]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Immediate => Array.push(): "); }
duk_pop(ctx); // [setInterval][this][func][delay][userFunc][array]
++i;
}
if (duk_pcall_method(ctx, 4) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Interval => interval(): "); duk_pop(ctx); return(NULL); }
retval = duk_get_heapptr(ctx, -1); // [immediate]
duk_push_heap_stash(ctx); // [immediate][stash]
duk_swap_top(ctx, -2); // [stash][immediate]
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(retval)); // [stash]
duk_pop(ctx); // ...
return(retval);
}
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));
}
void Duktape_Console_Log_ChainEx(duk_context *ctx, ILibDuktape_LogTypes logType, char *msg, duk_size_t msgLen)
{
duk_push_global_object(ctx); // [g]
duk_get_prop_string(ctx, -1, "console"); // [g][console]
switch (logType)
{
case ILibDuktape_LogType_Error:
duk_get_prop_string(ctx, -1, "error"); // [g][console][error]
break;
case ILibDuktape_LogType_Warn:
duk_get_prop_string(ctx, -1, "warn"); // [g][console][warn]
break;
default:
duk_get_prop_string(ctx, -1, "log"); // [g][console][log]
break;
}
duk_swap_top(ctx, -2); // [g][log][this]
duk_push_lstring(ctx, msg, msgLen); // [g][log][this][str]
duk_pcall_method(ctx, 1); duk_pop(ctx); // [g]
duk_pop(ctx); // ...
}
typedef struct Duktape_Console_Log_data
{
duk_context *ctx;
ILibDuktape_LogTypes logType;
}Duktape_Console_Log_data;
void Duktape_Console_Log_Chain(void *chain, void *user)
{
Duktape_Console_Log_data *data = (Duktape_Console_Log_data*)user;
char *msg = (char*)ILibMemory_Extra(data);
Duktape_Console_Log_ChainEx(data->ctx, data->logType, msg, ILibMemory_Size(msg));
ILibMemory_Free(user);
}
void Duktape_Console_Log(duk_context *ctx, void *chain, ILibDuktape_LogTypes logType, char *msg, duk_size_t msgLen)
{
if (ILibIsRunningOnChainThread(chain))
{
Duktape_Console_Log_ChainEx(ctx, logType, msg, msgLen);
}
else
{
Duktape_Console_Log_data *data = (Duktape_Console_Log_data*)ILibMemory_SmartAllocateEx(sizeof(Duktape_Console_Log_data), msgLen);
data->ctx = ctx;
data->logType = logType;
memcpy_s(ILibMemory_Extra(data), ILibMemory_ExtraSize(data), msg, msgLen);
ILibChain_RunOnMicrostackThreadEx(chain, Duktape_Console_Log_Chain, data);
}
}
char* ILibDuktape_String_AsWide(duk_context *ctx, duk_idx_t idx, duk_size_t *len)
{
char *src;
src = (char*)duk_require_string(ctx, idx);
#ifdef WIN32
size_t inBufferLen = 2 + (2 * MultiByteToWideChar(CP_UTF8, 0, (LPCCH)src, -1, NULL, 0));
LPWSTR inBuffer = (LPWSTR)ILibMemory_AllocateTemp(Duktape_GetChain(ctx), inBufferLen);
int r = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)src, -1, inBuffer, (int)inBufferLen);
if (len != NULL)
{
*len = (duk_size_t)r;
}
return(r == 0 ? NULL : (char*)inBuffer);
#else
return(src);
#endif
}
void ILibDuktape_String_PushWideString(duk_context *ctx, char *wstr, size_t wstrlen)
{
#ifdef WIN32
char *tmp;
size_t tmpLen;
tmpLen = 2 + (size_t)WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)wstr, (int)(wstrlen > 0 ? wstrlen : -1), NULL, 0, NULL, NULL);
tmp = (char*)duk_push_fixed_buffer(ctx, tmpLen); // [buffer]
if (WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)wstr, (int)(wstrlen > 0 ? wstrlen : -1), (LPSTR)tmp, (int)tmpLen, NULL, NULL) != 0)
{
duk_push_string(ctx, tmp); // [buffer][string]
duk_remove(ctx, -2); // [string]
}
else
{
ILibDuktape_Error(ctx, "String_PushWideString() Error: %u", GetLastError());
}
#else
if (wstrlen == 0)
{
duk_push_string(ctx, wstr);
}
else
{
duk_push_lstring(ctx, wstr, wstrlen);
}
#endif
}
char *ILibDuktape_String_WideToUTF8(duk_context *ctx, char *wstr)
{
#ifdef WIN32
char *tmp;
size_t tmpLen;
tmpLen = 2 + (size_t)WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)wstr, -1, NULL, 0, NULL, NULL);
tmp = (char*)ILibMemory_AllocateTemp(Duktape_GetChain(ctx), tmpLen);
WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)wstr, -1, tmp, (int)tmpLen, NULL, NULL);
return(tmp);
#else
// NOP for non-Windows, because should already be UTF8
return(wstr);
#endif
}
void ILibDuktape_String_UTF8ToWideEx(duk_context *ctx, char *str)
{
#ifdef WIN32
size_t tmpLen = 2 + (2 * MultiByteToWideChar(CP_UTF8, 0, (LPCCH)str, -1, NULL, 0));
LPWSTR retVal = (LPWSTR)Duktape_PushBuffer(ctx, tmpLen);
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)str, -1, retVal, (int)tmpLen);
#else
duk_push_string(ctx, str);
#endif
}
char *ILibDuktape_String_UTF8ToWide(duk_context *ctx, char *str)
{
#ifdef WIN32
size_t tmpLen = 2 + (2 * MultiByteToWideChar(CP_UTF8, 0, (LPCCH)str, -1, NULL, 0));
LPWSTR retVal = (LPWSTR)ILibMemory_AllocateTemp(Duktape_GetChain(ctx), tmpLen);
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)str, -1, retVal, (int)tmpLen);
return((char*)retVal);
#else
// NOP on non-Windows, as strings should always be UTF-8 by default
return(str);
#endif
}
void ILibDuktape_Log_Object(duk_context *ctx, duk_idx_t i, char *meta)
{
void *h = duk_get_heapptr(ctx, i);
duk_enum(ctx, i, DUK_ENUM_INCLUDE_HIDDEN | DUK_ENUM_INCLUDE_SYMBOLS);
while (duk_next(ctx, -1, 1))
{
printf(" [%s: %p] => %s (%p)\n", (meta==NULL?"OBJ":meta), h, (char*)duk_get_string(ctx, -2), duk_get_heapptr(ctx, -1));
duk_pop_2(ctx);
}
duk_pop(ctx);
}