ssb: sequence: Sequential 32-bit integer starting at 1.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 32m2s

This commit is contained in:
2025-06-11 20:12:23 -04:00
parent 2a6789063e
commit a1f1eb34d5
13 changed files with 89 additions and 84 deletions

View File

@ -204,7 +204,7 @@ class TfNewsElement extends LitElement {
this.finalize_messages(messages_by_id) this.finalize_messages(messages_by_id)
); );
let unread_rowid = -1; let unread_rowid = -1;
if (this.unread_allowed()) { if (this.unread_allowed()) {
for (let message of final_messages) { for (let message of final_messages) {
if (message.rowid >= this.channel_unread) { if (message.rowid >= this.channel_unread) {
unread_rowid = message.rowid; unread_rowid = message.rowid;

View File

@ -428,11 +428,16 @@ class TfTabNewsFeedElement extends LitElement {
if (!this.hash.startsWith('#%')) { if (!this.hash.startsWith('#%')) {
more = html` more = html`
<p> <p>
${this.unread_allowed() ? html` ${this.unread_allowed()
<button class="w3-button w3-theme-d1" @click=${this.mark_all_read}> ? html`
Mark All Read <button
</button> class="w3-button w3-theme-d1"
` : undefined} @click=${this.mark_all_read}
>
Mark All Read
</button>
`
: undefined}
<button <button
?disabled=${this.loading} ?disabled=${this.loading}
class="w3-button w3-theme-d1" class="w3-button w3-theme-d1"

View File

@ -501,7 +501,7 @@ static int _tf_command_publish(const char* file, int argc, char* argv[])
if (tf_ssb_db_identity_get_private_key(ssb, user, identity, private_key, sizeof(private_key))) if (tf_ssb_db_identity_get_private_key(ssb, user, identity, private_key, sizeof(private_key)))
{ {
JSContext* context = tf_ssb_get_context(ssb); JSContext* context = tf_ssb_get_context(ssb);
int64_t sequence = 0; int32_t sequence = 0;
char previous[k_id_base64_len] = { 0 }; char previous[k_id_base64_len] = { 0 };
tf_ssb_db_get_latest_message_by_author(ssb, identity, &sequence, previous, sizeof(previous)); tf_ssb_db_get_latest_message_by_author(ssb, identity, &sequence, previous, sizeof(previous));
JSValue content_value = JS_ParseJSON(context, content, strlen(content), NULL); JSValue content_value = JS_ParseJSON(context, content, strlen(content), NULL);
@ -653,7 +653,7 @@ static int _tf_command_private(const char* file, int argc, char* argv[])
char* encrypted = tf_ssb_private_message_encrypt(private_key, recipient_list, recipient_count, message_str, strlen(message_str)); char* encrypted = tf_ssb_private_message_encrypt(private_key, recipient_list, recipient_count, message_str, strlen(message_str));
if (encrypted) if (encrypted)
{ {
int64_t sequence = 0; int32_t sequence = 0;
char previous[k_id_base64_len] = { 0 }; char previous[k_id_base64_len] = { 0 };
tf_ssb_db_get_latest_message_by_author(ssb, identity, &sequence, previous, sizeof(previous)); tf_ssb_db_get_latest_message_by_author(ssb, identity, &sequence, previous, sizeof(previous));
@ -1084,9 +1084,9 @@ static int _tf_command_get_sequence(const char* file, int argc, char* argv[])
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL); tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
tf_ssb_set_quiet(ssb, true); tf_ssb_set_quiet(ssb, true);
int64_t sequence = -1; int32_t sequence = -1;
int result = tf_ssb_db_get_latest_message_by_author(ssb, identity, &sequence, NULL, 0) ? EXIT_SUCCESS : EXIT_FAILURE; int result = tf_ssb_db_get_latest_message_by_author(ssb, identity, &sequence, NULL, 0) ? EXIT_SUCCESS : EXIT_FAILURE;
tf_printf("%" PRId64 "\n", sequence); tf_printf("%d\n", sequence);
tf_ssb_destroy(ssb); tf_ssb_destroy(ssb);
tf_free((void*)default_db_path); tf_free((void*)default_db_path);
return result; return result;
@ -1304,7 +1304,7 @@ static int _tf_command_verify(const char* file, int argc, char* argv[])
const char* identity = NULL; const char* identity = NULL;
const char* default_db_path = _get_db_path(); const char* default_db_path = _get_db_path();
const char* db_path = default_db_path; const char* db_path = default_db_path;
int64_t sequence = 0; int32_t sequence = 0;
bool show_usage = false; bool show_usage = false;
while (!show_usage) while (!show_usage)
@ -1333,7 +1333,7 @@ static int _tf_command_verify(const char* file, int argc, char* argv[])
identity = optarg; identity = optarg;
break; break;
case 's': case 's':
sequence = atoll(optarg); sequence = atoi(optarg);
break; break;
case 'd': case 'd':
db_path = optarg; db_path = optarg;

View File

@ -1917,10 +1917,10 @@ static bool _tf_ssb_connection_box_stream_recv(tf_ssb_connection_t* connection)
return true; return true;
} }
JSValue tf_ssb_sign_message(tf_ssb_t* ssb, const char* author, const uint8_t* private_key, JSValue message, const char* previous_id, int64_t previous_sequence) JSValue tf_ssb_sign_message(tf_ssb_t* ssb, const char* author, const uint8_t* private_key, JSValue message, const char* previous_id, int32_t previous_sequence)
{ {
char actual_previous_id[crypto_hash_sha256_BYTES * 2]; char actual_previous_id[crypto_hash_sha256_BYTES * 2];
int64_t actual_previous_sequence = 0; int32_t actual_previous_sequence = 0;
bool have_previous = false; bool have_previous = false;
if (previous_id) if (previous_id)
{ {
@ -1938,7 +1938,7 @@ JSValue tf_ssb_sign_message(tf_ssb_t* ssb, const char* author, const uint8_t* pr
JS_SetPropertyStr(context, root, "previous", have_previous ? JS_NewString(context, actual_previous_id) : JS_NULL); JS_SetPropertyStr(context, root, "previous", have_previous ? JS_NewString(context, actual_previous_id) : JS_NULL);
JS_SetPropertyStr(context, root, "author", JS_NewString(context, author)); JS_SetPropertyStr(context, root, "author", JS_NewString(context, author));
JS_SetPropertyStr(context, root, "sequence", JS_NewInt64(context, actual_previous_sequence + 1)); JS_SetPropertyStr(context, root, "sequence", JS_NewInt32(context, actual_previous_sequence + 1));
int64_t now = (int64_t)time(NULL); int64_t now = (int64_t)time(NULL);
JS_SetPropertyStr(context, root, "timestamp", JS_NewInt64(context, now * 1000LL)); JS_SetPropertyStr(context, root, "timestamp", JS_NewInt64(context, now * 1000LL));
@ -3923,7 +3923,7 @@ void tf_ssb_notify_blob_stored(tf_ssb_t* ssb, const char* id)
ssb->blobs_stored++; ssb->blobs_stored++;
} }
void tf_ssb_notify_message_added(tf_ssb_t* ssb, const char* author, int64_t sequence, const char* id, JSValue message_keys) void tf_ssb_notify_message_added(tf_ssb_t* ssb, const char* author, int32_t sequence, const char* id, JSValue message_keys)
{ {
tf_ssb_message_added_callback_node_t* next = NULL; tf_ssb_message_added_callback_node_t* next = NULL;
ssb->messages_stored++; ssb->messages_stored++;

View File

@ -495,7 +495,7 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
tf_ssb_release_db_writer(ssb, db); tf_ssb_release_db_writer(ssb, db);
} }
static bool _tf_ssb_db_previous_message_exists(sqlite3* db, const char* author, int64_t sequence, const char* previous, bool* out_id_mismatch) static bool _tf_ssb_db_previous_message_exists(sqlite3* db, const char* author, int32_t sequence, const char* previous, bool* out_id_mismatch)
{ {
bool exists = false; bool exists = false;
if (sequence == 1) if (sequence == 1)
@ -507,7 +507,7 @@ static bool _tf_ssb_db_previous_message_exists(sqlite3* db, const char* author,
sqlite3_stmt* statement; sqlite3_stmt* statement;
if (sqlite3_prepare_v2(db, "SELECT COUNT(*), id != ?3 AS is_mismatch FROM messages WHERE author = ?1 AND sequence = ?2", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare_v2(db, "SELECT COUNT(*), id != ?3 AS is_mismatch FROM messages WHERE author = ?1 AND sequence = ?2", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, sequence - 1) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 2, sequence - 1) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, previous, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW) sqlite3_bind_text(statement, 3, previous, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW)
{ {
exists = sqlite3_column_int(statement, 0) != 0; exists = sqlite3_column_int(statement, 0) != 0;
@ -519,7 +519,7 @@ static bool _tf_ssb_db_previous_message_exists(sqlite3* db, const char* author,
return exists; return exists;
} }
static int64_t _tf_ssb_db_store_message_raw(sqlite3* db, const char* id, const char* previous, const char* author, int64_t sequence, double timestamp, const char* content, static int64_t _tf_ssb_db_store_message_raw(sqlite3* db, const char* id, const char* previous, const char* author, int32_t sequence, double timestamp, const char* content,
size_t content_len, const char* signature, int flags) size_t content_len, const char* signature, int flags)
{ {
int64_t last_row_id = -1; int64_t last_row_id = -1;
@ -534,7 +534,7 @@ static int64_t _tf_ssb_db_store_message_raw(sqlite3* db, const char* id, const c
{ {
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK &&
(previous ? sqlite3_bind_text(statement, 2, previous, -1, NULL) : sqlite3_bind_null(statement, 2)) == SQLITE_OK && (previous ? sqlite3_bind_text(statement, 2, previous, -1, NULL) : sqlite3_bind_null(statement, 2)) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 4, sequence) == SQLITE_OK && sqlite3_bind_text(statement, 3, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 4, sequence) == SQLITE_OK &&
sqlite3_bind_double(statement, 5, timestamp) == SQLITE_OK && sqlite3_bind_text(statement, 6, content, content_len, NULL) == SQLITE_OK && sqlite3_bind_double(statement, 5, timestamp) == SQLITE_OK && sqlite3_bind_text(statement, 6, content, content_len, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 7, "sha256", 6, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 8, signature, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 7, "sha256", 6, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 8, signature, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int(statement, 9, flags) == SQLITE_OK) sqlite3_bind_int(statement, 9, flags) == SQLITE_OK)
@ -568,7 +568,7 @@ static int64_t _tf_ssb_db_store_message_raw(sqlite3* db, const char* id, const c
** message when trying to receive what we don't have, and ** message when trying to receive what we don't have, and
** that's not helping anybody. ** that's not helping anybody.
*/ */
tf_printf("%p: Previous message doesn't exist for author=%s sequence=%" PRId64 " previous=%s.\n", db, author, sequence, previous); tf_printf("%p: Previous message doesn't exist for author=%s sequence=%d previous=%s.\n", db, author, sequence, previous);
} }
return last_row_id; return last_row_id;
} }
@ -625,7 +625,7 @@ typedef struct _message_store_t
int flags; int flags;
char previous[k_id_base64_len]; char previous[k_id_base64_len];
char author[k_id_base64_len]; char author[k_id_base64_len];
int64_t sequence; int32_t sequence;
double timestamp; double timestamp;
const char* content; const char* content;
size_t length; size_t length;
@ -761,9 +761,9 @@ void tf_ssb_db_store_message(
const char* author = JS_ToCString(context, authorval); const char* author = JS_ToCString(context, authorval);
JS_FreeValue(context, authorval); JS_FreeValue(context, authorval);
int64_t sequence = -1; int32_t sequence = -1;
JSValue sequenceval = JS_GetPropertyStr(context, val, "sequence"); JSValue sequenceval = JS_GetPropertyStr(context, val, "sequence");
JS_ToInt64(context, &sequence, sequenceval); JS_ToInt32(context, &sequence, sequenceval);
JS_FreeValue(context, sequenceval); JS_FreeValue(context, sequenceval);
double timestamp = -1.0; double timestamp = -1.0;
@ -1055,7 +1055,7 @@ bool tf_ssb_db_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char*
return result; return result;
} }
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, char* out_previous, bool tf_ssb_db_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* author, int32_t sequence, char* out_message_id, size_t out_message_id_size, char* out_previous,
size_t out_previous_size, double* out_timestamp, char** out_content, char* out_hash, size_t out_hash_size, char* out_signature, size_t out_signature_size, int* out_flags) size_t out_previous_size, double* out_timestamp, char** out_content, char* out_hash, size_t out_hash_size, char* out_signature, size_t out_signature_size, int* out_flags)
{ {
bool found = false; bool found = false;
@ -1064,7 +1064,7 @@ bool tf_ssb_db_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* aut
sqlite3* db = tf_ssb_acquire_db_reader(ssb); sqlite3* db = tf_ssb_acquire_db_reader(ssb);
if (sqlite3_prepare_v2(db, query, -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare_v2(db, query, -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, sequence) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW) if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 2, sequence) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW)
{ {
if (out_message_id) if (out_message_id)
{ {
@ -1116,7 +1116,7 @@ bool tf_ssb_db_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* aut
return found; return found;
} }
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) bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, int32_t* out_sequence, char* out_message_id, size_t out_message_id_size)
{ {
bool found = false; bool found = false;
sqlite3_stmt* statement; sqlite3_stmt* statement;
@ -1131,7 +1131,7 @@ bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, i
{ {
if (out_sequence) if (out_sequence)
{ {
*out_sequence = sqlite3_column_int64(statement, 1); *out_sequence = sqlite3_column_int(statement, 1);
} }
if (out_message_id) if (out_message_id)
{ {
@ -1155,7 +1155,7 @@ bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, i
{ {
if (out_sequence) if (out_sequence)
{ {
*out_sequence = sqlite3_column_int64(statement, 0); *out_sequence = sqlite3_column_int(statement, 0);
} }
found = true; found = true;
} }
@ -1333,19 +1333,19 @@ JSValue tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue bi
} }
JSValue tf_ssb_format_message( 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, int flags) JSContext* context, const char* previous, const char* author, int32_t sequence, double timestamp, const char* hash, const char* content, const char* signature, int flags)
{ {
JSValue value = JS_NewObject(context); JSValue value = JS_NewObject(context);
JS_SetPropertyStr(context, value, "previous", (previous && *previous) ? JS_NewString(context, previous) : JS_NULL); JS_SetPropertyStr(context, value, "previous", (previous && *previous) ? JS_NewString(context, previous) : JS_NULL);
if (flags & k_tf_ssb_message_flag_sequence_before_author) if (flags & k_tf_ssb_message_flag_sequence_before_author)
{ {
JS_SetPropertyStr(context, value, "sequence", JS_NewInt64(context, sequence)); JS_SetPropertyStr(context, value, "sequence", JS_NewInt32(context, sequence));
JS_SetPropertyStr(context, value, "author", JS_NewString(context, author)); JS_SetPropertyStr(context, value, "author", JS_NewString(context, author));
} }
else else
{ {
JS_SetPropertyStr(context, value, "author", JS_NewString(context, author)); JS_SetPropertyStr(context, value, "author", JS_NewString(context, author));
JS_SetPropertyStr(context, value, "sequence", JS_NewInt64(context, sequence)); JS_SetPropertyStr(context, value, "sequence", JS_NewInt32(context, sequence));
} }
JS_SetPropertyStr(context, value, "timestamp", JS_NewFloat64(context, timestamp)); JS_SetPropertyStr(context, value, "timestamp", JS_NewFloat64(context, timestamp));
JS_SetPropertyStr(context, value, "hash", JS_NewString(context, hash)); JS_SetPropertyStr(context, value, "hash", JS_NewString(context, hash));
@ -1552,12 +1552,12 @@ typedef struct _following_t following_t;
typedef struct _following_t typedef struct _following_t
{ {
char id[k_id_base64_len]; char id[k_id_base64_len];
int depth;
bool populated; bool populated;
following_t** following; following_t** following;
following_t** blocking; following_t** blocking;
int following_count; int following_count;
int blocking_count; int blocking_count;
int depth;
int ref_count; int ref_count;
int block_ref_count; int block_ref_count;
} following_t; } following_t;
@ -1783,8 +1783,7 @@ tf_ssb_following_t* tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, in
{ {
if (following[i]->ref_count > 0 || include_blocks) if (following[i]->ref_count > 0 || include_blocks)
{ {
result[write_index] = (tf_ssb_following_t) result[write_index] = (tf_ssb_following_t) {
{
.following_count = following[i]->following_count, .following_count = following[i]->following_count,
.blocking_count = following[i]->blocking_count, .blocking_count = following[i]->blocking_count,
.followed_by_count = following[i]->ref_count, .followed_by_count = following[i]->ref_count,
@ -1902,7 +1901,7 @@ JSValue tf_ssb_db_get_message_by_id(tf_ssb_t* ssb, const char* id, bool is_keys)
{ {
JSValue message = JS_UNDEFINED; JSValue message = JS_UNDEFINED;
JSValue formatted = tf_ssb_format_message(context, (const char*)sqlite3_column_text(statement, 0), (const char*)sqlite3_column_text(statement, 1), JSValue formatted = tf_ssb_format_message(context, (const char*)sqlite3_column_text(statement, 0), (const char*)sqlite3_column_text(statement, 1),
sqlite3_column_int64(statement, 3), sqlite3_column_double(statement, 4), (const char*)sqlite3_column_text(statement, 5), sqlite3_column_int(statement, 3), sqlite3_column_double(statement, 4), (const char*)sqlite3_column_text(statement, 5),
(const char*)sqlite3_column_text(statement, 6), (const char*)sqlite3_column_text(statement, 7), sqlite3_column_int(statement, 8)); (const char*)sqlite3_column_text(statement, 6), (const char*)sqlite3_column_text(statement, 7), sqlite3_column_int(statement, 8));
if (is_keys) if (is_keys)
{ {
@ -2290,14 +2289,14 @@ static void _tf_ssb_db_set_flags(tf_ssb_t* ssb, const char* message_id, int flag
tf_ssb_release_db_writer(ssb, db); tf_ssb_release_db_writer(ssb, db);
} }
bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, int64_t debug_sequence, bool fix) bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, int32_t debug_sequence, bool fix)
{ {
JSContext* context = tf_ssb_get_context(ssb); JSContext* context = tf_ssb_get_context(ssb);
bool verified = true; bool verified = true;
int64_t sequence = -1; int32_t sequence = -1;
if (tf_ssb_db_get_latest_message_by_author(ssb, id, &sequence, NULL, 0)) if (tf_ssb_db_get_latest_message_by_author(ssb, id, &sequence, NULL, 0))
{ {
for (int64_t i = 1; i <= sequence; i++) for (int32_t i = 1; i <= sequence; i++)
{ {
char message_id[k_id_base64_len]; char message_id[k_id_base64_len];
char previous[256]; char previous[256];
@ -2316,12 +2315,12 @@ bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, int64_t debug_sequence, boo
if (!tf_ssb_verify_and_strip_signature(context, message, i == debug_sequence ? k_tf_ssb_verify_flag_debug : 0, calculated_id, sizeof(calculated_id), if (!tf_ssb_verify_and_strip_signature(context, message, i == debug_sequence ? k_tf_ssb_verify_flag_debug : 0, calculated_id, sizeof(calculated_id),
extracted_signature, sizeof(extracted_signature), &calculated_flags)) extracted_signature, sizeof(extracted_signature), &calculated_flags))
{ {
tf_printf("author=%s sequence=%" PRId64 " verify failed.\n", id, i); tf_printf("author=%s sequence=%d verify failed.\n", id, i);
verified = false; verified = false;
} }
if (calculated_flags != flags) if (calculated_flags != flags)
{ {
tf_printf("author=%s sequence=%" PRId64 " flag mismatch %d => %d.\n", id, i, flags, calculated_flags); tf_printf("author=%s sequence=%d flag mismatch %d => %d.\n", id, i, flags, calculated_flags);
if (fix) if (fix)
{ {
_tf_ssb_db_set_flags(ssb, message_id, calculated_flags); _tf_ssb_db_set_flags(ssb, message_id, calculated_flags);
@ -2333,7 +2332,7 @@ bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, int64_t debug_sequence, boo
} }
if (strcmp(message_id, calculated_id)) if (strcmp(message_id, calculated_id))
{ {
tf_printf("author=%s sequence=%" PRId64 " id mismatch %s => %s.\n", id, i, message_id, calculated_id); tf_printf("author=%s sequence=%d id mismatch %s => %s.\n", id, i, message_id, calculated_id);
verified = false; verified = false;
} }
JS_FreeValue(context, message); JS_FreeValue(context, message);
@ -2346,7 +2345,7 @@ bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, int64_t debug_sequence, boo
} }
else else
{ {
tf_printf("Unable to find message with sequence=%" PRId64 " for author=%s.", i, id); tf_printf("Unable to find message with sequence=%d for author=%s.", i, id);
verified = false; verified = false;
break; break;
} }

View File

@ -151,7 +151,7 @@ JSValue tf_ssb_db_get_message_by_id(tf_ssb_t* ssb, const char* id, bool is_keys)
** @param[out] out_flags Populated with flags describing the format of the message. ** @param[out] out_flags Populated with flags describing the format of the message.
** @return True if the message was found and retrieved. ** @return True if the message was found and retrieved.
*/ */
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, char* out_previous, bool tf_ssb_db_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* author, int32_t sequence, char* out_message_id, size_t out_message_id_size, char* out_previous,
size_t out_previous_size, double* out_timestamp, char** out_content, char* out_hash, size_t out_hash_size, char* out_signature, size_t out_signature_size, int* out_flags); size_t out_previous_size, double* out_timestamp, char** out_content, char* out_hash, size_t out_hash_size, char* out_signature, size_t out_signature_size, int* out_flags);
/** /**
@ -163,7 +163,7 @@ bool tf_ssb_db_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* aut
** @param out_message_id_size The size of the out_message_id buffer. ** @param out_message_id_size The size of the out_message_id buffer.
** @return True if the message was found and information was retrieved. ** @return True if the message was found and information was retrieved.
*/ */
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); bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, int32_t* out_sequence, char* out_message_id, size_t out_message_id_size);
/** /**
** Call a function for each result row of an SQL query. ** Call a function for each result row of an SQL query.
@ -281,7 +281,7 @@ bool tf_ssb_db_identity_get_private_key(tf_ssb_t* ssb, const char* user, const c
** @param flags tf_ssb_message_flags_t describing the message. ** @param flags tf_ssb_message_flags_t describing the message.
*/ */
JSValue tf_ssb_format_message( 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, int flags); JSContext* context, const char* previous, const char* author, int32_t sequence, double timestamp, const char* hash, const char* content, const char* signature, int flags);
/** Information about a single followed account. */ /** Information about a single followed account. */
typedef struct _tf_ssb_following_t typedef struct _tf_ssb_following_t
@ -460,7 +460,7 @@ void tf_ssb_db_resolve_index_async(tf_ssb_t* ssb, const char* host, void (*callb
** @param fix Fix invalid messages when possible. ** @param fix Fix invalid messages when possible.
** @return true If the feed verified successfully. ** @return true If the feed verified successfully.
*/ */
bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, int64_t debug_sequence, bool fix); bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, int32_t debug_sequence, bool fix);
/** /**
** Check if a user has a specific permission. ** Check if a user has a specific permission.

View File

@ -128,8 +128,8 @@ void tf_ssb_ebt_receive_clock(tf_ssb_ebt_t* ebt, JSContext* context, JSValue clo
if (!JS_IsUndefined(in_clock)) if (!JS_IsUndefined(in_clock))
{ {
const char* author = JS_AtomToCString(context, ptab[i].atom); const char* author = JS_AtomToCString(context, ptab[i].atom);
int64_t sequence = -1; int32_t sequence = -1;
JS_ToInt64(context, &sequence, in_clock); JS_ToInt32(context, &sequence, in_clock);
ebt_entry_t* entry = _ebt_get_entry(ebt, author); ebt_entry_t* entry = _ebt_get_entry(ebt, author);
if (entry) if (entry)
@ -235,12 +235,12 @@ static void _tf_ssb_ebt_get_send_clock_work(tf_ssb_connection_t* connection, voi
const char** visible = tf_ssb_db_get_all_visible_identities(ssb, depth); const char** visible = tf_ssb_db_get_all_visible_identities(ssb, depth);
if (visible) if (visible)
{ {
int64_t* sequences = NULL; int32_t* sequences = NULL;
for (int i = 0; visible[i]; i++) for (int i = 0; visible[i]; i++)
{ {
int64_t sequence = 0; int32_t sequence = 0;
tf_ssb_db_get_latest_message_by_author(ssb, visible[i], &sequence, NULL, 0); tf_ssb_db_get_latest_message_by_author(ssb, visible[i], &sequence, NULL, 0);
sequences = tf_resize_vec(sequences, (i + 1) * sizeof(int64_t)); sequences = tf_resize_vec(sequences, (i + 1) * sizeof(int32_t));
sequences[i] = sequence; sequences[i] = sequence;
} }
@ -259,7 +259,7 @@ static void _tf_ssb_ebt_get_send_clock_work(tf_ssb_connection_t* connection, voi
char id[k_id_base64_len] = ""; char id[k_id_base64_len] = "";
if (tf_ssb_connection_get_id(connection, id, sizeof(id))) if (tf_ssb_connection_get_id(connection, id, sizeof(id)))
{ {
int64_t sequence = 0; int32_t sequence = 0;
tf_ssb_db_get_latest_message_by_author(ssb, id, &sequence, NULL, 0); tf_ssb_db_get_latest_message_by_author(ssb, id, &sequence, NULL, 0);
uv_mutex_lock(&work->ebt->mutex); uv_mutex_lock(&work->ebt->mutex);
_ebt_add_to_clock(work, id, sequence, true, true); _ebt_add_to_clock(work, id, sequence, true, true);
@ -348,7 +348,7 @@ tf_ssb_ebt_clock_t* tf_ssb_ebt_get_messages_to_send(tf_ssb_ebt_t* ebt)
return clock; return clock;
} }
void tf_ssb_ebt_set_messages_sent(tf_ssb_ebt_t* ebt, const char* id, int64_t sequence) void tf_ssb_ebt_set_messages_sent(tf_ssb_ebt_t* ebt, const char* id, int32_t sequence)
{ {
uv_mutex_lock(&ebt->mutex); uv_mutex_lock(&ebt->mutex);
ebt_entry_t* entry = _ebt_get_entry(ebt, id); ebt_entry_t* entry = _ebt_get_entry(ebt, id);
@ -363,7 +363,7 @@ void tf_ssb_ebt_set_messages_sent(tf_ssb_ebt_t* ebt, const char* id, int64_t seq
uv_mutex_unlock(&ebt->mutex); uv_mutex_unlock(&ebt->mutex);
} }
void tf_ssb_ebt_set_messages_received(tf_ssb_ebt_t* ebt, const char* id, int64_t sequence) void tf_ssb_ebt_set_messages_received(tf_ssb_ebt_t* ebt, const char* id, int32_t sequence)
{ {
uv_mutex_lock(&ebt->mutex); uv_mutex_lock(&ebt->mutex);
ebt_entry_t* entry = _ebt_get_entry(ebt, id); ebt_entry_t* entry = _ebt_get_entry(ebt, id);

View File

@ -19,7 +19,7 @@ typedef struct _tf_ssb_ebt_clock_entry_t
/** The identity. */ /** The identity. */
char id[k_id_base64_len]; char id[k_id_base64_len];
/** The sequence number. */ /** The sequence number. */
int64_t value; int32_t value;
} tf_ssb_ebt_clock_entry_t; } tf_ssb_ebt_clock_entry_t;
/** /**
@ -76,7 +76,7 @@ tf_ssb_ebt_clock_t* tf_ssb_ebt_get_messages_to_send(tf_ssb_ebt_t* ebt);
** @param id The identity to update. ** @param id The identity to update.
** @param sequence The maximum sequence number sent. ** @param sequence The maximum sequence number sent.
*/ */
void tf_ssb_ebt_set_messages_sent(tf_ssb_ebt_t* ebt, const char* id, int64_t sequence); void tf_ssb_ebt_set_messages_sent(tf_ssb_ebt_t* ebt, const char* id, int32_t sequence);
/** /**
** Update the clock state indicating the messages that have been received for an account. ** Update the clock state indicating the messages that have been received for an account.
@ -84,7 +84,7 @@ void tf_ssb_ebt_set_messages_sent(tf_ssb_ebt_t* ebt, const char* id, int64_t seq
** @param id The identity to update. ** @param id The identity to update.
** @param sequence The maximum sequence number received. ** @param sequence The maximum sequence number received.
*/ */
void tf_ssb_ebt_set_messages_received(tf_ssb_ebt_t* ebt, const char* id, int64_t sequence); void tf_ssb_ebt_set_messages_received(tf_ssb_ebt_t* ebt, const char* id, int32_t sequence);
/** /**
** Destroy an EBT instance. ** Destroy an EBT instance.

View File

@ -323,7 +323,7 @@ void tf_ssb_run(tf_ssb_t* ssb);
** @param previous_sequence The sequence number of the previous message in the feed. Optional. ** @param previous_sequence The sequence number of the previous message in the feed. Optional.
** @return The signed message. ** @return The signed message.
*/ */
JSValue tf_ssb_sign_message(tf_ssb_t* ssb, const char* author, const uint8_t* private_key, JSValue message, const char* previous_id, int64_t previous_sequence); JSValue tf_ssb_sign_message(tf_ssb_t* ssb, const char* author, const uint8_t* private_key, JSValue message, const char* previous_id, int32_t previous_sequence);
/** /**
** Get the server's identity. ** Get the server's identity.
@ -651,7 +651,7 @@ void tf_ssb_remove_broadcasts_changed_callback(tf_ssb_t* ssb, tf_ssb_broadcasts_
** @param id The message identifier. ** @param id The message identifier.
** @param user_data The user data. ** @param user_data The user data.
*/ */
typedef void(tf_ssb_message_added_callback_t)(tf_ssb_t* ssb, const char* author, int64_t sequence, const char* id, void* user_data); typedef void(tf_ssb_message_added_callback_t)(tf_ssb_t* ssb, const char* author, int32_t sequence, const char* id, void* user_data);
/** /**
** Register a callback called when a message is added to the database. ** Register a callback called when a message is added to the database.
@ -678,7 +678,7 @@ void tf_ssb_remove_message_added_callback(tf_ssb_t* ssb, tf_ssb_message_added_ca
** @param id The message identity added. ** @param id The message identity added.
** @param message_with_keys The message added in the format required if keys are requested. ** @param message_with_keys The message added in the format required if keys are requested.
*/ */
void tf_ssb_notify_message_added(tf_ssb_t* ssb, const char* author, int64_t sequence, const char* id, JSValue message_with_keys); void tf_ssb_notify_message_added(tf_ssb_t* ssb, const char* author, int32_t sequence, const char* id, JSValue message_with_keys);
/** /**
** Record that a new blob was stored. ** Record that a new blob was stored.

View File

@ -696,7 +696,7 @@ typedef struct _append_message_t
uint8_t private_key[crypto_sign_SECRETKEYBYTES]; uint8_t private_key[crypto_sign_SECRETKEYBYTES];
bool got_private_key; bool got_private_key;
char previous_id[512]; char previous_id[512];
int64_t previous_sequence; int32_t previous_sequence;
JSContext* context; JSContext* context;
JSValue promise[2]; JSValue promise[2];
JSValue message; JSValue message;
@ -1604,7 +1604,7 @@ static void _tf_ssb_cleanup_value(tf_ssb_t* ssb, void* user_data)
JS_FreeValue(tf_ssb_get_context(ssb), callback); JS_FreeValue(tf_ssb_get_context(ssb), callback);
} }
static void _tf_ssb_on_message_added_callback(tf_ssb_t* ssb, const char* author, int64_t sequence, const char* id, void* user_data) static void _tf_ssb_on_message_added_callback(tf_ssb_t* ssb, const char* author, int32_t sequence, const char* id, void* user_data)
{ {
JSContext* context = tf_ssb_get_context(ssb); JSContext* context = tf_ssb_get_context(ssb);
JSValue callback = JS_MKPTR(JS_TAG_OBJECT, user_data); JSValue callback = JS_MKPTR(JS_TAG_OBJECT, user_data);

View File

@ -16,7 +16,7 @@
#include <time.h> #include <time.h>
static void _tf_ssb_connection_send_history_stream( static void _tf_ssb_connection_send_history_stream(
tf_ssb_connection_t* connection, int32_t request_number, const char* author, int64_t sequence, bool keys, bool live, bool end_request); tf_ssb_connection_t* connection, int32_t request_number, const char* author, int32_t sequence, bool keys, bool live, bool end_request);
static void _tf_ssb_rpc_send_peers_exchange(tf_ssb_connection_t* connection); static void _tf_ssb_rpc_send_peers_exchange(tf_ssb_connection_t* connection);
static void _tf_ssb_rpc_start_delete_blobs(tf_ssb_t* ssb, int delay_ms); static void _tf_ssb_rpc_start_delete_blobs(tf_ssb_t* ssb, int delay_ms);
static void _tf_ssb_rpc_start_delete_feeds(tf_ssb_t* ssb, int delay_ms); static void _tf_ssb_rpc_start_delete_feeds(tf_ssb_t* ssb, int delay_ms);
@ -863,13 +863,13 @@ typedef struct _tf_ssb_connection_send_history_stream_t
{ {
int32_t request_number; int32_t request_number;
char author[k_id_base64_len]; char author[k_id_base64_len];
int64_t sequence; int32_t sequence;
bool keys; bool keys;
bool live; bool live;
bool end_request; bool end_request;
bool out_finished; bool out_finished;
int64_t out_max_sequence_seen; int32_t out_max_sequence_seen;
char** out_messages; char** out_messages;
int out_messages_count; int out_messages_count;
} tf_ssb_connection_send_history_stream_t; } tf_ssb_connection_send_history_stream_t;
@ -890,8 +890,8 @@ static void _tf_ssb_connection_send_history_stream_work(tf_ssb_connection_t* con
"sequence < ?3 ORDER BY sequence", "sequence < ?3 ORDER BY sequence",
-1, &statement, NULL) == SQLITE_OK) -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, request->author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, request->sequence) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, request->author, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 2, request->sequence) == SQLITE_OK &&
sqlite3_bind_int64(statement, 3, request->sequence + k_max) == SQLITE_OK) sqlite3_bind_int(statement, 3, request->sequence + k_max) == SQLITE_OK)
{ {
JSMallocFunctions funcs = { 0 }; JSMallocFunctions funcs = { 0 };
tf_get_js_malloc_functions(&funcs); tf_get_js_malloc_functions(&funcs);
@ -902,7 +902,7 @@ static void _tf_ssb_connection_send_history_stream_work(tf_ssb_connection_t* con
while ((r = sqlite3_step(statement)) == SQLITE_ROW) while ((r = sqlite3_step(statement)) == SQLITE_ROW)
{ {
JSValue message = JS_UNDEFINED; JSValue message = JS_UNDEFINED;
request->out_max_sequence_seen = sqlite3_column_int64(statement, 3); request->out_max_sequence_seen = sqlite3_column_int(statement, 3);
JSValue formatted = tf_ssb_format_message(context, (const char*)sqlite3_column_text(statement, 0), (const char*)sqlite3_column_text(statement, 1), JSValue formatted = tf_ssb_format_message(context, (const char*)sqlite3_column_text(statement, 0), (const char*)sqlite3_column_text(statement, 1),
sqlite3_column_int64(statement, 3), sqlite3_column_double(statement, 4), (const char*)sqlite3_column_text(statement, 5), sqlite3_column_int64(statement, 3), sqlite3_column_double(statement, 4), (const char*)sqlite3_column_text(statement, 5),
@ -997,7 +997,7 @@ static void _tf_ssb_connection_send_history_stream_callback(tf_ssb_connection_t*
} }
static void _tf_ssb_connection_send_history_stream( static void _tf_ssb_connection_send_history_stream(
tf_ssb_connection_t* connection, int32_t request_number, const char* author, int64_t sequence, bool keys, bool live, bool end_request) tf_ssb_connection_t* connection, int32_t request_number, const char* author, int32_t sequence, bool keys, bool live, bool end_request)
{ {
if (tf_ssb_connection_is_connected(connection) && !tf_ssb_is_shutting_down(tf_ssb_connection_get_ssb(connection)) && !tf_ssb_connection_is_closing(connection)) if (tf_ssb_connection_is_connected(connection) && !tf_ssb_is_shutting_down(tf_ssb_connection_get_ssb(connection)) && !tf_ssb_connection_is_closing(connection))
{ {
@ -1036,8 +1036,8 @@ static void _tf_ssb_rpc_createHistoryStream(
JSValue live = JS_GetPropertyStr(context, arg, "live"); JSValue live = JS_GetPropertyStr(context, arg, "live");
bool is_keys = JS_IsUndefined(keys) || JS_ToBool(context, keys) > 0; bool is_keys = JS_IsUndefined(keys) || JS_ToBool(context, keys) > 0;
bool is_live = JS_ToBool(context, live) > 0 && (tf_ssb_connection_get_flags(connection) & k_tf_ssb_connect_flag_one_shot) == 0; bool is_live = JS_ToBool(context, live) > 0 && (tf_ssb_connection_get_flags(connection) & k_tf_ssb_connect_flag_one_shot) == 0;
int64_t sequence = 0; int32_t sequence = 0;
JS_ToInt64(context, &sequence, seq); JS_ToInt32(context, &sequence, seq);
const char* author = JS_ToCString(context, id); const char* author = JS_ToCString(context, id);
_tf_ssb_connection_send_history_stream(connection, -request_number, author, sequence, is_keys, is_live, true); _tf_ssb_connection_send_history_stream(connection, -request_number, author, sequence, is_keys, is_live, true);
@ -1258,7 +1258,7 @@ typedef struct _invite_use_t
; ;
uint8_t private_key[512]; uint8_t private_key[512];
char previous_id[64]; char previous_id[64];
int64_t previous_sequence; int32_t previous_sequence;
char host[256]; char host[256];
int port; int port;
@ -1780,7 +1780,7 @@ typedef struct _invite_t
int32_t request_number; int32_t request_number;
bool accepted; bool accepted;
char previous_id[256]; char previous_id[256];
int64_t previous_sequence; int32_t previous_sequence;
char* message; char* message;
} invite_t; } invite_t;
@ -1882,7 +1882,7 @@ static void _tf_ssb_rpc_invite_use(tf_ssb_connection_t* connection, uint8_t flag
tf_ssb_connection_run_work(connection, _tf_ssb_rpc_invite_use_work, _tf_ssb_rpc_invite_use_after_work, work); tf_ssb_connection_run_work(connection, _tf_ssb_rpc_invite_use_work, _tf_ssb_rpc_invite_use_after_work, work);
} }
static void _tf_ssb_rpc_message_added_callback(tf_ssb_t* ssb, const char* author, int64_t sequence, const char* id, void* user_data) static void _tf_ssb_rpc_message_added_callback(tf_ssb_t* ssb, const char* author, int32_t sequence, const char* id, void* user_data)
{ {
tf_ssb_connection_t* connections[256]; tf_ssb_connection_t* connections[256];
int count = tf_ssb_get_connections(ssb, connections, tf_countof(connections)); int count = tf_ssb_get_connections(ssb, connections, tf_countof(connections));

View File

@ -114,7 +114,7 @@ static int _ssb_test_count_messages(tf_ssb_t* ssb)
return count.count; return count.count;
} }
static void _message_added(tf_ssb_t* ssb, const char* author, int64_t sequence, const char* id, void* user_data) static void _message_added(tf_ssb_t* ssb, const char* author, int32_t sequence, const char* id, void* user_data)
{ {
++*(int*)user_data; ++*(int*)user_data;
} }
@ -1046,11 +1046,11 @@ void tf_ssb_test_publish(const tf_test_options_t* options)
static void _test_print_identity(const char* identity, void* user_data) static void _test_print_identity(const char* identity, void* user_data)
{ {
tf_ssb_t* ssb = user_data; tf_ssb_t* ssb = user_data;
int64_t sequence = -1; int32_t sequence = -1;
char id[k_id_base64_len] = { 0 }; char id[k_id_base64_len] = { 0 };
snprintf(id, sizeof(id), "@%s", identity); snprintf(id, sizeof(id), "@%s", identity);
tf_ssb_db_get_latest_message_by_author(ssb, id, &sequence, NULL, 0); tf_ssb_db_get_latest_message_by_author(ssb, id, &sequence, NULL, 0);
tf_printf("IDENTITY %s: %d\n", id, (int)sequence); tf_printf("IDENTITY %s: %d\n", id, sequence);
} }
void tf_ssb_test_replicate(const tf_test_options_t* options) void tf_ssb_test_replicate(const tf_test_options_t* options)
@ -1436,9 +1436,9 @@ void tf_ssb_test_triggers(const tf_test_options_t* options)
clock_gettime(CLOCK_REALTIME, &end_time); clock_gettime(CLOCK_REALTIME, &end_time);
tf_printf("insert = %f seconds\n", (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1e9); tf_printf("insert = %f seconds\n", (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1e9);
int64_t max_sequence = 0; int32_t max_sequence = 0;
tf_ssb_db_get_latest_message_by_author(ssb0, id0, &max_sequence, NULL, 0); tf_ssb_db_get_latest_message_by_author(ssb0, id0, &max_sequence, NULL, 0);
tf_printf("max_sequence=%" PRId64 "\n", max_sequence); tf_printf("max_sequence=%d\n", max_sequence);
assert(max_sequence == 5); assert(max_sequence == 5);
sqlite3* db = tf_ssb_acquire_db_writer(ssb0); sqlite3* db = tf_ssb_acquire_db_writer(ssb0);
@ -1447,7 +1447,7 @@ void tf_ssb_test_triggers(const tf_test_options_t* options)
max_sequence = 0; max_sequence = 0;
tf_ssb_db_get_latest_message_by_author(ssb0, id0, &max_sequence, NULL, 0); tf_ssb_db_get_latest_message_by_author(ssb0, id0, &max_sequence, NULL, 0);
tf_printf("max_sequence=%" PRId64 "\n", max_sequence); tf_printf("max_sequence=%d\n", max_sequence);
assert(max_sequence == 4); assert(max_sequence == 4);
tf_ssb_acquire_db_writer(ssb0); tf_ssb_acquire_db_writer(ssb0);
@ -1456,7 +1456,7 @@ void tf_ssb_test_triggers(const tf_test_options_t* options)
max_sequence = 0; max_sequence = 0;
tf_ssb_db_get_latest_message_by_author(ssb0, id0, &max_sequence, NULL, 0); tf_ssb_db_get_latest_message_by_author(ssb0, id0, &max_sequence, NULL, 0);
tf_printf("max_sequence=%" PRId64 "\n", max_sequence); tf_printf("max_sequence=%d\n", max_sequence);
assert(max_sequence == 0); assert(max_sequence == 0);
uv_run(&loop, UV_RUN_DEFAULT); uv_run(&loop, UV_RUN_DEFAULT);

View File

@ -84,7 +84,7 @@ typedef struct _promise_stack_t
uint32_t hash; uint32_t hash;
int count; int count;
const char* stack; const char* stack;
void* cstack[32]; void* cstack[31];
int cstack_count; int cstack_count;
} promise_stack_t; } promise_stack_t;
@ -1220,6 +1220,7 @@ static void _add_promise_stack(tf_task_t* task, uint32_t hash, const char* stack
{ {
memmove(task->_promise_stacks + index + 1, task->_promise_stacks + index, sizeof(promise_stack_t) * (task->_promise_stack_count - index)); memmove(task->_promise_stacks + index + 1, task->_promise_stacks + index, sizeof(promise_stack_t) * (task->_promise_stack_count - index));
} }
count = tf_min(count, tf_countof(task->_promise_stacks[index].cstack));
task->_promise_stacks[index] = (promise_stack_t) { .hash = hash, .stack = tf_strdup(stack), .count = 1, .cstack_count = count }; task->_promise_stacks[index] = (promise_stack_t) { .hash = hash, .stack = tf_strdup(stack), .count = 1, .cstack_count = count };
memcpy(task->_promise_stacks[index].cstack, buffer, sizeof(void*) * count); memcpy(task->_promise_stacks[index].cstack, buffer, sizeof(void*) * count);
task->_promise_stack_count++; task->_promise_stack_count++;
@ -1261,7 +1262,7 @@ JSValue tf_task_allocate_promise(tf_task_t* task, promiseid_t* out_promise)
size_t length = 0; size_t length = 0;
const char* stack = JS_ToCStringLen(task->_context, &length, stack_value); const char* stack = JS_ToCStringLen(task->_context, &length, stack_value);
stack_hash = tf_util_fnv32a((const void*)stack, (int)length, 0); stack_hash = tf_util_fnv32a((const void*)stack, (int)length, 0);
void* buffer[32]; void* buffer[31];
int count = tf_util_backtrace(buffer, sizeof(buffer) / sizeof(*buffer)); int count = tf_util_backtrace(buffer, sizeof(buffer) / sizeof(*buffer));
stack_hash = tf_util_fnv32a((const void*)buffer, sizeof(void*) * count, stack_hash); stack_hash = tf_util_fnv32a((const void*)buffer, sizeof(void*) * count, stack_hash);
_add_promise_stack(task, stack_hash, stack, buffer, count); _add_promise_stack(task, stack_hash, stack, buffer, count);