[gjs: 4/6] jsapi-util-args: Add 'S' conversion specifier
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 4/6] jsapi-util-args: Add 'S' conversion specifier
- Date: Sun, 4 Jul 2021 19:13:21 +0000 (UTC)
commit 309a51ccc878760c4fb8275c5b0e563711a050b7
Author: Philip Chimento <philip chimento gmail com>
Date: Fri Jul 2 18:09:23 2021 -0700
jsapi-util-args: Add 'S' conversion specifier
The 'S' specifier also expects a string argument, or additionally null if
it is given as '?S'. Unlike 's' and 'F', it does not convert the string
value at all, and instead puts it into a JS::MutableHandleString.
This will be used in the Encoding specification.
gjs/jsapi-util-args.h | 37 ++++++++++++++++++++++--------
test/gjs-test-call-args.cpp | 56 ++++++++++++++++++++++++++++-----------------
2 files changed, 62 insertions(+), 31 deletions(-)
---
diff --git a/gjs/jsapi-util-args.h b/gjs/jsapi-util-args.h
index 62843121..576d638d 100644
--- a/gjs/jsapi-util-args.h
+++ b/gjs/jsapi-util-args.h
@@ -98,6 +98,21 @@ assign(JSContext *cx,
throw g_strdup("Couldn't convert to filename");
}
+GJS_ALWAYS_INLINE
+static inline void assign(JSContext*, char c, bool nullable,
+ JS::HandleValue value, JS::MutableHandleString ref) {
+ if (c != 'S')
+ throw g_strdup_printf("Wrong type for %c, got JS::MutableHandleString",
+ c);
+ if (nullable && value.isNull()) {
+ ref.set(nullptr);
+ return;
+ }
+ if (!value.isString())
+ throw g_strdup("Not a string");
+ ref.set(value.toString());
+}
+
GJS_ALWAYS_INLINE
static inline void
assign(JSContext *cx,
@@ -187,12 +202,13 @@ GJS_ALWAYS_INLINE static inline void assign(JSContext* cx, char c,
template <typename T>
static inline void free_if_necessary(T param_ref [[maybe_unused]]) {}
-GJS_ALWAYS_INLINE
-static inline void free_if_necessary(JS::RootedObject* param_ref) {
- /* This is not exactly right, since before we consumed a JS::ObjectValue
- * there may have been something different inside the handle. But it has
- * already been clobbered at this point anyhow */
- JS::MutableHandleObject(param_ref).set(nullptr);
+template <typename T>
+GJS_ALWAYS_INLINE static inline void free_if_necessary(
+ JS::Rooted<T>* param_ref) {
+ // This is not exactly right, since before we consumed a JS::Value there may
+ // have been something different inside the handle. But it has already been
+ // clobbered at this point anyhow.
+ JS::MutableHandle<T>(param_ref).set(nullptr);
}
template <typename T>
@@ -247,7 +263,7 @@ GJS_JSAPI_RETURN_CONVENTION static bool parse_call_args_helper(
bool retval = parse_call_args_helper(cx, function_name, args, fmt_required,
fmt_optional, ++param_ix, params...);
- /* We still own the strings in the error case, free any we converted */
+ // We still own JSString/JSObject in the error case, free any we converted
if (!retval)
free_if_necessary(param_ref);
return retval;
@@ -295,6 +311,7 @@ GJS_JSAPI_RETURN_CONVENTION [[maybe_unused]] static bool gjs_parse_call_args(
* s: A string, converted into UTF-8 (pass a JS::UniqueChars*)
* F: A string, converted into "filename encoding" (i.e. active locale) (pass
* a GjsAutoChar *)
+ * S: A string, no conversion (pass a JS::MutableHandleString)
* i: A number, will be converted to a 32-bit int (pass an int32_t * or a
* pointer to an enum type)
* u: A number, converted into a 32-bit unsigned int (pass a uint32_t *)
@@ -309,9 +326,9 @@ GJS_JSAPI_RETURN_CONVENTION [[maybe_unused]] static bool gjs_parse_call_args(
* after a '|' when not specified, do not cause any changes in the C
* value location.
*
- * A prefix character '?' in front of 's', 'F', or 'o' means that the next value
- * may be null. For 's' or 'F' a null pointer is returned, for 'o' the handle is
- * set to null.
+ * A prefix character '?' in front of 's', 'F', 'S', or 'o' means that the next
+ * value may be null. For 's' or 'F' a null pointer is returned, for 'S' or 'o'
+ * the handle is set to null.
*/
template <typename... Args>
GJS_JSAPI_RETURN_CONVENTION static bool gjs_parse_call_args(
diff --git a/test/gjs-test-call-args.cpp b/test/gjs-test-call-args.cpp
index 17d2039d..d5413600 100644
--- a/test/gjs-test-call-args.cpp
+++ b/test/gjs-test-call-args.cpp
@@ -116,23 +116,23 @@ JSNATIVE_TEST_FUNC_BEGIN(one_of_each_type)
bool boolval;
JS::UniqueChars strval;
GjsAutoChar fileval;
+ JS::RootedString jsstrval(cx);
int intval;
unsigned uintval;
int64_t int64val;
double dblval;
JS::RootedObject objval(cx);
- retval = gjs_parse_call_args(cx, "oneOfEachType", args, "bsFiutfo",
- "bool", &boolval,
- "str", &strval,
- "file", &fileval,
- "int", &intval,
- "uint", &uintval,
- "int64", &int64val,
- "dbl", &dblval,
- "obj", &objval);
+ retval = gjs_parse_call_args(
+ cx, "oneOfEachType", args, "bsFSiutfo", "bool", &boolval, "str",
+ &strval, "file", &fileval, "jsstr", &jsstrval, "int", &intval, "uint",
+ &uintval, "int64", &int64val, "dbl", &dblval, "obj", &objval);
g_assert_cmpint(boolval, ==, true);
g_assert_cmpstr(strval.get(), ==, "foo");
g_assert_cmpstr(fileval, ==, "foo");
+ bool match;
+ bool ok = JS_StringEqualsLiteral(cx, jsstrval, "foo", &match);
+ g_assert_true(ok);
+ g_assert_true(match);
g_assert_cmpint(intval, ==, 1);
g_assert_cmpint(uintval, ==, 1);
g_assert_cmpint(int64val, ==, 1);
@@ -186,25 +186,27 @@ JSNATIVE_TEST_FUNC_END
JSNATIVE_TEST_FUNC_BEGIN(one_of_each_nullable_type)
JS::UniqueChars strval;
GjsAutoChar fileval;
+ JS::RootedString jsstrval(cx);
JS::RootedObject objval(cx);
- retval = gjs_parse_call_args(cx, "oneOfEachNullableType", args, "?s?F?o",
- "strval", &strval,
- "fileval", &fileval,
- "objval", &objval);
+ retval = gjs_parse_call_args(cx, "oneOfEachNullableType", args, "?s?F?S?o",
+ "strval", &strval, "fileval", &fileval,
+ "jsstrval", &jsstrval, "objval", &objval);
g_assert_null(strval);
g_assert_null(fileval);
+ g_assert_false(jsstrval);
g_assert_false(objval);
JSNATIVE_TEST_FUNC_END
JSNATIVE_TEST_FUNC_BEGIN(unwind_free_test)
int intval;
unsigned uval;
+ JS::RootedString jsstrval(cx);
JS::RootedObject objval(cx);
- retval = gjs_parse_call_args(cx, "unwindFreeTest", args, "oiu",
- "objval", &objval,
- "intval", &intval,
- "error", &uval);
+ retval = gjs_parse_call_args(cx, "unwindFreeTest", args, "oSiu", "objval",
+ &objval, "jsstrval", &jsstrval, "intval",
+ &intval, "error", &uval);
g_assert_false(objval);
+ g_assert_false(jsstrval);
JSNATIVE_TEST_FUNC_END
#define JSNATIVE_BAD_NULLABLE_TEST_FUNC(type, fmt) \
@@ -245,6 +247,12 @@ JSNATIVE_TEST_FUNC_BEGIN(UniqueChars_invalid_type)
"value", &value);
JSNATIVE_TEST_FUNC_END
+JSNATIVE_TEST_FUNC_BEGIN(JSString_invalid_type)
+ JS::RootedString val(cx);
+ retval =
+ gjs_parse_call_args(cx, "JSStringInvalidType", args, "i", "val", &val);
+JSNATIVE_TEST_FUNC_END
+
JSNATIVE_TEST_FUNC_BEGIN(object_invalid_type)
JS::RootedObject val(cx);
retval = gjs_parse_call_args(cx, "objectInvalidType", args, "i",
@@ -279,6 +287,7 @@ static JSFunctionSpec native_test_funcs[] = {
JS_FN("doubleInvalidType", double_invalid_type, 0, 0),
JS_FN("GjsAutoCharInvalidType", GjsAutoChar_invalid_type, 0, 0),
JS_FN("UniqueCharsInvalidType", UniqueChars_invalid_type, 0, 0),
+ JS_FN("JSStringInvalidType", JSString_invalid_type, 0, 0),
JS_FN("objectInvalidType", object_invalid_type, 0, 0),
JS_FS_END};
@@ -371,8 +380,9 @@ gjs_test_add_tests_for_parse_call_args(void)
"optionalIntArgsNoAssert()//*At least 1 argument "
"required, but only 0 passed");
ADD_CALL_ARGS_TEST("args-ignores-trailing", "argsIgnoreTrailing(1, 2, 3)");
- ADD_CALL_ARGS_TEST("one-of-each-type-works",
- "oneOfEachType(true, 'foo', 'foo', 1, 1, 1, 1, {})");
+ ADD_CALL_ARGS_TEST(
+ "one-of-each-type-works",
+ "oneOfEachType(true, 'foo', 'foo', 'foo', 1, 1, 1, 1, {})");
ADD_CALL_ARGS_TEST("optional-args-work-when-passing-all-args",
"optionalArgsAll(true, true, true)");
ADD_CALL_ARGS_TEST("optional-args-work-when-passing-only-required-args",
@@ -380,7 +390,7 @@ gjs_test_add_tests_for_parse_call_args(void)
ADD_CALL_ARGS_TEST("enum-types-work", "unsignedEnumArg(1)");
ADD_CALL_ARGS_TEST("signed-enum-types-work", "signedEnumArg(-1)");
ADD_CALL_ARGS_TEST("one-of-each-nullable-type-works",
- "oneOfEachNullableType(null, null, null)");
+ "oneOfEachNullableType(null, null, null, null)");
ADD_CALL_ARGS_TEST("passing-no-arguments-when-all-optional",
"onlyOptionalArgs()");
ADD_CALL_ARGS_TEST("passing-some-arguments-when-all-optional",
@@ -388,7 +398,7 @@ gjs_test_add_tests_for_parse_call_args(void)
ADD_CALL_ARGS_TEST("passing-all-arguments-when-all-optional",
"onlyOptionalArgs(1, 1)");
ADD_CALL_ARGS_TEST_XFAIL("allocated-args-are-freed-on-error",
- "unwindFreeTest({}, 1, -1)"
+ "unwindFreeTest({}, 'foo', 1, -1)"
"//*Value * is out of range");
ADD_CALL_ARGS_TEST_XFAIL("nullable-bool-is-invalid",
"boolInvalidNullable(true)"
@@ -426,6 +436,10 @@ gjs_test_add_tests_for_parse_call_args(void)
ADD_CALL_ARGS_TEST_XFAIL("invalid-autojschar-type",
"UniqueCharsInvalidType(1)"
"//*Wrong type for i, got JS::UniqueChars?");
+ ADD_CALL_ARGS_TEST_XFAIL(
+ "invalid-jsstring-type",
+ "JSStringInvalidType(1)"
+ "//*Wrong type for i, got JS::MutableHandleString");
ADD_CALL_ARGS_TEST_XFAIL("invalid-object-type",
"objectInvalidType(1)"
"//*Wrong type for i, got JS::MutableHandleObject");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]