Introduce new API functions to obtain detailed object type information (#4162)

- jerry_object_get_type
- jerry_function_get_type
- jerry_iterator_get_type
- jerry_value_is_async_function

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2020-08-28 12:53:56 +02:00
committed by GitHub
parent 4ed9e2c033
commit 6d0e948bef
7 changed files with 920 additions and 8 deletions
+303
View File
@@ -738,6 +738,41 @@ jerry_value_is_function (const jerry_value_t value) /**< api value */
return ecma_op_is_callable (value);
} /* jerry_value_is_function */
/**
* Check if the specified value is an async function object value.
*
* @return true - if the specified value is an async function,
* false - otherwise
*/
bool
jerry_value_is_async_function (const jerry_value_t value) /**< api value */
{
jerry_assert_api_available ();
#if ENABLED (JERRY_ESNEXT)
if (ecma_is_value_object (value))
{
ecma_object_t *obj_p = ecma_get_object_from_value (value);
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION
&& !ecma_get_object_is_builtin (obj_p))
{
const ecma_compiled_code_t *bytecode_data_p;
bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) obj_p);
uint16_t type = CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags);
return (type == CBC_FUNCTION_ASYNC
|| type == CBC_FUNCTION_ASYNC_ARROW
|| type == CBC_FUNCTION_ASYNC_GENERATOR);
}
}
#else /* !ENABLED (JERRY_ESNEXT) */
JERRY_UNUSED (value);
#endif /* ENABLED (JERRY_ESNEXT) */
return false;
} /* jerry_value_is_async_function */
/**
* Check if the specified value is number.
*
@@ -943,6 +978,274 @@ jerry_value_get_type (const jerry_value_t value) /**< input value to check */
}
} /* jerry_value_get_type */
/**
* Get the object type of the given value
*
* @return JERRY_OBJECT_TYPE_NONE - if the given value is not an object
* jerry_object_type_t value - otherwise
*/
jerry_object_type_t
jerry_object_get_type (const jerry_value_t value) /**< input value to check */
{
jerry_assert_api_available ();
if (!ecma_is_value_object (value))
{
return JERRY_OBJECT_TYPE_NONE;
}
ecma_object_t *obj_p = ecma_get_object_from_value (value);
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
switch (ecma_get_object_type (obj_p))
{
case ECMA_OBJECT_TYPE_FUNCTION:
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
{
return JERRY_OBJECT_TYPE_FUNCTION;
}
case ECMA_OBJECT_TYPE_ARRAY:
{
return JERRY_OBJECT_TYPE_ARRAY;
}
#if ENABLED (JERRY_ESNEXT)
case ECMA_OBJECT_TYPE_PROXY:
{
return JERRY_OBJECT_TYPE_PROXY;
}
#endif /* ENABLED (JERRY_ESNEXT) */
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
{
switch (ext_obj_p->u.pseudo_array.type)
{
case ECMA_PSEUDO_ARRAY_ARGUMENTS:
{
return JERRY_OBJECT_TYPE_ARGUMENTS;
}
#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
case ECMA_PSEUDO_ARRAY_TYPEDARRAY:
case ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO:
{
return JERRY_OBJECT_TYPE_TYPEDARRAY;
}
#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
#if ENABLED (JERRY_ESNEXT)
case ECMA_PSEUDO_STRING_ITERATOR:
case ECMA_PSEUDO_ARRAY_ITERATOR:
#if ENABLED (JERRY_BUILTIN_MAP)
case ECMA_PSEUDO_MAP_ITERATOR:
#endif /* ENABLED (JERRY_BUILTIN_MAP) */
#if ENABLED (JERRY_BUILTIN_SET)
case ECMA_PSEUDO_SET_ITERATOR:
#endif /* ENABLED (JERRY_BUILTIN_SET) */
{
return JERRY_OBJECT_TYPE_ITERATOR;
}
#endif /* ENABLED (JERRY_ESNEXT) */
}
break;
}
case ECMA_OBJECT_TYPE_CLASS:
{
switch (ext_obj_p->u.class_prop.class_id)
{
case LIT_MAGIC_STRING_ARGUMENTS_UL:
{
return JERRY_OBJECT_TYPE_ARGUMENTS;
}
case LIT_MAGIC_STRING_BOOLEAN_UL:
{
return JERRY_OBJECT_TYPE_BOOLEAN;
}
case LIT_MAGIC_STRING_DATE_UL:
{
return JERRY_OBJECT_TYPE_DATE;
}
case LIT_MAGIC_STRING_NUMBER_UL:
{
return JERRY_OBJECT_TYPE_NUMBER;
}
case LIT_MAGIC_STRING_REGEXP_UL:
{
return JERRY_OBJECT_TYPE_REGEXP;
}
case LIT_MAGIC_STRING_STRING_UL:
{
return JERRY_OBJECT_TYPE_STRING;
}
#if ENABLED (JERRY_ESNEXT)
case LIT_MAGIC_STRING_SYMBOL_UL:
{
return JERRY_OBJECT_TYPE_SYMBOL;
}
case LIT_MAGIC_STRING_GENERATOR_UL:
{
return JERRY_OBJECT_TYPE_GENERATOR;
}
#endif /* ENABLED (JERRY_ESNEXT) */
#if ENABLED (JERRY_BUILTIN_BIGINT)
case LIT_MAGIC_STRING_BIGINT_UL:
{
return JERRY_OBJECT_TYPE_BIGINT;
}
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
#if ENABLED (JERRY_BUILTIN_CONTAINER)
#if ENABLED (JERRY_BUILTIN_MAP)
case LIT_MAGIC_STRING_MAP_UL:
#endif /* ENABLED (JERRY_BUILTIN_MAP) */
#if ENABLED (JERRY_BUILTIN_SET)
case LIT_MAGIC_STRING_SET_UL:
#endif /* ENABLED (JERRY_BUILTIN_SET) */
#if ENABLED (JERRY_BUILTIN_WEAKMAP)
case LIT_MAGIC_STRING_WEAKMAP_UL:
#endif /* ENABLED (JERRY_BUILTIN_WEAKMAP) */
#if ENABLED (JERRY_BUILTIN_WEAKSET)
case LIT_MAGIC_STRING_WEAKSET_UL:
#endif /* ENABLED (JERRY_BUILTIN_WEAKSET) */
{
return JERRY_OBJECT_TYPE_CONTAINER;
}
#endif /* ENABLED (JERRY_BUILTIN_CONTAINER) */
default:
{
break;
}
}
break;
}
default:
{
break;
}
}
return JERRY_OBJECT_TYPE_GENERIC;
} /* jerry_object_get_type */
/**
* Get the function type of the given value
*
* @return JERRY_FUNCTION_TYPE_NONE - if the given value is not a function object
* jerry_function_type_t value - otherwise
*/
jerry_function_type_t
jerry_function_get_type (const jerry_value_t value) /**< input value to check */
{
jerry_assert_api_available ();
if (ecma_is_value_object (value))
{
ecma_object_t *obj_p = ecma_get_object_from_value (value);
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
switch (ecma_get_object_type (obj_p))
{
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
{
return JERRY_FUNCTION_TYPE_BOUND;
}
case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
{
return JERRY_FUNCTION_TYPE_GENERIC;
}
case ECMA_OBJECT_TYPE_FUNCTION:
{
if (!ecma_get_object_is_builtin (obj_p))
{
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_obj_p);
switch (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags))
{
#if ENABLED (JERRY_ESNEXT)
case CBC_FUNCTION_ARROW:
case CBC_FUNCTION_ASYNC_ARROW:
{
return JERRY_FUNCTION_TYPE_ARROW;
}
case CBC_FUNCTION_GENERATOR:
case CBC_FUNCTION_ASYNC_GENERATOR:
{
return JERRY_FUNCTION_TYPE_GENERATOR;
}
#endif /* ENABLED (JERRY_ESNEXT) */
case CBC_FUNCTION_ACCESSOR:
{
return JERRY_FUNCTION_TYPE_ACCESSOR;
}
default:
{
break;
}
}
}
return JERRY_FUNCTION_TYPE_GENERIC;
}
default:
{
break;
}
}
}
return JERRY_FUNCTION_TYPE_NONE;
} /* jerry_function_get_type */
/**
* Get the itearator type of the given value
*
* @return JERRY_ITERATOR_TYPE_NONE - if the given value is not an iterator object
* jerry_iterator_type_t value - otherwise
*/
jerry_iterator_type_t
jerry_iterator_get_type (const jerry_value_t value) /**< input value to check */
{
jerry_assert_api_available ();
#if ENABLED (JERRY_ESNEXT)
if (ecma_is_value_object (value))
{
ecma_object_t *obj_p = ecma_get_object_from_value (value);
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY)
{
switch (ext_obj_p->u.pseudo_array.type)
{
case ECMA_PSEUDO_ARRAY_ITERATOR:
{
return JERRY_ITERATOR_TYPE_ARRAY;
}
case ECMA_PSEUDO_STRING_ITERATOR:
{
return JERRY_ITERATOR_TYPE_STRING;
}
#if ENABLED (JERRY_BUILTIN_MAP)
case ECMA_PSEUDO_MAP_ITERATOR:
{
return JERRY_ITERATOR_TYPE_MAP;
}
#endif /* ENABLED (JERRY_BUILTIN_MAP) */
#if ENABLED (JERRY_BUILTIN_SET)
case ECMA_PSEUDO_SET_ITERATOR:
{
return JERRY_ITERATOR_TYPE_SET;
}
#endif /* ENABLED (JERRY_BUILTIN_SET) */
default:
{
break;
}
}
}
}
#else /* !ENABLED (JERRY_ESNEXT) */
JERRY_UNUSED (value);
#endif /* ENABLED (JERRY_ESNEXT) */
return JERRY_ITERATOR_TYPE_NONE;
} /* jerry_iterator_get_type */
/**
* Check if the specified feature is enabled.
*
+54
View File
@@ -381,6 +381,7 @@ bool jerry_value_is_boolean (const jerry_value_t value);
bool jerry_value_is_constructor (const jerry_value_t value);
bool jerry_value_is_error (const jerry_value_t value);
bool jerry_value_is_function (const jerry_value_t value);
bool jerry_value_is_async_function (const jerry_value_t value);
bool jerry_value_is_number (const jerry_value_t value);
bool jerry_value_is_null (const jerry_value_t value);
bool jerry_value_is_object (const jerry_value_t value);
@@ -408,7 +409,60 @@ typedef enum
JERRY_TYPE_SYMBOL, /**< symbol type */
} jerry_type_t;
/**
* JerryScript object type information.
*/
typedef enum
{
JERRY_OBJECT_TYPE_NONE = 0u, /**< Non object type */
JERRY_OBJECT_TYPE_GENERIC, /**< Generic JavaScript object without any internal property */
JERRY_OBJECT_TYPE_ARRAY, /**< Array object */
JERRY_OBJECT_TYPE_PROXY, /**< Proxy object */
JERRY_OBJECT_TYPE_FUNCTION, /**< Function object (see jerry_function_get_type) */
JERRY_OBJECT_TYPE_TYPEDARRAY, /**< %TypedArray% object (see jerry_get_typedarray_type) */
JERRY_OBJECT_TYPE_ITERATOR, /**< Iterator object (see jerry_iterator_get_type) */
JERRY_OBJECT_TYPE_CONTAINER, /**< Container object (see jerry_container_get_type) */
JERRY_OBJECT_TYPE_ARGUMENTS, /**< Arguments object */
JERRY_OBJECT_TYPE_BOOLEAN, /**< Boolean object */
JERRY_OBJECT_TYPE_DATE, /**< Date object */
JERRY_OBJECT_TYPE_NUMBER, /**< Number object */
JERRY_OBJECT_TYPE_REGEXP, /**< RegExp object */
JERRY_OBJECT_TYPE_STRING, /**< String object */
JERRY_OBJECT_TYPE_SYMBOL, /**< Symbol object */
JERRY_OBJECT_TYPE_GENERATOR, /**< Generator object */
JERRY_OBJECT_TYPE_BIGINT, /**< BigInt object */
} jerry_object_type_t;
/**
* JerryScript function object type information.
*/
typedef enum
{
JERRY_FUNCTION_TYPE_NONE = 0u, /**< Non function type */
JERRY_FUNCTION_TYPE_GENERIC, /**< Generic JavaScript function */
JERRY_FUNCTION_TYPE_ACCESSOR, /**< Accessor function */
JERRY_FUNCTION_TYPE_BOUND, /**< Bound function */
JERRY_FUNCTION_TYPE_ARROW, /**< Arrow fuction */
JERRY_FUNCTION_TYPE_GENERATOR, /**< Generator function */
} jerry_function_type_t;
/**
* JerryScript iterator object type information.
*/
typedef enum
{
JERRY_ITERATOR_TYPE_NONE = 0u, /**< Non iterator type */
JERRY_ITERATOR_TYPE_ARRAY, /**< Array iterator */
JERRY_ITERATOR_TYPE_STRING, /**< String iterator */
JERRY_ITERATOR_TYPE_MAP, /**< Map iterator */
JERRY_ITERATOR_TYPE_SET, /**< Set iterator */
} jerry_iterator_type_t;
jerry_type_t jerry_value_get_type (const jerry_value_t value);
jerry_object_type_t jerry_object_get_type (const jerry_value_t value);
jerry_function_type_t jerry_function_get_type (const jerry_value_t value);
jerry_iterator_type_t jerry_iterator_get_type (const jerry_value_t value);
/**
* Checker function of whether the specified compile feature is enabled.
+3 -8
View File
@@ -1313,12 +1313,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */
byte_code_p = (uint8_t *) compiled_code_p;
compiled_code_p->size = (uint16_t) (total_size >> JMEM_ALIGNMENT_LOG);
compiled_code_p->refs = 1;
#if ENABLED (JERRY_ESNEXT)
compiled_code_p->status_flags = 0;
#else /* !ENABLED (JERRY_ESNEXT) */
compiled_code_p->status_flags = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_NORMAL);
#endif /* ENABLED (JERRY_ESNEXT) */
#if ENABLED (JERRY_ESNEXT)
if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
@@ -1396,13 +1391,13 @@ parser_post_processing (parser_context_t *context_p) /**< context */
compiled_code_p->status_flags |= CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED;
}
#if ENABLED (JERRY_ESNEXT)
uint16_t function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_NORMAL);
if (context_p->status_flags & (PARSER_IS_PROPERTY_GETTER | PARSER_IS_PROPERTY_SETTER))
{
function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ACCESSOR);
}
#if ENABLED (JERRY_ESNEXT)
else if (context_p->status_flags & PARSER_IS_ARROW_FUNCTION)
{
if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)
@@ -1442,8 +1437,6 @@ parser_post_processing (parser_context_t *context_p) /**< context */
function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_NORMAL);
}
compiled_code_p->status_flags |= function_type;
if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
{
compiled_code_p->status_flags |= CBC_CODE_FLAGS_REST_PARAMETER;
@@ -1461,6 +1454,8 @@ parser_post_processing (parser_context_t *context_p) /**< context */
}
#endif /* ENABLED (JERRY_ESNEXT) */
compiled_code_p->status_flags |= function_type;
literal_pool_p = ((ecma_value_t *) byte_code_p) - context_p->register_count;
byte_code_p += literal_length;
dst_p = byte_code_p;