[gjs/wip/ptomato/mozjs31prep] WIP - polymorphic gjs_object_require_property
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/ptomato/mozjs31prep] WIP - polymorphic gjs_object_require_property
- Date: Tue, 25 Oct 2016 02:23:33 +0000 (UTC)
commit 308a8582583ff294abc4177a5b29c71b78e6e01f
Author: Philip Chimento <philip endlessm com>
Date: Mon Oct 24 19:15:21 2016 -0700
WIP - polymorphic gjs_object_require_property
gi/arg.cpp | 14 ++----
gi/boxed.cpp | 9 ++--
gi/fundamental.cpp | 14 +++---
gi/gerror.cpp | 31 +++++-------
gi/repo.cpp | 67 +++++++++----------------
gi/value.cpp | 9 ++--
gjs/context.cpp | 2 +-
gjs/coverage.cpp | 106 ++++++++++++++++------------------------
gjs/importer.cpp | 23 ++-------
gjs/jsapi-dynamic-class.cpp | 19 ++-----
gjs/jsapi-util.cpp | 112 +++++++++++++++++++++++++++++++++++++------
gjs/jsapi-util.h | 29 +++++++++++
12 files changed, 241 insertions(+), 194 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 3df4437..7f9ed7b 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -1119,13 +1119,11 @@ gjs_array_to_explicit_array_internal(JSContext *context,
goto out;
} else if (JS_HasPropertyById(context, &value.toObject(), length_name, &found_length) &&
found_length) {
- JS::RootedValue length_value(context);
JS::RootedObject array_obj(context, &value.toObject());
guint32 length;
- if (!gjs_object_require_property(context, array_obj, NULL, length_name,
- &length_value) ||
- !JS::ToUint32(context, length_value, &length)) {
+ if (!gjs_object_require_converted_property_value(context, array_obj, NULL,
+ length_name, &length)) {
goto out;
} else {
if (!gjs_array_to_array(context,
@@ -1648,14 +1646,12 @@ gjs_value_to_g_argument(JSContext *context,
if (value.isObject() &&
JS_HasPropertyById(context, &value.toObject(), length_name, &found_length) &&
found_length) {
- JS::RootedValue length_value(context);
JS::RootedObject array_obj(context, &value.toObject());
guint32 length;
- if (!gjs_object_require_property(context, array_obj, NULL,
- length_name,
- &length_value) ||
- !JS::ToUint32(context, length_value, &length)) {
+ if (!gjs_object_require_converted_property_value(context, array_obj,
+ NULL, length_name,
+ &length)) {
wrong = true;
} else {
GList *list;
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 977622b..3cf4964 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -328,15 +328,16 @@ boxed_invoke_constructor(JSContext *context,
JS::HandleId constructor_name,
JS::CallArgs& args)
{
- JS::RootedValue js_constructor(context), js_constructor_func(context);
JS::RootedId constructor_const(context,
gjs_context_get_const_string(context, GJS_STRING_CONSTRUCTOR));
+ JS::RootedObject js_constructor(context);
- if (!gjs_object_require_property(context, obj, NULL, constructor_const, &js_constructor))
+ if (!gjs_object_require_property_value(context, obj, NULL, constructor_const,
+ &js_constructor))
return false;
- JS::RootedObject js_constructor_obj(context, &js_constructor.toObject());
- if (!gjs_object_require_property(context, js_constructor_obj, NULL,
+ JS::RootedValue js_constructor_func(context);
+ if (!gjs_object_require_property(context, js_constructor, NULL,
constructor_name, &js_constructor_func))
return false;
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 569ae26..34a881a 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -388,12 +388,12 @@ fundamental_invoke_constructor(FundamentalInstance *priv,
JS::Value *argv,
GArgument *rvalue)
{
- JS::RootedValue js_constructor(context), js_constructor_func(context);
JS::RootedId constructor_const(context,
gjs_context_get_const_string(context, GJS_STRING_CONSTRUCTOR));
+ JS::RootedObject js_constructor(context);
- if (!gjs_object_require_property(context, obj, NULL,
- constructor_const, &js_constructor) ||
+ if (!gjs_object_require_property_value(context, obj, NULL,
+ constructor_const, &js_constructor) ||
priv->prototype->constructor_name == JSID_VOID) {
gjs_throw (context,
"Couldn't find a constructor for type %s.%s",
@@ -402,9 +402,10 @@ fundamental_invoke_constructor(FundamentalInstance *priv,
return false;
}
- JS::RootedObject js_constructor_obj(context, js_constructor.toObjectOrNull());
- if (!gjs_object_require_property(context, js_constructor_obj, NULL,
- priv->prototype->constructor_name, &js_constructor_func)) {
+ JS::RootedObject constructor(context);
+ if (!gjs_object_require_property_value(context, js_constructor, NULL,
+ priv->prototype->constructor_name,
+ &constructor)) {
gjs_throw (context,
"Couldn't find a constructor for type %s.%s",
g_base_info_get_namespace((GIBaseInfo*) priv->prototype->info),
@@ -412,7 +413,6 @@ fundamental_invoke_constructor(FundamentalInstance *priv,
return false;
}
- JS::RootedObject constructor(context, js_constructor_func.toObjectOrNull());
return gjs_invoke_constructor_from_c(context, constructor, obj, argc, argv, rvalue);
}
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index c0042c7..4c38953 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -54,6 +54,7 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
Error *priv;
Error *proto_priv;
gchar *message;
+ int32_t code;
/* Check early to avoid allocating memory for nothing */
if (argc != 1 || !argv[0].isObject()) {
@@ -94,25 +95,23 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
g_base_info_ref( (GIBaseInfo*) priv->info);
priv->domain = proto_priv->domain;
- JS::RootedValue v_message(context), v_code(context);
JS::RootedObject params_obj(context, &argv[0].toObject());
JS::RootedId message_name(context,
gjs_context_get_const_string(context, GJS_STRING_MESSAGE));
JS::RootedId code_name(context,
gjs_context_get_const_string(context, GJS_STRING_CODE));
- if (!gjs_object_require_property(context, params_obj,
- "GError constructor", message_name, &v_message))
+ if (!gjs_object_require_property_value(context, params_obj,
+ "GError constructor", message_name,
+ &message))
return false;
- if (!gjs_object_require_property(context, params_obj,
- "GError constructor", code_name, &v_code))
- return false;
- if (!gjs_string_to_utf8 (context, v_message, &message))
+ if (!gjs_object_require_property_value(context, params_obj,
+ "GError constructor", code_name,
+ &code))
return false;
- priv->gerror = g_error_new_literal(priv->domain, v_code.toInt32(),
- message);
+ priv->gerror = g_error_new_literal(priv->domain, code, message);
- g_free (message);
+ JS_free(context, message);
/* We assume this error will be thrown in the same line as the constructor */
define_error_properties(context, object);
@@ -246,22 +245,20 @@ error_constructor_value_of(JSContext *context,
JS::Value *vp)
{
GJS_GET_THIS(context, argc, vp, rec, self);
- JS::RootedValue v_prototype(context);
Error *priv;
JS::RootedId prototype_name(context,
gjs_context_get_const_string(context, GJS_STRING_PROTOTYPE));
+ JS::RootedObject prototype(context);
- if (!gjs_object_require_property(context, self, "constructor",
- prototype_name, &v_prototype))
- return false;
-
- if (!v_prototype.isObject()) {
+ if (!gjs_object_require_property_value(context, self, "constructor",
+ prototype_name, &prototype)) {
+ /* This error message will be more informative */
+ JS_ClearPendingException(context);
gjs_throw(context, "GLib.Error.valueOf() called on something that is not"
" a constructor");
return false;
}
- JS::RootedObject prototype(context, &v_prototype.toObject());
priv = priv_from_js(context, prototype);
if (priv == NULL)
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 9a3b6f9..a3d7204 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -59,27 +59,23 @@ static JSObject *lookup_override_function(JSContext *, JS::HandleId);
static bool
get_version_for_ns (JSContext *context,
JS::HandleObject repo_obj,
- jsid ns_id,
+ JS::HandleId ns_id,
char **version)
{
- JS::RootedValue versions_val(context);
- JSObject *versions;
+ JS::RootedObject versions(context);
JS::RootedValue version_val(context);
JS::RootedId versions_name(context,
gjs_context_get_const_string(context, GJS_STRING_GI_VERSIONS));
- if (!gjs_object_require_property(context, repo_obj, "GI repository object", versions_name,
&versions_val) ||
- !versions_val.isObject()) {
- gjs_throw(context, "No 'versions' property in GI repository object");
+ if (!gjs_object_require_property_value(context, repo_obj,
+ "GI repository object", versions_name,
+ &versions))
return false;
- }
-
- versions = &versions_val.toObject();
- *version = NULL;
- if (JS_GetPropertyById(context, versions, ns_id, version_val.address()) &&
- version_val.isString()) {
- gjs_string_to_utf8(context, version_val, version);
+ if (!gjs_object_require_property_value(context, versions, NULL, ns_id, version)) {
+ /* Property not actually required, so clear an exception */
+ JS_ClearPendingException(context);
+ *version = NULL;
}
return true;
@@ -588,27 +584,23 @@ lookup_override_function(JSContext *cx,
JS::RootedValue importer(cx, gjs_get_global_slot(cx, GJS_GLOBAL_SLOT_IMPORTS));
g_assert(importer.isObject());
- JS::RootedValue overridespkg(cx), module(cx), function(cx);
+ JS::RootedValue function(cx);
JS::RootedId overrides_name(cx,
gjs_context_get_const_string(cx, GJS_STRING_GI_OVERRIDES));
JS::RootedId object_init_name(cx,
gjs_context_get_const_string(cx, GJS_STRING_GOBJECT_INIT));
- JS::RootedObject overridespkg_obj(cx), module_obj(cx);
+ JS::RootedObject overridespkg(cx), module(cx);
JS::RootedObject importer_obj(cx, &importer.toObject());
- if (!gjs_object_require_property(cx, importer_obj, "importer",
- overrides_name, &overridespkg) ||
- !overridespkg.isObject())
+ if (!gjs_object_require_property_value(cx, importer_obj, "importer",
+ overrides_name, &overridespkg))
goto fail;
- overridespkg_obj = &overridespkg.toObject();
- if (!gjs_object_require_property(cx, overridespkg_obj,
- "GI repository object", ns_name, &module)
- || !module.isObject())
+ if (!gjs_object_require_property_value(cx, overridespkg, "GI repository object",
+ ns_name, &module))
goto fail;
- module_obj = &module.toObject();
- if (!gjs_object_require_property(cx, module_obj, "override module",
+ if (!gjs_object_require_property(cx, module, "override module",
object_init_name, &function) ||
!function.isObjectOrNull())
goto fail;
@@ -633,33 +625,22 @@ gjs_lookup_namespace_object_by_name(JSContext *context,
JS::RootedId gi_name(context,
gjs_context_get_const_string(context, GJS_STRING_GI_MODULE));
- JS::RootedObject importer_obj(context, &importer.toObject());
- JS::RootedValue girepository(context);
- if (!gjs_object_require_property(context, importer_obj, "importer",
- gi_name, &girepository) ||
- !girepository.isObject()) {
+ JS::RootedObject repo(context), retval(context),
+ importer_obj(context, &importer.toObject());
+
+ if (!gjs_object_require_property_value(context, importer_obj, "importer",
+ gi_name, &repo)) {
gjs_log_exception(context);
gjs_throw(context, "No gi property in importer");
return NULL;
}
- JS::RootedObject repo_obj(context, &girepository.toObject());
JS::RootedValue ns_obj(context);
- if (!gjs_object_require_property(context, repo_obj, "GI repository object", ns_name, &ns_obj)) {
- return NULL;
- }
-
- if (!ns_obj.isObject()) {
- char *name;
-
- gjs_get_string_id(context, ns_name, &name);
- gjs_throw(context, "Namespace '%s' is not an object?", name);
-
- g_free(name);
+ if (!gjs_object_require_property_value(context, repo, "GI repository object",
+ ns_name, &retval))
return NULL;
- }
- return &ns_obj.toObject();
+ return retval;
}
const char*
diff --git a/gi/value.cpp b/gi/value.cpp
index 0be77ab..85099ee 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -493,14 +493,13 @@ gjs_value_to_g_value_internal(JSContext *context,
/* do nothing */
} else if (JS_HasPropertyById(context, &value.toObject(), length_name, &found_length) &&
found_length) {
- JS::RootedValue length_value(context);
JS::RootedObject array_obj(context, &value.toObject());
guint32 length;
- if (!gjs_object_require_property(context, array_obj, NULL,
- length_name,
- &length_value) ||
- !JS::ToUint32(context, length_value, &length)) {
+ if (!gjs_object_require_converted_property_value(context, array_obj,
+ NULL, length_name,
+ &length)) {
+ JS_ClearPendingException(context);
gjs_throw(context,
"Wrong type %s; strv expected",
gjs_get_type_name(value));
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 1d2d1c0..4d9417f 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -82,7 +82,7 @@ static const char *const_strings[] = {
"gi", "versions", "overrides",
"_init", "_instance_init", "_new_internal", "new",
"message", "code", "stack", "fileName", "lineNumber", "name",
- "x", "y", "width", "height",
+ "x", "y", "width", "height", "CoverageStatistics"
};
G_STATIC_ASSERT(G_N_ELEMENTS(const_strings) == GJS_STRING_LAST);
diff --git a/gjs/coverage.cpp b/gjs/coverage.cpp
index 06237c7..81dc138 100644
--- a/gjs/coverage.cpp
+++ b/gjs/coverage.cpp
@@ -506,24 +506,40 @@ clear_coverage_function(gpointer info_location)
}
static bool
+get_hit_count_and_line_data(JSContext *cx,
+ JS::HandleObject obj,
+ const char *description,
+ int32_t *hit_count,
+ int32_t *line)
+{
+ JS::RootedId hit_count_name(cx, gjs_intern_string_to_id(cx, "hitCount"));
+ if (!gjs_object_require_property_value(cx, obj, "function element",
+ hit_count_name, hit_count))
+ return false;
+
+ JS::RootedId line_number_name(cx, gjs_intern_string_to_id(cx, "line"));
+ return gjs_object_require_property_value(cx, obj, "function_element",
+ line_number_name, line);
+}
+
+static bool
convert_and_insert_function_decl(GArray *array,
JSContext *context,
JS::Value *element)
{
- JSObject *object;
-
if (!element->isObject()) {
gjs_throw(context, "Function element is not an object");
return false;
}
- object = &element->toObject();
- JS::Value function_name_property_value;
+ JS::RootedObject object(context, &element->toObject());
+ JS::RootedValue function_name_property_value(context);
+ JS::RootedId function_name(context,
+ gjs_context_get_const_string(context, GJS_STRING_NAME));
- if (!JS_GetProperty(context, object, "name", &function_name_property_value)) {
- gjs_throw(context, "Failed to get name property for function object");
+ if (!gjs_object_require_property(context, object, NULL, function_name,
+ &function_name_property_value))
return false;
- }
char *utf8_string;
@@ -541,22 +557,10 @@ convert_and_insert_function_decl(GArray *array,
return false;
}
- JS::Value hit_count_property_value;
- if (!JS_GetProperty(context, object, "hitCount", &hit_count_property_value) ||
- !hit_count_property_value.isInt32()) {
- gjs_throw(context, "Failed to get hitCount property for function object");
- return false;
- }
-
- JS::Value line_number_property_value;
- if (!JS_GetProperty(context, object, "line", &line_number_property_value) ||
- !line_number_property_value.isInt32()) {
- gjs_throw(context, "Failed to get line property for function object");
- return false;
- }
-
- unsigned int line_number = line_number_property_value.toInt32();
- unsigned int hit_count = hit_count_property_value.toInt32();
+ int32_t hit_count;
+ int32_t line_number;
+ get_hit_count_and_line_data(context, object, "function element",
+ &hit_count, &line_number);
GjsCoverageFunction info;
init_covered_function(&info,
@@ -618,29 +622,12 @@ convert_and_insert_branch_exit(GArray *array,
return false;
}
- JSObject *object = &element->toObject();
-
- JS::Value line_value;
- int32_t line;
+ JS::RootedObject object(context, &element->toObject());
- if (!JS_GetProperty(context, object, "line", &line_value) ||
- !line_value.isInt32()) {
- gjs_throw(context, "Failed to get line property from element");
- return false;
- }
-
- line = line_value.toInt32();
-
- JS::Value hit_count_value;
int32_t hit_count;
-
- if (!JS_GetProperty(context, object, "hitCount", &hit_count_value) ||
- !hit_count_value.isInt32()) {
- gjs_throw(context, "Failed to get hitCount property from element");
- return false;
- }
-
- hit_count = hit_count_value.toInt32();
+ int32_t line;
+ get_hit_count_and_line_data(context, object, "branch exit array element",
+ &hit_count, &line);
GjsCoverageBranchExit exit = {
(unsigned int) line,
@@ -663,19 +650,15 @@ convert_and_insert_branch_info(GArray *array,
}
if (element->isObject()) {
- JSObject *object = &element->toObject();
- JS::Value branch_point_value;
+ JS::RootedObject object(context, &element->toObject());
int32_t branch_point;
- if (!JS_GetProperty(context, object, "point", &branch_point_value) ||
- !branch_point_value.isInt32()) {
- gjs_throw(context, "Failed to get point property from element");
- return false;
- }
+ JS::RootedId point_name(context, gjs_intern_string_to_id(context, "point"));
- branch_point = branch_point_value.toInt32();
+ if (!gjs_object_require_property_value(context, object, "branch array element",
+ point_name, &branch_point))
+ return false;
- JS::Value was_hit_value;
bool was_hit;
if (!JS_GetProperty(context, object, "hit", &was_hit_value) ||
@@ -684,9 +667,6 @@ convert_and_insert_branch_info(GArray *array,
return false;
}
- was_hit = was_hit_value.toBoolean();
-
- JS::Value branch_exits_value;
GArray *branch_exits_array = NULL;
if (!JS_GetProperty(context, object, "exits", &branch_exits_value) ||
@@ -1633,12 +1613,14 @@ bootstrap_coverage(GjsCoverage *coverage)
&error))
g_error("Failed to eval coverage script: %s\n", error->message);
- JS::Value coverage_statistics_prototype_value;
- if (!JS_GetProperty(context, debugger_compartment, "CoverageStatistics",
&coverage_statistics_prototype_value) ||
- !coverage_statistics_prototype_value.isObject()) {
- gjs_throw(context, "Failed to get CoverageStatistics prototype");
+ JS::RootedObject coverage_statistics_constructor(context);
+ JS::RootedId coverage_statistics_name(context,
+ gjs_intern_string_to_id(context, "CoverageStatistics"));
+ if (!gjs_object_require_property_value(context, debugger_compartment,
+ "debugger compartment",
+ coverage_statistics_name,
+ &coverage_statistics_constructor))
return false;
- }
/* Create value for holding the cache. This will be undefined if
* the cache does not exist, otherwise it will be an object set
@@ -1658,8 +1640,6 @@ bootstrap_coverage(GjsCoverage *coverage)
cache_value.set(JS::UndefinedValue());
}
- JSObject *coverage_statistics_constructor = &coverage_statistics_prototype_value.toObject();
-
/* Now create the array to pass the desired prefixes over */
JSObject *prefixes = gjs_build_string_array(context, -1, priv->prefixes);
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index bf022e6..8b548fe 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -411,7 +411,7 @@ do_import(JSContext *context,
char *filename;
char *full_path;
char *dirname = NULL;
- JS::RootedValue search_path_val(context);
+ JS::RootedObject search_path(context);
guint32 search_path_len;
guint32 i;
bool result;
@@ -421,17 +421,12 @@ do_import(JSContext *context,
JS::RootedId search_path_name(context,
gjs_context_get_const_string(context, GJS_STRING_SEARCH_PATH));
- if (!gjs_object_require_property(context, obj, "importer", search_path_name, &search_path_val)) {
- return false;
- }
- if (!search_path_val.isObject()) {
- gjs_throw(context, "searchPath property on importer is not an object");
+ if (!gjs_object_require_property_value(context, obj, "importer",
+ search_path_name, &search_path)) {
return false;
}
- JS::RootedObject search_path(context, &search_path_val.toObject());
-
if (!JS_IsArrayObject(context, search_path)) {
gjs_throw(context, "searchPath property on importer is not an array");
return false;
@@ -662,7 +657,7 @@ importer_new_enumerate(JSContext *context,
case JSENUMERATE_INIT_ALL:
case JSENUMERATE_INIT: {
Importer *priv;
- JS::RootedValue search_path_val(context);
+ JS::RootedObject search_path(context);
guint32 search_path_len;
guint32 i;
@@ -678,16 +673,10 @@ importer_new_enumerate(JSContext *context,
JS::RootedId search_path_name(context,
gjs_context_get_const_string(context, GJS_STRING_SEARCH_PATH));
- if (!gjs_object_require_property(context, object, "importer", search_path_name, &search_path_val))
+ if (!gjs_object_require_property_value(context, object, "importer",
+ search_path_name, &search_path))
return false;
- if (!search_path_val.isObject()) {
- gjs_throw(context, "searchPath property on importer is not an object");
- return false;
- }
-
- JS::RootedObject search_path(context, &search_path_val.toObject());
-
if (!JS_IsArrayObject(context, search_path)) {
gjs_throw(context, "searchPath property on importer is not an array");
return false;
diff --git a/gjs/jsapi-dynamic-class.cpp b/gjs/jsapi-dynamic-class.cpp
index 3965f59..f85c57e 100644
--- a/gjs/jsapi-dynamic-class.cpp
+++ b/gjs/jsapi-dynamic-class.cpp
@@ -172,22 +172,15 @@ gjs_construct_object_dynamic(JSContext *context,
unsigned argc,
JS::Value *argv)
{
- JSObject *constructor;
- JSObject *result = NULL;
- JS::RootedValue value(context);
-
- JS_BeginRequest(context);
+ JSAutoRequest ar(context);
JS::RootedId constructor_name(context,
gjs_context_get_const_string(context, GJS_STRING_CONSTRUCTOR));
- if (!gjs_object_require_property(context, proto, "prototype",
- constructor_name, &value))
- goto out;
+ JS::RootedObject constructor(context);
- constructor = &value.toObject();
- result = JS_New(context, constructor, argc, argv);
+ if (!gjs_object_require_property_value(context, proto, "prototype",
+ constructor_name, &constructor))
+ return NULL;
- out:
- JS_EndRequest(context);
- return result;
+ return JS_New(context, constructor, argc, argv);
}
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index b33e1d8..4b8f7c4 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -128,6 +128,29 @@ gjs_get_global_slot (JSContext *context,
return JS_GetReservedSlot(global, JSCLASS_GLOBAL_SLOT_COUNT + slot);
}
+static void
+throw_property_lookup_error(JSContext *cx,
+ JS::HandleObject obj,
+ const char *description,
+ JS::HandleId property_name,
+ const char *reason)
+{
+ /* remember gjs_throw() is a no-op if JS_GetProperty()
+ * already set an exception
+ */
+ char *name;
+ gjs_get_string_id(cx, property_name, &name);
+
+ if (description)
+ gjs_throw(cx, "No property '%s' in %s (or %s)", name, description,
+ reason);
+ else
+ gjs_throw(cx, "No property '%s' in object %p (or %s)", name,
+ obj.address(), reason);
+
+ g_free(name);
+}
+
/* Returns whether the object had the property; if the object did
* not have the property, always sets an exception. Treats
* "the property's value is undefined" the same as "no such property,".
@@ -143,8 +166,6 @@ gjs_object_require_property(JSContext *context,
JS::HandleId property_name,
JS::MutableHandleValue value)
{
- char *name;
-
value.setUndefined();
if (G_UNLIKELY(!JS_GetPropertyById(context, obj, property_name, value.address())))
@@ -153,22 +174,83 @@ gjs_object_require_property(JSContext *context,
if (G_LIKELY(!value.isUndefined()))
return true;
- /* remember gjs_throw() is a no-op if JS_GetProperty()
- * already set an exception
- */
+ throw_property_lookup_error(context, obj, obj_description, property_name,
+ "its value was undefined");
+ return false;
+}
- gjs_get_string_id(context, property_name, &name);
+bool
+gjs_object_require_property_value(JSContext *cx,
+ JS::HandleObject obj,
+ const char *description,
+ JS::HandleId property_name,
+ int32_t *value)
+{
+ JS::RootedValue prop_value(cx);
+ if (JS_GetPropertyById(cx, obj, property_name, prop_value.address()) &&
+ prop_value.isInt32()) {
+ *value = prop_value.toInt32();
+ return true;
+ }
- if (obj_description)
- gjs_throw(context,
- "No property '%s' in %s (or its value was undefined)",
- name, obj_description);
- else
- gjs_throw(context,
- "No property '%s' in object %p (or its value was undefined)",
- name, obj.address());
+ throw_property_lookup_error(cx, obj, description, property_name,
+ "it was not a 32-bit integer");
+ return false;
+}
- g_free(name);
+/* Converts JS string value to UTF-8 string. value must be freed with JS_free. */
+bool
+gjs_object_require_property_value(JSContext *cx,
+ JS::HandleObject obj,
+ const char *description,
+ JS::HandleId property_name,
+ char **value)
+{
+ JS::RootedValue prop_value(cx);
+ if (JS_GetPropertyById(cx, obj, property_name, prop_value.address()) &&
+ gjs_string_to_utf8(cx, prop_value, value)) {
+ return true;
+ }
+
+ throw_property_lookup_error(cx, obj, description, property_name,
+ "it was not a valid string");
+ return false;
+}
+
+bool
+gjs_object_require_property_value(JSContext *cx,
+ JS::HandleObject obj,
+ const char *description,
+ JS::HandleId property_name,
+ JS::MutableHandleObject value)
+{
+ JS::RootedValue prop_value(cx);
+ if (JS_GetPropertyById(cx, obj, property_name, prop_value.address()) &&
+ prop_value.isObject()) {
+ value.set(&prop_value.toObject());
+ return true;
+ }
+
+ throw_property_lookup_error(cx, obj, description, property_name,
+ "it was not an object");
+ return false;
+}
+
+bool
+gjs_object_require_converted_property_value(JSContext *cx,
+ JS::HandleObject obj,
+ const char *description,
+ JS::HandleId property_name,
+ uint32_t *value)
+{
+ JS::RootedValue prop_value(cx);
+ if (JS_GetPropertyById(cx, obj, property_name, prop_value.address()) &&
+ JS::ToUint32(cx, prop_value, value)) {
+ return true;
+ }
+
+ throw_property_lookup_error(cx, obj, description, property_name,
+ "it couldn't be converted to uint32");
return false;
}
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 45b6503..0f3cd9a 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -309,6 +309,13 @@ bool gjs_object_require_property(JSContext *context,
JS::HandleId property_name,
JS::MutableHandleValue value);
+/* This is intended to be overloaded with more types as the opportunity arises */
+bool gjs_object_require_converted_property_value(JSContext *context,
+ JS::HandleObject obj,
+ const char *description,
+ JS::HandleId property_name,
+ uint32_t *value);
+
bool gjs_init_class_dynamic(JSContext *context,
JSObject *in_object,
JSObject *parent_proto,
@@ -466,6 +473,7 @@ typedef enum {
GJS_STRING_Y,
GJS_STRING_WIDTH,
GJS_STRING_HEIGHT,
+ GJS_STRING_COVERAGE_STATISTICS,
GJS_STRING_LAST
} GjsConstString;
@@ -483,4 +491,25 @@ const char * gjs_strip_unix_shebang(const char *script,
G_END_DECLS
+/* Overloaded functions, must be outside extern G_DECLS. More types are intended
+ * to be added as the opportunity arises. */
+
+bool gjs_object_require_property_value(JSContext *cx,
+ JS::HandleObject obj,
+ const char *description,
+ JS::HandleId property_name,
+ int32_t *value);
+
+bool gjs_object_require_property_value(JSContext *cx,
+ JS::HandleObject obj,
+ const char *description,
+ JS::HandleId property_name,
+ char **value);
+
+bool gjs_object_require_property_value(JSContext *cx,
+ JS::HandleObject obj,
+ const char *description,
+ JS::HandleId property_name,
+ JS::MutableHandleObject value);
+
#endif /* __GJS_JSAPI_UTIL_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]