Fix minor implementation issues found in the JerryScript API.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2016-07-20 01:54:00 -07:00
parent 8d69e26e75
commit 12916c6c55
4 changed files with 127 additions and 104 deletions
+18 -14
View File
@@ -379,7 +379,8 @@ jerry_run_simple (const jerry_char_t *script_source,
**Summary**
Parse specified script to execute in Global scope.
Parse script and construct an EcmaScript function. The
lexical environment is set to the global lexical environment.
*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
@@ -425,7 +426,7 @@ jerry_parse (const jerry_char_t *source_p,
**Summary**
Run code in Global scope.
Run an EcmaScript function created by jerry_parse.
*Note*: The code should be previously parsed with `jerry_parse`.
@@ -1102,7 +1103,7 @@ jerry_get_number_value (const jerry_value_t value);
**Summary**
Get the size of a string. Returns zero, if the specified string is not a value.
Get the size of a string. Returns zero, if the value parameter is not a string.
**Prototype**
@@ -1138,7 +1139,7 @@ jerry_get_string_size (const jerry_value_t value);
**Summary**
Get the length of a string. Returns zero, if the specified string is not a value.
Get the length of a string. Returns zero, if the value parameter is not a string.
**Prototype**
@@ -1175,10 +1176,10 @@ jerry_get_string_length (const jerry_value_t value);
**Summary**
Copy string characters to specified buffer. It is the caller's responsibility to make sure that
the string fits in the buffer.
*Note*: '\0' could occur in characters.
Copy the characters of a string into a specified buffer. The
'\0' character could occur in character buffer. Returns 0,
if the value parameter is not a string or the buffer is
not large enough for the whole string.
**Prototype**
@@ -1933,7 +1934,7 @@ jerry_create_undefined (void);
**Summary**
Checks whether the object or it's prototype has the given property.
Checks whether the object or it's prototype objects have the given property.
**Prototype**
@@ -2436,7 +2437,8 @@ jerry_free_property_descriptor_fields (const jerry_property_descriptor_t *prop_d
**Summary**
Call function specified by a function value.
Call function specified by a function value. Error flag
must not be set for any arguments of this function.
*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
@@ -2492,6 +2494,7 @@ jerry_call_function (const jerry_value_t func_obj_val,
**Summary**
Construct object, invoking specified function object as constructor.
Error flag must not be set for any arguments of this function.
*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
@@ -2704,13 +2707,14 @@ jerry_get_object_native_handle (const jerry_value_t obj_val,
**Summary**
Set native handle and, optionally, free callback for the specified object
Set native handle and an optional free callback for the specified object
*Note*: If native handle was already set for the object, its value is updated.
*Note*: If free callback is specified, it is set to be called upon specified JS-object is freed (by GC).
Otherwise, if NULL is specified for free callback pointer, free callback is not created and, if
a free callback was added earlier for the object, it is removed.
*Note*: If a non-NULL free callback is specified, it will be called
by the garbage collector when the object is freed. The free
callback always overwrites the previous value, so passing
a NULL value deletes the current free callback.
**Prototype**
+1 -2
View File
@@ -70,14 +70,13 @@ ecma_finalize_environment (void)
/**
* Get reference to Global lexical environment
* without increasing its reference count.
*
* @return pointer to the object's instance
*/
ecma_object_t *
ecma_get_global_environment (void)
{
ecma_ref_object (ecma_global_lex_env_p);
return ecma_global_lex_env_p;
} /* ecma_get_global_environment */
+104 -80
View File
@@ -88,18 +88,20 @@ static const char *wrong_args_msg_p = "wrong type of argument";
* While, API can be invoked jerry_api_available flag is set,
* and while it is incorrect to invoke API - it is not set.
*
* The procedure checks that it is correct to invoke API in current state.
* If it is correct, procedure just returns; otherwise - engine is stopped.
* This procedure checks whether the API is available, and terminates
* the engine if it is unavailable. Otherwise it is a no-op.
*
* Note:
* API could not be invoked in the following cases:
* - between enter to and return from native free callback.
* The API could not be invoked in the following cases:
* - before jerry_init and after jerry_cleanup
* - between enter to and return from a native free callback
*/
static inline void __attr_always_inline___
jerry_assert_api_available (void)
{
if (!jerry_api_available)
if (unlikely (!jerry_api_available))
{
/* Terminates the execution. */
JERRY_UNREACHABLE ();
}
} /* jerry_assert_api_available */
@@ -140,6 +142,12 @@ jerry_create_type_error (void)
void
jerry_init (jerry_init_flag_t flags) /**< combination of Jerry flags */
{
if (unlikely (jerry_api_available))
{
/* This function cannot be called twice unless jerry_cleanup is called. */
JERRY_UNREACHABLE ();
}
if (flags & (JERRY_INIT_ENABLE_LOG))
{
#ifndef JERRY_ENABLE_LOG
@@ -177,10 +185,9 @@ jerry_cleanup (void)
{
jerry_assert_api_available ();
bool is_show_mem_stats = ((jerry_init_flags & JERRY_INIT_MEM_STATS) != 0);
jerry_make_api_unavailable ();
ecma_finalize ();
jmem_finalize (is_show_mem_stats);
jmem_finalize ((jerry_init_flags & JERRY_INIT_MEM_STATS) != 0);
} /* jerry_cleanup */
/**
@@ -190,8 +197,10 @@ void
jerry_register_magic_strings (const jerry_char_ptr_t *ex_str_items, /**< character arrays, representing
* external magic strings' contents */
uint32_t count, /**< number of the strings */
const jerry_length_t *str_lengths) /**< lengths of the strings */
const jerry_length_t *str_lengths) /**< lengths of all strings */
{
jerry_assert_api_available ();
lit_magic_strings_ex_set ((const lit_utf8_byte_t **) ex_str_items, count, (const lit_utf8_size_t *) str_lengths);
} /* jerry_register_magic_strings */
@@ -254,7 +263,8 @@ jerry_run_simple (const jerry_char_t *script_source, /**< script source */
} /* jerry_run_simple */
/**
* Parse script for specified context
* Parse script and construct an EcmaScript function. The lexical
* environment is set to the global lexical environment.
*
* @return function object value - if script was parsed successfully,
* thrown error - otherwise
@@ -296,14 +306,13 @@ jerry_parse (const jerry_char_t *source_p, /**< script source */
ecma_object_t *func_obj_p = ecma_op_create_function_object (lex_env_p,
is_strict,
bytecode_data_p);
ecma_deref_object (lex_env_p);
ecma_bytecode_deref (bytecode_data_p);
return ecma_make_object_value (func_obj_p);
} /* jerry_parse */
/**
* Run Jerry in specified run context
* Run an EcmaScript function created by jerry_parse.
*
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
@@ -330,6 +339,15 @@ jerry_run (const jerry_value_t func_val) /**< function to run */
}
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p;
ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
ext_func_p->u.function.scope_cp);
if (scope_p != ecma_get_global_environment ())
{
return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
}
const ecma_compiled_code_t *bytecode_data_p;
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
ext_func_p->u.function.bytecode_cp);
@@ -912,7 +930,7 @@ jerry_create_undefined (void)
* Get length of an array object
*
* Note:
* Returns 0, if the given parameter is not an array object.
* Returns 0, if the value parameter is not an array object.
*
* @return length of the given array
*/
@@ -921,8 +939,7 @@ jerry_get_array_length (const jerry_value_t value)
{
jerry_assert_api_available ();
if (!jerry_value_is_array (value)
|| ECMA_IS_VALUE_ERROR (value))
if (!jerry_value_is_array (value))
{
return 0;
}
@@ -943,6 +960,9 @@ jerry_get_array_length (const jerry_value_t value)
/**
* Get size of Jerry string
*
* Note:
* Returns 0, if the value parameter is not a string.
*
* @return number of bytes in the buffer needed to represent the string
*/
jerry_size_t
@@ -961,6 +981,9 @@ jerry_get_string_size (const jerry_value_t value) /**< input string */
/**
* Get length of Jerry string
*
* Note:
* Returns 0, if the value parameter is not a string.
*
* @return number of characters in the string
*/
jerry_length_t
@@ -977,11 +1000,12 @@ jerry_get_string_length (const jerry_value_t value) /**< input string */
} /* jerry_get_string_length */
/**
* Copy string characters to specified buffer. It is the caller's responsibility
* to make sure that the string fits in the buffer.
* Copy the characters of a string into a specified buffer.
*
* Note:
* '\0' could occur in character buffer.
* The '\0' character could occur in character buffer.
* Returns 0, if the value parameter is not a string or
* the buffer is not large enough for the whole string.
*
* @return number of bytes, actually copied to the buffer.
*/
@@ -1010,7 +1034,7 @@ jerry_string_to_char_buffer (const jerry_value_t value, /**< input string value
} /* jerry_string_to_char_buffer */
/**
* Checks whether the object or it's prototype has the given property.
* Checks whether the object or it's prototype objects have the given property.
*
* @return true - if the property exists
* false - otherwise
@@ -1088,8 +1112,8 @@ jerry_delete_property (const jerry_value_t obj_val, /**< object value */
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
*
* @return value of property - if success
* thrown error - otherwise
* @return value of the property - if success
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_get_property (const jerry_value_t obj_val, /**< object value */
@@ -1113,8 +1137,8 @@ jerry_get_property (const jerry_value_t obj_val, /**< object value */
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
*
* @return stored value on the specified index - if success
* thrown exception - otherwise.
* @return value of the property specified by the index - if success
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_get_property_by_index (const jerry_value_t obj_val, /**< object value */
@@ -1140,8 +1164,8 @@ jerry_get_property_by_index (const jerry_value_t obj_val, /**< object value */
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
*
* @return true - if success
* thrown error - otherwise
* @return true value - if the operation was successful
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_set_property (const jerry_value_t obj_val, /**< object value */
@@ -1169,8 +1193,8 @@ jerry_set_property (const jerry_value_t obj_val, /**< object value */
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
*
* @return true - if field value was set successfully
* thrown exception - otherwise
* @return true value - if the operation was successful
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_set_property_by_index (const jerry_value_t obj_val, /**< object value */
@@ -1199,7 +1223,7 @@ jerry_set_property_by_index (const jerry_value_t obj_val, /**< object value */
* Initialize property descriptor.
*/
void
jerry_init_property_descriptor_fields (jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */
jerry_init_property_descriptor_fields (jerry_property_descriptor_t *prop_desc_p) /**< [out] property descriptor */
{
prop_desc_p->is_value_defined = false;
prop_desc_p->value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
@@ -1221,8 +1245,8 @@ jerry_init_property_descriptor_fields (jerry_property_descriptor_t *prop_desc_p)
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
*
* @return true - if success
* thrown error - otherwise
* @return true value - if the operation was successful
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_define_own_property (const jerry_value_t obj_val, /**< object value */
@@ -1256,6 +1280,11 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */
if (prop_desc_p->is_value_defined)
{
if (ECMA_IS_VALUE_ERROR (prop_desc_p->value))
{
return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
}
prop_desc.value = prop_desc_p->value;
}
@@ -1268,6 +1297,11 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */
ecma_value_t getter = prop_desc_p->getter;
prop_desc.is_get_defined = true;
if (ECMA_IS_VALUE_ERROR (getter))
{
return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
}
if (ecma_op_is_callable (getter))
{
prop_desc.get_p = ecma_get_object_from_value (getter);
@@ -1283,6 +1317,11 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */
ecma_value_t setter = prop_desc_p->setter;
prop_desc.is_set_defined = true;
if (ECMA_IS_VALUE_ERROR (setter))
{
return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
}
if (ecma_op_is_callable (setter))
{
prop_desc.set_p = ecma_get_object_from_value (setter);
@@ -1315,7 +1354,7 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object val
if (!ecma_is_value_object (obj_val)
|| !ecma_is_value_string (prop_name_val))
{
return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
return false;
}
ecma_property_t *property_p = ecma_op_object_get_property (ecma_get_object_from_value (obj_val),
@@ -1333,18 +1372,23 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object val
prop_desc_p->is_enumerable_defined = true;
prop_desc_p->is_enumerable = prop_desc.is_enumerable;
prop_desc_p->is_writable = prop_desc.is_writable;
prop_desc_p->is_writable_defined = prop_desc.is_writable_defined;
prop_desc_p->is_value_defined = prop_desc.is_value_defined;
prop_desc_p->value = prop_desc.value;
prop_desc_p->is_writable = prop_desc.is_writable_defined ? prop_desc.is_writable : false;
prop_desc_p->is_value_defined = prop_desc.is_value_defined;
prop_desc_p->is_get_defined = prop_desc.is_get_defined;
prop_desc_p->is_set_defined = prop_desc.is_set_defined;
prop_desc_p->value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
prop_desc_p->getter = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
prop_desc_p->setter = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
if (prop_desc_p->is_get_defined)
if (prop_desc.is_value_defined)
{
prop_desc_p->value = prop_desc.value;
}
if (prop_desc.is_get_defined)
{
if (prop_desc.get_p != NULL)
{
@@ -1356,7 +1400,7 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object val
}
}
if (prop_desc_p->is_set_defined)
if (prop_desc.is_set_defined)
{
if (prop_desc.set_p != NULL)
{
@@ -1419,12 +1463,6 @@ jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke functio
{
return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p));
}
else if (!ecma_is_value_object (func_obj_val)
|| (!ecma_is_value_object (this_val)
&& !ecma_is_value_undefined (this_val)))
{
return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
}
for (uint32_t i = 0; i < args_count; i++)
{
@@ -1439,17 +1477,17 @@ jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke functio
JERRY_ASSERT (jerry_value_is_constructor (func_obj_val));
return ecma_op_function_construct (ecma_get_object_from_value (func_obj_val),
args_p,
args_count);
args_p,
args_count);
}
else
{
JERRY_ASSERT (jerry_value_is_function (func_obj_val));
return ecma_op_function_call (ecma_get_object_from_value (func_obj_val),
this_val,
args_p,
args_count);
this_val,
args_p,
args_count);
}
} /* jerry_invoke_function */
@@ -1458,6 +1496,7 @@ jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke functio
*
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
* error flag must not be set for any arguments of this function.
*
* @return returned jerry value of the called function
*/
@@ -1482,6 +1521,7 @@ jerry_call_function (const jerry_value_t func_obj_val, /**< function object to c
*
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
* error flag must not be set for any arguments of this function.
*
* @return returned jerry value of the invoked constructor
*/
@@ -1509,7 +1549,7 @@ jerry_construct_object (const jerry_value_t func_obj_val, /**< function object t
* returned value must be freed with jerry_release_value, when it is no longer needed.
*
* @return array object value - if success
* thrown error - otherwise
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_get_object_keys (const jerry_value_t obj_val) /**< object value */
@@ -1527,8 +1567,8 @@ jerry_get_object_keys (const jerry_value_t obj_val) /**< object value */
/**
* Get the prototype of the specified object
*
* @return object value - if success
* null or thrown error - otherwise
* @return prototype object or null value - if success
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_get_prototype (const jerry_value_t obj_val) /**< object value */
@@ -1553,8 +1593,8 @@ jerry_get_prototype (const jerry_value_t obj_val) /**< object value */
/**
* Set the prototype of the specified object
*
* @return true - if success
* thrown error - otherwise
* @return true value - if success
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_set_prototype (const jerry_value_t obj_val, /**< object value */
@@ -1562,8 +1602,8 @@ jerry_set_prototype (const jerry_value_t obj_val, /**< object value */
{
jerry_assert_api_available ();
if (ECMA_IS_VALUE_ERROR (proto_obj_val)
|| !ecma_is_value_object (obj_val)
if (!ecma_is_value_object (obj_val)
|| ECMA_IS_VALUE_ERROR (proto_obj_val)
|| (!ecma_is_value_object (proto_obj_val) && !ecma_is_value_null (proto_obj_val)))
{
return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
@@ -1585,7 +1625,7 @@ jerry_set_prototype (const jerry_value_t obj_val, /**< object value */
/**
* Get native handle, associated with specified object
*
* @return true - if there is associated handle (handle is returned through out_handle_p),
* @return true - if there is an associated handle (handle is returned through out_handle_p),
* false - otherwise.
*/
bool
@@ -1594,11 +1634,6 @@ jerry_get_object_native_handle (const jerry_value_t obj_val, /**< object to get
{
jerry_assert_api_available ();
if (ECMA_IS_VALUE_ERROR (obj_val))
{
return false;
}
uintptr_t handle_value;
bool does_exist = ecma_get_external_pointer_value (ecma_get_object_from_value (obj_val),
@@ -1614,16 +1649,16 @@ jerry_get_object_native_handle (const jerry_value_t obj_val, /**< object to get
} /* jerry_get_object_native_handle */
/**
* Set native handle and, optionally, free callback for the specified object
* Set native handle and an optional free callback for the specified object
*
* Note:
* If native handle was already set for the object, its value is updated.
*
* Note:
* If free callback is specified, it is set to be called upon specified JS-object is freed (by GC).
*
* Otherwise, if NULL is specified for free callback pointer, free callback is not created
* and, if a free callback was added earlier for the object, it is removed.
* If a non-NULL free callback is specified, it will be called
* by the garbage collector when the object is freed. The free
* callback always overwrites the previous value, so passing
* a NULL value deletes the current free callback.
*/
void
jerry_set_object_native_handle (const jerry_value_t obj_val, /**< object to set handle in */
@@ -1632,16 +1667,12 @@ jerry_set_object_native_handle (const jerry_value_t obj_val, /**< object to set
{
jerry_assert_api_available ();
if (ECMA_IS_VALUE_ERROR (obj_val))
{
return;
}
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
ecma_create_external_pointer_property (object_p,
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE,
handle);
if (freecb_p != NULL)
{
ecma_create_external_pointer_property (object_p,
@@ -1675,11 +1706,6 @@ jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */
{
jerry_assert_api_available ();
if (ECMA_IS_VALUE_ERROR (obj_val))
{
return false;
}
ecma_collection_iterator_t names_iter;
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
ecma_collection_header_t *names_p = ecma_op_object_get_property_names (object_p, false, true, true);
@@ -1710,11 +1736,9 @@ jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */
{
return true;
}
else
{
ecma_free_value (property_value);
return false;
}
ecma_free_value (property_value);
return false;
} /* jerry_foreach_object_property */
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
+4 -8
View File
@@ -213,18 +213,15 @@ ecma_value_t
vm_run_global (const ecma_compiled_code_t *bytecode_p) /**< pointer to bytecode to run */
{
ecma_object_t *glob_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL);
ecma_object_t *lex_env_p = ecma_get_global_environment ();
ecma_value_t ret_value = vm_run (bytecode_p,
ecma_make_object_value (glob_obj_p),
lex_env_p,
ecma_get_global_environment (),
false,
NULL,
0);
ecma_deref_object (glob_obj_p);
ecma_deref_object (lex_env_p);
return ret_value;
} /* vm_run_global */
@@ -237,8 +234,6 @@ ecma_value_t
vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */
bool is_direct) /**< is eval called in direct mode? */
{
bool is_strict = ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0);
ecma_value_t this_binding;
ecma_object_t *lex_env_p;
@@ -247,7 +242,6 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */
{
this_binding = ecma_copy_value (vm_top_context_p->this_binding);
lex_env_p = vm_top_context_p->lex_env_p;
ecma_ref_object (vm_top_context_p->lex_env_p);
}
else
{
@@ -255,7 +249,9 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */
lex_env_p = ecma_get_global_environment ();
}
if (is_strict)
ecma_ref_object (lex_env_p);
if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0)
{
ecma_object_t *strict_lex_env_p = ecma_create_decl_lex_env (lex_env_p);
ecma_deref_object (lex_env_p);