[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#694452: unblock: gjs/1.32.0-5



Control: retitle -1 unblock: gjs/1.32.0-5

Le mardi 18 décembre 2012 à 21:39 +0100, Julien Cristau a écrit : 
> gjs/context.h seems to be a public header, and
> gjs_context_print_stack_to_buffer is exported.  This looks like ABI
> breakage to me?

I have uploaded version 1.32.0-5 which reverts the ABI breakage.

gjs (1.32.0-5) unstable; urgency=low

  * 11_revert_abi_breakage.patch: new patch. Revert the ABI breakage 
    introduced by 03_gerror_details.patch.
  * 05_log_typo.patch: upstream patch adapted. Fix a typo in a logging 
    function. Closes: #697211.

I’m attaching the two new patches, as well as the full diff against
1.32.0-2 in testing, just in case.

Unblocking this version should allow gnome-documents and gnome-shell
(also fixed) to migrate.

Cheers,
-- 
 .''`.      Josselin Mouette
: :' :
`. `'
  `-
Index: gjs-1.32.0/modules/overrides/Gio.js
===================================================================
--- gjs-1.32.0.orig/modules/overrides/Gio.js	2011-11-10 22:34:29.000000000 +0100
+++ gjs-1.32.0/modules/overrides/Gio.js	2013-01-02 22:26:54.799677045 +0100
@@ -147,7 +147,7 @@ function _propertySetter(value, name, si
 		      this.call_finish(result);
 		  } catch(e) {
 		      log('Could not set property ' + name + ' on remote object ' +
-			  this.g_object_path, '. Error is ' + e.message);
+			  this.g_object_path + ': ' + e.message);
 		  }
 	      }));
 }
Index: gjs-1.32.0/gi/gerror.c
===================================================================
--- gjs-1.32.0.orig/gi/gerror.c	2012-12-20 00:49:02.670259754 +0100
+++ gjs-1.32.0/gi/gerror.c	2012-12-20 01:05:37.971125507 +0100
@@ -520,6 +520,9 @@ find_error_domain_info(GQuark domain)
     return info;
 }
 
+/* Temporary hack to avoid breaking ABI */
+new_gjs_context_print_stack_to_buffer(GjsContext* context, void *initial, GString *buf);
+
 /* define properties that JS Error() expose, such as
    fileName, lineNumber and stack
 */
