[gjs/wip/ptomato/develop: 7/11] Add marshalling for native JS errors
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/ptomato/develop: 7/11] Add marshalling for native JS errors
- Date: Mon, 18 Sep 2017 08:13:44 +0000 (UTC)
commit b65f34d7b2e00b2aa7c1b595806802f5acdbfe41
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Sun Aug 26 00:23:24 2012 +0200
Add marshalling for native JS errors
Introduce a GError domain for representing native JS errors (such as
TypeError or ReferenceError) throw by JS code, to be reported to calling
C code.
Introduce also a way to retrieve something similar to the original C
error from this GError, in case it comes through a called C function
unmodified.
https://bugzilla.gnome.org/show_bug.cgi?id=682701
gi/gerror.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gi/gerror.h | 3 ++
util/error.cpp | 34 +++++++++++++++++++++
util/error.h | 22 +++++++++++++-
4 files changed, 146 insertions(+), 1 deletions(-)
---
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index d4d5e28..d0e827b 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -32,6 +32,7 @@
#include "gjs/mem.h"
#include "repo.h"
#include "gerror.h"
+#include "util/error.h"
#include <util/log.h>
@@ -428,6 +429,48 @@ define_error_properties(JSContext *cx,
exc.restore();
}
+static JSProtoKey
+proto_key_from_error_enum(int val)
+{
+ switch (val) {
+ case GJS_JS_ERROR_EVAL_ERROR:
+ return JSProto_EvalError;
+ case GJS_JS_ERROR_INTERNAL_ERROR:
+ return JSProto_InternalError;
+ case GJS_JS_ERROR_RANGE_ERROR:
+ return JSProto_RangeError;
+ case GJS_JS_ERROR_REFERENCE_ERROR:
+ return JSProto_ReferenceError;
+ case GJS_JS_ERROR_STOP_ITERATION:
+ return JSProto_StopIteration;
+ case GJS_JS_ERROR_SYNTAX_ERROR:
+ return JSProto_SyntaxError;
+ case GJS_JS_ERROR_TYPE_ERROR:
+ return JSProto_TypeError;
+ case GJS_JS_ERROR_URI_ERROR:
+ return JSProto_URIError;
+ case GJS_JS_ERROR_ERROR:
+ default:
+ return JSProto_Error;
+ }
+}
+
+static JSObject *
+gjs_error_from_js_gerror(JSContext *cx,
+ GError *gerror)
+{
+ JS::AutoValueArray<1> error_args(cx);
+ if (!gjs_string_from_utf8(cx, gerror->message, -1, error_args[0]))
+ return nullptr;
+
+ JSProtoKey error_kind = proto_key_from_error_enum(gerror->code);
+ JS::RootedObject error_constructor(cx);
+ if (!JS_GetClassObject(cx, error_kind, &error_constructor))
+ return nullptr;
+
+ return JS_New(cx, error_constructor, error_args);
+}
+
JSObject*
gjs_error_from_gerror(JSContext *context,
GError *gerror,
@@ -440,6 +483,9 @@ gjs_error_from_gerror(JSContext *context,
if (gerror == NULL)
return NULL;
+ if (gerror->domain == GJS_JS_ERROR)
+ return gjs_error_from_js_gerror(context, gerror);
+
info = find_error_domain_info(gerror->domain);
if (!info) {
@@ -520,3 +566,45 @@ gjs_typecheck_gerror (JSContext *context,
return do_base_typecheck(context, obj, throw_error);
}
+
+GError *
+gjs_gerror_make_from_error(JSContext *cx,
+ JS::HandleObject obj)
+{
+ using AutoEnumClass = std::unique_ptr<GEnumClass, decltype(&g_type_class_unref)>;
+
+ if (gjs_typecheck_gerror(cx, obj, false)) {
+ /* This is already a GError, just copy it */
+ GError *inner = gjs_gerror_from_error(cx, obj);
+ return g_error_copy(inner);
+ }
+
+ /* Try to make something useful from the error
+ name and message (in case this is a JS error) */
+ JS::RootedValue v_name(cx);
+ if (!gjs_object_get_property(cx, obj, GJS_STRING_NAME, &v_name))
+ return nullptr;
+
+ GjsAutoJSChar name(cx);
+ if (!gjs_string_to_utf8(cx, v_name, &name))
+ return nullptr;
+
+ JS::RootedValue v_message(cx);
+ if (!gjs_object_get_property(cx, obj, GJS_STRING_MESSAGE, &v_message))
+ return nullptr;
+
+ GjsAutoJSChar message(cx);
+ if (!gjs_string_to_utf8(cx, v_message, &message))
+ return nullptr;
+
+ AutoEnumClass klass(static_cast<GEnumClass *>(g_type_class_ref(GJS_TYPE_JS_ERROR)),
+ g_type_class_unref);
+ const GEnumValue *value = g_enum_get_value_by_name(klass.get(), name);
+ int code;
+ if (value)
+ code = value->value;
+ else
+ code = GJS_JS_ERROR_ERROR;
+
+ return g_error_new_literal(GJS_JS_ERROR, code, message);
+}
diff --git a/gi/gerror.h b/gi/gerror.h
index 913877c..8f7d549 100644
--- a/gi/gerror.h
+++ b/gi/gerror.h
@@ -44,6 +44,9 @@ bool gjs_typecheck_gerror (JSContext *context,
JS::HandleObject obj,
bool throw_error);
+GError *gjs_gerror_make_from_error(JSContext *cx,
+ JS::HandleObject obj);
+
G_END_DECLS
#endif /* __GJS_ERROR_H__ */
diff --git a/util/error.cpp b/util/error.cpp
index 8c8b586..b653b08 100644
--- a/util/error.cpp
+++ b/util/error.cpp
@@ -22,6 +22,9 @@
*/
#include <config.h>
+
+#include <glib-object.h>
+
#include "error.h"
GQuark
@@ -29,3 +32,34 @@ gjs_error_quark (void)
{
return g_quark_from_static_string ("gjs-error-quark");
}
+
+GQuark
+gjs_js_error_quark(void)
+{
+ return g_quark_from_static_string("gjs-js-error-quark");
+}
+
+GType
+gjs_js_error_get_type(void)
+{
+ static volatile GType g_type_id;
+
+ if (g_once_init_enter(&g_type_id)) {
+ static GEnumValue errors[] = {
+ { GJS_JS_ERROR_ERROR, "Error", "error" },
+ { GJS_JS_ERROR_EVAL_ERROR, "EvalError", "eval-error" },
+ { GJS_JS_ERROR_INTERNAL_ERROR, "InternalError", "internal-error" },
+ { GJS_JS_ERROR_RANGE_ERROR, "RangeError", "range-error" },
+ { GJS_JS_ERROR_REFERENCE_ERROR, "ReferenceError", "reference-error" },
+ { GJS_JS_ERROR_STOP_ITERATION, "StopIteration", "stop-iteration" },
+ { GJS_JS_ERROR_SYNTAX_ERROR, "SyntaxError", "syntax-error" },
+ { GJS_JS_ERROR_TYPE_ERROR, "TypeError", "type-error" },
+ { GJS_JS_ERROR_URI_ERROR, "URIError", "uri-error" },
+ { 0, nullptr, nullptr }
+ };
+
+ g_type_id = g_enum_register_static("GjsJSError", errors);
+ }
+
+ return g_type_id;
+}
diff --git a/util/error.h b/util/error.h
index 08a3128..9f97eb5 100644
--- a/util/error.h
+++ b/util/error.h
@@ -24,7 +24,7 @@
#ifndef __GJS_UTIL_ERROR_H__
#define __GJS_UTIL_ERROR_H__
-#include <glib.h>
+#include <glib-object.h>
#include <gjs/macros.h>
@@ -39,6 +39,26 @@ typedef enum {
GJS_ERROR_SYSTEM_EXIT,
} GjsError;
+GJS_EXPORT
+GQuark gjs_js_error_quark(void);
+#define GJS_JS_ERROR gjs_js_error_quark()
+
+GJS_EXPORT
+GType gjs_js_error_get_type(void);
+#define GJS_TYPE_JS_ERROR gjs_js_error_get_type()
+
+typedef enum {
+ GJS_JS_ERROR_ERROR,
+ GJS_JS_ERROR_EVAL_ERROR,
+ GJS_JS_ERROR_INTERNAL_ERROR,
+ GJS_JS_ERROR_RANGE_ERROR,
+ GJS_JS_ERROR_REFERENCE_ERROR,
+ GJS_JS_ERROR_STOP_ITERATION,
+ GJS_JS_ERROR_SYNTAX_ERROR,
+ GJS_JS_ERROR_TYPE_ERROR,
+ GJS_JS_ERROR_URI_ERROR,
+} GjsJSError;
+
G_END_DECLS
#endif /* __GJS_UTIL_ERROR_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]