diff --git a/src/serialize.c b/src/serialize.c index 4f796239..498bdaa0 100644 --- a/src/serialize.c +++ b/src/serialize.c @@ -187,6 +187,36 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_ fprintf(stderr, "Unable to store number.\n"); } } + else if (JS_IsException(value)) + { + JSValue exception = JS_GetException(context); + const char* message = JS_ToCString(context, exception); + + JSValue error = JS_NewObject(context); + JS_SetPropertyStr(context, error, "message", JS_NewString(context, message ? message : "[exception]")); + + if (JS_IsError(context, exception)) + { + JSValue m = JS_GetPropertyStr(context, exception, "message"); + if (!JS_IsUndefined(m) && !JS_IsException(m)) + { + const char* ms = JS_ToCString(context, m); + JS_FreeCString(context, ms); + } + + JSValue stack = JS_GetPropertyStr(context, exception, "stack"); + if (!JS_IsUndefined(stack) && !JS_IsException(stack)) + { + JS_SetPropertyStr(context, error, "stack", JS_DupValue(context, stack)); + } + JS_FreeValue(context, stack); + } + _serialize_writeInt32(buffer, kException); + _serialize_storeInternal(task, to, buffer, error, depth + 1); + JS_FreeCString(context, message); + JS_FreeValue(context, error); + JS_FreeValue(context, exception); + } else if (JS_IsString(value)) { size_t len = 0; @@ -235,27 +265,6 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_ exportid_t exportId = tf_task_export_function(task, to, value); _serialize_writeInt32(buffer, exportId); } - else if (JS_IsException(value)) - { - JSValue exception = JS_GetException(context); - JSValue error = JS_NewObject(context); - JSValue message = JS_GetPropertyStr(context, exception, "message"); - if (!JS_IsException(message)) - { - JS_SetPropertyStr(context, error, "message", message); - } - if (JS_IsError(context, exception)) - { - JSValue stack = JS_GetPropertyStr(context, exception, "stack"); - if (!JS_IsUndefined(stack)) - { - JS_SetPropertyStr(context, error, "stack", JS_DupValue(context, stack)); - } - } - _serialize_writeInt32(buffer, kException); - _serialize_storeInternal(task, to, buffer, error, depth + 1); - JS_FreeValue(context, error); - } else if (JS_IsError(tf_task_get_context(task), value)) { _serialize_writeInt32(buffer, kError); diff --git a/src/ssb.db.c b/src/ssb.db.c index 4836af24..4e854826 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -526,17 +526,19 @@ static int _tf_ssb_sqlite_authorizer(void* user_data, int action_code, const cha return SQLITE_DENY; } -void tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds, void (*callback)(JSValue row, void* user_data), void* user_data) +JSValue tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds, void (*callback)(JSValue row, void* user_data), void* user_data) { + JSValue result = JS_UNDEFINED; sqlite3* db = tf_ssb_get_db(ssb); + JSContext* context = tf_ssb_get_context(ssb); sqlite3_stmt* statement; sqlite3_set_authorizer(db, _tf_ssb_sqlite_authorizer, ssb); if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK) { - JSContext* context = tf_ssb_get_context(ssb); if (_tf_ssb_sqlite_bind_json(context, db, statement, binds)) { - while (sqlite3_step(statement) == SQLITE_ROW) + int r = SQLITE_OK; + while ((r = sqlite3_step(statement)) == SQLITE_ROW) { JSValue row = _tf_ssb_sqlite_row_to_json(context, statement); tf_trace_t* trace = tf_ssb_get_trace(ssb); @@ -545,14 +547,19 @@ void tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds tf_trace_end(trace); JS_FreeValue(context, row); } + if (r != SQLITE_DONE) + { + result = JS_ThrowInternalError(context, "SQL Error %s: running \"%s\".", sqlite3_errmsg(db), query); + } } sqlite3_finalize(statement); } else { - printf("prepare failed: %s: %s\n", sqlite3_errmsg(db), query); + result = JS_ThrowInternalError(context, "SQL Error %s: preparing \"%s\".", sqlite3_errmsg(db), query); } sqlite3_set_authorizer(db, NULL, NULL); + return result; } static JSValue _tf_ssb_format_message(JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content, const char* signature, bool sequence_before_author) diff --git a/src/ssb.db.h b/src/ssb.db.h index 3016eea4..8a4b1571 100644 --- a/src/ssb.db.h +++ b/src/ssb.db.h @@ -13,7 +13,7 @@ bool tf_ssb_db_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char* bool tf_ssb_db_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* author, int64_t sequence, char* out_message_id, size_t out_message_id_size, double* out_timestamp, char** out_content); bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, int64_t* out_sequence, char* out_message_id, size_t out_message_id_size); -void tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds, void (*callback)(JSValue row, void* user_data), void* user_data); +JSValue tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds, void (*callback)(JSValue row, void* user_data), void* user_data); typedef struct sqlite3 sqlite3; bool tf_ssb_db_check(sqlite3* db, const char* author); diff --git a/src/ssb.js.c b/src/ssb.js.c index 293760e1..0241ea3e 100644 --- a/src/ssb.js.c +++ b/src/ssb.js.c @@ -177,21 +177,23 @@ static void _tf_ssb_sqlStream_callback(JSValue row, void* user_data) static JSValue _tf_ssb_sqlStream(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) { + JSValue result = JS_NULL; tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId); if (ssb) { const char* query = JS_ToCString(context, argv[0]); if (query) { - sqlStream_callback_t info = { + sqlStream_callback_t info = + { .context = context, .callback = argv[2], }; - tf_ssb_db_visit_query(ssb, query, argv[1], _tf_ssb_sqlStream_callback, &info); + result = tf_ssb_db_visit_query(ssb, query, argv[1], _tf_ssb_sqlStream_callback, &info); JS_FreeCString(context, query); } } - return JS_NULL; + return result; } static JSValue _tf_ssb_post(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) diff --git a/src/task.c b/src/task.c index e9f17751..93d3321a 100644 --- a/src/task.c +++ b/src/task.c @@ -1346,6 +1346,7 @@ static bool _tf_task_run_jobs(tf_task_t* task) if (context) { tf_util_report_error(context, result); + JS_FreeValue(context, result); } if (r < 0) { diff --git a/src/util.js.c b/src/util.js.c index c9c9a3af..43ea3d75 100644 --- a/src/util.js.c +++ b/src/util.js.c @@ -130,17 +130,15 @@ bool tf_util_report_error(JSContext* context, JSValue value) } else if (JS_IsException(value)) { - js_std_dump_error(context); - JSValue exception = JS_GetException(context); - const char* string = JS_ToCString(context, exception); - printf("Exception: %s\n", string); - JS_FreeCString(context, string); tf_task_t* task = tf_task_get(context); if (task) { - tf_task_send_error_to_parent(task, exception); + tf_task_send_error_to_parent(task, value); + } + else + { + js_std_dump_error(context); } - JS_FreeValue(context, exception); is_error = true; } return is_error;