. auto/feature
+ njs_feature="QuickJS JS_NewError() attaches stack"
+ njs_feature_run=value
+ njs_feature_name=NJS_HAVE_QUICKJS_NEW_ERROR_STACK
+ njs_feature_test="#include <quickjs_compat.h>
+
+ int main() {
+ int rc;
+ JSAtom atom;
+ JSValue err;
+ JSRuntime *rt;
+ JSContext *ctx;
+
+ rt = JS_NewRuntime();
+ ctx = JS_NewContext(rt);
+ err = JS_NewError(ctx);
+ atom = JS_NewAtom(ctx, \"stack\");
+ rc = JS_HasProperty(ctx, err, atom);
+ printf(\"%d\", rc);
+ JS_FreeAtom(ctx, atom);
+ JS_FreeValue(ctx, err);
+ JS_FreeContext(ctx);
+ JS_FreeRuntime(rt);
+ return 0;
+ }"
+
+ . auto/feature
+
njs_feature="QuickJS version"
njs_feature_name=NJS_QUICKJS_VERSION
njs_feature_run=value
{
JSValue value;
- value = JS_NewError(cx);
+ value = qjs_new_error(cx);
if (JS_IsException(value)) {
return JS_EXCEPTION;
}
static void
ngx_qjs_fetch_error(ngx_js_http_t *http, const char *err)
{
+ JSValue reason;
ngx_qjs_fetch_t *fetch;
fetch = (ngx_qjs_fetch_t *) http;
- JS_ThrowInternalError(fetch->cx, "%s", err);
+ fetch->response_value = qjs_new_error(fetch->cx);
+ if (JS_IsException(fetch->response_value)) {
+ fetch->response_value = JS_UNDEFINED;
+ goto done;
+ }
+
+ reason = JS_NewString(fetch->cx, err);
+ if (JS_IsException(reason)) {
+ goto done;
+ }
+
+ if (JS_SetPropertyStr(fetch->cx, fetch->response_value, "message",
+ reason) < 0)
+ {
+ JS_FreeValue(fetch->cx, reason);
+ goto done;
+ }
- fetch->response_value = JS_GetException(fetch->cx);
+done:
ngx_qjs_fetch_done(fetch, fetch->response_value, NGX_ERROR);
}
|| JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED;
}
+/*
+ * QuickJS-NG attaches the "stack" property to an Error object too early,
+ * which results in empty stack trace when called from C code.
+ * Removing it allows the stack to be attached later during unwinding.
+ */
+static inline JSValue qjs_new_error2(JSContext *cx)
+{
+ JSAtom stack;
+ JSValue error;
+
+ stack = JS_NewAtom(cx, "stack");
+ if (stack == JS_ATOM_NULL) {
+ return JS_EXCEPTION;
+ }
+
+ error = JS_NewError(cx);
+ if (JS_IsException(error)) {
+ JS_FreeAtom(cx, stack);
+ return JS_EXCEPTION;
+ }
+
+ JS_DeleteProperty(cx, error, stack, 0);
+ JS_FreeAtom(cx, stack);
+
+ return error;
+}
+
#ifdef NJS_HAVE_QUICKJS_IS_SAME_VALUE
#define qjs_is_same_value(cx, a, b) JS_IsSameValue(cx, a, b)
#else
#define qjs_is_error(cx, a) JS_IsError(cx, a)
#endif
+#ifdef NJS_HAVE_QUICKJS_NEW_ERROR_STACK
+#define qjs_new_error(cx) qjs_new_error2(cx)
+#else
+#define qjs_new_error(cx) JS_NewError(cx)
+#endif
+
extern qjs_module_t *qjs_modules[];
#endif /* _QJS_H_INCLUDED_ */