1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-10 13:23:41 +00:00
Files
MeshAgent/microscript/ILibDuktape_Helpers.c
2017-10-12 14:28:03 -07:00

596 lines
21 KiB
C

/*
Copyright 2006 - 2017 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 "ILibParsers_Duktape.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"
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;
}
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_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 (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;
}
int Duktape_GetIntPropertyValue(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 = duk_to_int(ctx, -1);
duk_pop(ctx);
}
return retVal;
}
void Duktape_CreateEnum(duk_context *ctx, char* enumName, char** fieldNames, int * fieldValues, int numFields)
{
int i;
duk_push_global_object(ctx); // [global]
duk_push_object(ctx); // [global][obj]
for (i = 0; i < numFields; ++i)
{
duk_push_int(ctx, fieldValues[i]); // [global][obj][val]
duk_put_prop_string(ctx, -2, fieldNames[i]); // [global][obj]
}
duk_put_prop_string(ctx, -2, enumName); // [global]
duk_pop(ctx);
}
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;
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,bufLen);
}
else if(duk_is_buffer_data(ctx, i))
{
retVal = (char*)duk_require_buffer_data(ctx, i, bufLen);
}
else if (duk_is_object(ctx, i))
{
duk_json_encode(ctx, i);
retVal = (char*)duk_get_lstring(ctx, i, bufLen);
}
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_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_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, "name"); // [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]
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);
}
ILibDuktape_EventEmitter *ILibDuktape_Process_GetEventEmitter(duk_context *ctx)
{
ILibDuktape_EventEmitter *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 = ILibDuktape_EventEmitter_GetEmitter_fromCurrent(ctx);
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;
}
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_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, ...)
{
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;
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 (j != NULL)
{
duk_push_heapptr(ctx, j); // [process]
if (duk_has_prop_string(ctx, -1, ILibDuktape_NativeUncaughtExceptionPtr))
{
duk_get_prop_string(ctx, -1, ILibDuktape_NativeUncaughtExceptionPtr); // [process][ptr]
duk_get_prop_string(ctx, -2, ILibDuktape_NativeUncaughtExceptionUserPtr); // [process][ptr][user]
((ILibDuktape_NativeUncaughtExceptionHandler)duk_get_pointer(ctx, -2))(ctx, (char*)dest, duk_get_pointer(ctx, -1));
duk_pop_2(ctx); // [process]
}
duk_pop(ctx); // ...
}
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_UNCAUGHT_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)
{
ILibDuktape_Process_UncaughtExceptionEx(ctx, "");
}
char* Duktape_GetContextGuidHex(duk_context *ctx)
{
char *retVal = NULL;
char *guid;
duk_size_t guidLength;
int i;
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, CONTEXT_GUID_BUFFER))
{
duk_get_prop_string(ctx, -1, CONTEXT_GUID_BUFFER); // [stash][str]
guid = (char*)Duktape_GetBuffer(ctx, -1, &guidLength);
for (i = (int)guidLength-1; i > 1 && guid[i] == 0; --i)
{
}
util_tohex(guid, (int)guidLength, ILibScratchPad);
duk_pop(ctx); // [stash]
for (i = ((int)guidLength * 2) - 1; i > 1 && ILibScratchPad[i] == 48; --i)
{
}
retVal = ILibScratchPad;
retVal[i] = 0;
}
duk_pop(ctx); // ...
return retVal;
}
void *Duktape_GetChain(duk_context *ctx)
{
void *retVal = NULL;
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, ILibDuktape_Context_Chain))
{
duk_get_prop_string(ctx, -1, ILibDuktape_Context_Chain); // [stash][ptr]
retVal = duk_get_pointer(ctx, -1);
duk_pop_2(ctx); // ...
}
else
{
duk_pop(ctx); // ...
}
return retVal;
}
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_CreateIndependentFinalizer(duk_context *ctx, ILibDuktape_IndependentFinalizerHandler handler)
{
char tmp[255];
duk_push_object(ctx); // [obj]
duk_push_pointer(ctx, handler); // [obj][ptr]
duk_put_prop_string(ctx, -2, "ptr"); // [obj]
duk_dup(ctx, -2); // [obj][parent]
duk_put_prop_string(ctx, -2, "parent"); // [obj]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_IndependentFinalizer_Dispatch);
sprintf_s(tmp, sizeof(tmp), "\xFF_%s", Duktape_GetStashKey(duk_get_heapptr(ctx, -1)));
duk_put_prop_string(ctx, -2, tmp);
}
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);
}