Various fixes I've accrued. Minor cleanups and more tracing in serialize. Turn off memory tracking. Fix Let's Encrypt.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4218 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
parent
2ab1b84432
commit
a32bb02223
@ -831,10 +831,12 @@ function message(event) {
|
|||||||
function reconnect(path) {
|
function reconnect(path) {
|
||||||
let oldSocket = gSocket;
|
let oldSocket = gSocket;
|
||||||
gSocket = null
|
gSocket = null
|
||||||
|
if (oldSocket) {
|
||||||
oldSocket.onopen = null;
|
oldSocket.onopen = null;
|
||||||
oldSocket.onclose = null;
|
oldSocket.onclose = null;
|
||||||
oldSocket.onmessage = null;
|
oldSocket.onmessage = null;
|
||||||
oldSocket.close();
|
oldSocket.close();
|
||||||
|
}
|
||||||
connectSocket(path);
|
connectSocket(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +493,7 @@ function handleConnection(client) {
|
|||||||
parsing_header = false;
|
parsing_header = false;
|
||||||
inputBuffer = inputBuffer.slice(result.bytes_parsed);
|
inputBuffer = inputBuffer.slice(result.bytes_parsed);
|
||||||
|
|
||||||
if (!client.tls && tildefriends.https_port && core.globalSettings.http_redirect) {
|
if (!client.tls && tildefriends.https_port && core.globalSettings.http_redirect && !result.path.startsWith('/.well-known/')) {
|
||||||
let requestObject = new Request(request[0], request[1], request[2], headers, body, client);
|
let requestObject = new Request(request[0], request[1], request[2], headers, body, client);
|
||||||
let response = new Response(requestObject, client);
|
let response = new Response(requestObject, client);
|
||||||
response.writeHead(303, {"Location": `${core.globalSettings.http_redirect}${result.path}`, "Content-Length": "0"});
|
response.writeHead(303, {"Location": `${core.globalSettings.http_redirect}${result.path}`, "Content-Length": "0"});
|
||||||
|
@ -687,7 +687,7 @@ static void _backtrace_error(void* data, const char* message, int errnum)
|
|||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
bool tracking = true;
|
bool tracking = false;
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
if (strcmp(argv[i], "sandbox") == 0)
|
if (strcmp(argv[i], "sandbox") == 0)
|
||||||
|
111
src/serialize.c
111
src/serialize.c
@ -3,6 +3,7 @@
|
|||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "taskstub.js.h"
|
#include "taskstub.js.h"
|
||||||
|
#include "trace.h"
|
||||||
#include "util.js.h"
|
#include "util.js.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -53,16 +54,23 @@ static double _serialize_readDouble(const char** buffer, size_t* size);
|
|||||||
|
|
||||||
void tf_serialize_store(tf_task_t* task, tf_taskstub_t* to, void** out_buffer, size_t* out_size, JSValue value)
|
void tf_serialize_store(tf_task_t* task, tf_taskstub_t* to, void** out_buffer, size_t* out_size, JSValue value)
|
||||||
{
|
{
|
||||||
|
tf_trace_t* trace = tf_task_get_trace(task);
|
||||||
|
tf_trace_begin(trace, "tf_serialize_store");
|
||||||
buffer_t tmp = { 0 };
|
buffer_t tmp = { 0 };
|
||||||
_serialize_store(task, to, &tmp, value);
|
_serialize_store(task, to, &tmp, value);
|
||||||
tmp.data = tf_realloc(tmp.data, tmp.size);
|
tmp.data = tf_realloc(tmp.data, tmp.size);
|
||||||
*out_buffer = tmp.data;
|
*out_buffer = tmp.data;
|
||||||
*out_size = tmp.size;
|
*out_size = tmp.size;
|
||||||
|
tf_trace_end(trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSValue tf_serialize_load(tf_task_t* task, tf_taskstub_t* from, const char* buffer, size_t size)
|
JSValue tf_serialize_load(tf_task_t* task, tf_taskstub_t* from, const char* buffer, size_t size)
|
||||||
{
|
{
|
||||||
return _serialize_load(task, from, buffer, size);
|
tf_trace_t* trace = tf_task_get_trace(task);
|
||||||
|
tf_trace_begin(trace, "tf_serialize_load");
|
||||||
|
JSValue result = _serialize_load(task, from, buffer, size);
|
||||||
|
tf_trace_end(trace);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _buffer_append(buffer_t* buffer, const void* data, size_t size)
|
static void _buffer_append(buffer_t* buffer, const void* data, size_t size)
|
||||||
@ -161,12 +169,12 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_
|
|||||||
else if (JS_IsBool(value))
|
else if (JS_IsBool(value))
|
||||||
{
|
{
|
||||||
_serialize_writeInt32(buffer, kBoolean);
|
_serialize_writeInt32(buffer, kBoolean);
|
||||||
_serialize_writeInt8(buffer, JS_ToBool(tf_task_get_context(task), value) ? 1 : 0);
|
_serialize_writeInt8(buffer, JS_ToBool(context, value) ? 1 : 0);
|
||||||
}
|
}
|
||||||
else if (JS_IsNumber(value))
|
else if (JS_IsNumber(value))
|
||||||
{
|
{
|
||||||
int64_t result = 0;
|
int64_t result = 0;
|
||||||
if (JS_ToInt64(tf_task_get_context(task), &result, value) == 0)
|
if (JS_ToInt64(context, &result, value) == 0)
|
||||||
{
|
{
|
||||||
_serialize_writeInt32(buffer, kInt64);
|
_serialize_writeInt32(buffer, kInt64);
|
||||||
_serialize_writeInt64(buffer, result);
|
_serialize_writeInt64(buffer, result);
|
||||||
@ -179,7 +187,7 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_
|
|||||||
else if (JS_IsNumber(value))
|
else if (JS_IsNumber(value))
|
||||||
{
|
{
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
if (JS_ToFloat64(tf_task_get_context(task), &result, value) == 0)
|
if (JS_ToFloat64(context, &result, value) == 0)
|
||||||
{
|
{
|
||||||
_serialize_writeInt32(buffer, kNumber);
|
_serialize_writeInt32(buffer, kNumber);
|
||||||
_serialize_writeDouble(buffer, result);
|
_serialize_writeDouble(buffer, result);
|
||||||
@ -215,102 +223,102 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_
|
|||||||
else if (JS_IsString(value))
|
else if (JS_IsString(value))
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
const char* result = JS_ToCStringLen(tf_task_get_context(task), &len, value);
|
const char* result = JS_ToCStringLen(context, &len, value);
|
||||||
_serialize_writeInt32(buffer, kString);
|
_serialize_writeInt32(buffer, kString);
|
||||||
_serialize_writeInt32(buffer, (int32_t)len);
|
_serialize_writeInt32(buffer, (int32_t)len);
|
||||||
_buffer_append(buffer, result, len);
|
_buffer_append(buffer, result, len);
|
||||||
JS_FreeCString(tf_task_get_context(task), result);
|
JS_FreeCString(context, result);
|
||||||
}
|
}
|
||||||
else if ((bytes = tf_util_try_get_array_buffer(tf_task_get_context(task), &size, value)) != 0)
|
else if ((bytes = tf_util_try_get_array_buffer(context, &size, value)) != 0)
|
||||||
{
|
{
|
||||||
_serialize_writeInt32(buffer, kArrayBuffer);
|
_serialize_writeInt32(buffer, kArrayBuffer);
|
||||||
_serialize_writeInt32(buffer, (int32_t)size);
|
_serialize_writeInt32(buffer, (int32_t)size);
|
||||||
_buffer_append(buffer, bytes, size);
|
_buffer_append(buffer, bytes, size);
|
||||||
}
|
}
|
||||||
else if (!JS_IsException((typed = tf_util_try_get_typed_array_buffer(tf_task_get_context(task), value, &offset, &size, &element_size))))
|
else if (!JS_IsException((typed = tf_util_try_get_typed_array_buffer(context, value, &offset, &size, &element_size))))
|
||||||
{
|
{
|
||||||
size_t total_size;
|
size_t total_size;
|
||||||
uint8_t* bytes = tf_util_try_get_array_buffer(tf_task_get_context(task), &total_size, typed);
|
uint8_t* bytes = tf_util_try_get_array_buffer(context, &total_size, typed);
|
||||||
_serialize_writeInt32(buffer, kArrayBuffer);
|
_serialize_writeInt32(buffer, kArrayBuffer);
|
||||||
_serialize_writeInt32(buffer, (int32_t)size);
|
_serialize_writeInt32(buffer, (int32_t)size);
|
||||||
_buffer_append(buffer, bytes, size);
|
_buffer_append(buffer, bytes, size);
|
||||||
JS_FreeValue(tf_task_get_context(task), typed);
|
JS_FreeValue(context, typed);
|
||||||
}
|
}
|
||||||
else if (JS_IsArray(tf_task_get_context(task), value))
|
else if (JS_IsArray(context, value))
|
||||||
{
|
{
|
||||||
_serialize_writeInt32(buffer, kArray);
|
_serialize_writeInt32(buffer, kArray);
|
||||||
int length = tf_util_get_length(tf_task_get_context(task), value);
|
int length = tf_util_get_length(context, value);
|
||||||
_serialize_writeInt32(buffer, length);
|
_serialize_writeInt32(buffer, length);
|
||||||
for (int i = 0; i < length; ++i)
|
for (int i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
JSValue element = JS_GetPropertyUint32(tf_task_get_context(task), value, i);
|
JSValue element = JS_GetPropertyUint32(context, value, i);
|
||||||
_serialize_storeInternal(task, to, buffer, element, depth + 1);
|
_serialize_storeInternal(task, to, buffer, element, depth + 1);
|
||||||
JS_FreeValue(context, element);
|
JS_FreeValue(context, element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (JS_IsFunction(tf_task_get_context(task), value))
|
else if (JS_IsFunction(context, value))
|
||||||
{
|
{
|
||||||
_serialize_writeInt32(buffer, kFunction);
|
_serialize_writeInt32(buffer, kFunction);
|
||||||
exportid_t exportId = tf_task_export_function(task, to, value);
|
exportid_t exportId = tf_task_export_function(task, to, value);
|
||||||
_serialize_writeInt32(buffer, exportId);
|
_serialize_writeInt32(buffer, exportId);
|
||||||
}
|
}
|
||||||
else if (JS_IsError(tf_task_get_context(task), value))
|
else if (JS_IsError(context, value))
|
||||||
{
|
{
|
||||||
_serialize_writeInt32(buffer, kError);
|
_serialize_writeInt32(buffer, kError);
|
||||||
JSPropertyEnum* ptab;
|
JSPropertyEnum* ptab;
|
||||||
uint32_t plen;
|
uint32_t plen;
|
||||||
JS_GetOwnPropertyNames(tf_task_get_context(task), &ptab, &plen, value, JS_GPN_STRING_MASK);
|
JS_GetOwnPropertyNames(context, &ptab, &plen, value, JS_GPN_STRING_MASK);
|
||||||
_serialize_writeInt32(buffer, plen);
|
_serialize_writeInt32(buffer, plen);
|
||||||
for (uint32_t i = 0; i < plen; ++i)
|
for (uint32_t i = 0; i < plen; ++i)
|
||||||
{
|
{
|
||||||
JSValue key = JS_AtomToString(tf_task_get_context(task), ptab[i].atom);
|
JSValue key = JS_AtomToString(context, ptab[i].atom);
|
||||||
JSPropertyDescriptor desc;
|
JSPropertyDescriptor desc;
|
||||||
JSValue key_value = JS_NULL;
|
JSValue key_value = JS_NULL;
|
||||||
if (JS_GetOwnProperty(tf_task_get_context(task), &desc, value, ptab[i].atom) == 1)
|
if (JS_GetOwnProperty(context, &desc, value, ptab[i].atom) == 1)
|
||||||
{
|
{
|
||||||
key_value = desc.value;
|
key_value = desc.value;
|
||||||
JS_FreeValue(tf_task_get_context(task), desc.setter);
|
JS_FreeValue(context, desc.setter);
|
||||||
JS_FreeValue(tf_task_get_context(task), desc.getter);
|
JS_FreeValue(context, desc.getter);
|
||||||
}
|
}
|
||||||
_serialize_storeInternal(task, to, buffer, key, depth + 1);
|
_serialize_storeInternal(task, to, buffer, key, depth + 1);
|
||||||
_serialize_storeInternal(task, to, buffer, key_value, depth + 1);
|
_serialize_storeInternal(task, to, buffer, key_value, depth + 1);
|
||||||
JS_FreeValue(tf_task_get_context(task), key);
|
JS_FreeValue(context, key);
|
||||||
JS_FreeValue(tf_task_get_context(task), key_value);
|
JS_FreeValue(context, key_value);
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < plen; ++i)
|
for (uint32_t i = 0; i < plen; ++i)
|
||||||
{
|
{
|
||||||
JS_FreeAtom(tf_task_get_context(task), ptab[i].atom);
|
JS_FreeAtom(context, ptab[i].atom);
|
||||||
}
|
}
|
||||||
js_free(tf_task_get_context(task), ptab);
|
js_free(context, ptab);
|
||||||
}
|
}
|
||||||
else if (JS_IsObject(value))
|
else if (JS_IsObject(value))
|
||||||
{
|
{
|
||||||
_serialize_writeInt32(buffer, kObject);
|
_serialize_writeInt32(buffer, kObject);
|
||||||
JSPropertyEnum* ptab;
|
JSPropertyEnum* ptab;
|
||||||
uint32_t plen;
|
uint32_t plen;
|
||||||
JS_GetOwnPropertyNames(tf_task_get_context(task), &ptab, &plen, value, JS_GPN_STRING_MASK);
|
JS_GetOwnPropertyNames(context, &ptab, &plen, value, JS_GPN_STRING_MASK);
|
||||||
_serialize_writeInt32(buffer, plen);
|
_serialize_writeInt32(buffer, plen);
|
||||||
for (uint32_t i = 0; i < plen; ++i)
|
for (uint32_t i = 0; i < plen; ++i)
|
||||||
{
|
{
|
||||||
JSValue key = JS_AtomToString(tf_task_get_context(task), ptab[i].atom);
|
JSValue key = JS_AtomToString(context, ptab[i].atom);
|
||||||
JSPropertyDescriptor desc;
|
JSPropertyDescriptor desc;
|
||||||
JSValue key_value = JS_NULL;
|
JSValue key_value = JS_NULL;
|
||||||
if (JS_GetOwnProperty(tf_task_get_context(task), &desc, value, ptab[i].atom) == 1)
|
if (JS_GetOwnProperty(context, &desc, value, ptab[i].atom) == 1)
|
||||||
{
|
{
|
||||||
key_value = desc.value;
|
key_value = desc.value;
|
||||||
JS_FreeValue(tf_task_get_context(task), desc.setter);
|
JS_FreeValue(context, desc.setter);
|
||||||
JS_FreeValue(tf_task_get_context(task), desc.getter);
|
JS_FreeValue(context, desc.getter);
|
||||||
}
|
}
|
||||||
_serialize_storeInternal(task, to, buffer, key, depth + 1);
|
_serialize_storeInternal(task, to, buffer, key, depth + 1);
|
||||||
_serialize_storeInternal(task, to, buffer, key_value, depth + 1);
|
_serialize_storeInternal(task, to, buffer, key_value, depth + 1);
|
||||||
JS_FreeValue(tf_task_get_context(task), key);
|
JS_FreeValue(context, key);
|
||||||
JS_FreeValue(tf_task_get_context(task), key_value);
|
JS_FreeValue(context, key_value);
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < plen; ++i)
|
for (uint32_t i = 0; i < plen; ++i)
|
||||||
{
|
{
|
||||||
JS_FreeAtom(tf_task_get_context(task), ptab[i].atom);
|
JS_FreeAtom(context, ptab[i].atom);
|
||||||
}
|
}
|
||||||
js_free(tf_task_get_context(task), ptab);
|
js_free(context, ptab);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -334,6 +342,7 @@ static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, con
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
JSContext* context = tf_task_get_context(task);
|
||||||
int32_t type = _serialize_readInt32(buffer, size);
|
int32_t type = _serialize_readInt32(buffer, size);
|
||||||
JSValue result = JS_UNDEFINED;
|
JSValue result = JS_UNDEFINED;
|
||||||
|
|
||||||
@ -349,21 +358,21 @@ static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, con
|
|||||||
result = JS_UNINITIALIZED;
|
result = JS_UNINITIALIZED;
|
||||||
break;
|
break;
|
||||||
case kBoolean:
|
case kBoolean:
|
||||||
result = JS_NewBool(tf_task_get_context(task), _serialize_readInt8(buffer, size) != 0);
|
result = JS_NewBool(context, _serialize_readInt8(buffer, size) != 0);
|
||||||
break;
|
break;
|
||||||
case kInt32:
|
case kInt32:
|
||||||
result = JS_NewInt32(tf_task_get_context(task), _serialize_readInt32(buffer, size));
|
result = JS_NewInt32(context, _serialize_readInt32(buffer, size));
|
||||||
break;
|
break;
|
||||||
case kInt64:
|
case kInt64:
|
||||||
result = JS_NewInt64(tf_task_get_context(task), _serialize_readInt64(buffer, size));
|
result = JS_NewInt64(context, _serialize_readInt64(buffer, size));
|
||||||
break;
|
break;
|
||||||
case kNumber:
|
case kNumber:
|
||||||
result = JS_NewFloat64(tf_task_get_context(task), _serialize_readDouble(buffer, size));
|
result = JS_NewFloat64(context, _serialize_readDouble(buffer, size));
|
||||||
break;
|
break;
|
||||||
case kString:
|
case kString:
|
||||||
{
|
{
|
||||||
int32_t length = _serialize_readInt32(buffer, size);
|
int32_t length = _serialize_readInt32(buffer, size);
|
||||||
result = JS_NewStringLen(tf_task_get_context(task), *buffer, length);
|
result = JS_NewStringLen(context, *buffer, length);
|
||||||
*buffer += length;
|
*buffer += length;
|
||||||
*size -= length;
|
*size -= length;
|
||||||
}
|
}
|
||||||
@ -371,7 +380,7 @@ static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, con
|
|||||||
case kArrayBuffer:
|
case kArrayBuffer:
|
||||||
{
|
{
|
||||||
int32_t length = _serialize_readInt32(buffer, size);
|
int32_t length = _serialize_readInt32(buffer, size);
|
||||||
result = JS_NewArrayBufferCopy(tf_task_get_context(task), (const uint8_t*)*buffer, length);
|
result = JS_NewArrayBufferCopy(context, (const uint8_t*)*buffer, length);
|
||||||
*buffer += length;
|
*buffer += length;
|
||||||
*size -= length;
|
*size -= length;
|
||||||
}
|
}
|
||||||
@ -379,10 +388,10 @@ static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, con
|
|||||||
case kArray:
|
case kArray:
|
||||||
{
|
{
|
||||||
int32_t length = _serialize_readInt32(buffer, size);
|
int32_t length = _serialize_readInt32(buffer, size);
|
||||||
result = JS_NewArray(tf_task_get_context(task));
|
result = JS_NewArray(context);
|
||||||
for (int i = 0; i < length; ++i)
|
for (int i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
JS_SetPropertyUint32(tf_task_get_context(task), result, i, _serialize_loadInternal(task, from, buffer, size, depth + 1));
|
JS_SetPropertyUint32(context, result, i, _serialize_loadInternal(task, from, buffer, size, depth + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -395,16 +404,16 @@ static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, con
|
|||||||
case kException:
|
case kException:
|
||||||
{
|
{
|
||||||
_serialize_readInt32(buffer, size);
|
_serialize_readInt32(buffer, size);
|
||||||
JSValue error = JS_NewError(tf_task_get_context(task));
|
JSValue error = JS_NewError(context);
|
||||||
int32_t length = _serialize_readInt32(buffer, size);
|
int32_t length = _serialize_readInt32(buffer, size);
|
||||||
for (int i = 0; i < length; ++i)
|
for (int i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
JSValue key = _serialize_loadInternal(task, from, buffer, size, depth + 1);
|
JSValue key = _serialize_loadInternal(task, from, buffer, size, depth + 1);
|
||||||
JSValue value = _serialize_loadInternal(task, from, buffer, size, depth + 1);
|
JSValue value = _serialize_loadInternal(task, from, buffer, size, depth + 1);
|
||||||
const char* key_str = JS_ToCString(tf_task_get_context(task), key);
|
const char* key_str = JS_ToCString(context, key);
|
||||||
JS_SetPropertyStr(tf_task_get_context(task), error, key_str, value);
|
JS_SetPropertyStr(context, error, key_str, value);
|
||||||
JS_FreeCString(tf_task_get_context(task), key_str);
|
JS_FreeCString(context, key_str);
|
||||||
JS_FreeValue(tf_task_get_context(task), key);
|
JS_FreeValue(context, key);
|
||||||
}
|
}
|
||||||
result = error;
|
result = error;
|
||||||
}
|
}
|
||||||
@ -413,15 +422,15 @@ static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, con
|
|||||||
case kObject:
|
case kObject:
|
||||||
{
|
{
|
||||||
int32_t length = _serialize_readInt32(buffer, size);
|
int32_t length = _serialize_readInt32(buffer, size);
|
||||||
result = JS_NewObject(tf_task_get_context(task));
|
result = JS_NewObject(context);
|
||||||
for (int i = 0; i < length; ++i)
|
for (int i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
JSValue key = _serialize_loadInternal(task, from, buffer, size, depth + 1);
|
JSValue key = _serialize_loadInternal(task, from, buffer, size, depth + 1);
|
||||||
JSValue value = _serialize_loadInternal(task, from, buffer, size, depth + 1);
|
JSValue value = _serialize_loadInternal(task, from, buffer, size, depth + 1);
|
||||||
const char* key_str = JS_ToCString(tf_task_get_context(task), key);
|
const char* key_str = JS_ToCString(context, key);
|
||||||
JS_SetPropertyStr(tf_task_get_context(task), result, key_str, value);
|
JS_SetPropertyStr(context, result, key_str, value);
|
||||||
JS_FreeCString(tf_task_get_context(task), key_str);
|
JS_FreeCString(context, key_str);
|
||||||
JS_FreeValue(tf_task_get_context(task), key);
|
JS_FreeValue(context, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user