Repository navigation
Conversation
Embedders can opt in so crossing JS_SetMemoryLimit is a host-visible termination that JavaScript cannot catch, including when no Error object can be allocated. Co-authored-by: Cursor <cursoragent@cursor.com>
|
What's the use case here? Can't the host app check the error and decide whether it allows the app to continue or stop it? |
|
Use case: a host running untrusted scripts under a memory limit. The script can catch the out-of-memory error itself ( |
|
Im trying to come up with a case in which a he catch would be the right thing to do... @bnoordhuis You have more experience here. What do other engines do? Perhaps memory errors should always be uncatchable? |
|
Other JS engines just terminate the process. :-) IMO, the only change we need to make is to turn OOM errors uncatchable by JS. Easy: diff --git a/quickjs.c b/quickjs.c
index bc72af2..8be4dd3 100644
--- a/quickjs.c
+++ b/quickjs.c
@@ -8563,6 +8563,7 @@ JSValue JS_ThrowOutOfMemory(JSContext *ctx)
if (!rt->in_out_of_memory) {
rt->in_out_of_memory = true;
JS_ThrowInternalError(ctx, "out of memory");
+ JS_SetUncatchableError(ctx, ctx->rt->current_exception);
rt->in_out_of_memory = false;
}
return JS_EXCEPTION;
@@ -49777,7 +49778,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
JS_ThrowInterrupted(ctx);
break;
case LRE_RET_MEMORY_ERROR:
- JS_ThrowInternalError(ctx, "out of memory in regexp execution");
+ JS_ThrowOutOfMemory(ctx);
break;
case LRE_RET_BYTECODE_ERROR:
JS_ThrowInternalError(ctx, "corrupted bytecode in regexp execution");Agree/disagree? |
|
Agree, that's what I was thinking indeed! |
|
#1810 - and maybe there's a broader discussion to be had of making all InternalError exceptions uncatchable. |
Summary
Fixes #1773
JS_SetMemoryLimitTermination()opts in (off by default) so a rejection from the engine's ownJS_SetMemoryLimitcheck is a runtime-scoped terminal condition.null.catchdoes not resume, andJS_ExecutePendingJob()returns failure instead of running a rejection continuation.JS_GetTerminationStatus()reportsJS_TERMINATION_MEMORY_LIMITwithout parsing exception text.NULL, ordinary exceptions, and the previous catchable memory-limit behavior are unchanged. After termination the runtime is not reusable and should be freed.Test plan
api-testin Debug and ASan+UBSan, including catchable exhaustion, terminal sync (including 1-byte headroom /null), promise reaction, async resumption, promise constructor, thenable job, ordinary Error/RangeError/TypeError/syntax/rejection, custom-allocatorNULL, and a fresh runtimelre-testin Debug and ASan+UBSanrun-test262 -c tests.conf): 0/117 errors, 9 excluded, in Debug and ASan+UBSanctest,cxxtest, andjscheck(Apple Clang needs-Wno-unused-command-line-argumentforjscheck)JS_ABORT_ON_LEAKSviaapi-test; macOSleaks --atExitreported 0 leaksMade with Cursor