diff --git a/core/core.js b/core/core.js index de9ef811..9ed87d14 100644 --- a/core/core.js +++ b/core/core.js @@ -122,12 +122,6 @@ function postMessageInternal(from, to, message) { } } -function killProcess(process) { - if (process && process.task) { - return process.task.kill(); - } -} - async function getSessionProcessBlob(blobId, session, options) { var actualOptions = {timeout: kPingInterval}; if (options) { diff --git a/src/bcrypt.h b/src/bcrypt.h deleted file mode 100644 index e9247aa3..00000000 --- a/src/bcrypt.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "quickjs.h" - -void tf_bcrypt_init(JSContext* context); diff --git a/src/bcrypt.c b/src/bcrypt.js.c similarity index 95% rename from src/bcrypt.c rename to src/bcrypt.js.c index f3397070..3154c691 100644 --- a/src/bcrypt.c +++ b/src/bcrypt.js.c @@ -1,4 +1,4 @@ -#include "bcrypt.h" +#include "bcrypt.js.h" #include "ow-crypt.h" @@ -7,7 +7,7 @@ JSValue _crypt_hashpw(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); JSValue _crypt_gensalt(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); -void tf_bcrypt_init(JSContext* context) +void tf_bcrypt_register(JSContext* context) { JSValue global = JS_GetGlobalObject(context); JSValue bcrypt = JS_NewObject(context); diff --git a/src/bcrypt.js.h b/src/bcrypt.js.h new file mode 100644 index 00000000..a1869580 --- /dev/null +++ b/src/bcrypt.js.h @@ -0,0 +1,5 @@ +#pragma once + +#include "quickjs.h" + +void tf_bcrypt_register(JSContext* context); diff --git a/src/database.c b/src/database.js.c similarity index 98% rename from src/database.c rename to src/database.js.c index f4d73d65..fdb9144f 100644 --- a/src/database.c +++ b/src/database.js.c @@ -1,4 +1,4 @@ -#include "database.h" +#include "database.js.h" #include #include @@ -27,7 +27,7 @@ static JSValue _database_remove(JSContext* context, JSValueConst this_val, int a static JSValue _database_get_all(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); static JSValue _database_get_like(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); -void tf_database_init(JSContext* context, sqlite3* sqlite) +void tf_database_register(JSContext* context, sqlite3* sqlite) { JS_NewClassID(&_database_class_id); JSClassDef def = { diff --git a/src/database.h b/src/database.js.h similarity index 51% rename from src/database.h rename to src/database.js.h index 42e3d033..20f17c3e 100644 --- a/src/database.h +++ b/src/database.js.h @@ -4,4 +4,4 @@ typedef struct sqlite3 sqlite3; -void tf_database_init(JSContext* context, sqlite3* sqlite); +void tf_database_register(JSContext* context, sqlite3* sqlite); diff --git a/src/file.h b/src/file.h deleted file mode 100644 index 7a276dd2..00000000 --- a/src/file.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "quickjs.h" - -void tf_file_init(JSContext* context); diff --git a/src/file.c b/src/file.js.c similarity index 99% rename from src/file.c rename to src/file.js.c index 63463ec0..9336958f 100644 --- a/src/file.c +++ b/src/file.js.c @@ -1,4 +1,4 @@ -#include "file.h" +#include "file.js.h" #include "task.h" @@ -31,7 +31,7 @@ typedef struct file_stat_t { uv_fs_t _request; } file_stat_t; -void tf_file_init(JSContext* context) +void tf_file_register(JSContext* context) { JSValue global = JS_GetGlobalObject(context); JSValue file = JS_NewObject(context); diff --git a/src/file.js.h b/src/file.js.h new file mode 100644 index 00000000..ccb96ce5 --- /dev/null +++ b/src/file.js.h @@ -0,0 +1,5 @@ +#pragma once + +#include "quickjs.h" + +void tf_file_register(JSContext* context); diff --git a/src/main.c b/src/main.c index 4a83c4f8..1ed80ae6 100644 --- a/src/main.c +++ b/src/main.c @@ -2,7 +2,7 @@ #include "ssb.import.h" #include "ssb.export.h" #include "task.h" -#include "taskstub.h" +#include "taskstub.js.h" #include "tests.h" #include diff --git a/src/serialize.c b/src/serialize.c index 41e5b839..9529f7c2 100644 --- a/src/serialize.c +++ b/src/serialize.c @@ -1,6 +1,6 @@ #include "serialize.h" #include "task.h" -#include "taskstub.h" +#include "taskstub.js.h" #include #include diff --git a/src/socket.c b/src/socket.js.c similarity index 99% rename from src/socket.c rename to src/socket.js.c index 73819d69..c898e570 100644 --- a/src/socket.c +++ b/src/socket.js.c @@ -1,7 +1,7 @@ -#include "socket.h" +#include "socket.js.h" #include "task.h" #include "tls.h" -#include "tlscontextwrapper.h" +#include "tlscontext.js.h" #include #include @@ -79,14 +79,7 @@ static void _socket_processOutgoingTls(socket_t* socket); static void _socket_reportTlsErrors(socket_t* socket); static void _socket_reportError(socket_t* socket, const char* error); -/* -class Socket { -private: - -}; -*/ - -JSValue tf_socket_init(JSContext* context) +JSValue tf_socket_register(JSContext* context) { JS_NewClassID(&_classId); JSClassDef def = { @@ -238,7 +231,7 @@ JSValue _socket_startTls(JSContext* context, JSValueConst this_val, int argc, JS if (argc > 0 && JS_IsObject(argv[0])) { - context = tf_tls_context_wrapper_get(argv[0]); + context = tf_tls_context_get(argv[0]); } else { diff --git a/src/socket.h b/src/socket.js.h similarity index 66% rename from src/socket.h rename to src/socket.js.h index 6677bcff..61b38d92 100644 --- a/src/socket.h +++ b/src/socket.js.h @@ -2,6 +2,6 @@ #include "quickjs.h" -JSValue tf_socket_init(JSContext* context); +JSValue tf_socket_register(JSContext* context); int tf_socket_get_count(); int tf_socket_get_open_count(); diff --git a/src/ssb.qjs.c b/src/ssb.js.c similarity index 99% rename from src/ssb.qjs.c rename to src/ssb.js.c index d5be2529..fb62bf37 100644 --- a/src/ssb.qjs.c +++ b/src/ssb.js.c @@ -1,6 +1,6 @@ -#include "ssb.qjs.h" +#include "ssb.js.h" -#include "database.h" +#include "database.js.h" #include "ssb.db.h" #include "ssb.h" #include "task.h" @@ -678,7 +678,7 @@ static JSValue _utf8_decode(JSContext* context, JSValueConst this_val, int argc, return result; } -void tf_ssb_init(JSContext* context, tf_ssb_t* ssb) +void tf_ssb_register(JSContext* context, tf_ssb_t* ssb) { JS_NewClassID(&_tf_ssb_classId); JSClassDef def = @@ -718,6 +718,6 @@ void tf_ssb_init(JSContext* context, tf_ssb_t* ssb) JS_FreeValue(context, global); - tf_database_init(context, tf_ssb_get_db(ssb)); + tf_database_register(context, tf_ssb_get_db(ssb)); tf_ssb_run_file(context, "core/ssb.js"); } diff --git a/src/ssb.qjs.h b/src/ssb.js.h similarity index 55% rename from src/ssb.qjs.h rename to src/ssb.js.h index eceaaed0..243ea07e 100644 --- a/src/ssb.qjs.h +++ b/src/ssb.js.h @@ -4,4 +4,4 @@ typedef struct _tf_ssb_t tf_ssb_t; -void tf_ssb_init(JSContext* context, tf_ssb_t* ssb); +void tf_ssb_register(JSContext* context, tf_ssb_t* ssb); diff --git a/src/ssb.tests.c b/src/ssb.tests.c index 3fae8506..2cf21ff7 100644 --- a/src/ssb.tests.c +++ b/src/ssb.tests.c @@ -1,7 +1,7 @@ #include "ssb.h" #include "ssb.db.h" -#include "ssb.qjs.h" +#include "ssb.js.h" #include "tests.h" #include @@ -82,9 +82,9 @@ void tf_ssb_test_ssb(const tf_test_options_t* options) uv_loop_init(&loop); tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, db0, NULL); - tf_ssb_init(tf_ssb_get_context(ssb0), ssb0); + tf_ssb_register(tf_ssb_get_context(ssb0), ssb0); tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, db1, NULL); - tf_ssb_init(tf_ssb_get_context(ssb1), ssb1); + tf_ssb_register(tf_ssb_get_context(ssb1), ssb1); test_t test = { .ssb0 = ssb0, diff --git a/src/task.c b/src/task.c index 36b24bd0..0c085cb6 100644 --- a/src/task.c +++ b/src/task.c @@ -1,15 +1,15 @@ #include "task.h" -#include "bcrypt.h" -#include "database.h" -#include "file.h" +#include "bcrypt.js.h" +#include "database.js.h" +#include "file.js.h" #include "packetstream.h" #include "serialize.h" -#include "socket.h" +#include "socket.js.h" #include "ssb.h" -#include "ssb.qjs.h" -#include "taskstub.h" -#include "tlscontextwrapper.h" +#include "ssb.js.h" +#include "taskstub.js.h" +#include "tlscontext.js.h" #include "trace.h" #include @@ -1359,18 +1359,18 @@ void tf_task_activate(tf_task_t* task) sqlite3_open(task->_db_path ? task->_db_path : "db.sqlite", &task->_db); JS_SetPropertyStr(context, global, "require", JS_NewCFunction(context, _tf_task_require, "require", 1)); - JS_SetPropertyStr(context, global, "Task", tf_taskstub_init(context)); - JS_SetPropertyStr(context, global, "Socket", tf_socket_init(context)); - JS_SetPropertyStr(context, global, "TlsContext", tf_tls_context_wrapper_init(context)); - tf_database_init(context, task->_db); - tf_file_init(context); + JS_SetPropertyStr(context, global, "Task", tf_taskstub_register(context)); + JS_SetPropertyStr(context, global, "Socket", tf_socket_register(context)); + JS_SetPropertyStr(context, global, "TlsContext", tf_tls_context_register(context)); + tf_database_register(context, task->_db); + tf_file_register(context); task->_trace = tf_trace_create(); task->_ssb = tf_ssb_create(task->_loop, task->_context, task->_db, task->_secrets_path); tf_ssb_set_trace(task->_ssb, task->_trace); tf_ssb_broadcast_listener_start(task->_ssb, false); - tf_ssb_init(context, task->_ssb); + tf_ssb_register(context, task->_ssb); if (task->_ssb_port) { tf_ssb_server_open(task->_ssb, task->_ssb_port); @@ -1383,7 +1383,7 @@ void tf_task_activate(tf_task_t* task) JS_SetPropertyStr(context, global, "require", JS_NewCFunction(context, _tf_task_sandbox_require, "sandboxRequire", 0)); } - tf_bcrypt_init(context); + tf_bcrypt_register(context); JS_SetPropertyStr(context, global, "utf8Decode", JS_NewCFunction(context, _tf_task_utf8Decode, "utf8Decode", 1)); JS_SetPropertyStr(context, global, "print", JS_NewCFunction(context, _tf_task_print, "print", 0)); JS_SetPropertyStr(context, global, "exit", JS_NewCFunction(context, _tf_task_exit, "exit", 1)); diff --git a/src/taskstub.c b/src/taskstub.js.c similarity index 99% rename from src/taskstub.c rename to src/taskstub.js.c index 0b0b3d4f..8484e6ba 100644 --- a/src/taskstub.c +++ b/src/taskstub.js.c @@ -1,4 +1,4 @@ -#include "taskstub.h" +#include "taskstub.js.h" #include "packetstream.h" #include "serialize.h" @@ -168,7 +168,7 @@ void _taskstub_gc_mark(JSRuntime* rt, JSValueConst value, JS_MarkFunc mark_func) } } -JSValue tf_taskstub_init(JSContext* context) +JSValue tf_taskstub_register(JSContext* context) { JSClassDef def = { .class_name = "TaskStub", diff --git a/src/taskstub.h b/src/taskstub.js.h similarity index 93% rename from src/taskstub.h rename to src/taskstub.js.h index c481a0bb..31235c41 100644 --- a/src/taskstub.h +++ b/src/taskstub.js.h @@ -11,7 +11,7 @@ typedef struct _tf_task_t tf_task_t; typedef struct _tf_taskstub_t tf_taskstub_t; void tf_taskstub_startup(); -JSValue tf_taskstub_init(JSContext* context); +JSValue tf_taskstub_register(JSContext* context); taskid_t tf_taskstub_get_id(const tf_taskstub_t* stub); JSValue tf_taskstub_get_task_object(const tf_taskstub_t* stub); tf_packetstream_t* tf_taskstub_get_stream(const tf_taskstub_t* stub); diff --git a/src/tlscontext.js.c b/src/tlscontext.js.c new file mode 100644 index 00000000..01f8bf0f --- /dev/null +++ b/src/tlscontext.js.c @@ -0,0 +1,108 @@ +#include "tlscontext.js.h" + +#include "task.h" +#include "tls.h" + +#include +#include +#include + +static JSClassID _classId; +static int _count; + +typedef struct _tf_tls_context_t { + tf_tls_context_t* context; + tf_task_t* task; + JSValue object; +} tf_tls_context_t; + +static JSValue _tls_context_set_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); +static JSValue _tls_context_set_private_key(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); +static JSValue _tls_context_add_trusted_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); + +static JSValue _tls_context_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); +static void _tls_context_finalizer(JSRuntime *runtime, JSValue value); + +JSValue _tls_context_set_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) +{ + tf_tls_context_t* tls = JS_GetOpaque(this_val, _classId); + const char* value = JS_ToCString(context, argv[0]); + tf_tls_context_set_certificate(tls->context, value); + JS_FreeCString(context, value); + return JS_UNDEFINED; +} + +JSValue _tls_context_set_private_key(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) +{ + tf_tls_context_t* tls = JS_GetOpaque(this_val, _classId); + const char* value = JS_ToCString(context, argv[0]); + tf_tls_context_set_private_key(tls->context, value); + JS_FreeCString(context, value); + return JS_UNDEFINED; +} + +JSValue _tls_context_add_trusted_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) +{ + tf_tls_context_t* tls = JS_GetOpaque(this_val, _classId); + const char* value = JS_ToCString(context, argv[0]); + tf_tls_context_add_trusted_certificate(tls->context, value); + JS_FreeCString(context, value); + return JS_UNDEFINED; +} + +JSValue tf_tls_context_register(JSContext* context) +{ + JS_NewClassID(&_classId); + JSClassDef def = + { + .class_name = "TlsContext", + .finalizer = _tls_context_finalizer, + }; + if (JS_NewClass(JS_GetRuntime(context), _classId, &def) != 0) + { + fprintf(stderr, "Failed to register TlsContext.\n"); + } + return JS_NewCFunction2(context, _tls_context_create, "TlsContext", 0, JS_CFUNC_constructor, 0); +} + +tf_tls_context_t* tf_tls_context_get(JSValue value) +{ + tf_tls_context_t* tls = JS_GetOpaque(value, _classId); + return tls ? tls->context : NULL; +} + +int tf_tls_context_get_count() +{ + return _count; +} + +JSValue _tls_context_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) +{ + tf_tls_context_t* tls = malloc(sizeof(tf_tls_context_t)); + memset(tls, 0, sizeof(*tls)); + + ++_count; + tls->object = JS_NewObjectClass(context, _classId); + JS_SetOpaque(tls->object, tls); + + JS_SetPropertyStr(context, tls->object, "setCertificate", JS_NewCFunction(context, _tls_context_set_certificate, "setCertificate", 1)); + JS_SetPropertyStr(context, tls->object, "setPrivateKey", JS_NewCFunction(context, _tls_context_set_private_key, "setPrivateKey", 1)); + JS_SetPropertyStr(context, tls->object, "addTrustedCertificate", JS_NewCFunction(context, _tls_context_add_trusted_certificate, "addTrustedCertificate", 1)); + + tls->context = tf_tls_context_create(); + tls->task = tf_task_get(context); + + return tls->object; +} + +void _tls_context_finalizer(JSRuntime *runtime, JSValue value) +{ + tf_tls_context_t* tls = JS_GetOpaque(value, _classId); + if (tls->context) + { + tf_tls_context_destroy(tls->context); + tls->context = NULL; + } + --_count; + free(tls); +} diff --git a/src/tlscontext.js.h b/src/tlscontext.js.h new file mode 100644 index 00000000..f70f5e37 --- /dev/null +++ b/src/tlscontext.js.h @@ -0,0 +1,9 @@ +#pragma once + +#include "quickjs.h" + +typedef struct _tf_tls_context_t tf_tls_context_t; + +JSValue tf_tls_context_register(JSContext* context); +tf_tls_context_t* tf_tls_context_get(JSValue value); +int tf_tls_context_get_count(); diff --git a/src/tlscontextwrapper.c b/src/tlscontextwrapper.c deleted file mode 100644 index 6df0d9f1..00000000 --- a/src/tlscontextwrapper.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "tlscontextwrapper.h" - -#include "task.h" -#include "tls.h" - -#include -#include -#include - -static JSClassID _classId; -static int _count; - -typedef struct _tf_tls_context_wrapper_t { - tf_tls_context_t* context; - tf_task_t* task; - JSValue object; -} tf_tls_context_wrapper_t; - -static JSValue _tls_context_wrapper_set_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); -static JSValue _tls_context_wrapper_set_private_key(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); -static JSValue _tls_context_wrapper_add_trusted_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); - -static JSValue _tls_context_wrapper_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); -static void _tls_context_wrapper_finalizer(JSRuntime *runtime, JSValue value); - -JSValue _tls_context_wrapper_set_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) -{ - tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(this_val, _classId); - const char* value = JS_ToCString(context, argv[0]); - tf_tls_context_set_certificate(wrapper->context, value); - JS_FreeCString(context, value); - return JS_UNDEFINED; -} - -JSValue _tls_context_wrapper_set_private_key(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) -{ - tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(this_val, _classId); - const char* value = JS_ToCString(context, argv[0]); - tf_tls_context_set_private_key(wrapper->context, value); - JS_FreeCString(context, value); - return JS_UNDEFINED; -} - -JSValue _tls_context_wrapper_add_trusted_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) -{ - tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(this_val, _classId); - const char* value = JS_ToCString(context, argv[0]); - tf_tls_context_add_trusted_certificate(wrapper->context, value); - JS_FreeCString(context, value); - return JS_UNDEFINED; -} - -JSValue tf_tls_context_wrapper_init(JSContext* context) -{ - JS_NewClassID(&_classId); - JSClassDef def = - { - .class_name = "TlsContext", - .finalizer = _tls_context_wrapper_finalizer, - }; - if (JS_NewClass(JS_GetRuntime(context), _classId, &def) != 0) - { - fprintf(stderr, "Failed to register TlsContext.\n"); - } - return JS_NewCFunction2(context, _tls_context_wrapper_create, "TlsContext", 0, JS_CFUNC_constructor, 0); -} - -tf_tls_context_t* tf_tls_context_wrapper_get(JSValue value) -{ - tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(value, _classId); - return wrapper ? wrapper->context : NULL; -} - -int tf_tls_context_wrapper_get_count() -{ - return _count; -} - -JSValue _tls_context_wrapper_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) -{ - tf_tls_context_wrapper_t* wrapper = malloc(sizeof(tf_tls_context_wrapper_t)); - memset(wrapper, 0, sizeof(*wrapper)); - - ++_count; - wrapper->object = JS_NewObjectClass(context, _classId); - JS_SetOpaque(wrapper->object, wrapper); - - JS_SetPropertyStr(context, wrapper->object, "setCertificate", JS_NewCFunction(context, _tls_context_wrapper_set_certificate, "setCertificate", 1)); - JS_SetPropertyStr(context, wrapper->object, "setPrivateKey", JS_NewCFunction(context, _tls_context_wrapper_set_private_key, "setPrivateKey", 1)); - JS_SetPropertyStr(context, wrapper->object, "addTrustedCertificate", JS_NewCFunction(context, _tls_context_wrapper_add_trusted_certificate, "addTrustedCertificate", 1)); - - wrapper->context = tf_tls_context_create(); - wrapper->task = tf_task_get(context); - - return wrapper->object; -} - -void _tls_context_wrapper_finalizer(JSRuntime *runtime, JSValue value) -{ - tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(value, _classId); - if (wrapper->context) - { - tf_tls_context_destroy(wrapper->context); - wrapper->context = NULL; - } - --_count; - free(wrapper); -} diff --git a/src/tlscontextwrapper.h b/src/tlscontextwrapper.h deleted file mode 100644 index bd713618..00000000 --- a/src/tlscontextwrapper.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "quickjs.h" - -typedef struct _tf_tls_context_t tf_tls_context_t; - -JSValue tf_tls_context_wrapper_init(JSContext* context); -tf_tls_context_t* tf_tls_context_wrapper_get(JSValue value); -int tf_tls_context_wrapper_get_count(); diff --git a/src/trace.c b/src/trace.c index 217136f6..9357b7f1 100644 --- a/src/trace.c +++ b/src/trace.c @@ -8,14 +8,29 @@ #include +#if !defined(_countof) +#define _countof(a) ((int)(sizeof((a)) / sizeof(*(a)))) +#endif + enum { k_buffer_size = 4 * 1024 * 1024, }; +typedef struct _tf_trace_stack_t tf_trace_stack_t; + +typedef struct _tf_trace_stack_t +{ + const char* names[256]; + int count; + tf_trace_stack_t* next; +} tf_trace_stack_t; + typedef struct _tf_trace_t { char buffer[k_buffer_size]; int write_offset; + + tf_trace_stack_t* stack; } tf_trace_t; tf_trace_t* tf_trace_create() @@ -27,6 +42,12 @@ tf_trace_t* tf_trace_create() void tf_trace_destroy(tf_trace_t* trace) { + while (trace->stack) + { + tf_trace_stack_t* stack = trace->stack; + trace->stack = stack->next; + free(stack); + } free(trace); } @@ -82,8 +103,22 @@ void tf_trace_begin(tf_trace_t* trace, const char* name) return; } + if (!trace->stack || trace->stack->count + 1 < _countof(trace->stack->names)) + { + tf_trace_stack_t* stack = malloc(sizeof(tf_trace_stack_t)); + memset(stack, 0, sizeof(*stack)); + stack->next = trace->stack; + trace->stack = stack; + } + tf_trace_stack_t* stack = trace->stack; + while (stack->count == 0 && stack->next && stack->count + 1 < _countof(trace->stack->names)) + { + stack = stack->next; + } + stack->names[stack->count++] = name; + char line[1024]; - int p = snprintf(line, sizeof(line), "{\"ph\": \"B\", \"pid\": %d, \"ts\": %" PRId64 ", \"name\": \"", getpid(), _trace_ts()); + int p = snprintf(line, sizeof(line), "{\"ph\": \"B\", \"pid\": %d, \"tid\": 0, \"ts\": %" PRId64 ", \"name\": \"", getpid(), _trace_ts()); for (const char* c = name; *c && p < (int)sizeof(line); c++) { switch (*c) @@ -112,8 +147,33 @@ void tf_trace_end(tf_trace_t* trace) return; } + tf_trace_stack_t* stack = trace->stack; + while (stack && stack->count == 0) + { + stack = stack->next; + } + const char* name = stack && stack->count > 0 ? stack->names[stack->count - 1] : NULL; + char line[1024]; - int p = snprintf(line, sizeof(line), "{\"ph\": \"E\", \"pid\": %d, \"ts\": %" PRId64 "},", getpid(), _trace_ts()); + int p = snprintf(line, sizeof(line), "{\"ph\": \"E\", \"pid\": %d, \"tid\": 0, \"ts\": %" PRId64 ", \"name\": \"", getpid(), _trace_ts()); + for (const char* c = name; *c && p < (int)sizeof(line); c++) + { + switch (*c) + { + case '"': + case '\\': + line[p++] = '\\'; + if (p < (int)sizeof(line)) + { + line[p++] = *c; + } + break; + default: + line[p++] = *c; + break; + } + } + p += snprintf(line + p, sizeof(line) - p, "\"},"); _trace_append(trace, line, p); }