diff --git a/apps/docs/todo.md b/apps/docs/todo.md index b8c2eea0..52d09e56 100644 --- a/apps/docs/todo.md +++ b/apps/docs/todo.md @@ -16,9 +16,7 @@ - / => Something good. - update docs - audit + document API exposed to apps -- sqlStream => sqlExec or something - fix weird HTTP warnings -- ssb from child process? - channels - placeholder/missing images - no denial of service @@ -57,7 +55,9 @@ - keep working on good error feedback - build for windows - installable apps (bring back an app message?) +- sqlStream => sqlExec or something +- !ssb from child process? ## Done - update LICENSE -- logging to browser \ No newline at end of file +- logging to browser diff --git a/core/core.js b/core/core.js index 1a8352f6..fa743424 100644 --- a/core/core.js +++ b/core/core.js @@ -79,8 +79,8 @@ function printError(out, error) { out.print(error.fileName + ":" + error.lineNumber + ": " + error.message); out.print(error.stackTrace); } else { - for (let i in error) { - out.print(i); + for (let [k, v] of Object.entries(error)) { + out.print(k, v); } out.print(error.toString()); } @@ -360,10 +360,10 @@ async function getProcessBlob(blobId, key, options) { if (process.app) { process.app.makeFunction(['error'])(error); } else { - print(error); + printError({print: print}, error); } } catch (e) { - print(e); + printError({print: print}, error); } }; imports.ssb = Object.fromEntries(Object.keys(ssb).map(key => [key, ssb[key].bind(ssb)])); @@ -455,19 +455,23 @@ async function getProcessBlob(blobId, key, options) { printError({print: print}, e); } broadcastEvent('onSessionBegin', [getUser(process, process)]); - resolveReady(process); if (process.app) { process.app.send({action: "ready"}); process.sendPermissions(); } await process.task.execute({name: appSourceName, source: appSource}); + resolveReady(process); } catch (error) { - if (process?.task?.onError) { - process.task.onError(error); + if (process.app) { + if (process?.task?.onError) { + process.task.onError(error); + } else { + printError({print: print}, error); + } } else { printError({print: print}, error); } - rejectReady(); + rejectReady(error); } } return process; @@ -605,17 +609,26 @@ async function useAppHandler(response, handler_blob_id, path) { let promise = new Promise(async function(resolve, reject) { do_resolve = resolve; }); - let process = await getProcessBlob(handler_blob_id, 'handler_' + g_handler_index++, { - script: 'handler.js', - imports: { - request: { - path: path, + let process; + let result; + try { + process = await getProcessBlob(handler_blob_id, 'handler_' + g_handler_index++, { + script: 'handler.js', + imports: { + request: { + path: path, + }, + respond: do_resolve, }, - respond: do_resolve, - }, - }); - let result = await promise; - await process.task.kill(); + }); + await process.ready; + + result = await promise; + } finally { + if (process?.task) { + await process.task.kill(); + } + } return result; } @@ -777,8 +790,16 @@ async function blobHandler(request, response, blobId, uri) { let app_object = JSON.parse(utf8Decode(await getBlobOrContent(app_id))); id = app_object.files[uri.substring(1)]; if (!id && app_object.files['handler.js']) { - let answer = await useAppHandler(response, app_id, uri.substring(1)); - if (typeof answer.data == 'string') { + let answer; + try { + answer = await useAppHandler(response, app_id, uri.substring(1)); + } catch (error) { + data = utf8Encode(`Internal Server Error\n\n${error?.message}\n${error?.stack}`); + response.writeHead(500, {'Content-Type': 'text/plain; charset=utf-8', 'Content-Length': data.length}); + response.end(data); + return; + } + if (answer && typeof answer.data == 'string') { answer.data = utf8Encode(answer.data); } sendData(response, answer?.data, answer?.content_type, { diff --git a/src/ssb.js.c b/src/ssb.js.c index be38ff16..07a1d935 100644 --- a/src/ssb.js.c +++ b/src/ssb.js.c @@ -992,7 +992,6 @@ static JSValue _tf_ssb_createTunnel(JSContext* context, JSValueConst this_val, i tf_ssb_connection_t* connection = tf_ssb_connection_get(ssb, portal_id); if (connection) { - // let request_number = await tfrpc.rpc.connectionSendJson(portal, {name: ['tunnel', 'connect'], args: [{portal: portal, target: target}], type: 'duplex'}); int32_t request_number = tf_ssb_connection_next_request_number(connection); JSValue message = JS_NewObject(context); JSValue name = JS_NewArray(context);