core: Only the timeout remaing for the websocket handler in C?
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 9m2s

This commit is contained in:
2025-12-06 18:21:42 -05:00
parent 69f9646955
commit 7c1931f529
3 changed files with 104 additions and 66 deletions

View File

@@ -7,71 +7,11 @@
/** \cond */ /** \cond */
import * as core from './core.js'; import * as core from './core.js';
export {App};
/** \endcond */ /** \endcond */
/** A sequence number of apps. */ /** A sequence number of apps. */
let g_session_index = 0; let g_session_index = 0;
/**
** App constructor.
** @return An app instance.
*/
function App() {
this._send_queue = [];
this.calls = {};
this._next_call_id = 1;
return this;
}
/**
** Create a function wrapper that when called invokes a function on the app
** itself.
** @param api The function and argument names.
** @return A function.
*/
App.prototype.makeFunction = function (api) {
let self = this;
let result = function () {
let id = self._next_call_id++;
while (!id || self.calls[id]) {
id = self._next_call_id++;
}
let promise = new Promise(function (resolve, reject) {
self.calls[id] = {resolve: resolve, reject: reject};
});
let message = {
action: 'tfrpc',
method: api[0],
params: [...arguments],
id: id,
};
self.send(message);
return promise;
};
Object.defineProperty(result, 'name', {value: api[0], writable: false});
return result;
};
/**
** Send a message to the app.
** @param message The message to send.
*/
App.prototype.send = function (message) {
if (this._send_queue) {
if (this._on_output) {
this._send_queue.forEach((x) => this._on_output(x));
this._send_queue = null;
} else if (message) {
this._send_queue.push(message);
}
}
if (message && this._on_output) {
this._on_output(message);
}
};
/** /**
** App socket handler. ** App socket handler.
** @param request The HTTP request of the WebSocket connection. ** @param request The HTTP request of the WebSocket connection.

View File

@@ -6,7 +6,7 @@
*/ */
/** \cond */ /** \cond */
import * as app from './app.js'; import * as app_module from './app.js';
export {invoke, getProcessBlob}; export {invoke, getProcessBlob};
/** \endcond */ /** \endcond */
@@ -22,6 +22,64 @@ let g_update_accounts_scheduled;
/** Time between pings, in milliseconds. */ /** Time between pings, in milliseconds. */
const k_ping_interval = 60 * 1000; const k_ping_interval = 60 * 1000;
/**
** App constructor.
** @return An app instance.
*/
function App() {
this._send_queue = [];
this.calls = {};
this._next_call_id = 1;
return this;
}
/**
** Create a function wrapper that when called invokes a function on the app
** itself.
** @param api The function and argument names.
** @return A function.
*/
App.prototype.makeFunction = function (api) {
let self = this;
let result = function () {
let id = self._next_call_id++;
while (!id || self.calls[id]) {
id = self._next_call_id++;
}
let promise = new Promise(function (resolve, reject) {
self.calls[id] = {resolve: resolve, reject: reject};
});
let message = {
action: 'tfrpc',
method: api[0],
params: [...arguments],
id: id,
};
self.send(message);
return promise;
};
Object.defineProperty(result, 'name', {value: api[0], writable: false});
return result;
};
/**
** Send a message to the app.
** @param message The message to send.
*/
App.prototype.send = function (message) {
if (this._send_queue) {
if (this._on_output) {
this._send_queue.forEach((x) => this._on_output(x));
this._send_queue = null;
} else if (message) {
this._send_queue.push(message);
}
}
if (message && this._on_output) {
this._on_output(message);
}
};
/** /**
* Print an error. * Print an error.
* @param error The error. * @param error The error.
@@ -183,7 +241,7 @@ async function getProcessBlob(blobId, key, options) {
process.url = options?.url; process.url = options?.url;
process.eventHandlers = {}; process.eventHandlers = {};
if (!options?.script || options?.script === 'app.js') { if (!options?.script || options?.script === 'app.js') {
process.app = new app.App(); process.app = new App();
} }
process.lastActive = Date.now(); process.lastActive = Date.now();
process.lastPing = null; process.lastPing = null;

View File

@@ -291,7 +291,42 @@ static void _http_json_send(tf_http_request_t* request, JSContext* context, JSVa
static JSValue _httpd_app_on_tfrpc(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv, int magic, JSValue* func_data) static JSValue _httpd_app_on_tfrpc(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv, int magic, JSValue* func_data)
{ {
tf_printf("TODO: TFRPC\n"); const char* id = tf_util_get_property_as_string(context, argv[0], "id");
if (id)
{
JSClassID class_id = 0;
app_t* app = JS_GetAnyOpaque(func_data[0], &class_id);
JSValue process_app = JS_GetPropertyStr(context, app->process, "app");
JSValue calls = JS_IsObject(process_app) ? JS_GetPropertyStr(context, process_app, "calls") : JS_UNDEFINED;
JSValue call = JS_IsObject(calls) ? JS_GetPropertyStr(context, calls, id) : JS_UNDEFINED;
if (!JS_IsUndefined(call))
{
JSValue error = JS_GetPropertyStr(context, argv[0], "error");
if (!JS_IsUndefined(error))
{
JSValue reject = JS_GetPropertyStr(context, call, "reject");
JSValue result = JS_Call(context, reject, JS_UNDEFINED, 1, &error);
tf_util_report_error(context, result);
JS_FreeValue(context, result);
JS_FreeValue(context, reject);
}
else
{
JSValue resolve = JS_GetPropertyStr(context, call, "resolve");
JSValue message_result = JS_GetPropertyStr(context, argv[0], "result");
JSValue result = JS_Call(context, resolve, JS_UNDEFINED, 1, &message_result);
JS_FreeValue(context, message_result);
tf_util_report_error(context, result);
JS_FreeValue(context, result);
JS_FreeValue(context, resolve);
}
JS_FreeValue(context, error);
}
JS_FreeValue(context, call);
JS_FreeValue(context, calls);
JS_FreeValue(context, process_app);
}
JS_FreeCString(context, id);
return JS_UNDEFINED; return JS_UNDEFINED;
} }
@@ -311,7 +346,6 @@ static JSValue _httpd_app_on_process_start(JSContext* context, JSValueConst this
JSClassID class_id = 0; JSClassID class_id = 0;
app_t* app = JS_GetAnyOpaque(func_data[0], &class_id); app_t* app = JS_GetAnyOpaque(func_data[0], &class_id);
app->process = JS_DupValue(context, argv[0]); app->process = JS_DupValue(context, argv[0]);
tf_printf("ON START %p => %s\n", app, app->request->path);
JSValue client_api = JS_GetPropertyStr(context, app->process, "client_api"); JSValue client_api = JS_GetPropertyStr(context, app->process, "client_api");
JSValue tfrpc = JS_NewCFunctionData(context, _httpd_app_on_tfrpc, 1, 0, 1, func_data); JSValue tfrpc = JS_NewCFunctionData(context, _httpd_app_on_tfrpc, 1, 0, 1, func_data);
@@ -319,10 +353,16 @@ static JSValue _httpd_app_on_process_start(JSContext* context, JSValueConst this
JS_FreeValue(context, client_api); JS_FreeValue(context, client_api);
JSValue process_app = JS_GetPropertyStr(context, app->process, "app"); JSValue process_app = JS_GetPropertyStr(context, app->process, "app");
JSValue send = JS_NewCFunctionData(context, _httpd_app_on_output, 1, 0, 1, func_data); JSValue on_output = JS_NewCFunctionData(context, _httpd_app_on_output, 1, 0, 1, func_data);
JS_SetPropertyStr(context, process_app, "_on_output", send); JS_SetPropertyStr(context, process_app, "_on_output", on_output);
JS_FreeValue(context, process_app); JS_FreeValue(context, process_app);
JSValue send = JS_GetPropertyStr(context, process_app, "send");
JSValue result = JS_Call(context, send, process_app, 0, NULL);
JS_FreeValue(context, send);
tf_util_report_error(context, result);
JS_FreeValue(context, result);
return JS_UNDEFINED; return JS_UNDEFINED;
} }