[gjs] Don't use JS_ConstructObject
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] Don't use JS_ConstructObject
- Date: Tue, 20 Nov 2012 16:26:03 +0000 (UTC)
commit b483b9ad2d4ceabdcfb31440606b23266b205967
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Sat Jul 21 16:22:08 2012 +0200
Don't use JS_ConstructObject
JS_ConstructObject is deprecated with modern JSAPI, and should be
replaced by JS_NewObject and JS_New. Also, while we're there,
replace constructors with functions that throw, as it is generally
an error to call them from JS anyway.
https://bugzilla.gnome.org/show_bug.cgi?id=679688
gi/enumeration.c | 2 +-
gi/function.c | 36 ++++++++++++----------------------
gi/interface.c | 19 +-----------------
gi/keep-alive.c | 35 ++++++++++++---------------------
gi/ns.c | 34 +++++++++++---------------------
gi/repo.c | 42 ++++++++++++++-------------------------
gjs/compat.h | 13 ++++++++++++
gjs/importer.c | 50 +++++++++++++++--------------------------------
gjs/jsapi-util.c | 22 +++++++++++++++++++++
gjs/jsapi-util.h | 2 +
modules/dbus-exports.c | 50 +++++++++++++++--------------------------------
modules/dbus-values.c | 2 +-
modules/dbus.c | 13 ++---------
13 files changed, 128 insertions(+), 192 deletions(-)
---
diff --git a/gi/enumeration.c b/gi/enumeration.c
index 2fa7dfa..67c81db 100644
--- a/gi/enumeration.c
+++ b/gi/enumeration.c
@@ -172,7 +172,7 @@ gjs_define_enumeration(JSContext *context,
return JS_TRUE;
}
- enum_obj = JS_ConstructObject(context, NULL, NULL, NULL);
+ enum_obj = JS_NewObject(context, NULL, NULL, gjs_get_import_global (context));
if (enum_obj == NULL)
return JS_FALSE;
diff --git a/gi/function.c b/gi/function.c
index 5f8c7f2..20c4ccb 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -1206,27 +1206,7 @@ function_call(JSContext *context,
return success;
}
-GJS_NATIVE_CONSTRUCTOR_DECLARE(function)
-{
- GJS_NATIVE_CONSTRUCTOR_VARIABLES(function)
- Function *priv;
-
- GJS_NATIVE_CONSTRUCTOR_PRELUDE(name);
-
- priv = g_slice_new0(Function);
-
- GJS_INC_COUNTER(function);
-
- g_assert(priv_from_js(context, object) == NULL);
- JS_SetPrivate(context, object, priv);
-
- gjs_debug_lifecycle(GJS_DEBUG_GFUNCTION,
- "function constructor, obj %p priv %p", object, priv);
-
- GJS_NATIVE_CONSTRUCTOR_FINISH(name);
-
- return JS_TRUE;
-}
+GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(function)
/* Does not actually free storage for structure, just
* reverses init_cached_function_data
@@ -1602,13 +1582,23 @@ function_new(JSContext *context,
gjs_function_class.name, prototype);
}
- function = JS_ConstructObject(context, &gjs_function_class, NULL, global);
+ function = JS_NewObject(context, &gjs_function_class, NULL, global);
if (function == NULL) {
gjs_debug(GJS_DEBUG_GFUNCTION, "Failed to construct function");
return NULL;
}
- priv = priv_from_js(context, function);
+
+ priv = g_slice_new0(Function);
+
+ GJS_INC_COUNTER(function);
+
+ g_assert(priv_from_js(context, function) == NULL);
+ JS_SetPrivate(context, function, priv);
+
+ gjs_debug_lifecycle(GJS_DEBUG_GFUNCTION,
+ "function constructor, obj %p priv %p", function, priv);
+
if (!init_cached_function_data(context, priv, gtype, (GICallableInfo *)info))
return NULL;
diff --git a/gi/interface.c b/gi/interface.c
index 1b50077..ad00809 100644
--- a/gi/interface.c
+++ b/gi/interface.c
@@ -43,24 +43,7 @@ static struct JSClass gjs_interface_class;
GJS_DEFINE_DYNAMIC_PRIV_FROM_JS(Interface, gjs_interface_class)
-GJS_NATIVE_CONSTRUCTOR_DECLARE(interface)
-{
- jsval obj;
- JSObject *proto;
- JSObject *constructor;
- Interface *priv;
-
- constructor = JSVAL_TO_OBJECT(JS_CALLEE(context, vp));
- gjs_object_get_property(context, constructor, "prototype", &obj);
- proto = JSVAL_TO_OBJECT(obj);
- priv = priv_from_js(context, proto);
-
- gjs_throw(context, "You cannot construct new instances of '%s.%s'",
- g_base_info_get_namespace(priv->info),
- g_base_info_get_name(priv->info));
-
- return JS_TRUE;
-}
+GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(interface)
static void
interface_finalize(JSContext *context,
diff --git a/gi/keep-alive.c b/gi/keep-alive.c
index 3143d1e..704c47d 100644
--- a/gi/keep-alive.c
+++ b/gi/keep-alive.c
@@ -78,26 +78,7 @@ child_free(void *data)
g_slice_free(Child, child);
}
-GJS_NATIVE_CONSTRUCTOR_DECLARE(keep_alive)
-{
- GJS_NATIVE_CONSTRUCTOR_VARIABLES(keep_alive)
- KeepAlive *priv;
-
- GJS_NATIVE_CONSTRUCTOR_PRELUDE(keep_alive);
-
- priv = g_slice_new0(KeepAlive);
- priv->children = g_hash_table_new_full(child_hash, child_equal, NULL, child_free);
-
- g_assert(priv_from_js(context, object) == NULL);
- JS_SetPrivate(context, object, priv);
-
- gjs_debug_lifecycle(GJS_DEBUG_KEEP_ALIVE,
- "keep_alive constructor, obj %p priv %p", object, priv);
-
- GJS_NATIVE_CONSTRUCTOR_FINISH(keep_alive);
-
- return JS_TRUE;
-}
+GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(keep_alive)
static void
keep_alive_finalize(JSContext *context,
@@ -113,7 +94,7 @@ keep_alive_finalize(JSContext *context,
"keep_alive finalizing, obj %p priv %p", obj, priv);
if (priv == NULL)
- return; /* we are the prototype, not a real instance, so constructor never called */
+ return; /* we are the prototype, not a real instance */
priv->inside_finalize = TRUE;
@@ -200,6 +181,7 @@ static JSFunctionSpec gjs_keep_alive_proto_funcs[] = {
JSObject*
gjs_keep_alive_new(JSContext *context)
{
+ KeepAlive *priv;
JSObject *keep_alive;
JSObject *global;
@@ -259,12 +241,21 @@ gjs_keep_alive_new(JSContext *context)
"Creating new keep-alive object for context %p global %p",
context, global);
- keep_alive = JS_ConstructObject(context, &gjs_keep_alive_class, NULL, global);
+ keep_alive = JS_NewObject(context, &gjs_keep_alive_class, NULL, global);
if (keep_alive == NULL) {
gjs_log_exception(context, NULL);
gjs_fatal("Failed to create keep_alive object");
}
+ priv = g_slice_new0(KeepAlive);
+ priv->children = g_hash_table_new_full(child_hash, child_equal, NULL, child_free);
+
+ g_assert(priv_from_js(context, keep_alive) == NULL);
+ JS_SetPrivate(context, keep_alive, priv);
+
+ gjs_debug_lifecycle(GJS_DEBUG_KEEP_ALIVE,
+ "keep_alive constructor, obj %p priv %p", keep_alive, priv);
+
JS_EndRequest(context);
return keep_alive;
diff --git a/gi/ns.c b/gi/ns.c
index 28e1d76..23d0ebc 100644
--- a/gi/ns.c
+++ b/gi/ns.c
@@ -126,26 +126,7 @@ ns_new_resolve(JSContext *context,
return ret;
}
-GJS_NATIVE_CONSTRUCTOR_DECLARE(ns)
-{
- GJS_NATIVE_CONSTRUCTOR_VARIABLES(ns)
- Ns *priv;
-
- GJS_NATIVE_CONSTRUCTOR_PRELUDE(ns);
-
- priv = g_slice_new0(Ns);
-
- GJS_INC_COUNTER(ns);
-
- g_assert(priv_from_js(context, object) == NULL);
- JS_SetPrivate(context, object, priv);
-
- gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE, "ns constructor, obj %p priv %p", object, priv);
-
- GJS_NATIVE_CONSTRUCTOR_FINISH(ns);
-
- return JS_TRUE;
-}
+GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(ns)
static void
ns_finalize(JSContext *context,
@@ -157,7 +138,7 @@ ns_finalize(JSContext *context,
gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE,
"finalize, obj %p priv %p", obj, priv);
if (priv == NULL)
- return; /* we are the prototype, not a real instance, so constructor never called */
+ return; /* we are the prototype, not a real instance */
if (priv->namespace)
g_free(priv->namespace);
@@ -241,10 +222,19 @@ ns_new(JSContext *context,
gjs_ns_class.name, prototype);
}
- ns = JS_ConstructObject(context, &gjs_ns_class, NULL, global);
+ ns = JS_NewObject(context, &gjs_ns_class, NULL, global);
if (ns == NULL)
gjs_fatal("No memory to create ns object");
+ priv = g_slice_new0(Ns);
+
+ GJS_INC_COUNTER(ns);
+
+ g_assert(priv_from_js(context, ns) == NULL);
+ JS_SetPrivate(context, ns, priv);
+
+ gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE, "ns constructor, obj %p priv %p", ns, priv);
+
priv = priv_from_js(context, ns);
priv->repo = g_object_ref(repo);
priv->namespace = g_strdup(ns_name);
diff --git a/gi/repo.c b/gi/repo.c
index 4ecdf05..3b4502e 100644
--- a/gi/repo.c
+++ b/gi/repo.c
@@ -194,27 +194,7 @@ repo_new_resolve(JSContext *context,
return ret;
}
-GJS_NATIVE_CONSTRUCTOR_DECLARE(repo)
-{
- GJS_NATIVE_CONSTRUCTOR_VARIABLES(repo)
- Repo *priv;
-
- GJS_NATIVE_CONSTRUCTOR_PRELUDE(repo);
-
- priv = g_slice_new0(Repo);
-
- GJS_INC_COUNTER(repo);
-
- g_assert(priv_from_js(context, object) == NULL);
- JS_SetPrivate(context, object, priv);
-
- gjs_debug_lifecycle(GJS_DEBUG_GREPO,
- "repo constructor, obj %p priv %p", object, priv);
-
- GJS_NATIVE_CONSTRUCTOR_FINISH(repo);
-
- return JS_TRUE;
-}
+GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(repo)
static void
repo_finalize(JSContext *context,
@@ -226,7 +206,7 @@ repo_finalize(JSContext *context,
gjs_debug_lifecycle(GJS_DEBUG_GREPO,
"finalize, obj %p priv %p", obj, priv);
if (priv == NULL)
- return; /* we are the prototype, not a real instance, so constructor never called */
+ return; /* we are the prototype, not a real instance */
GJS_DEC_COUNTER(repo);
g_slice_free(Repo, priv);
@@ -263,6 +243,7 @@ static JSFunctionSpec gjs_repo_proto_funcs[] = {
static JSObject*
repo_new(JSContext *context)
{
+ Repo *priv;
JSObject *repo;
JSObject *global;
JSObject *versions;
@@ -302,16 +283,23 @@ repo_new(JSContext *context)
gjs_repo_class.name, prototype);
}
- repo = JS_ConstructObject(context, &gjs_repo_class, NULL, global);
+ repo = JS_NewObject(context, &gjs_repo_class, NULL, global);
if (repo == NULL) {
gjs_throw(context, "No memory to create repo object");
return JS_FALSE;
}
- versions = JS_ConstructObject(context, NULL, NULL, NULL);
- /* https://bugzilla.mozilla.org/show_bug.cgi?id=599651 means we
- * can't just pass in the global as the parent */
- JS_SetParent(context, versions, global);
+ priv = g_slice_new0(Repo);
+
+ GJS_INC_COUNTER(repo);
+
+ g_assert(priv_from_js(context, repo) == NULL);
+ JS_SetPrivate(context, repo, priv);
+
+ gjs_debug_lifecycle(GJS_DEBUG_GREPO,
+ "repo constructor, obj %p priv %p", repo, priv);
+
+ versions = JS_NewObject(context, NULL, NULL, global);
JS_DefineProperty(context, repo,
"versions",
diff --git a/gjs/compat.h b/gjs/compat.h
index 3053389..6a729af 100644
--- a/gjs/compat.h
+++ b/gjs/compat.h
@@ -86,6 +86,19 @@ gjs_##name##_constructor(JSContext *context, \
#define GJS_NATIVE_CONSTRUCTOR_FINISH(name) \
JS_SET_RVAL(context, vp, OBJECT_TO_JSVAL(object));
+/**
+ * GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT:
+ * Defines a constructor whose only purpose is to throw an error
+ * and fail. To be used with classes that require a constructor (because they have
+ * instances), but whose constructor cannot be used from JS code.
+ */
+#define GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(name) \
+ GJS_NATIVE_CONSTRUCTOR_DECLARE(name) \
+ { \
+ gjs_throw_abstract_constructor_error(context, vp); \
+ return JS_FALSE; \
+ }
+
G_END_DECLS
#endif /* __GJS_COMPAT_H__ */
diff --git a/gjs/importer.c b/gjs/importer.c
index 59095c7..4b8d8a1 100644
--- a/gjs/importer.c
+++ b/gjs/importer.c
@@ -228,7 +228,7 @@ import_native_file(JSContext *context,
gjs_debug(GJS_DEBUG_IMPORTER,
"Importing '%s' from '%s'", name, full_path ? full_path : "<internal>");
- module_obj = JS_ConstructObject(context, NULL, NULL, NULL);
+ module_obj = JS_NewObject(context, NULL, NULL, NULL);
if (module_obj == NULL) {
return JS_FALSE;
}
@@ -422,7 +422,7 @@ import_file(JSContext *context,
gjs_debug(GJS_DEBUG_IMPORTER,
"Importing '%s'", full_path);
- module_obj = JS_ConstructObject(context, NULL, NULL, NULL);
+ module_obj = JS_NewObject(context, NULL, NULL, NULL);
if (module_obj == NULL) {
return JS_FALSE;
}
@@ -981,35 +981,7 @@ importer_new_resolve(JSContext *context,
return ret;
}
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
- * identify the prototype as an object of our class with NULL private
- * data.
- */
-GJS_NATIVE_CONSTRUCTOR_DECLARE(importer)
-{
- GJS_NATIVE_CONSTRUCTOR_VARIABLES(importer)
- Importer *priv;
-
- GJS_NATIVE_CONSTRUCTOR_PRELUDE(importer);
-
- priv = g_slice_new0(Importer);
-
- GJS_INC_COUNTER(importer);
-
- g_assert(priv_from_js(context, object) == NULL);
- JS_SetPrivate(context, object, priv);
-
- gjs_debug_lifecycle(GJS_DEBUG_IMPORTER,
- "importer constructor, obj %p priv %p", object, priv);
-
- GJS_NATIVE_CONSTRUCTOR_FINISH(importer);
-
- return JS_TRUE;
-}
+GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(importer)
static void
importer_finalize(JSContext *context,
@@ -1021,7 +993,7 @@ importer_finalize(JSContext *context,
gjs_debug_lifecycle(GJS_DEBUG_IMPORTER,
"finalize, obj %p priv %p", obj, priv);
if (priv == NULL)
- return; /* we are the prototype, not a real instance, so constructor never called */
+ return; /* we are the prototype, not a real instance */
GJS_DEC_COUNTER(importer);
g_slice_free(Importer, priv);
@@ -1099,9 +1071,19 @@ importer_new(JSContext *context)
gjs_importer_class.name, prototype);
}
- importer = JS_ConstructObject(context, &gjs_importer_class, NULL, global);
+ importer = JS_NewObject(context, &gjs_importer_class, NULL, global);
if (importer == NULL)
- gjs_fatal("No memory to create ns object");
+ gjs_fatal("No memory to create importer importer");
+
+ priv = g_slice_new0(Importer);
+
+ GJS_INC_COUNTER(importer);
+
+ g_assert(priv_from_js(context, importer) == NULL);
+ JS_SetPrivate(context, importer, priv);
+
+ gjs_debug_lifecycle(GJS_DEBUG_IMPORTER,
+ "importer constructor, obj %p priv %p", importer, priv);
return importer;
}
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
index 59df435..394ac3c 100644
--- a/gjs/jsapi-util.c
+++ b/gjs/jsapi-util.c
@@ -567,6 +567,28 @@ gjs_throw_constructor_error(JSContext *context)
"Constructor called as normal method. Use 'new SomeObject()' not 'SomeObject()'");
}
+void
+gjs_throw_abstract_constructor_error(JSContext *context,
+ jsval *vp)
+{
+ jsval callee;
+ jsval prototype;
+ JSClass *proto_class;
+ const char *name = "anonymous";
+
+ callee = JS_CALLEE(context, vp);
+
+ if (JSVAL_IS_OBJECT(callee)) {
+ if (gjs_object_get_property(context, JSVAL_TO_OBJECT(callee),
+ "prototype", &prototype)) {
+ proto_class = JS_GetClass(context, JSVAL_TO_OBJECT(prototype));
+ name = proto_class->name;
+ }
+ }
+
+ gjs_throw(context, "You cannot construct new instances of '%s'", name);
+}
+
static const char*
format_dynamic_class_name (const char *name)
{
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 1540706..27f42ca 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -238,6 +238,8 @@ JSObject * gjs_init_class_dynamic (JSContext *context,
JSPropertySpec *static_ps,
JSFunctionSpec *static_fs);
void gjs_throw_constructor_error (JSContext *context);
+void gjs_throw_abstract_constructor_error (JSContext *context,
+ jsval *vp);
JSBool gjs_typecheck_static_instance (JSContext *context,
JSObject *obj,
diff --git a/modules/dbus-exports.c b/modules/dbus-exports.c
index 70fd983..1ad8c79 100644
--- a/modules/dbus-exports.c
+++ b/modules/dbus-exports.c
@@ -1697,38 +1697,7 @@ exports_new_resolve(JSContext *context,
return JS_TRUE;
}
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
- * identify the prototype as an object of our class with NULL private
- * data.
- */
-GJS_NATIVE_CONSTRUCTOR_DECLARE(js_exports)
-{
- GJS_NATIVE_CONSTRUCTOR_VARIABLES(js_exports)
- Exports *priv;
-
- GJS_NATIVE_CONSTRUCTOR_PRELUDE(js_exports);
-
- priv = g_slice_new0(Exports);
-
- GJS_INC_COUNTER(dbus_exports);
-
- g_assert(priv_from_js(context, object) == NULL);
- JS_SetPrivate(context, object, priv);
-
- gjs_debug_lifecycle(GJS_DEBUG_DBUS,
- "exports constructor, obj %p priv %p", object, priv);
-
- priv->runtime = JS_GetRuntime(context);
- priv->object = object;
-
- GJS_NATIVE_CONSTRUCTOR_FINISH(js_exports);
-
- return JS_TRUE;
-}
+GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(js_exports)
static JSBool
add_connect_funcs(JSContext *context,
@@ -1820,6 +1789,7 @@ static JSObject*
exports_new(JSContext *context,
DBusBusType which_bus)
{
+ Exports *priv;
JSObject *exports;
JSObject *global;
@@ -1860,8 +1830,20 @@ exports_new(JSContext *context,
gjs_js_exports_class.name, prototype);
}
- exports = JS_ConstructObject(context, &gjs_js_exports_class, NULL, global);
- /* may be NULL */
+ exports = JS_NewObject(context, &gjs_js_exports_class, NULL, global);
+
+ priv = g_slice_new0(Exports);
+
+ GJS_INC_COUNTER(dbus_exports);
+
+ g_assert(priv_from_js(context, exports) == NULL);
+ JS_SetPrivate(context, exports, priv);
+
+ gjs_debug_lifecycle(GJS_DEBUG_DBUS,
+ "exports constructor, obj %p priv %p", exports, priv);
+
+ priv->runtime = JS_GetRuntime(context);
+ priv->object = exports;
return exports;
}
diff --git a/modules/dbus-values.c b/modules/dbus-values.c
index 98e0c66..fe9c1c0 100644
--- a/modules/dbus-values.c
+++ b/modules/dbus-values.c
@@ -44,7 +44,7 @@ _gjs_js_one_value_from_dbus_array_dict_entry(JSContext *context,
char *key;
JSBool retval = JS_FALSE;
- obj = JS_ConstructObject(context, NULL, NULL, NULL);
+ obj = JS_NewObject(context, NULL, NULL, NULL);
if (obj == NULL)
return JS_FALSE;
diff --git a/modules/dbus.c b/modules/dbus.c
index 3a62025..c90018b 100644
--- a/modules/dbus.c
+++ b/modules/dbus.c
@@ -1644,7 +1644,7 @@ gjs_js_dbus_get_current_message_context(JSContext *context,
current_message = _gjs_current_dbus_messages->data;
- context_obj = JS_ConstructObject(context, NULL, NULL, NULL);
+ context_obj = JS_NewObject(context, NULL, NULL, NULL);
if (context_obj == NULL)
return JS_FALSE;
@@ -1693,7 +1693,7 @@ define_bus_proto(JSContext *context,
bus_proto_val = JSVAL_VOID;
JS_AddValueRoot(context, &bus_proto_val);
- bus_proto_obj = JS_ConstructObject(context, NULL, NULL, NULL);
+ bus_proto_obj = JS_NewObject(context, NULL, NULL, NULL);
if (bus_proto_obj == NULL)
goto out;
@@ -1812,16 +1812,9 @@ define_bus_object(JSContext *context,
bus_val = JSVAL_VOID;
JS_AddValueRoot(context, &bus_val);
- bus_obj = JS_ConstructObject(context, NULL, NULL, NULL);
+ bus_obj = JS_NewObject(context, NULL, proto_obj, NULL);
if (bus_obj == NULL)
goto out;
- /* We need to use a separate call to SetPrototype to work
- * around a SpiderMonkey bug where with clasp=NULL, the
- * parent and proto arguments to JS_ConstructObject are
- * lost.
- * https://bugzilla.mozilla.org/show_bug.cgi?id=599651
- */
- JS_SetPrototype(context, bus_obj, proto_obj);
bus_val = OBJECT_TO_JSVAL(bus_obj);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]