262 | 262 |
const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
|
263 | 263 |
JS::RootedObject array_obj(cx, &value.toObject());
|
264 | 264 |
|
265 | |
if (!JS_HasPropertyById(cx, array_obj, atoms.length(), &found_length)) {
|
266 | |
throw_invalid_argument(cx, value, type_info, arg_name, arg_type);
|
|
265 |
if (!JS_HasPropertyById(cx, array_obj, atoms.length(), &found_length))
|
267 | 266 |
return false;
|
268 | |
}
|
269 | |
|
270 | 267 |
if (!found_length) {
|
271 | 268 |
throw_invalid_argument(cx, value, type_info, arg_name, arg_type);
|
272 | 269 |
return false;
|
|
338 | 335 |
}
|
339 | 336 |
|
340 | 337 |
[[nodiscard]] static GHashTable* create_hash_table_for_key_type(
|
341 | |
GITypeInfo* key_param_info) {
|
|
338 |
GITypeTag key_type) {
|
342 | 339 |
/* Don't use key/value destructor functions here, because we can't
|
343 | 340 |
* construct correct ones in general if the value type is complex.
|
344 | 341 |
* Rely on the type-aware g_argument_release functions. */
|
345 | |
|
346 | |
GITypeTag key_type = g_type_info_get_tag(key_param_info);
|
347 | |
|
348 | 342 |
if (key_type == GI_TYPE_TAG_UTF8 || key_type == GI_TYPE_TAG_FILENAME)
|
349 | 343 |
return g_hash_table_new(g_str_hash, g_str_equal);
|
350 | 344 |
return g_hash_table_new(NULL, NULL);
|
|
374 | 368 |
* possible, otherwise giving the location of an allocated key in @pointer_out.
|
375 | 369 |
*/
|
376 | 370 |
GJS_JSAPI_RETURN_CONVENTION
|
377 | |
static bool
|
378 | |
value_to_ghashtable_key(JSContext *cx,
|
379 | |
JS::HandleValue value,
|
380 | |
GITypeInfo *type_info,
|
381 | |
gpointer *pointer_out)
|
382 | |
{
|
383 | |
GITypeTag type_tag = g_type_info_get_tag((GITypeInfo*) type_info);
|
|
371 |
static bool value_to_ghashtable_key(JSContext* cx, JS::HandleValue value,
|
|
372 |
GITypeTag type_tag, void** pointer_out) {
|
384 | 373 |
bool unsupported = false;
|
385 | 374 |
|
386 | |
g_return_val_if_fail(value.isString() || value.isInt32(), false);
|
|
375 |
g_assert((value.isString() || value.isInt32()) &&
|
|
376 |
"keys from JS_Enumerate must be non-symbol property keys");
|
387 | 377 |
|
388 | 378 |
gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
|
389 | 379 |
"Converting JS::Value to GHashTable key %s",
|
|
535 | 525 |
if (!JS_Enumerate(context, props, &ids))
|
536 | 526 |
return false;
|
537 | 527 |
|
|
528 |
GITypeTag key_tag = g_type_info_get_tag(key_param_info);
|
538 | 529 |
GjsAutoPointer<GHashTable, GHashTable, g_hash_table_destroy> result =
|
539 | |
create_hash_table_for_key_type(key_param_info);
|
|
530 |
create_hash_table_for_key_type(key_tag);
|
540 | 531 |
|
541 | 532 |
JS::RootedValue key_js(context), val_js(context);
|
542 | 533 |
JS::RootedId cur_id(context);
|
|
547 | 538 |
|
548 | 539 |
if (!JS_IdToValue(context, cur_id, &key_js) ||
|
549 | 540 |
// Type check key type.
|
550 | |
!value_to_ghashtable_key(context, key_js, key_param_info,
|
551 | |
&key_ptr) ||
|
|
541 |
!value_to_ghashtable_key(context, key_js, key_tag, &key_ptr) ||
|
552 | 542 |
!JS_GetPropertyById(context, props, cur_id, &val_js) ||
|
553 | 543 |
// Type check and convert value to a C type
|
554 | 544 |
!gjs_value_to_g_argument(context, val_js, val_param_info, nullptr,
|
|
684 | 674 |
}
|
685 | 675 |
|
686 | 676 |
GJS_JSAPI_RETURN_CONVENTION
|
687 | |
static bool
|
688 | |
gjs_string_to_intarray(JSContext *context,
|
689 | |
JS::HandleString str,
|
690 | |
GITypeInfo *param_info,
|
691 | |
void **arr_p,
|
692 | |
size_t *length)
|
693 | |
{
|
694 | |
GITypeTag element_type;
|
|
677 |
static bool gjs_string_to_intarray(JSContext* context, JS::HandleString str,
|
|
678 |
GITypeTag element_type, void** arr_p,
|
|
679 |
size_t* length) {
|
695 | 680 |
char16_t *result16;
|
696 | |
|
697 | |
element_type = g_type_info_get_tag(param_info);
|
698 | 681 |
|
699 | 682 |
switch (element_type) {
|
700 | 683 |
case GI_TYPE_TAG_INT8:
|
|
1119 | 1102 |
} else if (value.isString()) {
|
1120 | 1103 |
/* Allow strings as int8/uint8/int16/uint16 arrays */
|
1121 | 1104 |
JS::RootedString str(context, value.toString());
|
1122 | |
if (!gjs_string_to_intarray(context, str, param_info, contents, length_p))
|
|
1105 |
GITypeTag element_tag = g_type_info_get_tag(param_info);
|
|
1106 |
if (!gjs_string_to_intarray(context, str, element_tag, contents, length_p))
|
1123 | 1107 |
return false;
|
1124 | 1108 |
} else {
|
1125 | 1109 |
JS::RootedObject array_obj(context, &value.toObject());
|
1126 | |
const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
|
1127 | 1110 |
GITypeTag element_type = g_type_info_get_tag(param_info);
|
1128 | 1111 |
if (JS_IsUint8Array(array_obj) && (element_type == GI_TYPE_TAG_INT8 ||
|
1129 | 1112 |
element_type == GI_TYPE_TAG_UINT8)) {
|
1130 | 1113 |
GBytes* bytes = gjs_byte_array_get_bytes(array_obj);
|
1131 | 1114 |
*contents = g_bytes_unref_to_data(bytes, length_p);
|
1132 | |
} else if (JS_HasPropertyById(context, array_obj, atoms.length(),
|
1133 | |
&found_length) &&
|
1134 | |
found_length) {
|
|
1115 |
return true;
|
|
1116 |
}
|
|
1117 |
|
|
1118 |
const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
|
|
1119 |
if (!JS_HasPropertyById(context, array_obj, atoms.length(),
|
|
1120 |
&found_length))
|
|
1121 |
return false;
|
|
1122 |
if (found_length) {
|
1135 | 1123 |
guint32 length;
|
1136 | 1124 |
|
1137 | 1125 |
if (!gjs_object_require_converted_property(
|