@@ -553,7 +556,7 @@ define_error_properties(JSContext *conte
 
     stack = g_string_new(NULL);
     gjs_context = JS_GetContextPrivate(context);
-    gjs_context_print_stack_to_buffer(gjs_context, frame, stack);
+    new_gjs_context_print_stack_to_buffer(gjs_context, frame, stack);
 
     if (gjs_string_from_utf8(context, stack->str, stack->len, &v))
         JS_DefineProperty(context, obj, "stack", v,
Index: gjs-1.32.0/gjs/context.h
===================================================================
--- gjs-1.32.0.orig/gjs/context.h	2012-12-20 00:49:02.670259754 +0100
+++ gjs-1.32.0/gjs/context.h	2012-12-20 00:58:13.732953760 +0100
@@ -68,11 +68,7 @@ gboolean        gjs_context_define_strin
 GList*          gjs_context_get_all              (void);
 void*           gjs_context_get_native_context   (GjsContext *js_context);
 
-/* initial_frame is a JSStackFrame, but cannot be exposed as such in the
-   public API. Pass NULL to get the topmost frame.
-*/
 void            gjs_context_print_stack_to_buffer (GjsContext *js_context,
-                                                   void       *initial_frame,
                                                    GString    *buf);
 
 void            gjs_context_print_stack_stderr    (GjsContext *js_context);
Index: gjs-1.32.0/gjs/stack.c
===================================================================
--- gjs-1.32.0.orig/gjs/stack.c	2012-12-20 00:49:02.690259856 +0100
+++ gjs-1.32.0/gjs/stack.c	2012-12-20 01:03:28.702493578 +0100
@@ -203,8 +203,9 @@ format_frame(JSContext* cx, JSStackFrame
     JS_LeaveLocalRootScope(cx);
 }
 
-void
-gjs_context_print_stack_to_buffer(GjsContext* context, void *initial, GString *buf)
+
+void __attribute__((visibility("hidden")))
+new_gjs_context_print_stack_to_buffer(GjsContext* context, void *initial, GString *buf)
 {
     JSContext *js_context = (JSContext*)gjs_context_get_native_context(context);
     JSStackFrame *fp = initial;
@@ -222,12 +223,18 @@ gjs_context_print_stack_to_buffer(GjsCon
 }
 
 void
+gjs_context_print_stack_to_buffer(GjsContext* context, GString *buf)
+{
+    new_gjs_context_print_stack_to_buffer(context, NULL, buf);
+}
+
+void
 gjs_context_print_stack_stderr(GjsContext *context)
 {
   GString *str = g_string_new("");
 
   g_string_append_printf(str, "== Stack trace for context %p ==\n", context);
-  gjs_context_print_stack_to_buffer(context, NULL, str);
+  gjs_context_print_stack_to_buffer(context, str);
 
   g_printerr("%s\n", str->str);
   g_string_free(str, TRUE);
diff -Nru gjs-1.32.0/debian/changelog gjs-1.32.0/debian/changelog
--- gjs-1.32.0/debian/changelog	2012-04-26 17:18:36.000000000 +0200
+++ gjs-1.32.0/debian/changelog	2013-01-03 01:35:35.000000000 +0100
@@ -1,3 +1,29 @@
+gjs (1.32.0-5) unstable; urgency=low
+
+  * 11_revert_abi_breakage.patch: new patch. Revert the ABI breakage 
+    introduced by 03_gerror_details.patch.
+  * 05_log_typo.patch: upstream patch adapted. Fix a typo in a logging 
+    function. Closes: #697211.
+
+ -- Josselin Mouette <joss@debian.org>  Thu, 03 Jan 2013 01:35:29 +0100
+
+gjs (1.32.0-4) unstable; urgency=low
+
+  * 04_gjs_dumpstack.patch: patch from upstream git. Fix the 
+    gjs_dumpstack function after the changes introduced by 1.32.0-3.
+    Thanks to Niels Thykier’s awesome review for spotting this.
+
+ -- Josselin Mouette <joss@debian.org>  Wed, 12 Dec 2012 20:14:01 +0100
+
+gjs (1.32.0-3) unstable; urgency=low
+
+  * 02_gerror_class.patch, 03_gerror_details.patch: patches from 
+    upstream git. Introduce a class to manage GError correctly.
+    Closes: #691551.
+  * Bump shblibs version since this extends the API.
+
+ -- Josselin Mouette <joss@debian.org>  Mon, 26 Nov 2012 11:06:48 +0100
+
 gjs (1.32.0-2) unstable; urgency=low
 
   * Upload to unstable.
diff -Nru gjs-1.32.0/debian/control gjs-1.32.0/debian/control
--- gjs-1.32.0/debian/control	2012-04-26 17:21:58.000000000 +0200
+++ gjs-1.32.0/debian/control	2013-01-03 01:38:57.000000000 +0100
@@ -7,7 +7,7 @@
 Section: interpreters
 Priority: optional
 Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
-Uploaders: Emilio Pozuelo Monfort <pochu@debian.org>, Jordi Mallach <jordi@debian.org>, Josselin Mouette <joss@debian.org>, Laurent Bigonville <bigon@debian.org>, Michael Biebl <biebl@debian.org>, Sjoerd Simons <sjoerd@debian.org>
+Uploaders: Jordi Mallach <jordi@debian.org>, Josselin Mouette <joss@debian.org>, Michael Biebl <biebl@debian.org>, Sjoerd Simons <sjoerd@debian.org>
 Build-Depends: debhelper (>= 8),
                cdbs,
                gnome-pkg-tools,
diff -Nru gjs-1.32.0/debian/patches/02_gerror_class.patch gjs-1.32.0/debian/patches/02_gerror_class.patch
--- gjs-1.32.0/debian/patches/02_gerror_class.patch	1970-01-01 01:00:00.000000000 +0100
+++ gjs-1.32.0/debian/patches/02_gerror_class.patch	2012-11-26 12:01:17.000000000 +0100
@@ -0,0 +1,1227 @@
+From 2ab1b3f090edc4ac64075fb1a7f387e724ba63ff Mon Sep 17 00:00:00 2001
+From: Giovanni Campagna <gcampagna@src.gnome.org>
+Date: Fri, 02 Mar 2012 20:17:13 +0000
+Subject: Introduce special marshalling for GErrors
+
+Previously GErrors were transformed into plain Error with a custom
+message, which removed the code and domain metadata. This commit
+introduces a new class hierarchy (derived from GLib.Error) for each
+enumeration representing an error domain, and modifies existing
+code to throw instances of that when a function fails.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=591480
+---
+Index: gjs-1.32.0/Makefile.am
+===================================================================
+--- gjs-1.32.0.orig/Makefile.am	2012-11-26 10:59:32.382177869 +0100
++++ gjs-1.32.0/Makefile.am	2012-11-26 10:59:33.526183462 +0100
+@@ -53,7 +53,8 @@ nobase_gjs_module_include_HEADERS =	\
+ 	gi/function.h	\
+ 	gi/keep-alive.h	\
+ 	gi/interface.h	\
+-	gi/gtype.h
++	gi/gtype.h	\
++	gi/gerror.h
+ 
+ noinst_HEADERS +=		\
+ 	gjs/jsapi-private.h	\
+@@ -137,7 +138,8 @@ libgjs_la_SOURCES += \
+ 	gi/union.c	\
+         gi/value.c	\
+ 	gi/interface.c	\
+-	gi/gtype.c
++	gi/gtype.c	\
++	gi/gerror.c
+ 
+ # Also, these files used to be a separate library
+ gdbus_wrapper_source_files = \
+Index: gjs-1.32.0/gi/arg.c
+===================================================================
+--- gjs-1.32.0.orig/gi/arg.c	2012-03-21 14:51:34.000000000 +0100
++++ gjs-1.32.0/gi/arg.c	2012-11-26 10:59:33.534183501 +0100
+@@ -31,6 +31,7 @@
+ #include "union.h"
+ #include "param.h"
+ #include "value.h"
++#include "gerror.h"
+ #include "gjs/byteArray.h"
+ #include <gjs/gjs-module.h>
+ #include <gjs/compat.h>
+@@ -1326,7 +1327,6 @@ gjs_value_to_g_argument(JSContext      *
+                     arg->v_pointer = NULL;
+                     wrong = TRUE;
+                 }
+-
+             } else if (JSVAL_IS_NULL(value) &&
+                        interface_type != GI_INFO_TYPE_ENUM &&
+                        interface_type != GI_INFO_TYPE_FLAGS) {
+@@ -1336,8 +1336,16 @@ gjs_value_to_g_argument(JSContext      *
+                 if ((interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) &&
+                     /* We special case Closures later, so skip them here */
+                     !g_type_is_a(gtype, G_TYPE_CLOSURE)) {
+-                    arg->v_pointer = gjs_c_struct_from_boxed(context,
+-                                                             JSVAL_TO_OBJECT(value));
++
++                    /* special case GError too */
++                    if (g_type_is_a(gtype, G_TYPE_ERROR)) {
++                        arg->v_pointer = gjs_gerror_from_error(context,
++                                                               JSVAL_TO_OBJECT(value));
++                    } else {
++                        arg->v_pointer = gjs_c_struct_from_boxed(context,
++                                                                 JSVAL_TO_OBJECT(value));
++                    }
++
+                     if (transfer != GI_TRANSFER_NOTHING) {
+                         if (g_type_is_a(gtype, G_TYPE_BOXED))
+                             arg->v_pointer = g_boxed_copy (gtype, arg->v_pointer);
+@@ -2367,6 +2375,20 @@ gjs_value_from_g_argument (JSContext  *c
+             return JS_TRUE;
+         }
+ 
++    case GI_TYPE_TAG_ERROR:
++        {
++            if (arg->v_pointer) {
++                JSObject *obj = gjs_error_from_gerror(context, arg->v_pointer);
++                if (obj) {
++                    *value_p = OBJECT_TO_JSVAL(obj);
++                    return JS_TRUE;
++                }
++
++                return JS_FALSE;
++            }
++            return JS_TRUE;
++        }
++
+     case GI_TYPE_TAG_INTERFACE:
+         {
+             jsval value;
+@@ -2426,13 +2448,24 @@ gjs_value_from_g_argument (JSContext  *c
+                               "gtype of INTERFACE is %s", g_type_name(gtype));
+ 
+ 
+-            /* Test GValue before Struct, or it will be handled as the latter */
++            /* Test GValue and GError before Struct, or it will be handled as the latter */
+             if (g_type_is_a(gtype, G_TYPE_VALUE)) {
+                 if (!gjs_value_from_g_value(context, &value, arg->v_pointer))
+                     value = JSVAL_VOID; /* Make sure error is flagged */
+ 
+                 goto out;
+             }
++            if (g_type_is_a(gtype, G_TYPE_ERROR)) {
++                JSObject *obj;
++
++                obj = gjs_error_from_gerror(context, arg->v_pointer);
++                if (obj)
++                    value = OBJECT_TO_JSVAL(obj);
++                else
++                    value = JSVAL_VOID;
++
++                goto out;
++            }
+ 
+             if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
+                 JSObject *obj;
+Index: gjs-1.32.0/gi/enumeration.c
+===================================================================
+--- gjs-1.32.0.orig/gi/enumeration.c	2012-02-02 22:40:43.000000000 +0100
++++ gjs-1.32.0/gi/enumeration.c	2012-11-26 10:59:33.534183501 +0100
+@@ -103,17 +103,50 @@ gjs_define_enum_value(JSContext    *cont
+ }
+ 
+ JSBool
++gjs_define_enum_values(JSContext    *context,
++                       JSObject     *in_object,
++                       GIEnumInfo   *info)
++{
++    GType gtype;
++    int i, n_values;
++    jsval value;
++
++    /* Fill in enum values first, so we don't define the enum itself until we're
++     * sure we can finish successfully.
++     */
++    n_values = g_enum_info_get_n_values(info);
++    for (i = 0; i < n_values; ++i) {
++        GIValueInfo *value_info = g_enum_info_get_value(info, i);
++        gboolean failed;
++
++        failed = !gjs_define_enum_value(context, in_object, value_info);
++
++        g_base_info_unref( (GIBaseInfo*) value_info);
++
++        if (failed) {
++            return JS_FALSE;
++        }
++    }
++
++    gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)info);
++    value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, gtype));
++    JS_DefineProperty(context, in_object, "$gtype", value,
++                      NULL, NULL, JSPROP_PERMANENT);
++
++    return JS_TRUE;
++}
++
++
++JSBool
+ gjs_define_enumeration(JSContext    *context,
+                        JSObject     *in_object,
+                        GIEnumInfo   *info,
+                        JSObject    **enumeration_p)
+ {
+     const char *enum_name;
+-    GType gtype;
+     JSObject *enum_obj;
+     jsval value;
+-    int i;
+-    int n_values;
++
+ 
+     /* An enumeration is simply an object containing integer attributes for
+      * each enum value. It does not have a special JSClass.
+@@ -150,27 +183,8 @@ gjs_define_enumeration(JSContext    *con
+     JS_SetParent(context, enum_obj,
+                  gjs_get_import_global (context));
+ 
+-    /* Fill in enum values first, so we don't define the enum itself until we're
+-     * sure we can finish successfully.
+-     */
+-    n_values = g_enum_info_get_n_values(info);
+-    for (i = 0; i < n_values; ++i) {
+-        GIValueInfo *value_info = g_enum_info_get_value(info, i);
+-        gboolean failed;
+-
+-        failed = !gjs_define_enum_value(context, enum_obj, value_info);
+-
+-        g_base_info_unref( (GIBaseInfo*) value_info);
+-
+-        if (failed) {
+-            return JS_FALSE;
+-        }
+-    }
+-
+-    gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)info);
+-    value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, gtype));
+-    JS_DefineProperty(context, enum_obj, "$gtype", value,
+-                      NULL, NULL, JSPROP_PERMANENT);
++    if (!gjs_define_enum_values(context, enum_obj, info))
++        return JS_FALSE;
+ 
+     gjs_debug(GJS_DEBUG_GENUM,
+               "Defining %s.%s as %p",
+Index: gjs-1.32.0/gi/enumeration.h
+===================================================================
+--- gjs-1.32.0.orig/gi/enumeration.h	2011-06-10 00:31:56.000000000 +0200
++++ gjs-1.32.0/gi/enumeration.h	2012-11-26 10:59:33.534183501 +0100
+@@ -32,6 +32,9 @@
+ 
+ G_BEGIN_DECLS
+ 
++JSBool    gjs_define_enum_values       (JSContext    *context,
++                                        JSObject     *in_object,
++                                        GIEnumInfo   *info);
+ JSBool    gjs_define_enumeration       (JSContext    *context,
+                                         JSObject     *in_object,
+                                         GIEnumInfo   *info,
+Index: gjs-1.32.0/gi/function.c
+===================================================================
+--- gjs-1.32.0.orig/gi/function.c	2012-03-14 21:31:30.000000000 +0100
++++ gjs-1.32.0/gi/function.c	2012-11-26 10:59:33.538183526 +0100
+@@ -28,6 +28,7 @@
+ #include "object.h"
+ #include "boxed.h"
+ #include "union.h"
++#include "gerror.h"
+ #include <gjs/gjs-module.h>
+ #include <gjs/compat.h>
+ 
+@@ -674,7 +675,13 @@ gjs_invoke_c_function(JSContext      *co
+         g_assert_cmpuint(0, <, c_argc);
+ 
+         if (type == GI_INFO_TYPE_STRUCT || type == GI_INFO_TYPE_BOXED) {
+-            in_arg_cvalues[0].v_pointer = gjs_c_struct_from_boxed(context, obj);
++            GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *)container);
++
++            /* GError must be special cased */
++            if (g_type_is_a(gtype, G_TYPE_ERROR))
++                in_arg_cvalues[0].v_pointer = gjs_gerror_from_error(context, obj);
++            else
++                in_arg_cvalues[0].v_pointer = gjs_c_struct_from_boxed(context, obj);
+         } else if (type == GI_INFO_TYPE_UNION) {
+             in_arg_cvalues[0].v_pointer = gjs_c_union_from_union(context, obj);
+         } else { /* by fallback is always object */
+@@ -1208,11 +1215,7 @@ release:
+     }
+ 
+     if (!failed && did_throw_gerror) {
+-        gjs_throw(context, "Error invoking %s.%s: %s",
+-                  g_base_info_get_namespace( (GIBaseInfo*) function->info),
+-                  g_base_info_get_name( (GIBaseInfo*) function->info),
+-                  local_error->message);
+-        g_error_free(local_error);
++        gjs_throw_g_error(context, local_error);
+         return JS_FALSE;
+     } else if (failed) {
+         return JS_FALSE;
+Index: gjs-1.32.0/gi/gerror.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gjs-1.32.0/gi/gerror.c	2012-11-26 10:59:33.538183526 +0100
+@@ -0,0 +1,589 @@
++/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
++/*
++ * Copyright (c) 2008  litl, LLC
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <config.h>
++
++#include <string.h>
++
++#include <gjs/gjs-module.h>
++#include <gjs/compat.h>
++#include "boxed.h"
++#include "enumeration.h"
++#include "repo.h"
++#include "gerror.h"
++
++#include <util/log.h>
++
++#include <jsapi.h>
++
++#include <girepository.h>
++
++typedef struct {
++    GIEnumInfo *info;
++    GQuark domain;
++    GError *gerror; /* NULL if we are the prototype and not an instance */
++} Error;
++
++enum {
++    PROP_0,
++    PROP_DOMAIN,
++    PROP_CODE,
++    PROP_MESSAGE
++};
++
++static struct JSClass gjs_error_class;
++
++GJS_DEFINE_DYNAMIC_PRIV_FROM_JS(Error, gjs_error_class)
++
++GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
++{
++    GJS_NATIVE_CONSTRUCTOR_VARIABLES(error)
++    Error *priv;
++    Error *proto_priv;
++    JSObject *proto;
++    jsval v_message, v_code;
++    gchar *message;
++
++    /* Check early to avoid allocating memory for nothing */
++    if (argc != 1 || !JSVAL_IS_OBJECT(argv[0])) {
++        gjs_throw(context, "Invalid parameters passed to GError constructor, expected one object");
++        return JS_FALSE;
++    }
++
++    GJS_NATIVE_CONSTRUCTOR_PRELUDE(error);
++
++    priv = g_slice_new0(Error);
++
++    GJS_INC_COUNTER(gerror);
++
++    g_assert(priv_from_js(context, object) == NULL);
++    JS_SetPrivate(context, object, priv);
++
++    gjs_debug_lifecycle(GJS_DEBUG_GERROR,
++                        "GError constructor, obj %p priv %p",
++                        object, priv);
++
++    proto = JS_GetPrototype(context, object);
++    gjs_debug_lifecycle(GJS_DEBUG_GERROR, "GError instance __proto__ is %p", proto);
++
++    /* If we're the prototype, then post-construct we'll fill in priv->info.
++     * If we are not the prototype, though, then we'll get ->info from the
++     * prototype and then create a GObject if we don't have one already.
++     */
++    proto_priv = priv_from_js(context, proto);
++    if (proto_priv == NULL) {
++        gjs_debug(GJS_DEBUG_GERROR,
++                  "Bad prototype set on GError? Must match JSClass of object. JS error should have been reported.");
++        return JS_FALSE;
++    }
++
++    priv->info = proto_priv->info;
++    g_base_info_ref( (GIBaseInfo*) priv->info);
++    priv->domain = proto_priv->domain;
++
++    if (!gjs_object_require_property (context, JSVAL_TO_OBJECT(argv[0]),
++                                      "GError constructor", "message", &v_message))
++        return JS_FALSE;
++    if (!gjs_object_require_property (context, JSVAL_TO_OBJECT(argv[0]),
++                                      "GError constructor", "code", &v_code))
++        return JS_FALSE;
++    if (!gjs_string_to_utf8 (context, v_message, &message))
++        return JS_FALSE;
++
++    priv->gerror = g_error_new_literal (priv->domain, JSVAL_TO_INT(v_code),
++                                        message);
++
++    g_free (message);
++
++    GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
++
++    return JS_TRUE;
++}
++
++static void
++error_finalize(JSContext *context,
++               JSObject  *obj)
++{
++    Error *priv;
++
++    priv = priv_from_js(context, obj);
++    gjs_debug_lifecycle(GJS_DEBUG_GERROR,
++                        "finalize, obj %p priv %p", obj, priv);
++    if (priv == NULL)
++        return; /* wrong class? */
++
++    g_clear_error (&priv->gerror);
++
++    if (priv->info) {
++        g_base_info_unref( (GIBaseInfo*) priv->info);
++        priv->info = NULL;
++    }
++
++    GJS_DEC_COUNTER(gerror);
++    g_slice_free(Error, priv);
++}
++
++static JSBool
++error_get_domain(JSContext *context, JSObject *obj, jsid id, jsval *vp)
++{
++    Error *priv;
++
++    priv = priv_from_js(context, obj);
++
++    if (priv == NULL)
++        return JS_FALSE;
++
++    *vp = INT_TO_JSVAL(priv->domain);
++    return JS_TRUE;
++}
++
++static JSBool
++error_get_message(JSContext *context, JSObject *obj, jsid id, jsval *vp)
++{
++    Error *priv;
++
++    priv = priv_from_js(context, obj);
++
++    if (priv == NULL)
++        return JS_FALSE;
++
++    if (priv->gerror == NULL) {
++        /* Object is prototype, not instance */
++        gjs_throw(context, "Can't get a field from a GError prototype");
++        return JS_FALSE;
++    }
++
++    return gjs_string_from_utf8(context, priv->gerror->message, -1, vp);
++}
++
++static JSBool
++error_get_code(JSContext *context, JSObject *obj, jsid id, jsval *vp)
++{
++    Error *priv;
++
++    priv = priv_from_js(context, obj);
++
++    if (priv == NULL)
++        return JS_FALSE;
++
++    if (priv->gerror == NULL) {
++        /* Object is prototype, not instance */
++        gjs_throw(context, "Can't get a field from a GError prototype");
++        return JS_FALSE;
++    }
++
++    *vp = INT_TO_JSVAL(priv->gerror->code);
++    return JS_TRUE;
++}
++
++static JSBool
++error_to_string(JSContext *context, uintN argc, jsval *vp)
++{
++    jsval v_self;
++    JSObject *self;
++    Error *priv;
++    jsval v_out;
++    gchar *descr;
++    JSBool retval;
++
++    v_self = JS_THIS(context, vp);
++    if (!JSVAL_IS_OBJECT(v_self)) {
++        /* Lie a bit here... */
++        gjs_throw(context, "GLib.Error.prototype.toString() called on a non object");
++        return JS_FALSE;
++    }
++
++    self = JSVAL_TO_OBJECT(v_self);
++    priv = priv_from_js(context, self);
++
++    if (priv == NULL)
++        return JS_FALSE;
++
++    v_out = JSVAL_VOID;
++    retval = JS_FALSE;
++
++    /* We follow the same pattern as standard JS errors, at the expense of
++       hiding some useful information */
++
++    if (priv->gerror == NULL) {
++        descr = g_strdup_printf("%s.%s",
++                                g_base_info_get_namespace(priv->info),
++                                g_base_info_get_name(priv->info));
++
++        if (!gjs_string_from_utf8(context, descr, -1, &v_out))
++            goto out;
++    } else {
++        descr = g_strdup_printf("%s.%s: %s",
++                                g_base_info_get_namespace(priv->info),
++                                g_base_info_get_name(priv->info),
++                                priv->gerror->message);
++
++        if (!gjs_string_from_utf8(context, descr, -1, &v_out))
++            goto out;
++    }
++
++    JS_SET_RVAL(context, vp, v_out);
++    retval = JS_TRUE;
++
++ out:
++    g_free(descr);
++    return retval;
++}
++
++static JSBool
++error_constructor_value_of(JSContext *context, uintN argc, jsval *vp)
++{
++    jsval v_self, v_prototype;
++    Error *priv;
++    jsval v_out;
++
++    v_self = JS_THIS(context, vp);
++    if (!JSVAL_IS_OBJECT(v_self)) {
++        /* Lie a bit here... */
++        gjs_throw(context, "GLib.Error.valueOf() called on a non object");
++        return JS_FALSE;
++    }
++
++    if (!gjs_object_require_property(context,
++                                     JSVAL_TO_OBJECT(v_self),
++                                     "constructor",
++                                     "prototype",
++                                     &v_prototype))
++        return JS_FALSE;
++
++    if (!JSVAL_IS_OBJECT(v_prototype)) {
++        gjs_throw(context, "GLib.Error.valueOf() called on something that is not"
++                  " a constructor");
++        return JS_FALSE;
++    }
++
++    priv = priv_from_js(context, JSVAL_TO_OBJECT(v_prototype));
++
++    if (priv == NULL)
++        return JS_FALSE;
++
++    v_out = INT_TO_JSVAL(priv->domain);
++
++    JS_SET_RVAL(context, vp, v_out);
++    return TRUE;
++}
++
++
++/* The bizarre thing about this vtable is that it applies to both
++ * instances of the object, and to the prototype that instances of the
++ * class have.
++ */
++static struct JSClass gjs_error_class = {
++    NULL, /* dynamic class, no name here */
++    JSCLASS_HAS_PRIVATE |
++    JSCLASS_NEW_RESOLVE |
++    JSCLASS_NEW_RESOLVE_GETS_START,
++    JS_PropertyStub,
++    JS_PropertyStub,
++    JS_PropertyStub,
++    JS_StrictPropertyStub,
++    JS_EnumerateStub,
++    JS_ResolveStub,
++    JS_ConvertStub,
++    error_finalize,
++    NULL,
++    NULL,
++    NULL,
++    NULL, NULL, NULL, NULL, NULL
++};
++
++/* We need to shadow all fields of GError, to prevent calling the getter from GBoxed
++   (which would trash memory accessing the instance private data) */
++static JSPropertySpec gjs_error_proto_props[] = {
++    { "domain", PROP_DOMAIN, GJS_MODULE_PROP_FLAGS | JSPROP_READONLY, error_get_domain, NULL },
++    { "code", PROP_CODE, GJS_MODULE_PROP_FLAGS | JSPROP_READONLY, error_get_code, NULL },
++    { "message", PROP_MESSAGE, GJS_MODULE_PROP_FLAGS | JSPROP_READONLY, error_get_message, NULL },
++    { NULL }
++};
++
++static JSFunctionSpec gjs_error_proto_funcs[] = {
++    { "toString", error_to_string, 0, GJS_MODULE_PROP_FLAGS },
++    JS_FS_END
++};
++
++static JSFunctionSpec gjs_error_constructor_funcs[] = {
++    { "valueOf", error_constructor_value_of, 0, GJS_MODULE_PROP_FLAGS },
++    JS_FS_END
++};
++
++JSObject*
++gjs_lookup_error_constructor(JSContext    *context,
++                             GIEnumInfo  *info)
++{
++    JSObject *ns;
++    JSObject *constructor;
++
++    ns = gjs_lookup_namespace_object(context, (GIBaseInfo*) info);
++
++    if (ns == NULL)
++        return NULL;
++
++    constructor = NULL;
++    if (gjs_define_error_class(context, ns, info,
++                               &constructor, NULL))
++        return constructor;
++    else
++        return NULL;
++}
++
++JSObject*
++gjs_lookup_error_prototype(JSContext   *context,
++                           GIEnumInfo  *info)
++{
++    JSObject *ns;
++    JSObject *proto;
++
++    ns = gjs_lookup_namespace_object(context, (GIBaseInfo*) info);
++
++    if (ns == NULL)
++        return NULL;
++
++    proto = NULL;
++    if (gjs_define_error_class(context, ns, info, NULL, &proto))
++        return proto;
++    else
++        return NULL;
++}
++
++JSClass*
++gjs_lookup_error_class(JSContext    *context,
++                       GIEnumInfo   *info)
++{
++    JSObject *prototype;
++
++    prototype = gjs_lookup_error_prototype(context, info);
++
++    return JS_GET_CLASS(context, prototype);
++}
++
++JSBool
++gjs_define_error_class(JSContext    *context,
++                       JSObject     *in_object,
++                       GIEnumInfo   *info,
++                       JSObject    **constructor_p,
++                       JSObject    **prototype_p)
++{
++    const char *constructor_name;
++    GIBoxedInfo *glib_error_info;
++    JSObject *prototype, *parent_proto;
++    JSObject *constructor;
++    jsval value;
++    Error *priv;
++
++    /* See the comment in gjs_define_boxed_class() for an
++     * explanation of how this all works; Error is pretty much the
++     * same as Boxed (except that we inherit from GLib.Error).
++     */
++
++    constructor_name = g_base_info_get_name( (GIBaseInfo*) info);
++
++    if (gjs_object_get_property(context, in_object, constructor_name, &value)) {
++        JSObject *constructor;
++
++        if (!JSVAL_IS_OBJECT(value)) {
++            gjs_throw(context, "Existing property '%s' does not look like a constructor",
++                         constructor_name);
++            return JS_FALSE;
++        }
++
++        constructor = JSVAL_TO_OBJECT(value);
++
++        gjs_object_get_property(context, constructor, "prototype", &value);
++        if (!JSVAL_IS_OBJECT(value)) {
++            gjs_throw(context, "error %s prototype property does not appear to exist or has wrong type", constructor_name);
++            return JS_FALSE;
++        } else {
++            if (prototype_p)
++                *prototype_p = JSVAL_TO_OBJECT(value);
++            if (constructor_p)
++                *constructor_p = constructor;
++
++            return JS_TRUE;
++        }
++    }
++
++    g_irepository_require(NULL, "GLib", "2.0", 0, NULL);
++    glib_error_info = (GIBoxedInfo*) g_irepository_find_by_name(NULL, "GLib", "Error");
++    parent_proto = gjs_lookup_boxed_prototype(context, glib_error_info);
++    g_base_info_unref((GIBaseInfo*)glib_error_info);
++
++    prototype = gjs_init_class_dynamic(context, in_object,
++                                          parent_proto,
++                                          g_base_info_get_namespace( (GIBaseInfo*) info),
++                                          constructor_name,
++                                          &gjs_error_class,
++                                          gjs_error_constructor,
++                                          /* number of constructor args (less can be passed) */
++                                          1,
++                                          /* props of prototype */
++                                          &gjs_error_proto_props[0],
++                                          /* funcs of prototype */
++                                          &gjs_error_proto_funcs[0],
++                                          /* props of constructor, MyConstructor.myprop */
++                                          NULL,
++                                          /* funcs of constructor, MyConstructor.myfunc() */
++                                          &gjs_error_constructor_funcs[0]);
++    if (prototype == NULL) {
++        gjs_log_exception(context, NULL);
++        gjs_fatal("Can't init class %s", constructor_name);
++    }
++
++    g_assert(gjs_object_has_property(context, in_object, constructor_name));
++
++    priv = g_slice_new0(Error);
++    priv->info = info;
++    g_base_info_ref( (GIBaseInfo*) priv->info);
++    priv->domain = g_quark_from_string (g_enum_info_get_error_domain(priv->info));
++
++    JS_SetPrivate(context, prototype, priv);
++
++    gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
++              constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object);
++
++    constructor = NULL;
++    gjs_object_get_property(context, in_object, constructor_name, &value);
++    if (!JSVAL_IS_VOID(value)) {
++        if (!JSVAL_IS_OBJECT(value)) {
++            gjs_throw(context, "Property '%s' does not look like a constructor",
++                      constructor_name);
++            return JS_FALSE;
++        }
++    }
++
++    constructor = JSVAL_TO_OBJECT(value);
++
++    gjs_define_enum_values(context, constructor, priv->info);
++
++    if (constructor_p)
++        *constructor_p = constructor;
++
++    if (prototype_p)
++        *prototype_p = prototype;
++
++    return JS_TRUE;
++}
++
++static GIEnumInfo *
++find_error_domain_info(GQuark domain)
++{
++    GIEnumInfo *info;
++
++    /* first an attempt without loading extra libraries */
++    info = g_irepository_find_by_error_domain(NULL, domain);
++    if (info)
++        return info;
++
++    /* load standard stuff */
++    g_irepository_require(NULL, "GLib", "2.0", 0, NULL);
++    g_irepository_require(NULL, "GObject", "2.0", 0, NULL);
++    g_irepository_require(NULL, "Gio", "2.0", 0, NULL);
++    info = g_irepository_find_by_error_domain(NULL, domain);
++    if (info)
++        return info;
++
++    /* last attempt: load GIRepository (for invoke errors, rarely
++       needed) */
++    g_irepository_require(NULL, "GIRepository", "1.0", 0, NULL);
++    info = g_irepository_find_by_error_domain(NULL, domain);
++
++    return info;
++}
++
++JSObject*
++gjs_error_from_gerror(JSContext             *context,
++                      GError                *gerror)
++{
++    JSObject *obj;
++    JSObject *proto;
++    Error *priv;
++    Error *proto_priv;
++    GIEnumInfo *info;
++
++    if (gerror == NULL)
++        return NULL;
++
++    info = find_error_domain_info(gerror->domain);
++
++    if (!info) {
++        /* We don't have error domain metadata */
++        /* Marshal the error as a plain GError */
++        GIBaseInfo *glib_boxed;
++        JSObject *retval;
++
++        glib_boxed = g_irepository_find_by_name(NULL, "GLib", "Error");
++        retval = gjs_boxed_from_c_struct(context, glib_boxed, gerror, 0);
++
++        g_base_info_unref(glib_boxed);
++        return retval;
++    }
++
++    gjs_debug_marshal(GJS_DEBUG_GBOXED,
++                      "Wrapping struct %s %p with JSObject",
++                      g_base_info_get_name((GIBaseInfo *)info), gboxed);
++
++    proto = gjs_lookup_error_prototype(context, info);
++    proto_priv = priv_from_js(context, proto);
++
++    obj = JS_NewObjectWithGivenProto(context,
++                                     JS_GET_CLASS(context, proto), proto,
++                                     gjs_get_import_global (context));
++
++    priv = g_slice_new0(Error);
++    JS_SetPrivate(context, obj, priv);
++    priv->info = info;
++    priv->domain = proto_priv->domain;
++    g_base_info_ref( (GIBaseInfo*) priv->info);
++    priv->gerror = g_error_copy(gerror);
++
++    return obj;
++}
++
++GError*
++gjs_gerror_from_error(JSContext    *context,
++                      JSObject     *obj)
++{
++    Error *priv;
++
++    if (obj == NULL)
++        return NULL;
++
++    priv = priv_from_js(context, obj);
++
++    if (priv == NULL)
++        return NULL;
++
++    if (priv->gerror == NULL) {
++        gjs_throw(context,
++                  "Object is %s.%s.prototype, not an object instance - cannot convert to a boxed instance",
++                  g_base_info_get_namespace( (GIBaseInfo*) priv->info),
++                  g_base_info_get_name( (GIBaseInfo*) priv->info));
++        return NULL;
++    }
++
++    return priv->gerror;
++}
+Index: gjs-1.32.0/gi/gerror.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gjs-1.32.0/gi/gerror.h	2012-11-26 10:59:33.538183526 +0100
+@@ -0,0 +1,53 @@
++/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
++/*
++ * Copyright (c) 2008  litl, LLC
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#ifndef __GJS_ERROR_H__
++#define __GJS_ERROR_H__
++
++#include <glib.h>
++
++#include <jsapi.h>
++
++#include <girepository.h>
++
++G_BEGIN_DECLS
++
++JSBool    gjs_define_error_class       (JSContext             *context,
++                                        JSObject              *in_object,
++                                        GIEnumInfo            *info,
++                                        JSObject             **constructor_p,
++                                        JSObject             **prototype_p);
++JSObject* gjs_lookup_error_constructor (JSContext             *context,
++                                        GIEnumInfo            *info);
++JSObject* gjs_lookup_error_prototype   (JSContext             *context,
++                                        GIEnumInfo            *info);
++JSClass*  gjs_lookup_error_class       (JSContext             *context,
++                                        GIEnumInfo            *info);
++GError*   gjs_gerror_from_error        (JSContext             *context,
++                                        JSObject              *obj);
++JSObject* gjs_error_from_gerror        (JSContext             *context,
++                                        GError                *gerror);
++
++G_END_DECLS
++
++#endif  /* __GJS_ERROR_H__ */
+Index: gjs-1.32.0/gi/repo.c
+===================================================================
+--- gjs-1.32.0.orig/gi/repo.c	2012-02-06 15:17:48.000000000 +0100
++++ gjs-1.32.0/gi/repo.c	2012-11-26 10:59:33.542183540 +0100
+@@ -34,6 +34,7 @@
+ #include "arg.h"
+ #include "foreign.h"
+ #include "interface.h"
++#include "gerror.h"
+ 
+ #include <gjs/compat.h>
+ 
+@@ -499,6 +500,13 @@ gjs_define_info(JSContext  *context,
+             return JS_FALSE;
+         break;
+     case GI_INFO_TYPE_ENUM:
++        if (g_enum_info_get_error_domain((GIEnumInfo*) info)) {
++            /* define as GError subclass */
++            if (!gjs_define_error_class(context, in_object, (GIEnumInfo*) info, NULL, NULL))
++                return JS_FALSE;
++        }
++        /* fall through */
++
+     case GI_INFO_TYPE_FLAGS:
+         if (!gjs_define_enumeration(context, in_object, (GIEnumInfo*) info, NULL))
+             return JS_FALSE;
+Index: gjs-1.32.0/gi/value.c
+===================================================================
+--- gjs-1.32.0.orig/gi/value.c	2012-03-05 15:48:49.000000000 +0100
++++ gjs-1.32.0/gi/value.c	2012-11-26 10:59:33.542183540 +0100
+@@ -33,6 +33,7 @@
+ #include "boxed.h"
+ #include "union.h"
+ #include "gtype.h"
++#include "gerror.h"
+ #include <gjs/gjs-module.h>
+ #include <gjs/compat.h>
+ 
+@@ -387,7 +388,13 @@ gjs_value_to_g_value_internal(JSContext
+         } else if (JSVAL_IS_OBJECT(value)) {
+             JSObject *obj;
+             obj = JSVAL_TO_OBJECT(value);
+-            gboxed = gjs_c_struct_from_boxed(context, obj);
++
++            if (g_type_is_a(gtype, G_TYPE_ERROR)) {
++                /* special case GError */
++                gboxed = gjs_gerror_from_error(context, obj);
++            } else {
++                gboxed = gjs_c_struct_from_boxed(context, obj);
++            }
+         } else {
+             gjs_throw(context,
+                       "Wrong type %s; boxed type %s expected",
+@@ -665,6 +672,14 @@ gjs_value_from_g_value_internal(JSContex
+             gboxed = g_value_get_variant(gvalue);
+         boxed_flags = GJS_BOXED_CREATION_NONE;
+ 
++        /* special case GError */
++        if (g_type_is_a(gtype, G_TYPE_ERROR)) {
++            obj = gjs_error_from_gerror(context, gboxed);
++            *value_p = OBJECT_TO_JSVAL(obj);
++
++            return TRUE;
++        }
++
+         /* The only way to differentiate unions and structs is from
+          * their g-i info as both GBoxed */
+         info = g_irepository_find_by_gtype(g_irepository_get_default(),
+@@ -693,6 +708,7 @@ gjs_value_from_g_value_internal(JSContex
+                       g_type_name(gtype));
+             return JS_FALSE;
+         }
++
+         *value_p = OBJECT_TO_JSVAL(obj);
+     } else if (g_type_is_a(gtype, G_TYPE_ENUM)) {
+         return convert_int_to_enum(context, value_p, gtype, g_value_get_enum(gvalue));
+Index: gjs-1.32.0/gjs/jsapi-util-error.c
+===================================================================
+--- gjs-1.32.0.orig/gjs/jsapi-util-error.c	2012-03-05 15:48:49.000000000 +0100
++++ gjs-1.32.0/gjs/jsapi-util-error.c	2012-11-26 10:59:33.546183565 +0100
+@@ -25,6 +25,7 @@
+ 
+ #include "jsapi-util.h"
+ #include "compat.h"
++#include "gi/gerror.h"
+ 
+ #include <util/log.h>
+ 
+@@ -46,13 +47,9 @@ gjs_throw_valist(JSContext       *contex
+                     va_list          args)
+ {
+     char *s;
+-    jsval retval;
+-    jsval argv[1];
+-    JSFunction *func;
+-    const char *body;
+     JSBool result;
+-    const char *names[] = { "message" };
+-    guint options;
++    jsval v_constructor, v_message;
++    JSObject *err_obj;
+ 
+     s = g_strdup_vprintf(format, args);
+ 
+@@ -79,53 +76,20 @@ gjs_throw_valist(JSContext       *contex
+ 
+     (void)JS_EnterLocalRootScope(context);
+ 
+-    if (!gjs_string_from_utf8(context, s, -1, &argv[0])) {
++    if (!gjs_string_from_utf8(context, s, -1, &v_message)) {
+         JS_ReportError(context, "Failed to copy exception string");
+         goto out;
+     }
+ 
+-    body = "throw new Error(message);";
+-    func = JS_CompileFunction(context,
+-                              JS_GetGlobalObject(context), /* parent object (scope chain) */
+-                              NULL, /* name of function if we wanted to define it in parent */
+-                              1, /* nargs */
+-                              &names[0], /* array of arg names if we had args */
+-                              body,
+-                              strlen(body),
+-                              "gjs_throw", /* file */
+-                              0); /* line */
+-
+-    if (func == NULL) {
+-        JS_ReportError(context, "Failed to compile function");
++    if (!gjs_object_get_property(context, JS_GetGlobalObject(context),
++                                 "Error", &v_constructor)) {
++        JS_ReportError(context, "??? Missing Error constructor in global object?");
+         goto out;
+     }
+ 
+-    /* we need JS_CallFunctionValue() to leave the exception set */
+-    options = JS_GetOptions(context);
+-    if (!(options & JSOPTION_DONT_REPORT_UNCAUGHT)) {
+-        JS_SetOptions(context, options | JSOPTION_DONT_REPORT_UNCAUGHT);
+-    }
+-
+-    retval = JSVAL_VOID;
+-
+-    /* note the return value is whether function succeeded, which it shouldn't, since it
+-     * throws...
+-     */
+-    JS_CallFunctionValue(context,
+-                         JS_GetGlobalObject(context),
+-                         OBJECT_TO_JSVAL(JS_GetFunctionObject(func)),
+-                         1, &argv[0],
+-                         &retval);
+-
+-    if (!(options & JSOPTION_DONT_REPORT_UNCAUGHT)) {
+-        JS_SetOptions(context, options);
+-    }
+-
+-    if (!JS_IsExceptionPending(context)) {
+-        JS_ReportError(context,
+-                       "Failed to set exception by calling our exception-setting function");
+-        goto out;
+-    }
++    /* throw new Error(message) */
++    err_obj = JS_New(context, JSVAL_TO_OBJECT(v_constructor), 1, &v_message);
++    JS_SetPendingException(context, OBJECT_TO_JSVAL(err_obj));
+ 
+     result = JS_TRUE;
+ 
+@@ -182,17 +146,26 @@ gjs_throw_literal(JSContext       *conte
+  * gjs_throw_g_error:
+  *
+  * Convert a GError into a JavaScript Exception, and
+- * frees the GError.  Like gjs_throw(), will not overwrite
+- * an already pending exception.
++ * frees the GError. Differently from gjs_throw(), it
++ * will overwrite an existing exception, as it is used
++ * to report errors from C functions.
+  */
+ void
+ gjs_throw_g_error (JSContext       *context,
+                    GError          *error)
+ {
++    JSObject *err_obj;
++
+     if (error == NULL)
+         return;
+-    gjs_throw_literal(context, error->message);
+-    g_error_free (error);
++
++    JS_BeginRequest(context);
++
++    err_obj = gjs_error_from_gerror(context, error);
++    if (err_obj)
++        JS_SetPendingException(context, OBJECT_TO_JSVAL(err_obj));
++
++    JS_EndRequest(context);
+ }
+ 
+ #if GJS_BUILD_TESTS
+Index: gjs-1.32.0/gjs/mem.c
+===================================================================
+--- gjs-1.32.0.orig/gjs/mem.c	2012-01-04 19:24:48.000000000 +0100
++++ gjs-1.32.0/gjs/mem.c	2012-11-26 10:59:33.546183565 +0100
+@@ -36,6 +36,7 @@
+ GJS_DEFINE_COUNTER(everything)
+ 
+ GJS_DEFINE_COUNTER(boxed)
++GJS_DEFINE_COUNTER(gerror)
+ GJS_DEFINE_COUNTER(closure)
+ GJS_DEFINE_COUNTER(database)
+ GJS_DEFINE_COUNTER(dbus_exports)
+@@ -54,6 +55,7 @@ GJS_DEFINE_COUNTER(interface)
+ 
+ static GjsMemCounter* counters[] = {
+     GJS_LIST_COUNTER(boxed),
++    GJS_LIST_COUNTER(gerror),
+     GJS_LIST_COUNTER(closure),
+     GJS_LIST_COUNTER(database),
+     GJS_LIST_COUNTER(dbus_exports),
+Index: gjs-1.32.0/gjs/mem.h
+===================================================================
+--- gjs-1.32.0.orig/gjs/mem.h	2012-01-04 19:24:48.000000000 +0100
++++ gjs-1.32.0/gjs/mem.h	2012-11-26 10:59:33.546183565 +0100
+@@ -44,6 +44,7 @@ typedef struct {
+ GJS_DECLARE_COUNTER(everything)
+ 
+ GJS_DECLARE_COUNTER(boxed)
++GJS_DECLARE_COUNTER(gerror)
+ GJS_DECLARE_COUNTER(closure)
+ GJS_DECLARE_COUNTER(database)
+ GJS_DECLARE_COUNTER(dbus_exports)
+Index: gjs-1.32.0/modules/overrides/GLib.js
+===================================================================
+--- gjs-1.32.0.orig/modules/overrides/GLib.js	2011-11-10 19:58:10.000000000 +0100
++++ gjs-1.32.0/modules/overrides/GLib.js	2012-11-26 10:59:33.550183579 +0100
+@@ -240,6 +240,11 @@ function _init() {
+ 
+     GLib = this;
+ 
++    // small HACK: we add a matches() method to standard Errors so that
++    // you can do "catch(e if e.matches(Ns.FooError, Ns.FooError.SOME_CODE))"
++    // without checking instanceof
++    Error.prototype.matches = function() { return false; }
++
+     this.Variant.new = function (sig, value) {
+ 	let signature = Array.prototype.slice.call(sig);
+ 
+Index: gjs-1.32.0/test/js/testEverythingBasic.js
+===================================================================
+--- gjs-1.32.0.orig/test/js/testEverythingBasic.js	2012-02-07 17:30:49.000000000 +0100
++++ gjs-1.32.0/test/js/testEverythingBasic.js	2012-11-26 10:59:33.550183579 +0100
+@@ -521,4 +521,33 @@ function testVariant() {
+     assertEquals(3, as.length);
+ }
+ 
++function testGError() {
++    assertEquals(Gio.io_error_quark(), Number(Gio.IOErrorEnum));
++
++    try {
++	let file = Gio.file_new_for_path("\\/,.^!@&$_don't exist");
++	file.read(null);
++    } catch (x) {
++	assertTrue(x instanceof Gio.IOErrorEnum);
++	assertTrue(x.matches(Gio.io_error_quark(), Gio.IOErrorEnum.NOT_FOUND));
++	assertTrue(x.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND));
++
++	assertEquals(Gio.io_error_quark(), x.domain);
++	assertEquals(Gio.IOErrorEnum.NOT_FOUND, x.code);
++    }
++
++    Everything.test_gerror_callback(function(e) {
++	assertTrue(e instanceof Gio.IOErrorEnum);
++	assertEquals(Gio.io_error_quark(), e.domain);
++	assertEquals(Gio.IOErrorEnum.NOT_SUPPORTED, e.code);
++	assertEquals('regression test error', e.message);
++    });
++    Everything.test_owned_gerror_callback(function(e) {
++	assertTrue(e instanceof Gio.IOErrorEnum);
++	assertEquals(Gio.io_error_quark(), e.domain);
++	assertEquals(Gio.IOErrorEnum.PERMISSION_DENIED, e.code);
++	assertEquals('regression test owned error', e.message);
++    });
++}
++
+ gjstestRun();
+Index: gjs-1.32.0/util/log.c
+===================================================================
+--- gjs-1.32.0.orig/util/log.c	2011-06-10 00:31:56.000000000 +0200
++++ gjs-1.32.0/util/log.c	2012-11-26 10:59:33.550183579 +0100
+@@ -277,6 +277,9 @@ gjs_debug(GjsDebugTopic topic,
+     case GJS_DEBUG_BYTE_ARRAY:
+         prefix = "JS BYTE ARRAY";
+         break;
++    case GJS_DEBUG_GERROR:
++        prefix = "JS G ERR";
++        break;
+     }
+ 
+     if (!is_allowed_prefix(prefix))
+Index: gjs-1.32.0/util/log.h
+===================================================================
+--- gjs-1.32.0.orig/util/log.h	2011-06-10 00:31:56.000000000 +0200
++++ gjs-1.32.0/util/log.h	2012-11-26 10:59:33.550183579 +0100
+@@ -60,7 +60,8 @@ typedef enum {
+     GJS_DEBUG_PROPS,
+     GJS_DEBUG_SCOPE,
+     GJS_DEBUG_HTTP,
+-    GJS_DEBUG_BYTE_ARRAY
++    GJS_DEBUG_BYTE_ARRAY,
++    GJS_DEBUG_GERROR,
+ } GjsDebugTopic;
+ 
+ /* These defines are because we have some pretty expensive and
diff -Nru gjs-1.32.0/debian/patches/03_gerror_details.patch gjs-1.32.0/debian/patches/03_gerror_details.patch
--- gjs-1.32.0/debian/patches/03_gerror_details.patch	1970-01-01 01:00:00.000000000 +0100
+++ gjs-1.32.0/debian/patches/03_gerror_details.patch	2012-11-26 12:01:17.000000000 +0100
@@ -0,0 +1,384 @@
+From 52e921dacf553564f6503668bf0be82cfb782d7c Mon Sep 17 00:00:00 2001
+From: Giovanni Campagna <gcampagna@src.gnome.org>
+Date: Sat, 03 Mar 2012 17:03:14 +0000
+Subject: GError: add stack, fileName and lineNumber
+
+Similar to native Errors(), GLib.Error is extended to provide debug
+information in the form of fileName, lineNumber and stack (obtained
+using the JS debug API). At the same time, the existing stack logging
+facility is modified to be similar in format to the native one, and
+logError is modified to avoid iterating object properties (which
+gives an undefined order, and does not include prototype properties)
+
+https://bugzilla.gnome.org/show_bug.cgi?id=591480
+---
+diff --git a/gi/arg.c b/gi/arg.c
+index af1750d..8250eb8 100644
+--- a/gi/arg.c
++++ b/gi/arg.c
+@@ -2379,7 +2379,7 @@ gjs_value_from_g_argument (JSContext  *context,
+     case GI_TYPE_TAG_ERROR:
+         {
+             if (arg->v_pointer) {
+-                JSObject *obj = gjs_error_from_gerror(context, arg->v_pointer);
++                JSObject *obj = gjs_error_from_gerror(context, arg->v_pointer, FALSE);
+                 if (obj) {
+                     *value_p = OBJECT_TO_JSVAL(obj);
+                     return JS_TRUE;
+@@ -2459,7 +2459,7 @@ gjs_value_from_g_argument (JSContext  *context,
+             if (g_type_is_a(gtype, G_TYPE_ERROR)) {
+                 JSObject *obj;
+ 
+-                obj = gjs_error_from_gerror(context, arg->v_pointer);
++                obj = gjs_error_from_gerror(context, arg->v_pointer, FALSE);
+                 if (obj)
+                     value = OBJECT_TO_JSVAL(obj);
+                 else
+diff --git a/gi/gerror.c b/gi/gerror.c
+index 5d50cd5..45dc387 100644
+--- a/gi/gerror.c
++++ b/gi/gerror.c
+@@ -35,6 +35,7 @@
+ #include <util/log.h>
+ 
+ #include <jsapi.h>
++#include <jsdbgapi.h>
+ 
+ #include <girepository.h>
+ 
+@@ -53,6 +54,8 @@ enum {
+ 
+ static struct JSClass gjs_error_class;
+ 
++static void define_error_properties(JSContext *, JSObject *);
++
+ GJS_DEFINE_DYNAMIC_PRIV_FROM_JS(Error, gjs_error_class)
+ 
+ GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
+@@ -115,6 +118,9 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
+ 
+     g_free (message);
+ 
++    /* We assume this error will be thrown in the same line as the constructor */
++    define_error_properties(context, object);
++
+     GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
+ 
+     return JS_TRUE;
+@@ -514,9 +520,61 @@ find_error_domain_info(GQuark domain)
+     return info;
+ }
+ 
++/* define properties that JS Error() expose, such as
++   fileName, lineNumber and stack
++*/
++static void
++define_error_properties(JSContext *context,
++                        JSObject  *obj)
++{
++    JSStackFrame *frame;
++    JSScript *script;
++    jsbytecode *pc;
++    jsval v;
++    GString *stack;
++    const char *filename;
++    GjsContext *gjs_context;
++
++    /* find the JS frame that triggered the error */
++    frame = NULL;
++    while (JS_FrameIterator(context, &frame)) {
++        if (JS_IsScriptFrame(context, frame))
++            break;
++    }
++
++    /* someone called gjs_throw at top of the stack?
++       well, no stack in that case
++    */
++    if (!frame)
++        return;
++
++    script = JS_GetFrameScript(context, frame);
++    pc = JS_GetFramePC(context, frame);
++
++    stack = g_string_new(NULL);
++    gjs_context = JS_GetContextPrivate(context);
++    gjs_context_print_stack_to_buffer(gjs_context, frame, stack);
++
++    if (gjs_string_from_utf8(context, stack->str, stack->len, &v))
++        JS_DefineProperty(context, obj, "stack", v,
++                          NULL, NULL, JSPROP_ENUMERATE);
++
++    filename = JS_GetScriptFilename(context, script);
++    if (gjs_string_from_filename(context, filename, -1, &v))
++        JS_DefineProperty(context, obj, "fileName", v,
++                          NULL, NULL, JSPROP_ENUMERATE);
++
++    v = INT_TO_JSVAL(JS_PCToLineNumber(context, script, pc));
++    JS_DefineProperty(context, obj, "lineNumber", v,
++                      NULL, NULL, JSPROP_ENUMERATE);
++
++    g_string_free(stack, TRUE);
++}
++
+ JSObject*
+ gjs_error_from_gerror(JSContext             *context,
+-                      GError                *gerror)
++                      GError                *gerror,
++                      gboolean               add_stack)
+ {
+     JSObject *obj;
+     JSObject *proto;
+@@ -560,6 +618,9 @@ gjs_error_from_gerror(JSContext             *context,
+     g_base_info_ref( (GIBaseInfo*) priv->info);
+     priv->gerror = g_error_copy(gerror);
+ 
++    if (add_stack)
++        define_error_properties(context, obj);
++
+     return obj;
+ }
+ 
+diff --git a/gi/gerror.h b/gi/gerror.h
+index 0d93c44..3940d1a 100644
+--- a/gi/gerror.h
++++ b/gi/gerror.h
+@@ -46,7 +46,8 @@ JSClass*  gjs_lookup_error_class       (JSContext             *context,
+ GError*   gjs_gerror_from_error        (JSContext             *context,
+                                         JSObject              *obj);
+ JSObject* gjs_error_from_gerror        (JSContext             *context,
+-                                        GError                *gerror);
++                                        GError                *gerror,
++                                        gboolean               add_stack);
+ 
+ G_END_DECLS
+ 
+diff --git a/gi/value.c b/gi/value.c
+index c64564f..4d02827 100644
+--- a/gi/value.c
++++ b/gi/value.c
+@@ -675,7 +675,7 @@ gjs_value_from_g_value_internal(JSContext    *context,
+ 
+         /* special case GError */
+         if (g_type_is_a(gtype, G_TYPE_ERROR)) {
+-            obj = gjs_error_from_gerror(context, gboxed);
++            obj = gjs_error_from_gerror(context, gboxed, FALSE);
+             *value_p = OBJECT_TO_JSVAL(obj);
+ 
+             return TRUE;
+diff --git a/gjs/context.h b/gjs/context.h
+index 4e01cc7..d19d8a5 100644
+--- a/gjs/context.h
++++ b/gjs/context.h
+@@ -68,7 +68,11 @@ gboolean        gjs_context_define_string_array  (GjsContext  *js_context,
+ GList*          gjs_context_get_all              (void);
+ void*           gjs_context_get_native_context   (GjsContext *js_context);
+ 
++/* initial_frame is a JSStackFrame, but cannot be exposed as such in the
++   public API. Pass NULL to get the topmost frame.
++*/
+ void            gjs_context_print_stack_to_buffer (GjsContext *js_context,
++                                                   void       *initial_frame,
+                                                    GString    *buf);
+ 
+ void            gjs_context_print_stack_stderr    (GjsContext *js_context);
+diff --git a/gjs/jsapi-util-error.c b/gjs/jsapi-util-error.c
+index 8bce07e..88ac97e 100644
+--- a/gjs/jsapi-util-error.c
++++ b/gjs/jsapi-util-error.c
+@@ -161,7 +161,7 @@ gjs_throw_g_error (JSContext       *context,
+ 
+     JS_BeginRequest(context);
+ 
+-    err_obj = gjs_error_from_gerror(context, error);
++    err_obj = gjs_error_from_gerror(context, error, TRUE);
+     if (err_obj)
+         JS_SetPendingException(context, OBJECT_TO_JSVAL(err_obj));
+ 
+diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
+index 6efd528..ca2965e 100644
+--- a/gjs/jsapi-util.c
++++ b/gjs/jsapi-util.c
+@@ -970,6 +970,21 @@ gjs_explain_scope(JSContext  *context,
+     JS_EndRequest(context);
+ }
+ 
++static void
++log_one_exception_property(JSContext  *context,
++                           JSObject   *object,
++                           const char *name)
++{
++    jsval v;
++    char *debugstr;
++
++    gjs_object_get_property(context, object, name, &v);
++
++    debugstr = gjs_value_debug_string(context, v);
++    gjs_debug(GJS_DEBUG_ERROR, "  %s = '%s'", name, debugstr);
++    g_free(debugstr);
++}
++
+ void
+ gjs_log_exception_props(JSContext *context,
+                         jsval      exc)
+@@ -988,23 +1003,10 @@ gjs_log_exception_props(JSContext *context,
+ 
+         exc_obj = JSVAL_TO_OBJECT(exc);
+ 
+-        /* I guess this is a SpiderMonkey bug.  If we don't get these
+-         * properties here, only 'message' shows up when we enumerate
+-         * all properties below. I did not debug in detail, so maybe
+-         * it's something wrong with our enumeration loop below. In
+-         * any case, if you remove this code block, check that "throw
+-         * Error()" still results in printing all four of these props.
+-         * For me right now, if you remove this block, only message
+-         * gets printed.
+-         */
+-        gjs_object_has_property(context, exc_obj, "stack");
+-        gjs_object_has_property(context, exc_obj, "fileName");
+-        gjs_object_has_property(context, exc_obj, "lineNumber");
+-        gjs_object_has_property(context, exc_obj, "message");
+-
+-        gjs_log_object_props(context, exc_obj,
+-                             GJS_DEBUG_ERROR,
+-                             "  ");
++        log_one_exception_property(context, exc_obj, "message");
++        log_one_exception_property(context, exc_obj, "fileName");
++        log_one_exception_property(context, exc_obj, "lineNumber");
++        log_one_exception_property(context, exc_obj, "stack");
+     } else if (JSVAL_IS_STRING(exc)) {
+         gjs_debug(GJS_DEBUG_ERROR,
+                   "Exception was a String");
+diff --git a/gjs/stack.c b/gjs/stack.c
+index 363366d..84e1c6a 100644
+--- a/gjs/stack.c
++++ b/gjs/stack.c
+@@ -48,34 +48,40 @@
+ #include "compat.h"
+ #include "jsapi-util.h"
+ 
++/* Mimick the behaviour exposed by standard Error objects
++   (http://mxr.mozilla.org/mozilla-central/source/js/src/jsexn.cpp#554)
++*/
+ static char*
+ jsvalue_to_string(JSContext* cx, jsval val, gboolean* is_string)
+ {
+     char* value = NULL;
+-    JSString* value_str;
+-
+-    (void)JS_EnterLocalRootScope(cx);
+-
+-    value_str = JS_ValueToString(cx, val);
+-    if (value_str)
+-        value = gjs_value_debug_string(cx, val);
+-    if (value) {
+-        const char* found = strstr(value, "function ");
+-        if(found && (value == found || value+1 == found || value+2 == found)) {
+-            g_free(value);
+-            value = g_strdup("[function]");
+-        }
++    JSString* value_str = NULL;
++
++    if (JSVAL_IS_PRIMITIVE(val)) {
++      value_str = JS_ValueToSource(cx, val);
++    } else {
++      JSObject *obj = JSVAL_TO_OBJECT(val);
++
++      if (JS_ObjectIsFunction(cx, obj)) {
++	JSFunction *fn = JS_ValueToFunction(cx, val);
++	value_str = JS_GetFunctionId(fn);
++
++	if (!value_str)
++	  value = g_strdup("[unknown function]");
++      } else {
++	value = g_strdup_printf("[object %s]", JS_GetClass(cx, obj)->name);
++      }
+     }
+ 
++    if (!value && value_str)
++      value = gjs_value_debug_string(cx, val);
++
+     if (is_string)
+         *is_string = JSVAL_IS_STRING(val);
+ 
+-    JS_LeaveLocalRootScope(cx);
+-
+     return value;
+ }
+ 
+-
+ static void
+ format_frame(JSContext* cx, JSStackFrame* fp,
+              GString *buf, int num)
+@@ -167,14 +173,10 @@ format_frame(JSContext* cx, JSStackFrame* fp,
+         guint32 k;
+         guint32 arg_count;
+         JSObject* args_obj = JSVAL_TO_OBJECT(val);
+-        if (JS_GetProperty(cx, args_obj, "length", &val) &&
+-            JS_ValueToECMAUint32(cx, val, &arg_count) &&
++        if (JS_GetArrayLength(cx, args_obj, &arg_count) &&
+             arg_count > named_arg_count) {
+             for (k = named_arg_count; k < arg_count; k++) {
+-                char number[8];
+-                g_snprintf(number, 8, "%d", (int) k);
+-
+-                if (JS_GetProperty(cx, args_obj, number, &val)) {
++                if (JS_GetElement(cx, args_obj, k, &val)) {
+                     char *value = jsvalue_to_string(cx, val, &is_string);
+                     g_string_append_printf(buf, "%s%s%s%s",
+                                            k ? ", " : "",
+@@ -189,38 +191,41 @@ format_frame(JSContext* cx, JSStackFrame* fp,
+ 
+     /* print filename and line number */
+ 
+-    g_string_append_printf(buf, "%s [\"%s\":%d]\n",
++    g_string_append_printf(buf, "%s@%s:%d\n",
+                            fun ? ")" : "",
+-                           filename ? filename : "<unknown>",
++                           filename ? filename : "",
+                            lineno);
++
+   out:
++    if (call_props.array)
++      JS_PutPropertyDescArray(cx, &call_props);
++
+     JS_LeaveLocalRootScope(cx);
+ }
+ 
+ void
+-gjs_context_print_stack_to_buffer(GjsContext* context, GString *buf)
++gjs_context_print_stack_to_buffer(GjsContext* context, void *initial, GString *buf)
+ {
+     JSContext *js_context = (JSContext*)gjs_context_get_native_context(context);
+-    JSStackFrame* fp;
+-    JSStackFrame* iter = NULL;
++    JSStackFrame* fp = initial;
+     int num = 0;
+ 
+-    g_string_append_printf(buf, "== Stack trace for context %p ==\n", context);
+-    while ((fp = JS_FrameIterator(js_context, &iter)) != NULL) {
++    while (fp) {
+         format_frame(js_context, fp, buf, num);
+         num++;
+-    }
+ 
+-    if(!num)
+-        g_string_append_printf(buf, "(JavaScript stack is empty)\n");
+-    g_string_append(buf, "\n");
++	JS_FrameIterator(js_context, &fp);
++    }
+ }
+ 
+ void
+ gjs_context_print_stack_stderr(GjsContext *context)
+ {
+   GString *str = g_string_new("");
+-  gjs_context_print_stack_to_buffer(context, str);
++
++  g_string_append_printf(str, "== Stack trace for context %p ==\n", context);
++  gjs_context_print_stack_to_buffer(context, NULL, str);
++
+   g_printerr("%s\n", str->str);
+   g_string_free(str, TRUE);
+ }
+--
+cgit v0.9.0.2
diff -Nru gjs-1.32.0/debian/patches/04_gjs_dumpstack.patch gjs-1.32.0/debian/patches/04_gjs_dumpstack.patch
--- gjs-1.32.0/debian/patches/04_gjs_dumpstack.patch	1970-01-01 01:00:00.000000000 +0100
+++ gjs-1.32.0/debian/patches/04_gjs_dumpstack.patch	2012-12-12 11:40:39.000000000 +0100
@@ -0,0 +1,30 @@
+From 5c90e776ce3c096bccba5ad111bf6c80b9cfb060 Mon Sep 17 00:00:00 2001
+From: Jasper St. Pierre <jstpierre@mecheye.net>
+Date: Thu, 13 Sep 2012 22:48:27 +0000
+Subject: stack: Fix gjs_dumpstack
+
+We need to iterate the stack here at least once or the while
+loop will terminate early.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=683992
+---
+diff --git a/gjs/stack.c b/gjs/stack.c
+index 84e1c6a..8013e30 100644
+--- a/gjs/stack.c
++++ b/gjs/stack.c
+@@ -207,9 +207,12 @@ void
+ gjs_context_print_stack_to_buffer(GjsContext* context, void *initial, GString *buf)
+ {
+     JSContext *js_context = (JSContext*)gjs_context_get_native_context(context);
+-    JSStackFrame* fp = initial;
++    JSStackFrame *fp = initial;
+     int num = 0;
+ 
++    if (fp == NULL)
++        JS_FrameIterator(js_context, &fp);
++
+     while (fp) {
+         format_frame(js_context, fp, buf, num);
+         num++;
+--
+cgit v0.9.0.2
diff -Nru gjs-1.32.0/debian/patches/05_log_typo.patch gjs-1.32.0/debian/patches/05_log_typo.patch
--- gjs-1.32.0/debian/patches/05_log_typo.patch	1970-01-01 01:00:00.000000000 +0100
+++ gjs-1.32.0/debian/patches/05_log_typo.patch	2013-01-03 01:35:35.000000000 +0100
@@ -0,0 +1,13 @@
+Index: gjs-1.32.0/modules/overrides/Gio.js
+===================================================================
+--- gjs-1.32.0.orig/modules/overrides/Gio.js	2011-11-10 22:34:29.000000000 +0100
++++ gjs-1.32.0/modules/overrides/Gio.js	2013-01-02 22:26:54.799677045 +0100
+@@ -147,7 +147,7 @@ function _propertySetter(value, name, si
+ 		      this.call_finish(result);
+ 		  } catch(e) {
+ 		      log('Could not set property ' + name + ' on remote object ' +
+-			  this.g_object_path, '. Error is ' + e.message);
++			  this.g_object_path + ': ' + e.message);
+ 		  }
+ 	      }));
+ }
diff -Nru gjs-1.32.0/debian/patches/11_revert_abi_breakage.patch gjs-1.32.0/debian/patches/11_revert_abi_breakage.patch
--- gjs-1.32.0/debian/patches/11_revert_abi_breakage.patch	1970-01-01 01:00:00.000000000 +0100
+++ gjs-1.32.0/debian/patches/11_revert_abi_breakage.patch	2012-12-20 01:07:22.000000000 +0100
@@ -0,0 +1,75 @@
+Index: gjs-1.32.0/gi/gerror.c
+===================================================================
+--- gjs-1.32.0.orig/gi/gerror.c	2012-12-20 00:49:02.670259754 +0100
++++ gjs-1.32.0/gi/gerror.c	2012-12-20 01:05:37.971125507 +0100
+@@ -520,6 +520,9 @@ find_error_domain_info(GQuark domain)
+     return info;
+ }
+ 
++/* Temporary hack to avoid breaking ABI */
++new_gjs_context_print_stack_to_buffer(GjsContext* context, void *initial, GString *buf);
++
+ /* define properties that JS Error() expose, such as
+    fileName, lineNumber and stack
+ */
+@@ -553,7 +556,7 @@ define_error_properties(JSContext *conte
+ 
+     stack = g_string_new(NULL);
+     gjs_context = JS_GetContextPrivate(context);
+-    gjs_context_print_stack_to_buffer(gjs_context, frame, stack);
++    new_gjs_context_print_stack_to_buffer(gjs_context, frame, stack);
+ 
+     if (gjs_string_from_utf8(context, stack->str, stack->len, &v))
+         JS_DefineProperty(context, obj, "stack", v,
+Index: gjs-1.32.0/gjs/context.h
+===================================================================
+--- gjs-1.32.0.orig/gjs/context.h	2012-12-20 00:49:02.670259754 +0100
++++ gjs-1.32.0/gjs/context.h	2012-12-20 00:58:13.732953760 +0100
+@@ -68,11 +68,7 @@ gboolean        gjs_context_define_strin
+ GList*          gjs_context_get_all              (void);
+ void*           gjs_context_get_native_context   (GjsContext *js_context);
+ 
+-/* initial_frame is a JSStackFrame, but cannot be exposed as such in the
+-   public API. Pass NULL to get the topmost frame.
+-*/
+ void            gjs_context_print_stack_to_buffer (GjsContext *js_context,
+-                                                   void       *initial_frame,
+                                                    GString    *buf);
+ 
+ void            gjs_context_print_stack_stderr    (GjsContext *js_context);
+Index: gjs-1.32.0/gjs/stack.c
+===================================================================
+--- gjs-1.32.0.orig/gjs/stack.c	2012-12-20 00:49:02.690259856 +0100
++++ gjs-1.32.0/gjs/stack.c	2012-12-20 01:03:28.702493578 +0100
+@@ -203,8 +203,9 @@ format_frame(JSContext* cx, JSStackFrame
+     JS_LeaveLocalRootScope(cx);
+ }
+ 
+-void
+-gjs_context_print_stack_to_buffer(GjsContext* context, void *initial, GString *buf)
++
++void __attribute__((visibility("hidden")))
++new_gjs_context_print_stack_to_buffer(GjsContext* context, void *initial, GString *buf)
+ {
+     JSContext *js_context = (JSContext*)gjs_context_get_native_context(context);
+     JSStackFrame *fp = initial;
+@@ -222,12 +223,18 @@ gjs_context_print_stack_to_buffer(GjsCon
+ }
+ 
+ void
++gjs_context_print_stack_to_buffer(GjsContext* context, GString *buf)
++{
++    new_gjs_context_print_stack_to_buffer(context, NULL, buf);
++}
++
++void
+ gjs_context_print_stack_stderr(GjsContext *context)
+ {
+   GString *str = g_string_new("");
+ 
+   g_string_append_printf(str, "== Stack trace for context %p ==\n", context);
+-  gjs_context_print_stack_to_buffer(context, NULL, str);
++  gjs_context_print_stack_to_buffer(context, str);
+ 
+   g_printerr("%s\n", str->str);
+   g_string_free(str, TRUE);
diff -Nru gjs-1.32.0/debian/patches/series gjs-1.32.0/debian/patches/series
--- gjs-1.32.0/debian/patches/series	2012-04-26 17:01:41.000000000 +0200
+++ gjs-1.32.0/debian/patches/series	2013-01-03 01:35:35.000000000 +0100
@@ -1 +1,6 @@
 0001-Fold-libgjs-gdbus.so-into-libgjs.so.patch
+02_gerror_class.patch
+03_gerror_details.patch
+04_gjs_dumpstack.patch
+05_log_typo.patch
+11_revert_abi_breakage.patch
diff -Nru gjs-1.32.0/debian/rules gjs-1.32.0/debian/rules
--- gjs-1.32.0/debian/rules	2012-04-26 17:09:52.000000000 +0200
+++ gjs-1.32.0/debian/rules	2012-11-26 12:01:17.000000000 +0100
@@ -7,10 +7,13 @@
 include /usr/share/gnome-pkg-tools/1/rules/uploaders.mk
 include /usr/share/gnome-pkg-tools/1/rules/gnome-get-source.mk
 
+# SHVER := $(DEB_UPSTREAM_VERSION)
+SHVER := 1.32.0-3
+
 # Use recursive variables since this variable must not be expanded until 
 # files have been installed.
 LIBMOZJS = $(shell objdump -p debian/tmp/usr/lib/libgjs.so | awk '$$1=="NEEDED" && $$2~/^libmozjs/ { print $$2 }' | sed s/\\.so\\./-/ )
-DEB_DH_MAKESHLIBS_ARGS_libgjs0b = -Xusr/lib/gjs-1.0/ -V'libgjs0b (>= $(DEB_UPSTREAM_VERSION)), libgjs0-$(LIBMOZJS)' -- -c4
+DEB_DH_MAKESHLIBS_ARGS_libgjs0b = -Xusr/lib/gjs-1.0/ -V'libgjs0b (>= $(SHVER)), libgjs0-$(LIBMOZJS)' -- -c4
 
 DEB_MAKE_CHECK_TARGET := check || true
 

Reply to: