diff --git a/docs/03.API-EXAMPLE.md b/docs/03.API-EXAMPLE.md index 3ecb6fc5e0..cb9a221abd 100644 --- a/docs/03.API-EXAMPLE.md +++ b/docs/03.API-EXAMPLE.md @@ -6,7 +6,7 @@ This guide is intended to introduce you to JerryScript embedding API through cre ```c #include -#include "jerry.h" +#include "jerry-api.h" int main (int argc, char * argv[]) @@ -14,11 +14,9 @@ main (int argc, char * argv[]) const jerry_char_t script[] = "print ('Hello, World!');"; size_t script_size = strlen ((const char *) script); - jerry_completion_code_t return_code = jerry_run_simple (script, - script_size, - JERRY_FLAG_EMPTY); + bool ret_value = jerry_run_simple (script, script_size, JERRY_INIT_EMPTY); - return (int) return_code; + return (ret_value ? 1 : 0); } ``` @@ -40,7 +38,7 @@ Here we perform the same actions, as `jerry_run_simple`, while splitting into se ```c #include -#include "jerry.h" +#include "jerry-api.h" int main (int argc, char * argv[]) @@ -49,28 +47,23 @@ main (int argc, char * argv[]) size_t script_size = strlen ((const char *) script); /* Initialize engine */ - jerry_init (JERRY_FLAG_EMPTY); + jerry_init (JERRY_INIT_EMPTY); /* Setup Global scope code */ - jerry_object_t *error_object_p = NULL; - if (!jerry_parse (script, script_size, &error_object_p)) - { - /* Error object must be freed, if parsing failed */ - jerry_release_object (error_object_p); - } - else + jerry_value_t parsed_code = jerry_parse (script, script_size, false); + + if (!jerry_value_has_error_flag (parsed_code)) { - /* Execute Global scope code */ - jerry_value_t error_value = jerry_create_undefined_value (); - jerry_completion_code_t return_code = jerry_run (&error_value); + /* Execute the parsed source code in the Global scope */ + jerry_value_t ret_value = jerry_run (parsed_code); - if (return_code == JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION) - { - /* Error value must be freed, if 'jerry_run' returns with an unhandled exception */ - jerry_release_value (error_value); - } + /* Returned value must be freed */ + jerry_release_value (ret_value); } + /* Parsed source code must be freed */ + jerry_release_value (parsed_code); + /* Cleanup engine */ jerry_cleanup (); @@ -84,7 +77,7 @@ Our code is more complex now, but it introduces possibilities to interact with J ```c #include -#include "jerry.h" +#include "jerry-api.h" int main (int argc, char * argv[]) @@ -93,26 +86,22 @@ main (int argc, char * argv[]) const jerry_char_t script_2[] = "print (s);"; /* Initialize engine */ - jerry_init (JERRY_FLAG_EMPTY); + jerry_init (JERRY_INIT_EMPTY); jerry_value_t eval_ret; /* Evaluate script1 */ - jerry_eval (script_1, - strlen ((const char *) script_1), - false, - false, - &eval_ret); + eval_ret = jerry_eval (script_1, + strlen ((const char *) script_1), + false); /* Free JavaScript value, returned by eval */ jerry_release_value (eval_ret); /* Evaluate script2 */ - jerry_eval (script_2, - strlen ((const char *) script_2), - false, - false, - &eval_ret); + eval_ret = jerry_eval (script_2, + strlen ((const char *) script_2), + false); /* Free JavaScript value, returned by eval */ jerry_release_value (eval_ret); @@ -130,43 +119,37 @@ This way, we execute two independent script parts in one execution environment. ```c #include -#include "jerry.h" +#include "jerry-api.h" int main (int argc, char * argv[]) { const jerry_char_t str[] = "Hello, World!"; - const jerry_char_t var_name[] = "s"; const jerry_char_t script[] = "print (s);"; /* Initializing JavaScript environment */ - jerry_init (JERRY_FLAG_EMPTY); + jerry_init (JERRY_INIT_EMPTY); /* Getting pointer to the Global object */ - jerry_object_t *object_p = jerry_get_global (); + jerry_value_t global_object = jerry_get_global_object (); - /* Constructing string */ - jerry_string_t *str_val_p = jerry_create_string (str); + /* Constructing strings */ + jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "s"); + jerry_value_t prop_value = jerry_create_string (str); - /* Constructing string value descriptor */ - jerry_value_t value = jerry_create_string_value (str_val_p); + /* Setting the string value as a property of the Global object */ + jerry_set_property (global_object, prop_name, prop_value); - /* Setting the string value to field of the Global object */ - jerry_set_object_field_value (object_p, var_name, value); + /* Releasing string values, as it is no longer necessary outside of engine */ + jerry_release_value (prop_name); + jerry_release_value (prop_value); - /* Releasing string value, as it is no longer necessary outside of engine */ - jerry_release_string (str_val_p); - - /* Same for pointer to the Global object */ - jerry_release_object (object_p); - - jerry_value_t eval_ret; + /* Releasing the Global object */ + jerry_release_value (global_object); /* Now starting script that would output value of just initialized field */ - jerry_eval (script, - strlen ((const char *) script), - false, - false, - &eval_ret); + jerry_value_t eval_ret = jerry_eval (script, + strlen ((const char *) script), + false); /* Free JavaScript value, returned by eval */ jerry_release_value (eval_ret); @@ -180,36 +163,23 @@ main (int argc, char * argv[]) { The sample will also output 'Hello, World!'. However, now it is not just a part of the source script, but the value, dynamically supplied to the engine. -## Step 5. Description of JavaScript value descriptors - -Structure, used to put values to or receive values from the engine is the following: - -- `type` of the value: - - JERRY_API_DATA_TYPE_VOID (void); - - JERRY_API_DATA_TYPE_UNDEFINED (undefined); - - JERRY_API_DATA_TYPE_NULL (null); - - JERRY_API_DATA_TYPE_BOOLEAN (true / false); - - JERRY_API_DATA_TYPE_FLOAT32 (number); - - JERRY_API_DATA_TYPE_FLOAT64 (number); - - JERRY_API_DATA_TYPE_UINT32 (number); - - JERRY_API_DATA_TYPE_STRING (string); - - JERRY_API_DATA_TYPE_OBJECT (object reference); -- `v_bool` (if JERRY_API_DATA_TYPE_BOOLEAN) - boolean value; -- `v_float32` (if JERRY_API_DATA_TYPE_FLOAT32) - float value; -- `v_float64` (if JERRY_API_DATA_TYPE_FLOAT64) - double value; -- `v_uint32` (if JERRY_API_DATA_TYPE_UINT32) - 32 bit unsigned integer value; -- `v_string` (if JERRY_API_DATA_TYPE_STRING) - pointer to string; -- `v_object` (if JERRY_API_DATA_TYPE_OBJECT) - pointer to object. - -Abstract values, to be sent to or received from the engine are described with the structure. +## Step 5. Description of JerryScript value descriptors -Pointers to strings or objects and values should be released just when become unnecessary, using `jerry_release_string` or `jerry_release_object` and `jerry_release_value`, correspondingly. +JerryScript value can be a boolean, number, null, object, string or undefined. The value has an error flag, +that indicates whether is an error or not. Every type has an error flag not only objects. The error flag should +be cleared before the value is passed as an argument, otherwise it can lead to a type error. The error objects +created by API functions has the error flag set. The following example function will output a JavaScript value: ```c #include +#include + +#include "jerry-api.h" +#include "jerry-port.h" +static void print_value (const jerry_value_t value) { if (jerry_value_is_undefined (value)) @@ -240,11 +210,10 @@ print_value (const jerry_value_t value) else if (jerry_value_is_string (value)) { /* Determining required buffer size */ - jerry_string_t *str_p = jerry_get_string_value (value); - jerry_size_t req_sz = jerry_get_string_size (str_p); + jerry_size_t req_sz = jerry_get_string_size (value); jerry_char_t str_buf_p[req_sz]; - jerry_string_to_char_buffer (str_p, str_buf_p, req_sz); + jerry_string_to_char_buffer (value, str_buf_p, req_sz); jerry_port_logmsg (stdout, "%s", (const char *) str_buf_p); } @@ -273,22 +242,21 @@ Shell operation can be described with the following loop: - loop. ```c -#include #include #include -#include "jerry.h" +#include "jerry-api.h" +#include "jerry-port.h" static void print_value (const jerry_api_value_t); int main (int argc, char * argv[]) { - jerry_completion_code_t status = JERRY_COMPLETION_CODE_OK; bool is_done = false; /* Initialize engine */ - jerry_init (JERRY_FLAG_EMPTY); + jerry_init (JERRY_INIT_EMPTY); while (!is_done) { @@ -318,33 +286,26 @@ main (int argc, char * argv[]) jerry_value_t ret_val; /* Evaluate entered command */ - status = jerry_eval ((const jerry_char_t *) cmd, - len, - false, - false, - &ret_val); + ret_val = jerry_eval ((const jerry_char_t *) cmd, + len, + false); /* If command evaluated successfully, print value, returned by eval */ - if (status == JERRY_COMPLETION_CODE_OK) - { - /* 'eval' completed successfully */ - print_value (ret_val); - } - else + if (jerry_value_has_error_flag (ret_val)) { /* Evaluated JS code thrown an exception * and didn't handle it with try-catch-finally */ jerry_port_errormsg ("Unhandled JS exception occured: "); - print_value (ret_val); } + print_value (ret_val); jerry_release_value (ret_val); } /* Cleanup engine */ jerry_cleanup (); - return (int) status; + return 0; } ``` @@ -356,7 +317,7 @@ In this example we demonstrate how to use native function and structures in Java ```c #include -#include "jerry.h" +#include "jerry-api.h" struct my_struct { @@ -366,53 +327,45 @@ struct my_struct /** * Get a string from a native object */ -static bool -get_msg_handler (const jerry_object_t *function_obj_p, /**< function object */ - const jerry_value_t this_p, /**< this arg */ +static jerry_value_t +get_msg_handler (const jerry_value_t func_value, /**< function object */ + const jerry_value_t this_value, /**< this arg */ const jerry_value_t *args_p, /**< function arguments */ - const jerry_length_t args_cnt, /**< number of function arguments */ - jerry_value_t *ret_val_p) /**< [out] return argument */ + const jerry_length_t args_cnt) /**< number of function arguments */ { - jerry_string_t *msg_str_p = jerry_create_string ((const jerry_char_t *) my_struct.msg); - *ret_val_p = jerry_create_string_value (msg_str_p); - - return true; + return jerry_create_string ((const jerry_char_t *) my_struct.msg); } /* get_msg_handler */ int main (int argc, char * argv[]) { - jerry_completion_code_t status = JERRY_COMPLETION_CODE_OK; - /* Initialize engine */ - jerry_init (JERRY_FLAG_EMPTY); + jerry_init (JERRY_INIT_EMPTY); /* Do something with the native object */ my_struct.msg = "Hello World"; /* Create an empty JS object */ - jerry_object_t *object_p = jerry_create_object (); + jerry_value_t object = jerry_create_object (); /* Create a JS function object and wrap into a jerry value */ - jerry_object_t *func_obj_p = jerry_create_external_function (get_msg_handler); - jerry_value_t object_value = jerry_create_object_value (func_obj_p); + jerry_value_t func_obj = jerry_create_external_function (get_msg_handler); /* Set the native function as a property of the empty JS object */ - jerry_set_object_field_value (object_p, - (const jerry_char_t *) "myFunc", - object_value); - jerry_release_value (object_value); + jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "myFunc"); + jerry_set_property (object, prop_name, func_obj); + jerry_release_value (prop_name); + jerry_release_value (func_obj); /* Wrap the JS object (not empty anymore) into a jerry api value */ - object_value = jerry_create_object_value (object_p); - jerry_object_t *global_obj_p = jerry_get_global (); + jerry_value_t global_object = jerry_get_global_object (); /* Add the JS object to the global context */ - jerry_set_object_field_value (global_obj_p, - (const jerry_char_t *) "MyObject", - object_value); - jerry_release_value (object_value); - jerry_release_object (global_obj_p); + prop_name = jerry_create_string ((const jerry_char_t *) "MyObject"); + jerry_set_property (global_object, prop_name, object); + jerry_release_value (prop_name); + jerry_release_value (object); + jerry_release_value (global_object); /* Now we have a "builtin" object called MyObject with a function called myFunc() * @@ -425,14 +378,8 @@ main (int argc, char * argv[]) "; size_t script_size = strlen ((const char *) script); - jerry_value_t eval_ret; - /* Evaluate script */ - status = jerry_eval (script, - script_size, - false, - false, - &eval_ret); + jerry_value_t eval_ret = jerry_eval (script, script_size, false); /* Free JavaScript value, returned by eval */ jerry_release_value (eval_ret); @@ -440,7 +387,7 @@ main (int argc, char * argv[]) /* Cleanup engine */ jerry_cleanup (); - return (int) status; + return 0; } ``` @@ -456,48 +403,46 @@ Here we create a JS Object with `jerry_eval`, then extend it with a native funct ```c #include -#include "jerry.h" +#include "jerry-api.h" /** * Add param to 'this.x' */ -static bool -add_handler (const jerry_object_t *function_obj_p, /**< function object */ - const jerry_value_t this_p, /**< this arg */ +static jerry_value_t +add_handler (const jerry_value_t func_value, /**< function object */ + const jerry_value_t this_val, /**< this arg */ const jerry_value_t *args_p, /**< function arguments */ - const jerry_length_t args_cnt, /**< number of function arguments */ - jerry_value_t *ret_val_p) /**< [out] return argument */ + const jerry_length_t args_cnt) /**< number of function arguments */ { /* Get 'this.x' */ - jerry_value_t x_val = jerry_get_object_field_value (jerry_get_object_value (this_p), - (const jerry_char_t *) "x"); + jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "x"); + jerry_value_t x_val = jerry_get_property (this_val, prop_name); - - if (!jerry_value_is_error (x_val)) + if (!jerry_value_has_error_flag (x_val)) { /* Convert Jerry API values to double */ double x = jerry_get_number_value (x_val); double d = jerry_get_number_value (*args_p); /* Add the parameter to 'x' */ - jerry_value_t res_val = jerry_create_number_value (x + d); + jerry_value_t res_val = jerry_create_number (x + d); /* Set the new value of 'this.x' */ - jerry_set_object_field_value (jerry_get_object_value (this_p), - (const jerry_char_t *) "x", - res_val); + jerry_set_property (this_val, prop_name, res_val); + jerry_release_value (res_val); } - return true; + jerry_release_value (x_val); + jerry_release_value (prop_name); + + return jerry_create_undefined (); } /* add_handler */ int main (int argc, char * argv[]) { - jerry_completion_code_t status = JERRY_COMPLETION_CODE_OK; - /* Initialize engine */ - jerry_init (JERRY_FLAG_EMPTY); + jerry_init (JERRY_INIT_EMPTY); /* Create a JS object */ const jerry_char_t my_js_object[] = " \ @@ -514,23 +459,18 @@ main (int argc, char * argv[]) jerry_value_t my_js_obj_val; /* Evaluate script */ - status = jerry_eval (my_js_object, - strlen ((const char *) my_js_object), - false, - false, - &my_js_obj_val); - - jerry_object_t *object_p = jerry_get_object_value (my_js_obj_val); + my_js_obj_val = jerry_eval (my_js_object, + strlen ((const char *) my_js_object), + false); /* Create a JS function object and wrap into a jerry value */ - jerry_object_t *add_func_obj_p = jerry_create_external_function (add_handler); - jerry_value_t object_value = jerry_create_object_value (add_func_obj_p); + jerry_value_t add_func_obj = jerry_create_external_function (add_handler); /* Set the native function as a property of previously created MyObject */ - jerry_set_object_field_value (object_p, - (const jerry_char_t *) "add2x", - object_value); - jerry_release_value (object_value); + jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "add2x"); + jerry_set_property (my_js_obj_val, prop_name, add_func_obj); + jerry_release_value (add_func_obj); + jerry_release_value (prop_name); /* Free JavaScript value, returned by eval (my_js_object) */ jerry_release_value (my_js_obj_val); @@ -543,14 +483,8 @@ main (int argc, char * argv[]) "; size_t script_size = strlen ((const char *) script); - jerry_value_t eval_ret; - /* Evaluate script */ - status = jerry_eval (script, - script_size, - false, - false, - &eval_ret); + jerry_value_t eval_ret = jerry_eval (script, script_size, false); /* Free JavaScript value, returned by eval */ jerry_release_value (eval_ret); @@ -558,7 +492,7 @@ main (int argc, char * argv[]) /* Cleanup engine */ jerry_cleanup (); - return (int) status; + return 0; } ``` diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index a6fad1916b..1e7c28dce5 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -1,4 +1,5 @@ /* Copyright 2014-2016 Samsung Electronics Co., Ltd. + * Copyright 2016 University of Szeged. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -502,7 +503,7 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ } /* ecma_gc_sweep */ /** - * Run garbage collecting + * Run garbage collection */ void ecma_gc_run (void) diff --git a/jerry-core/ecma/operations/ecma-eval.c b/jerry-core/ecma/operations/ecma-eval.c index 5559138cd5..b4a8d0c19e 100644 --- a/jerry-core/ecma/operations/ecma-eval.c +++ b/jerry-core/ecma/operations/ecma-eval.c @@ -56,7 +56,7 @@ ecma_op_eval (ecma_string_t *code_p, /**< code string */ { ECMA_STRING_TO_UTF8_STRING (code_p, code_utf8_buffer_p, code_utf8_buffer_size); - ret_value = ecma_op_eval_chars_buffer ((jerry_char_t *) code_utf8_buffer_p, + ret_value = ecma_op_eval_chars_buffer (code_utf8_buffer_p, chars_num, is_direct, is_called_from_strict_mode_code); @@ -77,39 +77,28 @@ ecma_op_eval (ecma_string_t *code_p, /**< code string */ * @return ecma value */ ecma_value_t -ecma_op_eval_chars_buffer (const jerry_char_t *code_p, /**< code characters buffer */ +ecma_op_eval_chars_buffer (const lit_utf8_byte_t *code_p, /**< code characters buffer */ size_t code_buffer_size, /**< size of the buffer */ bool is_direct, /**< is eval called directly (ECMA-262 v5, 15.1.2.1.1) */ bool is_called_from_strict_mode_code) /**< is eval is called from strict mode code */ { JERRY_ASSERT (code_p != NULL); - ecma_value_t ret_value; - ecma_compiled_code_t *bytecode_data_p; - jsp_status_t parse_status; bool is_strict_call = (is_direct && is_called_from_strict_mode_code); - jerry_object_t *error_obj_p = NULL; - parse_status = parser_parse_eval (code_p, - code_buffer_size, - is_strict_call, - &bytecode_data_p, - &error_obj_p); + ecma_value_t parse_status = parser_parse_script (code_p, + code_buffer_size, + is_strict_call, + &bytecode_data_p); - if (parse_status == JSP_STATUS_OK) + if (ECMA_IS_VALUE_ERROR (parse_status)) { - ret_value = vm_run_eval (bytecode_data_p, is_direct); + return parse_status; } - else - { - JERRY_ASSERT (parse_status == JSP_STATUS_SYNTAX_ERROR); - ret_value = ecma_make_error_obj_value (error_obj_p); - } - - return ret_value; + return vm_run_eval (bytecode_data_p, is_direct); } /* ecma_op_eval_chars_buffer */ /** diff --git a/jerry-core/ecma/operations/ecma-eval.h b/jerry-core/ecma/operations/ecma-eval.h index ea60596270..0e9c5a2ed3 100644 --- a/jerry-core/ecma/operations/ecma-eval.h +++ b/jerry-core/ecma/operations/ecma-eval.h @@ -30,7 +30,7 @@ extern ecma_value_t ecma_op_eval (ecma_string_t *, bool, bool); extern ecma_value_t -ecma_op_eval_chars_buffer (const jerry_char_t *, size_t, bool, bool); +ecma_op_eval_chars_buffer (const lit_utf8_byte_t *, size_t, bool, bool); /** * @} diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 1be6df12b8..487da87c8e 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -1,4 +1,5 @@ /* Copyright 2014-2016 Samsung Electronics Co., Ltd. + * Copyright 2016 University of Szeged. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -277,8 +278,11 @@ ecma_op_object_put (ecma_object_t *obj_p, /**< the object */ * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * - * @return ecma value - * Returned value must be freed with ecma_free_value + * Note: + * returned value must be freed with ecma_free_value + * + * @return true, if deleted successfully + * false or type error otherwise (based in 'is_throw') */ ecma_value_t ecma_op_object_delete (ecma_object_t *obj_p, /**< the object */ @@ -315,7 +319,7 @@ ecma_op_object_delete (ecma_object_t *obj_p, /**< the object */ { JERRY_ASSERT (false); - return ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE); } } } /* ecma_op_object_delete */ diff --git a/jerry-core/jerry-api.h b/jerry-core/jerry-api.h index e3f14c76f0..2407747305 100644 --- a/jerry-core/jerry-api.h +++ b/jerry-core/jerry-api.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -32,15 +33,26 @@ extern "C" */ /** - * Jerry completion codes + * Major version of JerryScript API + */ +#define JERRY_API_MAJOR_VERSION 1 + +/** + * Minor version of JerryScript API + */ +#define JERRY_API_MINOR_VERSION 0 + +/** + * Jerry init flags */ typedef enum { - JERRY_COMPLETION_CODE_OK = 0, /**< successful completion */ - JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION = 1, /**< exception occured and it was not handled */ - JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_VERSION = 2, /**< snapshot version mismatch */ - JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_FORMAT = 3, /**< snapshot format is not valid */ -} jerry_completion_code_t; + JERRY_INIT_EMPTY = (0u), /**< empty flag set */ + JERRY_INIT_ENABLE_LOG = (1u << 0), /**< enable logging */ + JERRY_INIT_SHOW_OPCODES = (1u << 1), /**< dump byte-code to stdout after parse */ + JERRY_INIT_MEM_STATS = (1u << 2), /**< dump memory statistics */ + JERRY_INIT_MEM_STATS_SEPARATE = (1u << 3), /**< dump memory statistics and reset peak values after parse */ +} jerry_init_flag_t; /** * Jerry API Error object types @@ -77,28 +89,60 @@ typedef uint32_t jerry_size_t; typedef uint32_t jerry_length_t; /** - * Jerry's string value + * Description of a JerryScript value */ -typedef struct ecma_string_t jerry_string_t; +typedef uint32_t jerry_value_t; -/** - * Jerry's object value - */ -typedef struct ecma_object_t jerry_object_t; /** - * Description of a JerryScript value + * Description of ECMA property descriptor */ -typedef uint32_t jerry_value_t; +typedef struct +{ + /** Is [[Value]] defined? */ + bool is_value_defined; + + /** Is [[Get]] defined? */ + bool is_get_defined; + + /** Is [[Set]] defined? */ + bool is_set_defined; + + /** Is [[Writable]] defined? */ + bool is_writable_defined; + + /** [[Writable]] */ + bool is_writable; + + /** Is [[Enumerable]] defined? */ + bool is_enumerable_defined; + + /** [[Enumerable]] */ + bool is_enumerable; + + /** Is [[Configurable]] defined? */ + bool is_configurable_defined; + + /** [[Configurable]] */ + bool is_configurable; + + /** [[Value]] */ + jerry_value_t value; + + /** [[Get]] */ + jerry_value_t getter; + + /** [[Set]] */ + jerry_value_t setter; +} jerry_property_descriptor_t; /** * Type of an external function handler */ -typedef bool (*jerry_external_handler_t) (const jerry_object_t *function_obj_p, - const jerry_value_t this_val, - const jerry_value_t args_p[], - const jerry_length_t args_count, - jerry_value_t *ret_val_p); +typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_obj_p, + const jerry_value_t this_val, + const jerry_value_t args_p[], + const jerry_length_t args_count); /** * Native free callback of an object @@ -106,22 +150,49 @@ typedef bool (*jerry_external_handler_t) (const jerry_object_t *function_obj_p, typedef void (*jerry_object_free_callback_t) (const uintptr_t native_p); /** - * Function type applied for each fields in objects + * Function type applied for each data property of an object + */ +typedef bool (*jerry_object_property_foreach_t) (const jerry_value_t property_name_p, + const jerry_value_t property_value, + void *user_data_p); + + +/** + * Logger functions */ -typedef bool (*jerry_object_field_foreach_t) (const jerry_string_t *field_name_p, - const jerry_value_t field_value, - void *user_data_p); +#ifdef JERRY_ENABLE_LOG +extern int jerry_debug_level; +extern FILE *jerry_log_file; +#endif /* JERRY_ENABLE_LOG */ + +/** + * General engine functions + */ +void jerry_init (jerry_init_flag_t); +void jerry_cleanup (void); +void jerry_register_magic_strings (const jerry_char_ptr_t *, uint32_t, const jerry_length_t *); +void jerry_get_memory_limits (size_t *, size_t *); +void jerry_gc (void); + +/** + * Parser and executor functions + */ +bool jerry_run_simple (const jerry_char_t *, size_t, jerry_init_flag_t); +jerry_value_t jerry_parse (const jerry_char_t *, size_t, bool); +jerry_value_t jerry_run (const jerry_value_t); +jerry_value_t jerry_eval (const jerry_char_t *, size_t, bool); /** * Get the global context */ -jerry_object_t *jerry_get_global (void); +jerry_value_t jerry_get_global_object (void); /** * Checker functions of 'jerry_value_t' */ +bool jerry_value_is_array (const jerry_value_t); bool jerry_value_is_boolean (const jerry_value_t); -bool jerry_value_is_error (const jerry_value_t); +bool jerry_value_is_constructor (const jerry_value_t); bool jerry_value_is_function (const jerry_value_t); bool jerry_value_is_number (const jerry_value_t); bool jerry_value_is_null (const jerry_value_t); @@ -129,13 +200,30 @@ bool jerry_value_is_object (const jerry_value_t); bool jerry_value_is_string (const jerry_value_t); bool jerry_value_is_undefined (const jerry_value_t); +/** + * Error flag manipulation functions + */ +bool jerry_value_has_error_flag (const jerry_value_t); +void jerry_value_clear_error_flag (jerry_value_t *); +void jerry_value_set_error_flag (jerry_value_t *); + /** * Getter functions of 'jerry_value_t' */ bool jerry_get_boolean_value (const jerry_value_t); double jerry_get_number_value (const jerry_value_t); -jerry_string_t *jerry_get_string_value (const jerry_value_t); -jerry_object_t *jerry_get_object_value (const jerry_value_t); + +/** + * Functions for string values + */ +jerry_size_t jerry_get_string_size (const jerry_value_t); +jerry_length_t jerry_get_string_length (const jerry_value_t); +jerry_size_t jerry_string_to_char_buffer (const jerry_value_t, jerry_char_t *, jerry_size_t); + +/** + * Functions for array object values + */ +uint32_t jerry_get_array_length (const jerry_value_t); /** * Converters of 'jerry_value_t' @@ -143,75 +231,72 @@ jerry_object_t *jerry_get_object_value (const jerry_value_t); bool jerry_value_to_boolean (const jerry_value_t); jerry_value_t jerry_value_to_number (const jerry_value_t); jerry_value_t jerry_value_to_object (const jerry_value_t); +jerry_value_t jerry_value_to_primitive (const jerry_value_t); jerry_value_t jerry_value_to_string (const jerry_value_t); -jerry_value_t jerry_value_remove_error_flag (const jerry_value_t); - -/** - * Create functions of 'jerry_value_t' - */ -jerry_value_t jerry_create_null_value (void); -jerry_value_t jerry_create_undefined_value (void); -jerry_value_t jerry_create_boolean_value (bool); -jerry_value_t jerry_create_number_value (double); -jerry_value_t jerry_create_object_value (jerry_object_t *); -jerry_value_t jerry_create_string_value (jerry_string_t *); /** * Acquire types with reference counter (increase the references) */ -jerry_string_t *jerry_acquire_string (jerry_string_t *); -jerry_object_t *jerry_acquire_object (jerry_object_t *); jerry_value_t jerry_acquire_value (jerry_value_t); /** * Relase the referenced values */ -void jerry_release_object (jerry_object_t *); -void jerry_release_string (jerry_string_t *); void jerry_release_value (jerry_value_t); /** - * Create functions of API objects + * Create functions of API values */ -jerry_object_t *jerry_create_object (void); -jerry_object_t *jerry_create_array_object (jerry_size_t); -jerry_object_t *jerry_create_external_function (jerry_external_handler_t); -jerry_object_t *jerry_create_error (jerry_error_t, const jerry_char_t *); -jerry_object_t *jerry_create_error_sz (jerry_error_t, const jerry_char_t *, jerry_size_t); -jerry_string_t *jerry_create_string (const jerry_char_t *); -jerry_string_t *jerry_create_string_sz (const jerry_char_t *, jerry_size_t); +jerry_value_t jerry_create_array (uint32_t); +jerry_value_t jerry_create_boolean (bool); +jerry_value_t jerry_create_error (jerry_error_t, const jerry_char_t *); +jerry_value_t jerry_create_error_sz (jerry_error_t, const jerry_char_t *, jerry_size_t); +jerry_value_t jerry_create_external_function (jerry_external_handler_t); +jerry_value_t jerry_create_number (double); +jerry_value_t jerry_create_null (void); +jerry_value_t jerry_create_object (void); +jerry_value_t jerry_create_string (const jerry_char_t *); +jerry_value_t jerry_create_string_sz (const jerry_char_t *, jerry_size_t); +jerry_value_t jerry_create_undefined (void); /** - * Functions of array objects + * General API functions of JS objects */ -bool jerry_set_array_index_value (jerry_object_t *, jerry_length_t, jerry_value_t); -bool jerry_get_array_index_value (jerry_object_t *, jerry_length_t, jerry_value_t *); -uint32_t jerry_get_array_length (const jerry_object_t *); +bool jerry_has_property (const jerry_value_t, const jerry_value_t); +bool jerry_has_own_property (const jerry_value_t, const jerry_value_t); +bool jerry_delete_property (const jerry_value_t, const jerry_value_t); -/** - * Functions of 'jerry_string_t' - */ -jerry_size_t jerry_get_string_size (const jerry_string_t *); -jerry_length_t jerry_get_string_length (const jerry_string_t *); -jerry_size_t jerry_string_to_char_buffer (const jerry_string_t *, jerry_char_t *, jerry_size_t); +jerry_value_t jerry_get_property (const jerry_value_t, const jerry_value_t); +jerry_value_t jerry_get_property_by_index (const jerry_value_t , uint32_t); +jerry_value_t jerry_set_property (const jerry_value_t, const jerry_value_t, const jerry_value_t); +jerry_value_t jerry_set_property_by_index (const jerry_value_t, uint32_t, const jerry_value_t); + +void jerry_init_property_descriptor_fields (jerry_property_descriptor_t *); +jerry_value_t jerry_define_own_property (const jerry_value_t, + const jerry_value_t, + const jerry_property_descriptor_t *); + +bool jerry_get_own_property_descriptor (const jerry_value_t, + const jerry_value_t, + jerry_property_descriptor_t *); +void jerry_free_property_descriptor_fields (const jerry_property_descriptor_t *); + +jerry_value_t jerry_call_function (const jerry_value_t, const jerry_value_t, const jerry_value_t[], jerry_size_t); +jerry_value_t jerry_construct_object (const jerry_value_t, const jerry_value_t[], jerry_size_t); + +jerry_value_t jerry_get_object_keys (const jerry_value_t); +jerry_value_t jerry_get_prototype (const jerry_value_t); +jerry_value_t jerry_set_prototype (const jerry_value_t, const jerry_value_t); + +bool jerry_get_object_native_handle (const jerry_value_t, uintptr_t *); +void jerry_set_object_native_handle (const jerry_value_t, uintptr_t, jerry_object_free_callback_t); +bool jerry_foreach_object_property (const jerry_value_t, jerry_object_property_foreach_t, void *); /** - * General API functions of JS objects + * Snapshot functions */ -bool jerry_is_array (const jerry_object_t *); -bool jerry_is_constructor (const jerry_object_t *); -bool jerry_is_function (const jerry_object_t *); -bool jerry_add_object_field (jerry_object_t *, const jerry_char_t *, jerry_size_t, const jerry_value_t, bool); -bool jerry_delete_object_field (jerry_object_t *, const jerry_char_t *, jerry_size_t); -jerry_value_t jerry_get_object_field_value (jerry_object_t *, const jerry_char_t *); -jerry_value_t jerry_get_object_field_value_sz (jerry_object_t *, const jerry_char_t *, jerry_size_t); -bool jerry_set_object_field_value (jerry_object_t *, const jerry_char_t *, const jerry_value_t); -bool jerry_set_object_field_value_sz (jerry_object_t *, const jerry_char_t *, jerry_size_t, const jerry_value_t); -bool jerry_foreach_object_field (jerry_object_t *, jerry_object_field_foreach_t, void *); -bool jerry_get_object_native_handle (jerry_object_t *, uintptr_t *); -void jerry_set_object_native_handle (jerry_object_t *, uintptr_t, jerry_object_free_callback_t); -jerry_value_t jerry_construct_object (jerry_object_t *, const jerry_value_t[], uint16_t); -jerry_value_t jerry_call_function (jerry_object_t *, jerry_object_t *, const jerry_value_t[], uint16_t); +size_t jerry_parse_and_save_snapshot (const jerry_char_t *, size_t, bool, bool, uint8_t *, size_t); +jerry_value_t jerry_exec_snapshot (const void *, size_t, bool); /** * @} diff --git a/jerry-core/jerry.c b/jerry-core/jerry.c index dace471cd7..49d655cda2 100644 --- a/jerry-core/jerry.c +++ b/jerry-core/jerry.c @@ -18,6 +18,7 @@ #include "ecma-alloc.h" #include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" #include "ecma-builtins.h" #include "ecma-exceptions.h" #include "ecma-eval.h" @@ -25,10 +26,11 @@ #include "ecma-gc.h" #include "ecma-helpers.h" #include "ecma-init-finalize.h" +#include "ecma-lex-env.h" #include "ecma-literal-storage.h" #include "ecma-objects.h" #include "ecma-objects-general.h" -#include "ecma-try-catch-macro.h" +#include "jerry-api.h" #include "jerry-snapshot.h" #include "lit-magic-strings.h" #include "js-parser.h" @@ -37,39 +39,47 @@ #define JERRY_INTERNAL #include "jerry-internal.h" -/** - * Jerry engine build date - */ -const char * const jerry_build_date = JERRY_BUILD_DATE; +JERRY_STATIC_ASSERT (sizeof (jerry_value_t) == sizeof (ecma_value_t), + size_of_jerry_value_t_must_be_equal_to_size_of_ecma_value_t); + +JERRY_STATIC_ASSERT ((int) ECMA_ERROR_COMMON == (int) JERRY_ERROR_COMMON + && (int) ECMA_ERROR_EVAL == (int) JERRY_ERROR_EVAL + && (int) ECMA_ERROR_RANGE == (int) JERRY_ERROR_RANGE + && (int) ECMA_ERROR_REFERENCE == (int) JERRY_ERROR_REFERENCE + && (int) ECMA_ERROR_SYNTAX == (int) JERRY_ERROR_SYNTAX + && (int) ECMA_ERROR_TYPE == (int) JERRY_ERROR_TYPE + && (int) ECMA_ERROR_URI == (int) JERRY_ERROR_URI, + ecma_standard_error_t_must_be_equal_to_jerry_error_t); /** - * Jerry engine build commit hash + * Jerry run-time configuration flags */ -const char * const jerry_commit_hash = JERRY_COMMIT_HASH; +static jerry_init_flag_t jerry_init_flags; /** - * Jerry engine build branch name + * Jerry API availability flag */ -const char * const jerry_branch_name = JERRY_BRANCH_NAME; +static bool jerry_api_available; + +#ifdef JERRY_ENABLE_ERROR_MESSAGES /** - * Jerry run-time configuration flags + * Error message, if an argument is has an error flag */ -static jerry_flag_t jerry_flags; +static const char *error_value_msg_p = "argument cannot have an error flag"; /** - * Jerry API availability flag + * Error message, if types of arguments are incorrect */ -static bool jerry_api_available; +static const char *wrong_args_msg_p = "wrong type of argument"; -static const jerry_char_t *error_value_msg_p = (const jerry_char_t *) "argument cannot have an error flag"; +#endif /* JERRY_ENABLE_ERROR_MESSAGES */ /** \addtogroup jerry_extension Jerry engine extension interface * @{ */ #ifdef JERRY_ENABLE_LOG -/* TODO: Move logging-related functionality to separate module, like jerry-log.c */ /** * Verbosity level of logging @@ -80,6 +90,7 @@ int jerry_debug_level = 0; * File, used for logging */ FILE *jerry_log_file = NULL; + #endif /* JERRY_ENABLE_LOG */ /** @@ -98,7 +109,7 @@ FILE *jerry_log_file = NULL; * API could not be invoked in the following cases: * - between enter to and return from native free callback. */ -static void +static inline void __attr_always_inline___ jerry_assert_api_available (void) { if (!jerry_api_available) @@ -110,7 +121,7 @@ jerry_assert_api_available (void) /** * Turn on API availability */ -static void +static inline void __attr_always_inline___ jerry_make_api_available (void) { jerry_api_available = true; @@ -119,525 +130,645 @@ jerry_make_api_available (void) /** * Turn off API availability */ -static void +static inline void __attr_always_inline___ jerry_make_api_unavailable (void) { jerry_api_available = false; } /* jerry_make_api_unavailable */ /** - * Returns whether the given jerry_value_t is error. + * Construct new TypeError object + * + * @return TypeError object value */ -bool -jerry_value_is_error (const jerry_value_t value) /**< api value */ +static jerry_value_t +jerry_create_type_error (void) { - return ECMA_IS_VALUE_ERROR (value); -} /* jerry_value_is_error */ + ecma_object_t *type_error_obj_p = ecma_new_standard_error (ECMA_ERROR_TYPE); + return ecma_make_error_obj_value (type_error_obj_p); +} /* jerry_create_type_error */ /** - * Returns whether the given jerry_value_t is null. + * Jerry engine initialization */ -bool -jerry_value_is_null (const jerry_value_t value) /**< api value */ +void +jerry_init (jerry_init_flag_t flags) /**< combination of Jerry flags */ { - return ecma_is_value_null (value); -} /* jerry_value_is_null */ + if (flags & (JERRY_INIT_ENABLE_LOG)) + { +#ifndef JERRY_ENABLE_LOG + JERRY_WARNING_MSG ("Ignoring log options because of '!JERRY_ENABLE_LOG' build configuration.\n"); +#endif /* !JERRY_ENABLE_LOG */ + } -/** - * Returns whether the given jerry_value_t is undefined. - */ -bool -jerry_value_is_undefined (const jerry_value_t value) /**< api value */ -{ - return ecma_is_value_undefined (value); -} /* jerry_value_is_undefined */ + if (flags & (JERRY_INIT_MEM_STATS | JERRY_INIT_MEM_STATS_SEPARATE)) + { +#ifndef JMEM_STATS + flags &= (jerry_init_flag_t) ~(JERRY_INIT_MEM_STATS | JERRY_INIT_MEM_STATS_SEPARATE); -/** - * Returns whether the given jerry_value_t has boolean type. - */ -bool -jerry_value_is_boolean (const jerry_value_t value) /**< api value */ -{ - return ecma_is_value_boolean (value); -} /* jerry_value_is_boolean */ + JERRY_WARNING_MSG ("Ignoring memory statistics option because of '!JMEM_STATS' build configuration.\n"); +#else /* JMEM_STATS */ + if (flags & JERRY_INIT_MEM_STATS_SEPARATE) + { + flags |= JERRY_INIT_MEM_STATS; + } +#endif /* !JMEM_STATS */ + } + + jerry_init_flags = flags; + + jerry_make_api_available (); + + jmem_init (); + ecma_init (); +} /* jerry_init */ /** - * Returns whether the given jerry_value_t is number. - * - * More specifically, returns true if the type is JERRY_DATA_TYPE_FLOAT32, - * JERRY_DATA_TYPE_FLOAT64 or JERRY_DATA_TYPE_UINT32, false otherwise. + * Terminate Jerry engine */ -bool -jerry_value_is_number (const jerry_value_t value) /**< api value */ +void +jerry_cleanup (void) { - return ecma_is_value_number (value); -} /* jerry_value_is_number */ + jerry_assert_api_available (); + + bool is_show_mem_stats = ((jerry_init_flags & JERRY_INIT_MEM_STATS) != 0); + + ecma_finalize (); + jmem_finalize (is_show_mem_stats); +} /* jerry_cleanup */ /** - * Returns whether the given jerry_value_t is string. + * Register external magic string array */ -bool -jerry_value_is_string (const jerry_value_t value) /**< api value */ +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 */ { - return ecma_is_value_string (value); -} /* jerry_value_is_string */ + 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 */ /** - * Returns whether the given jerry_value_t is object. + * Get Jerry configured memory limits */ -bool -jerry_value_is_object (const jerry_value_t value) /**< api value */ +void +jerry_get_memory_limits (size_t *out_data_bss_brk_limit_p, /**< [out] Jerry's maximum usage of + * data + bss + brk sections */ + size_t *out_stack_limit_p) /**< [out] Jerry's maximum usage of stack */ { - return ecma_is_value_object (value); -} /* jerry_value_is_object */ + *out_data_bss_brk_limit_p = CONFIG_MEM_HEAP_AREA_SIZE + CONFIG_MEM_DATA_LIMIT_MINUS_HEAP_SIZE; + *out_stack_limit_p = CONFIG_MEM_STACK_LIMIT; +} /* jerry_get_memory_limits */ /** - * Returns whether the given jerry_value_t is a function object. + * Run garbage collection */ -bool -jerry_value_is_function (const jerry_value_t value) /**< api value */ +void +jerry_gc (void) { - return ecma_op_is_callable (value); -} /* jerry_value_is_function */ + jerry_assert_api_available (); + + ecma_gc_run (); +} /* jerry_gc */ /** - * Returns the boolean v_bool member of the given jerry_value_t structure. - * If the given jerry_value_t structure has type other than - * JERRY_DATA_TYPE_BOOLEAN, JERRY_ASSERT fails. + * Simple Jerry runner + * + * @return true - if run was successful + * false - otherwise */ bool -jerry_get_boolean_value (const jerry_value_t value) /**< api value */ +jerry_run_simple (const jerry_char_t *script_source, /**< script source */ + size_t script_source_size, /**< script source size */ + jerry_init_flag_t flags) /**< combination of Jerry flags */ { - JERRY_ASSERT (jerry_value_is_boolean (value)); + bool result = false; - return ecma_is_value_true (value); -} /* jerry_get_boolean_value */ + jerry_init (flags); -/** - * Returns the number value of the given jerry_value_t structure as a double. - */ -double -jerry_get_number_value (const jerry_value_t value) /**< api value */ -{ - JERRY_ASSERT (jerry_value_is_number (value)); + jerry_value_t parse_ret_val = jerry_parse (script_source, script_source_size, false); - return (double) ecma_get_number_from_value (value); -} /* jerry_get_number_value */ + if (!ECMA_IS_VALUE_ERROR (parse_ret_val)) + { + jerry_value_t run_ret_val = jerry_run (parse_ret_val); -/** - * Returns the v_string member of the given jerry_value_t structure. - * If the given jerry_value_t structure has type other than - * JERRY_DATA_TYPE_STRING, JERRY_ASSERT fails. - */ -jerry_string_t * -jerry_get_string_value (const jerry_value_t value) /**< api value */ -{ - JERRY_ASSERT (jerry_value_is_string (value)); + if (!ECMA_IS_VALUE_ERROR (run_ret_val)) + { + result = true; + } - return ecma_get_string_from_value (value); -} /* jerry_get_string_value */ + jerry_release_value (run_ret_val); + } -/** - * Returns the v_object member of the given jerry_value_t structure. - * If the given jerry_value_t structure has type other than - * JERRY_DATA_TYPE_OBJECT, JERRY_ASSERT fails. - */ -jerry_object_t * -jerry_get_object_value (const jerry_value_t value) /**< api value */ -{ - JERRY_ASSERT (jerry_value_is_object (value)); + jerry_release_value (parse_ret_val); + jerry_cleanup (); - return ecma_get_object_from_value (value); -} /* jerry_get_object_value */ + return result; +} /* jerry_run_simple */ /** - * Creates and returns a jerry_value_t with type - * JERRY_DATA_TYPE_NULL. + * Parse script for specified context + * + * @return function object value - if script was parsed successfully, + * thrown error - otherwise */ jerry_value_t -jerry_create_null_value (void) +jerry_parse (const jerry_char_t *source_p, /**< script source */ + size_t source_size, /**< script source size */ + bool is_strict) /**< strict mode */ { - return ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL); -} /* jerry_create_null_value */ + jerry_assert_api_available (); -/** - * Creates and returns a jerry_value_t with type - * JERRY_DATA_TYPE_UNDEFINED. - */ -jerry_value_t -jerry_create_undefined_value (void) -{ - return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); -} /* jerry_create_undefined_value */ + parser_set_show_instrs ((jerry_init_flags & JERRY_INIT_SHOW_OPCODES)); -/** - * Creates a JERRY_DATA_TYPE_BOOLEAN jerry_value_t from the given - * boolean parameter and returns with it. - */ -jerry_value_t -jerry_create_boolean_value (bool value) /**< bool value from which a jerry_value_t will be created */ -{ - return ecma_make_boolean_value (value); -} /* jerry_create_boolean_value */ + ecma_compiled_code_t *bytecode_data_p; + ecma_value_t parse_status; -/** - * Creates a jerry_value_t from the given double parameter and returns - * with it. - * The v_float64 member will be set and the will be JERRY_DATA_TYPE_FLOAT64. - */ -jerry_value_t -jerry_create_number_value (double value) /**< double value from which a jerry_value_t will be created */ -{ - return ecma_make_number_value ((ecma_number_t) value); -} /* jerry_create_number_value */ + parse_status = parser_parse_script (source_p, + source_size, + is_strict, + &bytecode_data_p); -/** - * Creates a JERRY_DATA_TYPE_OBJECT type jerry_value_t from the - * given jerry_object_t *parameter and returns with it. - */ -jerry_value_t -jerry_create_object_value (jerry_object_t *obj_p) /**< jerry_object_t from which a value will be created */ -{ - return ecma_make_object_value (obj_p); -} /* jerry_create_object_value */ + if (ECMA_IS_VALUE_ERROR (parse_status)) + { + return parse_status; + } -/** - * Creates a JERRY_DATA_TYPE_STRING type jerry_value_t from the - * given jerry_string_t *parameter and returns with it. - */ -jerry_value_t -jerry_create_string_value (jerry_string_t *str_p) /**< jerry_string_t from which a value will be created */ -{ - return ecma_make_string_value (str_p); -} /* jerry_create_string_value */ + ecma_free_value (parse_status); + +#ifdef JMEM_STATS + if (jerry_init_flags & JERRY_INIT_MEM_STATS_SEPARATE) + { + jmem_stats_print (); + jmem_stats_reset_peak (); + } +#endif /* JMEM_STATS */ + + is_strict = ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0); + ecma_object_t *lex_env_p = ecma_get_global_environment (); + 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 */ /** - * Convert completion of 'eval' to API value and completion code + * Run Jerry in specified run context * * Note: - * The value returned in 'retval_p' should be freed with jerry_release_value + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return completion code + * @return result of bytecode - if run was successful + * thrown error - otherwise */ -static inline jerry_completion_code_t __attr_always_inline___ -jerry_convert_eval_completion_to_retval (ecma_value_t completion, /**< completion of 'eval'-mode - * code execution */ - jerry_value_t *retval_p) /**< [out] api value */ +jerry_value_t +jerry_run (const jerry_value_t func_val) /**< function to run */ { - *retval_p = completion; + jerry_assert_api_available (); - return (ECMA_IS_VALUE_ERROR (completion)) ? JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION : JERRY_COMPLETION_CODE_OK; -} /* jerry_convert_eval_completion_to_retval */ + if (!ecma_is_value_object (func_val)) + { + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + } -/** - * @} - */ + ecma_object_t *func_obj_p = ecma_get_object_from_value (func_val); + + if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_FUNCTION + || ecma_get_object_is_builtin (func_obj_p)) + { + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + } + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_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); + + return vm_run_global (bytecode_data_p); +} /* jerry_run */ /** - * Copy string characters to specified buffer. It is the caller's responsibility - * to make sure that the string fits in the buffer. + * Perform eval * * Note: - * '\0' could occur in characters. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return number of bytes, actually copied to the buffer. + * @return result of eval, may be error value. */ -jerry_size_t -jerry_string_to_char_buffer (const jerry_string_t *string_p, /**< string descriptor */ - jerry_char_t *buffer_p, /**< [out] output characters buffer */ - jerry_size_t buffer_size) /**< size of output buffer */ +jerry_value_t +jerry_eval (const jerry_char_t *source_p, /**< source code */ + size_t source_size, /**< length of source code */ + bool is_strict) /**< source must conform with strict mode */ { jerry_assert_api_available (); - return ecma_string_copy_to_utf8_buffer (string_p, (lit_utf8_byte_t *) buffer_p, buffer_size); -} /* jerry_string_to_char_buffer */ + return ecma_op_eval_chars_buffer ((const lit_utf8_byte_t *) source_p, + source_size, + false, + is_strict); +} /* jerry_eval */ /** - * Acquire string pointer for usage outside of the engine - * from string retrieved in extension routine call from engine. + * Get global object * - * Warning: - * acquired pointer should be released with jerry_release_string + * Note: + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return pointer that may be used outside of the engine + * @return api value of global object */ -jerry_string_t * -jerry_acquire_string (jerry_string_t *string_p) /**< pointer passed to function */ +jerry_value_t +jerry_get_global_object (void) { jerry_assert_api_available (); - ecma_ref_ecma_string (string_p); - - return string_p; -} /* jerry_acquire_string */ + return ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL)); +} /* jerry_get_global_object */ /** - * Release string pointer - * - * See also: - * jerry_acquire_string - * jerry_call_function + * Check if the specified value is an array object value. * + * @return true - if the specified value is an array object, + * false - otherwise. */ -void -jerry_release_string (jerry_string_t *string_p) /**< pointer acquired through jerry_acquire_string */ +bool +jerry_value_is_array (const jerry_value_t value) /**< jerry api value */ { jerry_assert_api_available (); - ecma_deref_ecma_string (string_p); -} /* jerry_release_string */ + return (ecma_is_value_object (value) + && ecma_get_object_type (ecma_get_object_from_value (value)) == ECMA_OBJECT_TYPE_ARRAY); +} /* jerry_value_is_array */ /** - * Acquire object pointer for usage outside of the engine - * from object retrieved in extension routine call from engine. - * - * Warning: - * acquired pointer should be released with jerry_release_object + * Check if the specified value is boolean. * - * @return pointer that may be used outside of the engine + * @return true - if the specified value is boolean, + * false - otherwise. */ -jerry_object_t * -jerry_acquire_object (jerry_object_t *object_p) /**< pointer passed to function */ +bool +jerry_value_is_boolean (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - ecma_ref_object (object_p); - - return object_p; -} /* jerry_acquire_object */ + return ecma_is_value_boolean (value); +} /* jerry_value_is_boolean */ /** - * Release object pointer + * Check if the specified value is a constructor function object value. * - * See also: - * jerry_acquire_object - * jerry_call_function - * jerry_get_object_field_value + * @return true - if the specified value is a function value that implements [[Construct]], + * false - otherwise. */ -void -jerry_release_object (jerry_object_t *object_p) /**< pointer acquired through jerry_acquire_object */ +bool +jerry_value_is_constructor (const jerry_value_t value) /**< jerry api value */ { jerry_assert_api_available (); - ecma_deref_object (object_p); -} /* jerry_release_object */ + return ecma_is_constructor (value); +} /* jerry_value_is_constructor */ /** - * Acquire specified Jerry API value. - * - * Note: - * For values of string and object types this acquires the underlying data, - * for all other types it is a no-op. + * Check if the specified value is a function object value. * - * Warning: - * Acquired pointer should be released with jerry_release_value + * @return true - if the specified value is callable, + * false - otherwise. */ -jerry_value_t -jerry_acquire_value (jerry_value_t value) /**< API value */ +bool +jerry_value_is_function (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - if (jerry_value_is_string (value)) - { - jerry_string_t *str_p = jerry_acquire_string (jerry_get_string_value (value)); - return jerry_create_string_value (str_p); - } - else if (jerry_value_is_object (value)) - { - jerry_acquire_object (jerry_get_object_value (value)); - } - - return value; -} /* jerry_acquire_value */ + return ecma_op_is_callable (value); +} /* jerry_value_is_function */ /** - * Release specified Jerry API value + * Check if the specified value is number. * - * Note: - * For values of string and object types this releases the underlying data, - * for all other types it is a no-op. + * @return true - if the specified value is number, + * false - otherwise. */ -void -jerry_release_value (jerry_value_t value) /**< API value */ +bool +jerry_value_is_number (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - ecma_free_value (value); -} /* jerry_release_value */ + return ecma_is_value_number (value); +} /* jerry_value_is_number */ /** - * Create a string + * Check if the specified value is null. * - * Note: - * caller should release the string with jerry_release_string, just when the value becomes unnecessary. - * - * @return pointer to created string + * @return true - if the specified value is null, + * false - otherwise. */ -jerry_string_t * -jerry_create_string (const jerry_char_t *v) /**< string value */ +bool +jerry_value_is_null (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) v, lit_zt_utf8_string_size ((lit_utf8_byte_t *) v)); -} /* jerry_create_string */ + return ecma_is_value_null (value); +} /* jerry_value_is_null */ /** - * Create a string + * Check if the specified value is object. * - * Note: - * caller should release the string with jerry_release_string, just when the value becomes unnecessary. - * - * @return pointer to created string + * @return true - if the specified value is object, + * false - otherwise. */ -jerry_string_t * -jerry_create_string_sz (const jerry_char_t *v, /**< string value */ - jerry_size_t v_size) /**< string size */ +bool +jerry_value_is_object (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) v, - (lit_utf8_size_t) v_size); -} /* jerry_create_string_sz */ + return ecma_is_value_object (value); +} /* jerry_value_is_object */ /** - * Create an object + * Check if the specified value is string. * - * Note: - * caller should release the object with jerry_release_object, just when the value becomes unnecessary. + * @return true - if the specified value is string, + * false - otherwise. + */ +bool +jerry_value_is_string (const jerry_value_t value) /**< api value */ +{ + jerry_assert_api_available (); + + return ecma_is_value_string (value); +} /* jerry_value_is_string */ + +/** + * Check if the specified value is undefined. * - * @return pointer to created object + * @return true - if the specified value is undefined, + * false - otherwise. */ -jerry_object_t * -jerry_create_object (void) +bool +jerry_value_is_undefined (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_op_create_object_object_noarg (); -} /* jerry_create_object */ + return ecma_is_value_undefined (value); +} /* jerry_value_is_undefined */ /** - * Create an array object + * Check if the specified value is an error value. * - * Note: - * caller should release the object with jerry_release_object, just when the value becomes unnecessary. + * @return true - if the error flag of the specified value is true, + * false - otherwise. + */ +bool +jerry_value_has_error_flag (const jerry_value_t value) /**< api value */ +{ + jerry_assert_api_available (); + + return ECMA_IS_VALUE_ERROR (value); +} /* jerry_value_has_error_flag */ + +/** + * Clear the error flag + */ +void +jerry_value_clear_error_flag (jerry_value_t *value_p) +{ + jerry_assert_api_available (); + + *value_p = (*value_p) & ~ECMA_VALUE_ERROR_FLAG; +} /* jerry_value_clear_error_flag */ + +/** + * Set the error flag. + */ +void +jerry_value_set_error_flag (jerry_value_t *value_p) +{ + jerry_assert_api_available (); + + *value_p = (*value_p) | ECMA_VALUE_ERROR_FLAG; +} /* jerry_value_set_error_flag */ + +/** + * Get boolean from the specified value. * - * @return pointer to created array object + * @return true or false. */ -jerry_object_t * -jerry_create_array_object (jerry_size_t size) /**< size of array */ +bool +jerry_get_boolean_value (const jerry_value_t value) /**< api value */ { - JERRY_ASSERT (size > 0); + jerry_assert_api_available (); - ecma_value_t array_length = ecma_make_uint32_value (size); + if (!jerry_value_is_boolean (value)) + { + return false; + } - jerry_length_t argument_size = 1; - ecma_value_t new_array_completion = ecma_op_create_array_object (&array_length, argument_size, true); - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array_completion)); - jerry_object_t *obj_p = ecma_get_object_from_value (new_array_completion); + return ecma_is_value_true (value); +} /* jerry_get_boolean_value */ - ecma_free_value (array_length); - return obj_p; -} /* jerry_create_array_object */ +/** + * Get number from the specified value as a double. + * + * @return stored number as double + */ +double +jerry_get_number_value (const jerry_value_t value) /**< api value */ +{ + jerry_assert_api_available (); + + if (!jerry_value_is_number (value)) + { + return 0; + } + + return (double) ecma_get_number_from_value (value); +} /* jerry_get_number_value */ /** - * Set value of field in the specified array object + * Call ToBoolean operation on the api value. * - * @return true, if field value was set successfully - * false, otherwise + * @return true - if the logical value is true + * false - otherwise */ bool -jerry_set_array_index_value (jerry_object_t *array_obj_p, /**< array object */ - jerry_length_t index, /**< index to be written */ - jerry_value_t value) /**< value to set */ +jerry_value_to_boolean (const jerry_value_t value) /**< input value */ { + jerry_assert_api_available (); + if (ECMA_IS_VALUE_ERROR (value)) { return false; } - ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 ((uint32_t) index); - ecma_value_t set_completion = ecma_op_object_put (array_obj_p, str_idx_p, value, false); - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (set_completion)); + return ecma_op_to_boolean (value); +} /* jerry_value_to_boolean */ - ecma_free_value (set_completion); - ecma_deref_ecma_string (str_idx_p); +/** + * Call ToNumber operation on the api value. + * + * Note: + * returned value must be freed with jerry_release_value, when it is no longer needed. + * + * @return converted number value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_number (const jerry_value_t value) /**< input value */ +{ + jerry_assert_api_available (); - return true; -} /* jerry_set_array_index_value */ + if (ECMA_IS_VALUE_ERROR (value)) + { + return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); + } + + return ecma_op_to_number (value); +} /* jerry_value_to_number */ /** - * Get value of field in the specified array object + * Call ToObject operation on the api value. * * Note: - * if value was retrieved successfully, it should be freed - * with jerry_release_value just when it becomes unnecessary. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return true, if field value was retrieved successfully, i.e. upon the call: - * - there is field with specified name in the object; - * throw exception - otherwise. + * @return converted object value - if success + * thrown error - otherwise */ -bool -jerry_get_array_index_value (jerry_object_t *array_obj_p, /**< array object */ - jerry_length_t index, /**< index to be written */ - jerry_value_t *value_p) /**< [out] value at index */ +jerry_value_t +jerry_value_to_object (const jerry_value_t value) /**< input value */ { - ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 ((uint32_t) index); - ecma_value_t get_completion = ecma_op_object_get (array_obj_p, str_idx_p); - ecma_deref_ecma_string (str_idx_p); + jerry_assert_api_available (); - if (!ECMA_IS_VALUE_ERROR (get_completion)) + if (ECMA_IS_VALUE_ERROR (value)) { - *value_p = get_completion; - return true; + return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); } - *value_p = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - return false; -} /* jerry_get_array_index_value */ + return ecma_op_to_object (value); +} /* jerry_value_to_object */ /** - * Get length of an array object + * Call ToPrimitive operation on the api value. * * Note: - * Returns 0, if the given parameter is not an array object. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return length of the given array + * @return converted primitive value - if success + * thrown error - otherwise */ -uint32_t -jerry_get_array_length (const jerry_object_t *object_p) +jerry_value_t +jerry_value_to_primitive (const jerry_value_t value) /**< input value */ { jerry_assert_api_available (); - if (!jerry_is_array (object_p)) + if (ECMA_IS_VALUE_ERROR (value)) { - return 0; + return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); } - jerry_length_t length = 0; - ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); + return ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NO); +} /* jerry_value_to_primitive */ - ecma_value_t len_value = ecma_op_object_get ((jerry_object_t *) object_p, magic_string_length_p); - ecma_deref_ecma_string (magic_string_length_p); +/** + * Call the ToString ecma builtin operation on the api value. + * + * Note: + * returned value must be freed with jerry_release_value, when it is no longer needed. + * + * @return converted string value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_string (const jerry_value_t value) /**< input value */ +{ + + jerry_assert_api_available (); - if (ecma_is_value_number (len_value)) + if (ECMA_IS_VALUE_ERROR (value)) { - length = ecma_number_to_uint32 (ecma_get_number_from_value (len_value)); + return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); } - ecma_free_value (len_value); + return ecma_op_to_string (value); +} /* jerry_value_to_string */ - return length; -} /* jerry_get_array_length */ +/** + * Acquire specified Jerry API value. + * + * Note: + * returned value must be freed with jerry_release_value, when it is no longer needed. + * + * @return acquired api value + */ +jerry_value_t +jerry_acquire_value (jerry_value_t value) /**< API value */ +{ + jerry_assert_api_available (); + + return ecma_copy_value (value); +} /* jerry_acquire_value */ + +/** + * Release specified Jerry API value + */ +void +jerry_release_value (jerry_value_t value) /**< API value */ +{ + jerry_assert_api_available (); + + ecma_free_value (value); +} /* jerry_release_value */ + +/** + * Create an array object value + * + * Note: + * returned value must be freed with jerry_release_value, when it is no longer needed. + * + * @return value of the constructed array object + */ +jerry_value_t +jerry_create_array (uint32_t size) /**< size of array */ +{ + jerry_assert_api_available (); + + ecma_value_t array_length = ecma_make_uint32_value (size); + + jerry_length_t argument_size = 1; + ecma_value_t array_value = ecma_op_create_array_object (&array_length, argument_size, true); + ecma_free_value (array_length); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (array_value)); + + return array_value; +} /* jerry_create_array */ + +/** + * Create a jerry_value_t representing a boolean value from the given boolean parameter. + * + * @return value of the created boolean + */ +jerry_value_t +jerry_create_boolean (bool value) /**< bool value from which a jerry_value_t will be created */ +{ + jerry_assert_api_available (); + + return ecma_make_boolean_value (value); +} /* jerry_create_boolean */ /** * Create an error object * * Note: - * caller should release the object with jerry_release_object, just when the value becomes unnecessary. + * - returned value must be freed with jerry_release_value, when it is no longer needed + * - the error flag is set for the returned value * - * @return pointer to created error object + * @return value of the constructed error object */ -jerry_object_t * +jerry_value_t jerry_create_error (jerry_error_t error_type, /**< type of error */ const jerry_char_t *message_p) /**< value of 'message' property * of constructed error object */ @@ -651,11 +782,12 @@ jerry_create_error (jerry_error_t error_type, /**< type of error */ * Create an error object * * Note: - * caller should release the object with jerry_release_object, just when the value becomes unnecessary. + * - returned value must be freed with jerry_release_value, when it is no longer needed + * - the error flag is set for the returned value * - * @return pointer to created error object + * @return value of the constructed error object */ -jerry_object_t * +jerry_value_t jerry_create_error_sz (jerry_error_t error_type, /**< type of error */ const jerry_char_t *message_p, /**< value of 'message' property * of constructed error object */ @@ -663,65 +795,21 @@ jerry_create_error_sz (jerry_error_t error_type, /**< type of error */ { jerry_assert_api_available (); - ecma_standard_error_t standard_error_type = ECMA_ERROR_COMMON; - - switch (error_type) - { - case JERRY_ERROR_COMMON: - { - standard_error_type = ECMA_ERROR_COMMON; - break; - } - case JERRY_ERROR_EVAL: - { - standard_error_type = ECMA_ERROR_EVAL; - break; - } - case JERRY_ERROR_RANGE: - { - standard_error_type = ECMA_ERROR_RANGE; - break; - } - case JERRY_ERROR_REFERENCE: - { - standard_error_type = ECMA_ERROR_REFERENCE; - break; - } - case JERRY_ERROR_SYNTAX: - { - standard_error_type = ECMA_ERROR_SYNTAX; - break; - } - case JERRY_ERROR_TYPE: - { - standard_error_type = ECMA_ERROR_TYPE; - break; - } - case JERRY_ERROR_URI: - { - standard_error_type = ECMA_ERROR_URI; - break; - } - default: - { - JERRY_UNREACHABLE (); - } - } - - if (message_p == NULL) + if (message_p == NULL || message_size == 0) { - return ecma_new_standard_error (standard_error_type); + return ecma_make_error_obj_value (ecma_new_standard_error ((ecma_standard_error_t) error_type)); } else { ecma_string_t *message_string_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) message_p, (lit_utf8_size_t) message_size); - ecma_object_t *error_object_p = ecma_new_standard_error_with_message (standard_error_type, message_string_p); + ecma_object_t *error_object_p = ecma_new_standard_error_with_message ((ecma_standard_error_t) error_type, + message_string_p); ecma_deref_ecma_string (message_string_p); - return error_object_p; + return ecma_make_error_obj_value (error_object_p); } } /* jerry_create_error_sz */ @@ -729,815 +817,923 @@ jerry_create_error_sz (jerry_error_t error_type, /**< type of error */ * Create an external function object * * Note: - * caller should release the object with jerry_release_object, just when the value becomes unnecessary. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return pointer to created external function object + * @return value of the constructed function object */ -jerry_object_t * +jerry_value_t jerry_create_external_function (jerry_external_handler_t handler_p) /**< pointer to native handler * for the function */ { jerry_assert_api_available (); - return ecma_op_create_external_function_object ((ecma_external_pointer_t) handler_p); + ecma_object_t *func_obj_p = ecma_op_create_external_function_object ((ecma_external_pointer_t) handler_p); + return ecma_make_object_value (func_obj_p); } /* jerry_create_external_function */ /** - * Dispatch call to specified external function using the native handler + * Creates a jerry_value_t representing a null value. * * Note: - * if called native handler returns true, then dispatcher just returns value received - * through 'return value' output argument, otherwise - throws the value as an exception. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return ecma value - * Returned value must be freed with ecma_free_value + * @return jerry_value_t created from the given double argument. */ -ecma_value_t -jerry_dispatch_external_function (ecma_object_t *function_object_p, /**< external function object */ - ecma_external_pointer_t handler_p, /**< pointer to the function's native handler */ - ecma_value_t this_arg_value, /**< 'this' argument */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - ecma_length_t arguments_list_len) /**< arguments list length */ +jerry_value_t +jerry_create_number (double value) /**< double value from which a jerry_value_t will be created */ { jerry_assert_api_available (); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - - bool is_successful = ((jerry_external_handler_t) handler_p) (function_object_p, - this_arg_value, - arguments_list_p, - arguments_list_len, - &ret_value); + return ecma_make_number_value ((ecma_number_t) value); +} /* jerry_create_number */ - if (!is_successful) - { - ret_value = ecma_make_error_value (ret_value); - } +/** + * Creates and returns a jerry_value_t with type null object. + * + * @return jerry_value_t representing null + */ +jerry_value_t +jerry_create_null (void) +{ + jerry_assert_api_available (); - return ret_value; -} /* jerry_dispatch_external_function */ + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL); +} /* jerry_create_null */ /** - * Dispatch call to object's native free callback function + * Create new JavaScript object, like with new Object(). * * Note: - * the callback is called during critical GC phase, - * so, should not perform any requests to engine + * returned value must be freed with jerry_release_object, when it is no longer needed. + * + * @return value of the created object */ -void -jerry_dispatch_object_free_callback (ecma_external_pointer_t freecb_p, /**< pointer to free callback handler */ - ecma_external_pointer_t native_p) /**< native handle, associated - * with freed object */ +jerry_value_t +jerry_create_object (void) { - jerry_make_api_unavailable (); + jerry_assert_api_available (); - ((jerry_object_free_callback_t) freecb_p) ((uintptr_t) native_p); + return ecma_make_object_value (ecma_op_create_object_object_noarg ()); +} /* jerry_create_object */ - jerry_make_api_available (); -} /* jerry_dispatch_object_free_callback */ +/** + * Create string from a valid CESU8 string + * + * Note: + * returned value must be freed with jerry_release_object, when it is no longer needed. + * + * @return string value + */ +jerry_value_t +jerry_create_string (const jerry_char_t *str_p) /**< pointer to string */ +{ + return jerry_create_string_sz (str_p, lit_zt_utf8_string_size ((lit_utf8_byte_t *) str_p)); +} /* jerry_create_string */ /** - * Check if the specified object is an array object. + * Create string from a valid CESU8 string * - * @return true - if the specified object is an array object, - * false - otherwise. + * Note: + * returned value must be freed with jerry_release_object when it is no longer needed. + * + * @return string value */ -bool -jerry_is_array (const jerry_object_t *object_p) /**< an object */ +jerry_value_t +jerry_create_string_sz (const jerry_char_t *str_p, /**< pointer to string */ + jerry_size_t str_size) /**< string size */ { jerry_assert_api_available (); - return (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY); -} /* jerry_is_array */ + ecma_string_t *ecma_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) str_p, + (lit_utf8_size_t) str_size); + return ecma_make_string_value (ecma_str_p); +} /* jerry_create_string_sz */ /** - * Check if the specified object is a function object. + * Creates a jerry_value_t representing an undefined value. * - * @return true - if the specified object is a function object, - * false - otherwise. + * @return value of undefined */ -bool -jerry_is_function (const jerry_object_t *object_p) /**< an object */ +jerry_value_t +jerry_create_undefined (void) { jerry_assert_api_available (); - JERRY_ASSERT (object_p != NULL); - - ecma_value_t obj_val = ecma_make_object_value (object_p); - - return ecma_op_is_callable (obj_val); -} /* jerry_is_function */ + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); +} /* jerry_create_undefined */ /** - * Check if the specified object is a constructor function object. + * Get length of an array object * - * @return true - if the specified object is a function object that implements [[Construct]], - * false - otherwise. + * Note: + * Returns 0, if the given parameter is not an array object. + * + * @return length of the given array */ -bool -jerry_is_constructor (const jerry_object_t *object_p) /**< an object */ +uint32_t +jerry_get_array_length (const jerry_value_t value) { jerry_assert_api_available (); - JERRY_ASSERT (object_p != NULL); + if (!jerry_value_is_array (value) + || ECMA_IS_VALUE_ERROR (value)) + { + return 0; + } + + jerry_length_t length = 0; + ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); + + ecma_value_t len_value = ecma_op_object_get (ecma_get_object_from_value (value), + magic_string_length_p); + ecma_deref_ecma_string (magic_string_length_p); - ecma_value_t obj_val = ecma_make_object_value (object_p); + length = ecma_number_to_uint32 (ecma_get_number_from_value (len_value)); + ecma_free_value (len_value); - return ecma_is_constructor (obj_val); -} /* jerry_is_constructor */ + return length; +} /* jerry_get_array_length */ /** - * Create field (named data property) in the specified object + * Get size of Jerry string * - * @return true, if field was created successfully, i.e. upon the call: - * - there is no field with same name in the object; - * - the object is extensible; - * false - otherwise. + * @return number of bytes in the buffer needed to represent the string */ -bool -jerry_add_object_field (jerry_object_t *object_p, /**< object to add field at */ - const jerry_char_t *field_name_p, /**< name of the field */ - jerry_size_t field_name_size, /**< size of field name in bytes */ - const jerry_value_t field_value, /**< value of the field */ - bool is_writable) /**< flag indicating whether the created field should be writable */ +jerry_size_t +jerry_get_string_size (const jerry_value_t value) /**< input string */ { jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (field_value)) + if (!ecma_is_value_string (value)) { - return false; + return 0; } - bool is_successful = false; + return ecma_string_get_size (ecma_get_string_from_value (value)); +} /* jerry_get_string_size */ - if (ecma_get_object_extensible (object_p)) - { - ecma_string_t *field_name_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) field_name_p, - (lit_utf8_size_t) field_name_size); +/** + * Get length of Jerry string + * + * @return number of characters in the string + */ +jerry_length_t +jerry_get_string_length (const jerry_value_t value) /**< input string */ +{ + jerry_assert_api_available (); - ecma_property_t *prop_p = ecma_op_object_get_own_property (object_p, field_name_str_p); + if (!ecma_is_value_string (value)) + { + return 0; + } - if (prop_p == NULL) - { - is_successful = true; + return ecma_string_get_length (ecma_get_string_from_value (value)); +} /* jerry_get_string_length */ - uint8_t prop_attributes = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE; +/** + * 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 character buffer. + * + * @return number of bytes, actually copied to the buffer. + */ +jerry_size_t +jerry_string_to_char_buffer (const jerry_value_t value, /**< input string value */ + jerry_char_t *buffer_p, /**< [out] output characters buffer */ + jerry_size_t buffer_size) /**< size of output buffer */ +{ + jerry_assert_api_available (); - if (is_writable) - { - prop_attributes = (uint8_t) (prop_attributes | ECMA_PROPERTY_FLAG_WRITABLE); - } + if (!ecma_is_value_string (value) || buffer_p == NULL) + { + return 0; + } - prop_p = ecma_create_named_data_property (object_p, - field_name_str_p, - prop_attributes); - ecma_named_data_property_assign_value (object_p, prop_p, field_value); - } + ecma_string_t *str_p = ecma_get_string_from_value (value); - ecma_deref_ecma_string (field_name_str_p); + if (ecma_string_get_size (str_p) < buffer_size) + { + return 0; } - return is_successful; -} /* jerry_add_object_field */ + return ecma_string_copy_to_utf8_buffer (str_p, + (lit_utf8_byte_t *) buffer_p, + buffer_size); +} /* jerry_string_to_char_buffer */ /** - * Delete field in the specified object + * Checks whether the object or it's prototype has the given property. * - * @return true, if field was deleted successfully, i.e. upon the call: - * - there is field with specified name in the object; - * false - otherwise. + * @return true - if the property exists + * false - otherwise */ bool -jerry_delete_object_field (jerry_object_t *object_p, /**< object to delete field at */ - const jerry_char_t *field_name_p, /**< name of the field */ - jerry_size_t field_name_size) /**< size of the field name in bytes */ +jerry_has_property (const jerry_value_t obj_val, /**< object value */ + const jerry_value_t prop_name_val) /**< property name (string value) */ { jerry_assert_api_available (); - bool is_successful = true; + if (!ecma_is_value_object (obj_val) + || !ecma_is_value_string (prop_name_val)) + { + return false; + } + + ecma_property_t *prop_p = ecma_op_object_get_property (ecma_get_object_from_value (obj_val), + ecma_get_string_from_value (prop_name_val)); - ecma_string_t *field_name_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) field_name_p, - (lit_utf8_size_t) field_name_size); + return ecma_make_boolean_value (prop_p != NULL); +} /* jerry_has_property */ - ecma_value_t delete_completion = ecma_op_object_delete (object_p, - field_name_str_p, - true); +/** + * Checks whether the object has the given property. + * + * @return true - if the property exists + * false - otherwise + */ +bool +jerry_has_own_property (const jerry_value_t obj_val, /**< object value */ + const jerry_value_t prop_name_val) /**< property name (string value) */ +{ + jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (delete_completion)) + if (!ecma_is_value_object (obj_val) + || !ecma_is_value_string (prop_name_val)) { - is_successful = false; + return false; } - ecma_free_value (delete_completion); + ecma_property_t *prop_p = ecma_op_object_get_own_property (ecma_get_object_from_value (obj_val), + ecma_get_string_from_value (prop_name_val)); - ecma_deref_ecma_string (field_name_str_p); + return ecma_make_boolean_value (prop_p != NULL); +} /* jerry_has_own_property */ - return is_successful; -} /* jerry_delete_object_field */ /** - * Get value of field in the specified object + * Delete a property from an object. + * + * @return true - if property was deleted successfully + * false - otherwise + */ +bool +jerry_delete_property (const jerry_value_t obj_val, /**< object value */ + const jerry_value_t prop_name_val) /**< property name (string value) */ +{ + jerry_assert_api_available (); + + if (!ecma_is_value_object (obj_val) + || !ecma_is_value_string (prop_name_val)) + { + return false; + } + + ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_val), + ecma_get_string_from_value (prop_name_val), + false); + return ecma_is_value_true (ret_value); +} /* jerry_delete_property */ + +/** + * Get value of a property to the specified object with the given name. * * Note: - * if value was retrieved successfully, it should be freed - * with jerry_release_value just when it becomes unnecessary. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return true, if field value was retrieved successfully, i.e. upon the call: - * - there is field with specified name in the object; - * false - otherwise. + * @return value of property - if success + * thrown error - otherwise */ jerry_value_t -jerry_get_object_field_value (jerry_object_t *object_p, /**< object */ - const jerry_char_t *field_name_p) /**< field name */ +jerry_get_property (const jerry_value_t obj_val, /**< object value */ + const jerry_value_t prop_name_val) /**< property name (string value) */ { - return jerry_get_object_field_value_sz (object_p, - field_name_p, - lit_zt_utf8_string_size (field_name_p)); -} /* jerry_get_object_field_value */ + jerry_assert_api_available (); + + 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 ecma_op_object_get (ecma_get_object_from_value (obj_val), + ecma_get_string_from_value (prop_name_val)); +} /* jerry_get_property */ /** - * Applies the given function to the every fields in the objects + * Get value of field in the specified object * - * @return true, if object fields traversal was performed successfully, i.e.: - * - no unhandled exceptions were thrown in object fields traversal; - * - object fields traversal was stopped on callback that returned false; - * false - otherwise, - * if getter of field threw a exception or unhandled exceptions were thrown during traversal; + * 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. */ -bool -jerry_foreach_object_field (jerry_object_t *object_p, /**< object */ - jerry_object_field_foreach_t foreach_p, /**< foreach function */ - void *user_data_p) /**< user data for foreach function */ +jerry_value_t +jerry_get_property_by_index (const jerry_value_t obj_val, /**< object value */ + uint32_t index) /**< index to be written */ { jerry_assert_api_available (); - ecma_collection_iterator_t names_iter; - ecma_collection_header_t *names_p = ecma_op_object_get_property_names (object_p, false, true, true); - ecma_collection_iterator_init (&names_iter, names_p); - - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - bool continuous = true; - - while (ecma_is_value_empty (ret_value) - && continuous - && ecma_collection_iterator_next (&names_iter)) + if (!ecma_is_value_object (obj_val)) { - ecma_string_t *property_name_p = ecma_get_string_from_value (*names_iter.current_value_p); + return jerry_create_type_error (); + } - ECMA_TRY_CATCH (property_value, ecma_op_object_get (object_p, property_name_p), ret_value); + ecma_string_t str_idx; + ecma_init_ecma_string_from_uint32 (&str_idx, index); + ecma_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_val), &str_idx); - continuous = foreach_p (property_name_p, property_value, user_data_p); + return ret_value; +} /* jerry_get_property_by_index */ - ECMA_FINALIZE (property_value); - } +/** + * Set a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_release_value, when it is no longer needed. + * + * @return true - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_set_property (const jerry_value_t obj_val, /**< object value */ + const jerry_value_t prop_name_val, /**< property name (string value) */ + const jerry_value_t value_to_set) /**< value to set */ +{ + jerry_assert_api_available (); - ecma_free_values_collection (names_p, true); - if (ecma_is_value_empty (ret_value)) + if (ECMA_IS_VALUE_ERROR (value_to_set) + || !ecma_is_value_object (obj_val) + || !ecma_is_value_string (prop_name_val)) { - return true; + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); } - else - { - JERRY_ASSERT (ECMA_IS_VALUE_ERROR (ret_value)); - ecma_free_value (ret_value); - - return false; - } -} /* jerry_foreach_object_field */ + return ecma_op_object_put (ecma_get_object_from_value (obj_val), + ecma_get_string_from_value (prop_name_val), + value_to_set, + true); +} /* jerry_set_property */ /** - * Get value of field in the specified object + * Set indexed value in the specified object * * Note: - * returned value should be freed with jerry_release_value. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return jerry value of the given field + * @return true - if field value was set successfully + * thrown exception - otherwise */ jerry_value_t -jerry_get_object_field_value_sz (jerry_object_t *object_p, /**< object */ - const jerry_char_t *field_name_p, /**< name of the field */ - jerry_size_t field_name_size) /**< size of field name in bytes */ +jerry_set_property_by_index (const jerry_value_t obj_val, /**< object value */ + uint32_t index, /**< index to be written */ + const jerry_value_t value_to_set) /**< value to set */ { jerry_assert_api_available (); - ecma_string_t *field_name_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) field_name_p, - (lit_utf8_size_t) field_name_size); - - ecma_value_t field_value = ecma_op_object_get (object_p, field_name_str_p); + if (ECMA_IS_VALUE_ERROR (value_to_set) + || !ecma_is_value_object (obj_val)) + { + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + } - ecma_deref_ecma_string (field_name_str_p); + ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 ((uint32_t) index); + ecma_value_t ret_value = ecma_op_object_put (ecma_get_object_from_value (obj_val), + str_idx_p, + value_to_set, + true); + ecma_deref_ecma_string (str_idx_p); - return field_value; -} /* jerry_get_object_field_value_sz */ + return ret_value; +} /* jerry_set_property_by_index */ /** - * Set value of field in the specified object - * - * @return true - if field value was set successfully - * false - otherwise + * Initialize property descriptor */ -bool -jerry_set_object_field_value (jerry_object_t *object_p, /**< object */ - const jerry_char_t *field_name_p, /**< name of the field */ - const jerry_value_t field_value) /**< field value to set */ +void +jerry_init_property_descriptor_fields (jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ { - return jerry_set_object_field_value_sz (object_p, - field_name_p, - lit_zt_utf8_string_size (field_name_p), - field_value); -} /* jerry_set_object_field_value */ + prop_desc_p->is_value_defined = false; + prop_desc_p->value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); + prop_desc_p->is_writable_defined = false; + prop_desc_p->is_writable = false; + prop_desc_p->is_enumerable_defined = false; + prop_desc_p->is_enumerable = false; + prop_desc_p->is_configurable_defined = false; + prop_desc_p->is_configurable = false; + prop_desc_p->is_get_defined = false; + prop_desc_p->getter = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); + prop_desc_p->is_set_defined = false; + prop_desc_p->setter = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); +} /* jerry_init_property_descriptor_fields */ /** - * Set value of field in the specified object + * Define a property to the specified object with the given name. * - * @return true, if field value was set successfully, i.e. upon the call: - * - field value is writable; - * false - otherwise. + * Note: + * returned value must be freed with jerry_release_value, when it is no longer needed. + * + * @return true - if success + * thrown error - otherwise */ -bool -jerry_set_object_field_value_sz (jerry_object_t *object_p, /**< object */ - const jerry_char_t *field_name_p, /**< name of the field */ - jerry_size_t field_name_size, /**< size of field name in bytes */ - const jerry_value_t field_value) /**< field value to set */ +jerry_value_t +jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ + const jerry_value_t prop_name_val, /**< property name (string value) */ + const jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ { jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (field_value)) + if (!ecma_is_value_object (obj_val) + || !ecma_is_value_string (prop_name_val)) { - return false; + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + } + + if ((prop_desc_p->is_writable_defined || prop_desc_p->is_value_defined) + && (prop_desc_p->is_get_defined || prop_desc_p->is_set_defined)) + { + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); } - bool is_successful = true; + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + prop_desc.is_enumerable_defined = prop_desc_p->is_enumerable_defined; + prop_desc.is_enumerable = prop_desc_p->is_enumerable_defined ? prop_desc_p->is_enumerable : false; + + prop_desc.is_configurable_defined = prop_desc_p->is_configurable_defined; + prop_desc.is_configurable = prop_desc_p->is_configurable_defined ? prop_desc_p->is_configurable : false; + + /* Copy data property info. */ + prop_desc.is_value_defined = prop_desc_p->is_value_defined; - ecma_string_t *field_name_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) field_name_p, - (lit_utf8_size_t) field_name_size); + if (prop_desc_p->is_value_defined) + { + prop_desc.value = prop_desc_p->value; + } - ecma_value_t set_completion = ecma_op_object_put (object_p, - field_name_str_p, - field_value, - true); + prop_desc.is_writable_defined = prop_desc_p->is_writable_defined; + prop_desc.is_writable = prop_desc_p->is_writable_defined ? prop_desc_p->is_writable : false; - if (ECMA_IS_VALUE_ERROR (set_completion)) + /* Copy accessor property info. */ + if (prop_desc_p->is_get_defined) { - is_successful = false; + ecma_value_t getter = prop_desc_p->getter; + prop_desc.is_get_defined = true; + + if (ecma_op_is_callable (getter)) + { + prop_desc.get_p = ecma_get_object_from_value (getter); + } + else if (!ecma_is_value_null (getter)) + { + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + } } - ecma_free_value (set_completion); - ecma_deref_ecma_string (field_name_str_p); + if (prop_desc_p->is_set_defined) + { + ecma_value_t setter = prop_desc_p->setter; + prop_desc.is_set_defined = true; + + if (ecma_op_is_callable (setter)) + { + prop_desc.set_p = ecma_get_object_from_value (setter); + } + else if (!ecma_is_value_null (setter)) + { + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + } + } - return is_successful; -} /* jerry_set_object_field_value_sz */ + return ecma_op_object_define_own_property (ecma_get_object_from_value (obj_val), + ecma_get_string_from_value (prop_name_val), + &prop_desc, + true); +} /* jerry_define_own_property */ /** - * Get native handle, associated with specified object + * Construct property descriptor from specified property * - * @return true - if there is associated handle (handle is returned through out_handle_p), - * false - otherwise. + * @return true - if success, the prop_desc_p fields contains the property info + * false - otherwise, the prop_desc_p is unchanged */ bool -jerry_get_object_native_handle (jerry_object_t *object_p, /**< object to get handle from */ - uintptr_t *out_handle_p) /**< [out] handle value */ +jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object value */ + const jerry_value_t prop_name_val, /**< property name (string value) */ + jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ { jerry_assert_api_available (); - uintptr_t handle_value; + 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)); + } - bool does_exist = ecma_get_external_pointer_value (object_p, - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, - &handle_value); + ecma_property_t *property_p = ecma_op_object_get_property (ecma_get_object_from_value (obj_val), + ecma_get_string_from_value (prop_name_val)); - if (does_exist) + if (property_p == NULL) { - *out_handle_p = handle_value; + return false; } - return does_exist; -} /* jerry_get_object_native_handle */ + ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (property_p); + + prop_desc_p->is_configurable_defined = true; + prop_desc_p->is_configurable = prop_desc.is_configurable; + 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_get_defined = prop_desc.is_get_defined; + prop_desc_p->is_set_defined = prop_desc.is_set_defined; + + 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.get_p != NULL) + { + prop_desc_p->getter = ecma_make_object_value (prop_desc.get_p); + } + else + { + prop_desc_p->getter = ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL); + } + } + + if (prop_desc_p->is_set_defined) + { + if (prop_desc.set_p != NULL) + { + prop_desc_p->setter = ecma_make_object_value (prop_desc.set_p); + } + else + { + prop_desc_p->setter = ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL); + } + } + + return true; +} /* jerry_get_own_property_descriptor */ /** - * Set native handle and, optionally, 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. + * Free fields of property descriptor (setter, getter and value) */ void -jerry_set_object_native_handle (jerry_object_t *object_p, /**< object to set handle in */ - uintptr_t handle, /**< handle value */ - jerry_object_free_callback_t freecb_p) /**< object free callback or NULL */ +jerry_free_property_descriptor_fields (const jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ { - jerry_assert_api_available (); + if (prop_desc_p->is_value_defined) + { + ecma_free_value (prop_desc_p->value); + } - ecma_create_external_pointer_property (object_p, - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, - handle); - if (freecb_p != NULL) + if (prop_desc_p->is_get_defined) { - ecma_create_external_pointer_property (object_p, - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, - (uintptr_t) freecb_p); + ecma_free_value (prop_desc_p->getter); } - else + + if (prop_desc_p->is_set_defined) { - ecma_property_t *prop_p = ecma_find_internal_property (object_p, - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); - if (prop_p != NULL) - { - ecma_delete_property (object_p, prop_p); - } + ecma_free_value (prop_desc_p->setter); } -} /* jerry_set_object_native_handle */ +} /* jerry_free_property_descriptor_fields */ /** - * Invoke function specified by a function object - * - * Note: - * returned value must be freed with jerry_release_value + * Invoke function specified by a function value * * Note: - * If function is invoked as constructor, it should support [[Construct]] method, - * otherwise, if function is simply called - it should support [[Call]] method. + * - returned value must be freed with jerry_release_value, when it is no longer needed. + * - If function is invoked as constructor, it should support [[Construct]] method, + * otherwise, if function is simply called - it should support [[Call]] method. * - * @return returned jerry value of the given function object + * @return returned jerry value of the invoked function */ static jerry_value_t jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke function as constructor * (this_arg_p should be NULL, as it is ignored), * false - perform function call */ - jerry_object_t *function_object_p, /**< function object to call */ - jerry_object_t *this_arg_p, /**< object for 'this' binding - * or NULL (set 'this' binding to newly constructed object, - * if function is invoked as constructor; - * in case of simple function call set 'this' - * binding to the global object) */ - const jerry_value_t args_p[], /**< function's call arguments - * (NULL if arguments number is zero) */ - jerry_length_t args_count) /**< number of the arguments */ + const jerry_value_t func_obj_val, /**< function object to call */ + const jerry_value_t this_val, /**< object value of 'this' binding */ + const jerry_value_t args_p[], /**< function's call arguments */ + const jerry_size_t args_count) /**< number of the arguments */ { JERRY_ASSERT (args_count == 0 || args_p != NULL); - JERRY_STATIC_ASSERT (sizeof (args_count) == sizeof (ecma_length_t), - size_of_args_count_must_be_equal_to_size_of_ecma_length_t); - ecma_value_t call_completion; + if (ECMA_IS_VALUE_ERROR (func_obj_val) + || ECMA_IS_VALUE_ERROR (this_val)) + { + 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++) + { + if (ECMA_IS_VALUE_ERROR (args_p[i])) + { + return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); + } + } if (is_invoke_as_constructor) { - JERRY_ASSERT (this_arg_p == NULL); - JERRY_ASSERT (jerry_is_constructor (function_object_p)); + JERRY_ASSERT (jerry_value_is_constructor (func_obj_val)); - call_completion = ecma_op_function_construct (function_object_p, + return ecma_op_function_construct (ecma_get_object_from_value (func_obj_val), args_p, args_count); } else { - JERRY_ASSERT (jerry_is_function (function_object_p)); - - ecma_value_t this_arg_val; - - if (this_arg_p == NULL) - { - this_arg_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - } - else - { - this_arg_val = ecma_make_object_value (this_arg_p); - } + JERRY_ASSERT (jerry_value_is_function (func_obj_val)); - call_completion = ecma_op_function_call (function_object_p, - this_arg_val, + return ecma_op_function_call (ecma_get_object_from_value (func_obj_val), + this_val, args_p, args_count); } - - return call_completion; } /* jerry_invoke_function */ /** - * Construct new TypeError object - * - * @return TypeError object value - */ -static jerry_value_t __attr_always_inline___ -jerry_construct_type_error (void) -{ - ecma_object_t *type_error_obj_p = ecma_new_standard_error (ECMA_ERROR_TYPE); - return ecma_make_error_obj_value (type_error_obj_p); -} /* jerry_construct_type_error */ - -/** - * Call function specified by a function object + * Call function specified by a function value * * Note: - * returned value should be freed with jerry_release_value - * just when the value becomes unnecessary. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return returned jerry value of the given function object + * @return returned jerry value of the called function */ jerry_value_t -jerry_call_function (jerry_object_t *function_object_p, /**< function object to call */ - jerry_object_t *this_arg_p, /**< object for 'this' binding - * or NULL (set 'this' binding to the global object) */ - const jerry_value_t args_p[], /**< function's call arguments - * (NULL if arguments number is zero) */ - uint16_t args_count) /**< number of the arguments */ +jerry_call_function (const jerry_value_t func_obj_val, /**< function object to call */ + const jerry_value_t this_val, /**< object for 'this' binding */ + const jerry_value_t args_p[], /**< function's call arguments */ + jerry_size_t args_count) /**< number of the arguments */ { jerry_assert_api_available (); - for (uint16_t i = 0; i < args_count; i++) - { - if (ECMA_IS_VALUE_ERROR (args_p[i])) - { - return jerry_create_object_value (jerry_create_error (JERRY_ERROR_TYPE, error_value_msg_p)); - } - } - - if (jerry_is_function (function_object_p)) + if (jerry_value_is_function (func_obj_val)) { - return jerry_invoke_function (false, function_object_p, this_arg_p, args_p, args_count); + return jerry_invoke_function (false, func_obj_val, this_val, args_p, args_count); } - return jerry_construct_type_error (); + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); } /* jerry_call_function */ /** - * Construct object invoking specified function object as a constructor + * Construct object value invoking specified function value as a constructor * * Note: - * returned value should be freed with jerry_release_value - * just when the value becomes unnecessary. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return returned jerry value of the given constructor + * @return returned jerry value of the invoked constructor */ jerry_value_t -jerry_construct_object (jerry_object_t *function_object_p, /**< function object to call */ +jerry_construct_object (const jerry_value_t func_obj_val, /**< function object to call */ const jerry_value_t args_p[], /**< function's call arguments * (NULL if arguments number is zero) */ - uint16_t args_count) /**< number of the arguments */ + jerry_size_t args_count) /**< number of the arguments */ { jerry_assert_api_available (); - for (uint16_t i = 0; i < args_count; i++) + if (jerry_value_is_constructor (func_obj_val)) { - if (ECMA_IS_VALUE_ERROR (args_p[i])) - { - return jerry_create_object_value (jerry_create_error (JERRY_ERROR_TYPE, error_value_msg_p)); - } - } - - if (jerry_is_constructor (function_object_p)) - { - return jerry_invoke_function (true, function_object_p, NULL, args_p, args_count); + ecma_value_t this_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); + return jerry_invoke_function (true, func_obj_val, this_val, args_p, args_count); } - return jerry_construct_type_error (); + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); } /* jerry_construct_object */ /** - * Get global object - * - * Note: - * caller should release the object with jerry_release_object, just when the value becomes unnecessary. - * - * @return pointer to the global object - */ -jerry_object_t * -jerry_get_global (void) -{ - jerry_assert_api_available (); - - return ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL); -} /* jerry_get_global */ - -/** - * Perform eval + * Get keys of the specified object value * * Note: - * If current code is executed on top of interpreter, using is_direct argument, - * caller can enable direct eval mode that is equivalent to calling eval from - * within of current JS execution context. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return completion status - */ -jerry_completion_code_t -jerry_eval (const jerry_char_t *source_p, /**< source code */ - size_t source_size, /**< length of source code */ - bool is_direct, /**< perform eval invocation in direct mode */ - bool is_strict, /**< perform eval as it is called from strict mode code */ - jerry_value_t *retval_p) /**< [out] returned value */ -{ - jerry_assert_api_available (); - - jerry_completion_code_t status; - - ecma_value_t completion = ecma_op_eval_chars_buffer ((const lit_utf8_byte_t *) source_p, - source_size, - is_direct, - is_strict); - - status = jerry_convert_eval_completion_to_retval (completion, retval_p); - - return status; -} /* jerry_eval */ - -/** - * Perform GC + * @return array object value - if success + * thrown error - otherwise */ -void -jerry_gc (void) +jerry_value_t +jerry_get_object_keys (const jerry_value_t obj_val) /**< object value */ { jerry_assert_api_available (); - ecma_gc_run (); -} /* jerry_gc */ - -/** - * Jerry engine initialization - */ -void -jerry_init (jerry_flag_t flags) /**< combination of Jerry flags */ -{ - if (flags & (JERRY_FLAG_ENABLE_LOG)) - { -#ifndef JERRY_ENABLE_LOG - JERRY_WARNING_MSG ("Ignoring log options because of '!JERRY_ENABLE_LOG' build configuration.\n"); -#endif /* !JERRY_ENABLE_LOG */ - } - - if (flags & (JERRY_FLAG_MEM_STATS | JERRY_FLAG_MEM_STATS_SEPARATE)) + if (!ecma_is_value_object (obj_val)) { -#ifndef JMEM_STATS - flags &= (jerry_flag_t) ~(JERRY_FLAG_MEM_STATS | JERRY_FLAG_MEM_STATS_SEPARATE); - - JERRY_WARNING_MSG ("Ignoring memory statistics option because of '!JMEM_STATS' build configuration.\n"); -#else /* JMEM_STATS */ - if (flags & JERRY_FLAG_MEM_STATS_SEPARATE) - { - flags |= JERRY_FLAG_MEM_STATS; - } -#endif /* !JMEM_STATS */ + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); } - jerry_flags = flags; - - jerry_make_api_available (); - - jmem_init (); - ecma_init (); -} /* jerry_init */ - -/** - * Terminate Jerry engine - */ -void -jerry_cleanup (void) -{ - jerry_assert_api_available (); - - bool is_show_mem_stats = ((jerry_flags & JERRY_FLAG_MEM_STATS) != 0); - - vm_finalize (); - ecma_finalize (); - jmem_finalize (is_show_mem_stats); -} /* jerry_cleanup */ + return ecma_builtin_helper_object_get_properties (ecma_get_object_from_value (obj_val), true); +} /* jerry_get_object_keys */ -/** - * Get Jerry configured memory limits - */ -void -jerry_get_memory_limits (size_t *out_data_bss_brk_limit_p, /**< [out] Jerry's maximum usage of - * data + bss + brk sections */ - size_t *out_stack_limit_p) /**< [out] Jerry's maximum usage of stack */ -{ - *out_data_bss_brk_limit_p = CONFIG_MEM_HEAP_AREA_SIZE + CONFIG_MEM_DATA_LIMIT_MINUS_HEAP_SIZE; - *out_stack_limit_p = CONFIG_MEM_STACK_LIMIT; -} /* jerry_get_memory_limits */ - -/** - * Parse script for specified context - * - * Note: - * returned error object should be freed with jerry_release_object +/** + * Get the prototype of the specified object * - * @return true - if script was parsed successfully, - * false - otherwise (SyntaxError was raised). + * @return object value - if success + * null or thrown error - otherwise */ -bool -jerry_parse (const jerry_char_t *source_p, /**< script source */ - size_t source_size, /**< script source size */ - jerry_object_t **error_obj_p) /**< [out] error object */ +jerry_value_t +jerry_get_prototype (const jerry_value_t obj_val) /**< object value */ { jerry_assert_api_available (); - vm_finalize (); + if (!ecma_is_value_object (obj_val)) + { + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + } - int is_show_instructions = ((jerry_flags & JERRY_FLAG_SHOW_OPCODES) != 0); + ecma_object_t *proto_obj_p = ecma_get_object_prototype (ecma_get_object_from_value (obj_val)); - parser_set_show_instrs (is_show_instructions); + if (proto_obj_p == NULL) + { + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL); + } - ecma_compiled_code_t *bytecode_data_p; - jsp_status_t parse_status; + return ecma_make_object_value (proto_obj_p); +} /* jerry_get_prototype */ - parse_status = parser_parse_script (source_p, - source_size, - &bytecode_data_p, - error_obj_p); +/** + * Set the prototype of the specified object + * + * @return true - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_set_prototype (const jerry_value_t obj_val, /**< object value */ + const jerry_value_t proto_obj_val) /**< prototype object value */ +{ + jerry_assert_api_available (); - if (parse_status != JSP_STATUS_OK) + if (ECMA_IS_VALUE_ERROR (proto_obj_val) + || !ecma_is_value_object (obj_val) + || (!ecma_is_value_object (proto_obj_val) && !ecma_is_value_null (proto_obj_val))) { - JERRY_ASSERT (parse_status == JSP_STATUS_SYNTAX_ERROR); + return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + } - return false; + if (ecma_is_value_null (proto_obj_val)) + { + ECMA_SET_POINTER (ecma_get_object_from_value (obj_val)->prototype_or_outer_reference_cp, NULL); + } + else + { + ECMA_SET_POINTER (ecma_get_object_from_value (obj_val)->prototype_or_outer_reference_cp, + ecma_get_object_from_value (proto_obj_val)); } -#ifdef JMEM_STATS - if (jerry_flags & JERRY_FLAG_MEM_STATS_SEPARATE) + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); +} /* jerry_set_prototype */ + +/** + * Get native handle, associated with specified object + * + * @return true - if there is associated handle (handle is returned through out_handle_p), + * false - otherwise. + */ +bool +jerry_get_object_native_handle (const jerry_value_t obj_val, /**< object to get handle from */ + uintptr_t *out_handle_p) /**< [out] handle value */ +{ + jerry_assert_api_available (); + + if (ECMA_IS_VALUE_ERROR (obj_val)) { - jmem_stats_print (); - jmem_stats_reset_peak (); + return false; } -#endif /* JMEM_STATS */ - vm_init (bytecode_data_p); + uintptr_t handle_value; - return true; -} /* jerry_parse */ + bool does_exist = ecma_get_external_pointer_value (ecma_get_object_from_value (obj_val), + ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, + &handle_value); + + if (does_exist) + { + *out_handle_p = handle_value; + } + + return does_exist; +} /* jerry_get_object_native_handle */ /** - * Run Jerry in specified run context + * Set native handle and, optionally, free callback for the specified object * * Note: - * returned error value should be freed with jerry_release_value - * just when the value becomes unnecessary. + * 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). * - * @return completion status + * 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. */ -jerry_completion_code_t -jerry_run (jerry_value_t *error_value_p) /**< [out] error value */ +void +jerry_set_object_native_handle (const jerry_value_t obj_val, /**< object to set handle in */ + uintptr_t handle, /**< handle value */ + jerry_object_free_callback_t freecb_p) /**< object free callback or NULL */ { jerry_assert_api_available (); - jerry_completion_code_t ret_code = vm_run_global (error_value_p); + if (ECMA_IS_VALUE_ERROR (obj_val)) + { + return; + } - return ret_code; -} /* jerry_run */ + 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, + ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, + (uintptr_t) freecb_p); + } + else + { + ecma_property_t *prop_p = ecma_find_internal_property (object_p, + ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); + if (prop_p != NULL) + { + ecma_delete_property (object_p, prop_p); + } + } +} /* jerry_set_object_native_handle */ /** - * Simple jerry runner + * Applies the given function to the every fields in the objects * - * @return completion status + * @return true, if object fields traversal was performed successfully, i.e.: + * - no unhandled exceptions were thrown in object fields traversal; + * - object fields traversal was stopped on callback that returned false; + * false - otherwise, + * if getter of field threw a exception or unhandled exceptions were thrown during traversal; */ -jerry_completion_code_t -jerry_run_simple (const jerry_char_t *script_source, /**< script source */ - size_t script_source_size, /**< script source size */ - jerry_flag_t flags) /**< combination of Jerry flags */ +bool +jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */ + jerry_object_property_foreach_t foreach_p, /**< foreach function */ + void *user_data_p) /**< user data for foreach function */ { - jerry_init (flags); - - jerry_completion_code_t ret_code = JERRY_COMPLETION_CODE_OK; - jerry_object_t *error_obj_p = NULL; + jerry_assert_api_available (); - if (!jerry_parse (script_source, script_source_size, &error_obj_p)) + if (ECMA_IS_VALUE_ERROR (obj_val)) { - /* unhandled SyntaxError */ - ret_code = JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION; + return false; } - else if ((flags & JERRY_FLAG_PARSE_ONLY) == 0) + + 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); + ecma_collection_iterator_init (&names_iter, names_p); + + ecma_value_t property_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + + bool continuous = true; + + while (continuous + && ecma_collection_iterator_next (&names_iter)) { - jerry_value_t error_value; + ecma_string_t *property_name_p = ecma_get_string_from_value (*names_iter.current_value_p); + property_value = ecma_op_object_get (object_p, property_name_p); - ret_code = jerry_run (&error_value); + if (ECMA_IS_VALUE_ERROR (property_value)) + { + break; + } - jerry_release_value (error_value); + continuous = foreach_p (*names_iter.current_value_p, property_value, user_data_p); + ecma_free_value (property_value); } - jerry_cleanup (); - - return ret_code; -} /* jerry_run_simple */ + ecma_free_values_collection (names_p, true); -/** - * Register external magic string array - */ -void -jerry_register_external_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 */ -{ - lit_magic_strings_ex_set ((const lit_utf8_byte_t **) ex_str_items, count, (const lit_utf8_size_t *) str_lengths); -} /* jerry_register_external_magic_strings */ + if (!ECMA_IS_VALUE_ERROR (property_value)) + { + return true; + } + else + { + ecma_free_value (property_value); + return false; + } +} /* jerry_foreach_object_property */ #ifdef JERRY_ENABLE_SNAPSHOT_SAVE -/* +/** * Variables required to take a snapshot. */ static bool snapshot_error_occured; @@ -1784,11 +1980,12 @@ jerry_parse_and_save_snapshot (const jerry_char_t *source_p, /**< script source size_t source_size, /**< script source size */ bool is_for_global, /**< snapshot would be executed as global (true) * or eval (false) */ + bool is_strict, /**< strict mode */ uint8_t *buffer_p, /**< buffer to save snapshot to */ size_t buffer_size) /**< the buffer's size */ { #ifdef JERRY_ENABLE_SNAPSHOT_SAVE - jsp_status_t parse_status; + ecma_value_t parse_status; ecma_compiled_code_t *bytecode_data_p; snapshot_buffer_write_offset = JERRY_ALIGNUP (sizeof (jerry_snapshot_header_t), @@ -1796,32 +1993,15 @@ jerry_parse_and_save_snapshot (const jerry_char_t *source_p, /**< script source snapshot_error_occured = false; snapshot_buffer_p = buffer_p; snapshot_buffer_size = buffer_size; - jerry_object_t *error_obj_p = NULL; - if (is_for_global) - { - parse_status = parser_parse_script (source_p, - source_size, - &bytecode_data_p, - &error_obj_p); - } - else - { - parse_status = parser_parse_eval (source_p, + parse_status = parser_parse_script (source_p, source_size, - false, - &bytecode_data_p, - &error_obj_p); - } - - if (parse_status != JSP_STATUS_OK) - { - JERRY_ASSERT (error_obj_p != NULL); - ecma_deref_object (error_obj_p); - } + is_strict, + &bytecode_data_p); - if (parse_status != JSP_STATUS_OK) + if (ECMA_IS_VALUE_ERROR (parse_status)) { + ecma_free_value (parse_status); return 0; } @@ -2025,38 +2205,41 @@ snapshot_load_compiled_code (const uint8_t *snapshot_data_p, /**< snapshot data /** * Execute snapshot from specified buffer * - * @return completion code + * Note: + * returned value must be freed with jerry_release_value, when it is no longer needed. + * + * @return true - if success + * false or thrown error - otherwise */ -jerry_completion_code_t +jerry_value_t jerry_exec_snapshot (const void *snapshot_p, /**< snapshot */ size_t snapshot_size, /**< size of snapshot */ - bool copy_bytecode, /**< flag, indicating whether the passed snapshot + bool copy_bytecode) /**< flag, indicating whether the passed snapshot * buffer should be copied to the engine's memory. * If set the engine should not reference the buffer * after the function returns (in this case, the passed * buffer could be freed after the call). * Otherwise (if the flag is not set) - the buffer could only be * freed after the engine stops (i.e. after call to jerry_cleanup). */ - jerry_value_t *retval_p) /**< [out] returned value (ECMA-262 'undefined' if - * code is executed as global scope code) */ { - *retval_p = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - #ifdef JERRY_ENABLE_SNAPSHOT_EXEC JERRY_ASSERT (snapshot_p != NULL); + static const char *invalid_version_error_p = "Invalid snapshot version"; + static const char *invalid_format_error_p = "Invalid snapshot format"; + const uint8_t *snapshot_data_p = (uint8_t *) snapshot_p; if (snapshot_size <= sizeof (jerry_snapshot_header_t)) { - return JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_FORMAT; + return ecma_raise_type_error (invalid_format_error_p); } const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) snapshot_data_p; if (header_p->version != JERRY_SNAPSHOT_VERSION) { - return JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_VERSION; + return ecma_raise_type_error (invalid_version_error_p); } lit_mem_to_snapshot_id_map_entry_t *lit_map_p = NULL; @@ -2064,7 +2247,7 @@ jerry_exec_snapshot (const void *snapshot_p, /**< snapshot */ if (header_p->lit_table_offset >= snapshot_size) { - return JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_VERSION; + return ecma_raise_type_error (invalid_version_error_p); } if (!ecma_load_literals_from_snapshot (snapshot_data_p + header_p->lit_table_offset, @@ -2073,7 +2256,7 @@ jerry_exec_snapshot (const void *snapshot_p, /**< snapshot */ &literals_num)) { JERRY_ASSERT (lit_map_p == NULL); - return JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_FORMAT; + return ecma_raise_type_error (invalid_format_error_p); } ecma_compiled_code_t *bytecode_p; @@ -2089,172 +2272,79 @@ jerry_exec_snapshot (const void *snapshot_p, /**< snapshot */ if (bytecode_p == NULL) { - return JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_FORMAT; + return ecma_raise_type_error (invalid_format_error_p); } - jerry_completion_code_t ret_code; + ecma_value_t ret_val; if (header_p->is_run_global) { - vm_init (bytecode_p); - - ecma_value_t error_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ret_code = vm_run_global (&error_value); - - if (ret_code == JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION) - { - JERRY_ASSERT (ECMA_IS_VALUE_ERROR (error_value)); - ecma_free_value (error_value); - } - else - { - JERRY_ASSERT (ret_code == JERRY_COMPLETION_CODE_OK); - JERRY_ASSERT (ecma_is_value_undefined (error_value)); - } - - vm_finalize (); + ret_val = vm_run_global (bytecode_p); } else { - /* vm should be already initialized */ - ecma_value_t completion = vm_run_eval (bytecode_p, false); - - ret_code = jerry_convert_eval_completion_to_retval (completion, retval_p); - - ecma_free_value (completion); + ret_val = vm_run_eval (bytecode_p, false); } - return ret_code; + ecma_bytecode_deref (bytecode_p); + return ret_val; #else /* !JERRY_ENABLE_SNAPSHOT_EXEC */ - (void) snapshot_p; - (void) snapshot_size; - (void) copy_bytecode; - (void) retval_p; + JERRY_UNUSED (snapshot_p); + JERRY_UNUSED (snapshot_size); + JERRY_UNUSED (copy_bytecode); - return JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_VERSION; + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE); #endif /* JERRY_ENABLE_SNAPSHOT_EXEC */ } /* jerry_exec_snapshot */ /** - * Call ToBoolean operation on the api value. - * - * @return true - if the logical value is true - * false - otherwise + * @} */ -bool -jerry_value_to_boolean (const jerry_value_t value) /**< input value */ -{ - jerry_assert_api_available (); - - if (ECMA_IS_VALUE_ERROR (value)) - { - return false; - } - - return ecma_op_to_boolean (value); -} /* jerry_value_to_boolean */ /** - * Call ToNumber operation on the api value. - * - * Note: - * - Can throw error, so return value should be checked with 'jerry_value_is_error'. - * - Return value must be freed with 'jerry_release_value'. - * - * @return number value + * ====================== Internal functions ========================== */ -jerry_value_t -jerry_value_to_number (const jerry_value_t value) /**< input value */ -{ - jerry_assert_api_available (); - - if (ECMA_IS_VALUE_ERROR (value)) - { - return jerry_create_object_value (jerry_create_error (JERRY_ERROR_TYPE, error_value_msg_p)); - } - - return ecma_op_to_number (value); -} /* jerry_value_to_number */ /** - * Call ToObject operation on the api value. + * Dispatch call to specified external function using the native handler * * Note: - * - Can throw error, so return value should be checked with 'jerry_value_is_error'. - * - Return value must be freed with 'jerry_release_value'. + * returned value must be freed with jerry_release_value, when it is no longer needed. * - * @return object value + * @return returned ecma value of the invoked native function - if success + * thrown error - otherwise */ -jerry_value_t -jerry_value_to_object (const jerry_value_t value) /**< input value */ +ecma_value_t +jerry_dispatch_external_function (ecma_object_t *function_object_p, /**< external function object */ + ecma_external_pointer_t handler_p, /**< pointer to the function's native handler */ + ecma_value_t this_arg_value, /**< 'this' argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + ecma_length_t arguments_list_len) /**< arguments list length */ { jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (value)) - { - return jerry_create_object_value (jerry_create_error (JERRY_ERROR_TYPE, error_value_msg_p)); - } - - return ecma_op_to_object (value); -} /* jerry_value_to_object */ + ecma_value_t ret_value = ((jerry_external_handler_t) handler_p) (ecma_make_object_value (function_object_p), + this_arg_value, + arguments_list_p, + arguments_list_len); + return ret_value; +} /* jerry_dispatch_external_function */ /** - * Call the ToString ecma builtin operation on the api value. + * Dispatch call to object's native free callback function * * Note: - * - Can throw error, so return value should be checked with 'jerry_value_is_error'. - * - Return value must be freed with 'jerry_release_value'. - * - * @return string value - */ -jerry_value_t -jerry_value_to_string (const jerry_value_t value) /**< input value */ -{ - jerry_assert_api_available (); - - if (ECMA_IS_VALUE_ERROR (value)) - { - return jerry_create_object_value (jerry_create_error (JERRY_ERROR_TYPE, error_value_msg_p)); - } - - return ecma_op_to_string (value); -} /* jerry_value_to_string */ - -/** - * Remove the error flag - * - * @return converted normal value, if value is error - * unchanged value otherwise - */ -jerry_value_t -jerry_value_remove_error_flag (const jerry_value_t value) -{ - return (jerry_value_t) (value & ~ECMA_VALUE_ERROR_FLAG); -} /* jerry_value_remove_error_flag */ - -/** - * Get size of Jerry string - * - * @return number of bytes in the buffer needed to represent the string + * the callback is called during critical GC phase, + * so should not perform any requests to engine. */ -jerry_size_t -jerry_get_string_size (const jerry_string_t *str_p) /**< input string */ +void +jerry_dispatch_object_free_callback (ecma_external_pointer_t freecb_p, /**< pointer to free callback handler */ + ecma_external_pointer_t native_p) /**< native handle, associated + * with freed object */ { - jerry_assert_api_available (); - - return ecma_string_get_size ((ecma_string_t *) str_p); -} /* jerry_get_string_size */ + jerry_make_api_unavailable (); -/** - * Get length of Jerry string - * - * @return number of characters in the string - */ -jerry_length_t -jerry_get_string_length (const jerry_string_t *str_p) /**< input string */ -{ - jerry_assert_api_available (); + ((jerry_object_free_callback_t) freecb_p) ((uintptr_t) native_p); - return ecma_string_get_length ((ecma_string_t *) str_p); -} /* jerry_get_string_length */ + jerry_make_api_available (); +} /* jerry_dispatch_object_free_callback */ diff --git a/jerry-core/jerry.h b/jerry-core/jerry.h deleted file mode 100644 index 4e5e64fcc4..0000000000 --- a/jerry-core/jerry.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright 2015-2016 Samsung Electronics Co., Ltd. - * Copyright 2016 University of Szeged. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JERRY_H -#define JERRY_H - -#include -#include - -#include "jerry-api.h" -#include "jerry-port.h" - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -/** \addtogroup jerry Jerry engine interface - * @{ - */ - -/** - * Jerry flags - */ -typedef enum -{ - JERRY_FLAG_EMPTY = (0u), /**< empty flag set */ - JERRY_FLAG_SHOW_OPCODES = (1u << 0), /**< dump byte-code to stdout after parse */ - JERRY_FLAG_MEM_STATS = (1u << 1), /**< dump memory statistics */ - JERRY_FLAG_MEM_STATS_SEPARATE = (1u << 2), /**< dump memory statistics and reset peak values after parse */ - JERRY_FLAG_PARSE_ONLY = (1u << 3), /**< parse only, prevents script execution */ - JERRY_FLAG_ENABLE_LOG = (1u << 4), /**< enable logging */ -} jerry_flag_t; - -/** - * Jerry engine build date - */ -extern const char * const jerry_build_date; - -/** - * Jerry engine build commit hash - */ -extern const char * const jerry_commit_hash; - -/** - * Jerry engine build branch name - */ -extern const char * const jerry_branch_name; - -#ifdef JERRY_ENABLE_LOG -extern int jerry_debug_level; -extern FILE *jerry_log_file; -#endif /* JERRY_ENABLE_LOG */ - -void jerry_init (jerry_flag_t); -void jerry_cleanup (void); - -void jerry_get_memory_limits (size_t *, size_t *); - -bool jerry_parse (const jerry_char_t *, size_t, jerry_object_t **); -jerry_completion_code_t jerry_run (jerry_value_t *); -jerry_completion_code_t jerry_run_simple (const jerry_char_t *, size_t, jerry_flag_t); - -jerry_completion_code_t jerry_eval (const jerry_char_t *, size_t, bool, bool, jerry_value_t *); -void jerry_gc (void); -void jerry_register_external_magic_strings (const jerry_char_ptr_t *, uint32_t, const jerry_length_t *); - -size_t jerry_parse_and_save_snapshot (const jerry_char_t *, size_t, bool, uint8_t *, size_t); -jerry_completion_code_t jerry_exec_snapshot (const void *, size_t, bool, jerry_value_t *); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* !JERRY_H */ diff --git a/jerry-core/jrt/jrt.h b/jerry-core/jrt/jrt.h index b9f3f88cc6..27000a9529 100644 --- a/jerry-core/jrt/jrt.h +++ b/jerry-core/jrt/jrt.h @@ -20,7 +20,8 @@ #include #include -#include "jerry.h" +#include "jerry-api.h" +#include "jerry-port.h" #include "jrt-types.h" /** diff --git a/jerry-core/lit/lit-globals.h b/jerry-core/lit/lit-globals.h index c2109fee63..8081571595 100644 --- a/jerry-core/lit/lit-globals.h +++ b/jerry-core/lit/lit-globals.h @@ -1,4 +1,5 @@ /* Copyright 2015-2016 Samsung Electronics Co., Ltd. + * Copyright 2016 University of Szeged. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index 417d9adb93..4920b42e6d 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -19,6 +19,7 @@ #include "common.h" +#include "byte-code.h" #include "js-parser.h" #include "js-parser-limits.h" #include "js-lexer.h" diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index d838a5b12a..9c240aaf73 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "ecma-exceptions.h" #include "ecma-helpers.h" #include "ecma-literal-storage.h" #include "js-parser-internal.h" @@ -2238,52 +2239,27 @@ parser_set_show_instrs (int show_instrs) /**< flag indicating whether to dump by * Parse EcamScript source code * * Note: - * returned error object should be freed with jerry_release_object - */ -jsp_status_t -parser_parse_script (const jerry_char_t *source_p, /**< source code */ - size_t size, /**< size of the source code */ - ecma_compiled_code_t **bytecode_data_p, /**< [out] JS bytecode */ - jerry_object_t **error_obj_p) /**< [out] error object */ -{ - parser_error_location parse_error; - *bytecode_data_p = parser_parse_source (source_p, size, false, &parse_error); - - if (!*bytecode_data_p) - { - *error_obj_p = jerry_create_error (JERRY_ERROR_SYNTAX, - (const jerry_char_t *) parser_error_to_string (parse_error.error)); - return JSP_STATUS_SYNTAX_ERROR; - } - - return JSP_STATUS_OK; -} /* parser_parse_script */ - -/** - * Parse EcamScript eval source code + * returned value must be freed with ecma_free_value * - * Note: - * returned error object should be freed with jerry_release_object + * @return true - if success + * syntax error - otherwise */ -jsp_status_t -parser_parse_eval (const jerry_char_t *source_p, /**< source code */ - size_t size, /**< size of the source code */ - bool is_strict, /**< strict mode */ - ecma_compiled_code_t **bytecode_data_p, /**< [out] JS bytecode */ - jerry_object_t **error_obj_p) /**< [out] error object */ +ecma_value_t +parser_parse_script (const uint8_t *source_p, /**< source code */ + size_t size, /**< size of the source code */ + bool is_strict, /**< strict mode */ + ecma_compiled_code_t **bytecode_data_p) /**< [out] JS bytecode */ { parser_error_location parse_error; *bytecode_data_p = parser_parse_source (source_p, size, is_strict, &parse_error); if (!*bytecode_data_p) { - *error_obj_p = jerry_create_error (JERRY_ERROR_SYNTAX, - (const jerry_char_t *) parser_error_to_string (parse_error.error)); - return JSP_STATUS_SYNTAX_ERROR; + return ecma_raise_syntax_error (parser_error_to_string (parse_error.error)); } - return JSP_STATUS_OK; -} /* parser_parse_eval */ + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); +} /* parser_parse_script */ /** * @} diff --git a/jerry-core/parser/js/js-parser.h b/jerry-core/parser/js/js-parser.h index 73621644db..b873003ad8 100644 --- a/jerry-core/parser/js/js-parser.h +++ b/jerry-core/parser/js/js-parser.h @@ -17,7 +17,7 @@ #ifndef JS_PARSER_H #define JS_PARSER_H -#include "byte-code.h" +#include "ecma-globals.h" /** \addtogroup parser Parser * @{ @@ -128,25 +128,8 @@ typedef struct parser_line_counter_t column; /**< column where the error occured */ } parser_error_location; -/** - * Parser completion status - */ -typedef enum -{ - JSP_STATUS_OK, /**< parse finished successfully, no early errors occured */ - JSP_STATUS_SYNTAX_ERROR, /**< SyntaxError early error occured */ -} jsp_status_t; - /* Note: source must be a valid UTF-8 string */ -extern jsp_status_t parser_parse_script (const jerry_char_t *, - size_t, - ecma_compiled_code_t **, - jerry_object_t **); -extern jsp_status_t parser_parse_eval (const jerry_char_t *, - size_t, - bool, - ecma_compiled_code_t **, - jerry_object_t **); +extern ecma_value_t parser_parse_script (const uint8_t *, size_t, bool, ecma_compiled_code_t **); const char *parser_error_to_string (parser_error_t); diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index c95a5e2708..0ef671932f 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -54,11 +54,6 @@ static vm_frame_ctx_t *vm_top_context_p = NULL; */ static bool is_direct_eval_form_call = false; -/** - * Program bytecode pointer - */ -static ecma_compiled_code_t *__program = NULL; - /** * Get the value of object[property]. * @@ -193,17 +188,6 @@ vm_op_set_value (ecma_value_t object, /**< base object */ return completion_value; } /* vm_op_set_value */ -/** - * Initialize interpreter. - */ -void -vm_init (ecma_compiled_code_t *program_p) /**< pointer to byte-code data */ -{ - JERRY_ASSERT (__program == NULL); - - __program = program_p; -} /* vm_init */ - #define CBC_OPCODE(arg1, arg2, arg3, arg4) arg4, /** @@ -221,44 +205,27 @@ static const uint16_t vm_decode_table[] = * Run global code * * Note: - * returned error value should be freed with jerry_release_value - * just when the value becomes unnecessary. + * returned value must be freed with ecma_free_value, when it is no longer needed. * - * @return completion code + * @return ecma value */ -jerry_completion_code_t -vm_run_global (ecma_value_t *error_value_p) /**< [out] error value */ +ecma_value_t +vm_run_global (const ecma_compiled_code_t *bytecode_p) /**< pointer to bytecode to run */ { - jerry_completion_code_t ret_code; - - JERRY_ASSERT (__program != NULL); - 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 (__program, + ecma_value_t ret_value = vm_run (bytecode_p, ecma_make_object_value (glob_obj_p), lex_env_p, false, NULL, 0); - if (ECMA_IS_VALUE_ERROR (ret_value)) - { - *error_value_p = ret_value; - ret_code = JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION; - } - else - { - ecma_free_value (ret_value); - *error_value_p = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - ret_code = JERRY_COMPLETION_CODE_OK; - } - ecma_deref_object (glob_obj_p); ecma_deref_object (lex_env_p); - return ret_code; + return ret_value; } /* vm_run_global */ /** @@ -562,20 +529,6 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } \ while (0) -/** - * Cleanup interpreter - */ -void -vm_finalize (void) -{ - if (__program) - { - ecma_bytecode_deref (__program); - } - - __program = NULL; -} /* vm_finalize */ - /** * Run initializer byte codes. * diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index b158582663..c23bd8ff7b 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -275,9 +275,7 @@ typedef enum VM_EXEC_CONSTRUCT, /**< construct a new object */ } vm_call_operation; -extern void vm_init (ecma_compiled_code_t *); -extern void vm_finalize (void); -extern jerry_completion_code_t vm_run_global (ecma_value_t *); +extern ecma_value_t vm_run_global (const ecma_compiled_code_t *); extern ecma_value_t vm_run_eval (ecma_compiled_code_t *, bool); extern ecma_value_t vm_run (const ecma_compiled_code_t *, ecma_value_t, diff --git a/main-mcu.c b/main-mcu.c index 38ea0552d5..d69a0b2e0c 100644 --- a/main-mcu.c +++ b/main-mcu.c @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "jerry.h" +#include "jerry-api.h" /** * Standalone Jerry exit codes @@ -32,14 +32,7 @@ main (void) const char *source_p = generated_source; const size_t source_size = sizeof (generated_source); - jerry_completion_code_t ret_code = jerry_run_simple ((jerry_char_t *) source_p, source_size, JERRY_FLAG_EMPTY); + bool ret_code = jerry_run_simple ((jerry_char_t *) source_p, source_size, JERRY_INIT_EMPTY); - if (ret_code == JERRY_COMPLETION_CODE_OK) - { - return JERRY_STANDALONE_EXIT_CODE_OK; - } - else - { - return JERRY_STANDALONE_EXIT_CODE_FAIL; - } + return (ret_code ? JERRY_STANDALONE_EXIT_CODE_OK : JERRY_STANDALONE_EXIT_CODE_FAIL); } /* main */ diff --git a/main-unix.c b/main-unix.c index 4b3a34073b..66aa723af3 100644 --- a/main-unix.c +++ b/main-unix.c @@ -19,7 +19,7 @@ #include #include -#include "jerry.h" +#include "jerry-api.h" #include "jerry-port.h" #include "jerry-port-default.h" @@ -71,18 +71,17 @@ read_file (const char *file_name, * * @return true - if only one argument was passed and the argument is a boolean true. */ -static bool -assert_handler (const jerry_object_t *function_obj_p __attribute__((unused)), /**< function object */ +static jerry_value_t +assert_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */ const jerry_value_t this_p __attribute__((unused)), /**< this arg */ const jerry_value_t args_p[], /**< function arguments */ - const jerry_length_t args_cnt, /**< number of function arguments */ - jerry_value_t *ret_val_p __attribute__((unused))) /**< return argument */ + const jerry_length_t args_cnt) /**< number of function arguments */ { if (args_cnt == 1 && jerry_value_is_boolean (args_p[0]) && jerry_get_boolean_value (args_p[0])) { - return true; + return jerry_create_boolean (true); } else { @@ -143,11 +142,12 @@ main (int argc, // FIXME: // jrt_set_mem_limits (max_data_bss_size, max_stack_size); - jerry_flag_t flags = JERRY_FLAG_EMPTY; + jerry_init_flag_t flags = JERRY_INIT_EMPTY; const char *exec_snapshot_file_names[JERRY_MAX_COMMAND_LINE_ARGS]; int exec_snapshots_count = 0; + bool is_parse_only = false; bool is_save_snapshot_mode = false; bool is_save_snapshot_mode_for_global_or_eval = false; const char *save_snapshot_file_name_p = NULL; @@ -166,27 +166,24 @@ main (int argc, } else if (!strcmp ("-v", argv[i]) || !strcmp ("--version", argv[i])) { - printf ("Build date: \t%s\n", jerry_build_date); - printf ("Commit hash:\t%s\n", jerry_commit_hash); - printf ("Branch name:\t%s\n", jerry_branch_name); - printf ("\n"); + printf ("Version: \t%d.%d\n\n", JERRY_API_MAJOR_VERSION, JERRY_API_MINOR_VERSION); return JERRY_STANDALONE_EXIT_CODE_OK; } else if (!strcmp ("--mem-stats", argv[i])) { - flags |= JERRY_FLAG_MEM_STATS; + flags |= JERRY_INIT_MEM_STATS; } else if (!strcmp ("--mem-stats-separate", argv[i])) { - flags |= JERRY_FLAG_MEM_STATS_SEPARATE; + flags |= JERRY_INIT_MEM_STATS_SEPARATE; } else if (!strcmp ("--parse-only", argv[i])) { - flags |= JERRY_FLAG_PARSE_ONLY; + is_parse_only = true; } else if (!strcmp ("--show-opcodes", argv[i])) { - flags |= JERRY_FLAG_SHOW_OPCODES; + flags |= JERRY_INIT_SHOW_OPCODES; } else if (!strcmp ("--save-snapshot-for-global", argv[i]) || !strcmp ("--save-snapshot-for-eval", argv[i])) @@ -208,7 +205,6 @@ main (int argc, return JERRY_STANDALONE_EXIT_CODE_FAIL; } - flags |= JERRY_FLAG_PARSE_ONLY; save_snapshot_file_name_p = argv[i]; } else if (!strcmp ("--exec-snapshot", argv[i])) @@ -240,7 +236,7 @@ main (int argc, } #ifdef JERRY_ENABLE_LOG - flags |= JERRY_FLAG_ENABLE_LOG; + flags |= JERRY_INIT_ENABLE_LOG; jerry_debug_level = argv[i][0] - '0'; #endif /* JERRY_ENABLE_LOG */ } @@ -254,7 +250,7 @@ main (int argc, } #ifdef JERRY_ENABLE_LOG - flags |= JERRY_FLAG_ENABLE_LOG; + flags |= JERRY_INIT_ENABLE_LOG; log_file_name = argv[i]; #endif /* JERRY_ENABLE_LOG */ } @@ -313,23 +309,22 @@ main (int argc, jerry_init (flags); - jerry_object_t *global_obj_p = jerry_get_global (); - jerry_object_t *assert_func_p = jerry_create_external_function (assert_handler); - jerry_value_t assert_value = jerry_create_object_value (assert_func_p); + jerry_value_t global_obj_val = jerry_get_global_object (); + jerry_value_t assert_value = jerry_create_external_function (assert_handler); - bool is_assert_added = jerry_set_object_field_value (global_obj_p, - (jerry_char_t *) "assert", - assert_value); + jerry_value_t assert_func_name_val = jerry_create_string ((jerry_char_t *) "assert"); + bool is_assert_added = jerry_set_property (global_obj_val, assert_func_name_val, assert_value); + jerry_release_value (assert_func_name_val); jerry_release_value (assert_value); - jerry_release_object (global_obj_p); + jerry_release_value (global_obj_val); if (!is_assert_added) { jerry_port_errormsg ("Warning: failed to register 'assert' method."); } - jerry_completion_code_t ret_code = JERRY_COMPLETION_CODE_OK; + jerry_value_t ret_value = jerry_create_undefined (); for (int i = 0; i < exec_snapshots_count; i++) { @@ -338,28 +333,22 @@ main (int argc, if (snapshot_p == NULL) { - ret_code = JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION; + ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ""); } else { - jerry_value_t ret_value; - ret_code = jerry_exec_snapshot ((void *) snapshot_p, - snapshot_size, - true, - &ret_value); - assert (jerry_value_is_undefined (ret_value)); + ret_value = jerry_exec_snapshot ((void *) snapshot_p, + snapshot_size, + true); } - if (ret_code != JERRY_COMPLETION_CODE_OK) + if (jerry_value_has_error_flag (ret_value)) { break; } } - jerry_object_t *err_obj_p = NULL; - jerry_value_t err_value = jerry_create_undefined_value (); - - if (ret_code == JERRY_COMPLETION_CODE_OK) + if (!jerry_value_has_error_flag (ret_value)) { for (int i = 0; i < files_counter; i++) { @@ -368,7 +357,7 @@ main (int argc, if (source_p == NULL) { - ret_code = JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION; + ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ""); } if (is_save_snapshot_mode) @@ -378,11 +367,12 @@ main (int argc, size_t snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) source_p, source_size, is_save_snapshot_mode_for_global_or_eval, + false, snapshot_save_buffer, JERRY_BUFFER_SIZE); if (snapshot_size == 0) { - ret_code = JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION; + ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ""); } else { @@ -393,18 +383,17 @@ main (int argc, } else { - if (!jerry_parse (source_p, source_size, &err_obj_p)) - { - /* unhandled SyntaxError */ - ret_code = JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION; - } - else if ((flags & JERRY_FLAG_PARSE_ONLY) == 0) + ret_value = jerry_parse (source_p, source_size, false); + + if (!jerry_value_has_error_flag (ret_value) && !is_parse_only) { - ret_code = jerry_run (&err_value); + jerry_value_t func_val = ret_value; + ret_value = jerry_run (func_val); + jerry_release_value (func_val); } } - if (ret_code != JERRY_COMPLETION_CODE_OK) + if (jerry_value_has_error_flag (ret_value)) { break; } @@ -416,16 +405,18 @@ main (int argc, const char *prompt = "jerry> "; bool is_done = false; - jerry_object_t *global_obj_p = jerry_get_global (); - jerry_value_t print_function = jerry_get_object_field_value (global_obj_p, - (jerry_char_t *) "print"); + jerry_value_t global_obj_val = jerry_get_global_object (); + jerry_value_t print_func_name_val = jerry_create_string ((jerry_char_t *) "print"); + jerry_value_t print_function = jerry_get_property (global_obj_val, print_func_name_val); + + jerry_release_value (print_func_name_val); - if (jerry_value_is_error (print_function)) + if (jerry_value_has_error_flag (print_function)) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } - if (!jerry_is_function (jerry_get_object_value (print_function))) + if (!jerry_value_is_function (print_function)) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } @@ -457,22 +448,21 @@ main (int argc, if (len > 0) { /* Evaluate the line */ - jerry_value_t ret_val; - ret_code = jerry_eval (buffer, len, false, false, &ret_val); + jerry_value_t ret_val_eval = jerry_eval (buffer, len, false); /* Print return value */ - const jerry_value_t args[] = { ret_val }; - jerry_value_t ret_val_print = jerry_call_function (jerry_get_object_value (print_function), - NULL, + const jerry_value_t args[] = { ret_val_eval }; + jerry_value_t ret_val_print = jerry_call_function (print_function, + jerry_create_undefined (), args, 1); jerry_release_value (ret_val_print); - jerry_release_value (ret_val); + jerry_release_value (ret_val_eval); } } - jerry_release_object (global_obj_p); + jerry_release_value (global_obj_val); jerry_release_value (print_function); } @@ -484,49 +474,31 @@ main (int argc, } #endif /* JERRY_ENABLE_LOG */ - if (ret_code == JERRY_COMPLETION_CODE_OK) - { - jerry_cleanup (); - return JERRY_STANDALONE_EXIT_CODE_OK; - } - else if (ret_code == JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION) - { - jerry_string_t *err_str_p = NULL; + int ret_code = JERRY_STANDALONE_EXIT_CODE_OK; - if (err_obj_p != NULL) - { - jerry_value_t err_value = jerry_create_object_value (err_obj_p); - err_str_p = jerry_get_string_value (jerry_value_to_string (err_value)); - jerry_release_object (err_obj_p); - } - else if (!jerry_value_is_undefined (err_value)) - { - err_value = jerry_value_remove_error_flag (err_value); - err_str_p = jerry_get_string_value (jerry_value_to_string (err_value)); - jerry_release_value (err_value); - } + if (jerry_value_has_error_flag (ret_value)) + { + jerry_value_clear_error_flag (&ret_value); + jerry_value_t err_str_val = jerry_value_to_string (ret_value); - if (__builtin_expect (!!(err_str_p != NULL), 1)) - { - jerry_char_t err_str_buf[256]; + jerry_char_t err_str_buf[256]; + jerry_size_t err_str_size = jerry_get_string_size (err_str_val); - jerry_size_t err_str_size = jerry_get_string_size (err_str_p); - assert (err_str_size < 256); - jerry_size_t sz = jerry_string_to_char_buffer (err_str_p, err_str_buf, err_str_size); - assert (sz == err_str_size); - err_str_buf[err_str_size] = 0; + assert (err_str_size < 256); + jerry_size_t sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); + assert (sz == err_str_size); + err_str_buf[err_str_size] = 0; - jerry_port_errormsg ("Script Error: unhandled exception: %s\n", err_str_buf); + jerry_port_errormsg ("Script Error: unhandled exception: %s\n", err_str_buf); - jerry_release_string (err_str_p); - } + jerry_release_value (err_str_val); - jerry_cleanup (); - return JERRY_STANDALONE_EXIT_CODE_FAIL; + ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; } - assert (ret_code == JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_FORMAT - || ret_code == JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_VERSION); + jerry_release_value (ret_value); jerry_cleanup (); - return JERRY_STANDALONE_EXIT_CODE_FAIL; + + return ret_code; + } /* main */ diff --git a/tests/unit/test-api.c b/tests/unit/test-api.c index 349ec5d32f..22aa4f6431 100644 --- a/tests/unit/test-api.c +++ b/tests/unit/test-api.c @@ -14,9 +14,8 @@ * limitations under the License. */ -#include "jerry.h" -#include "jerry-api.h" #include "config.h" +#include "jerry-api.h" #include "test-common.h" @@ -63,24 +62,23 @@ const char *test_source = ( bool test_api_is_free_callback_was_called = false; -static bool -handler (const jerry_object_t *function_obj_p, /**< function object */ +static jerry_value_t +handler (const jerry_value_t func_obj_val, /**< function object */ const jerry_value_t this_val, /**< this value */ const jerry_value_t args_p[], /**< arguments list */ - const jerry_length_t args_cnt, /**< arguments length */ - jerry_value_t *ret_val_p) /**< [out] return value */ + const jerry_length_t args_cnt) /**< arguments length */ { char buffer[32]; jerry_size_t sz; - printf ("ok %p %p %p %d %p\n", function_obj_p, this_val, args_p, args_cnt, ret_val_p); + printf ("ok %d %d %p %d\n", func_obj_val, this_val, args_p, args_cnt); JERRY_ASSERT (args_cnt == 2); JERRY_ASSERT (jerry_value_is_string (args_p[0])); - sz = jerry_get_string_size (jerry_get_string_value (args_p[0])); + sz = jerry_get_string_size (args_p[0]); JERRY_ASSERT (sz == 1); - sz = jerry_string_to_char_buffer (jerry_get_string_value (args_p[0]), + sz = jerry_string_to_char_buffer (args_p[0], (jerry_char_t *) buffer, sz); JERRY_ASSERT (sz == 1); @@ -88,26 +86,18 @@ handler (const jerry_object_t *function_obj_p, /**< function object */ JERRY_ASSERT (jerry_value_is_boolean (args_p[1])); - *ret_val_p = jerry_create_string_value (jerry_create_string ((jerry_char_t *) "string from handler")); - - return true; + return jerry_create_string ((jerry_char_t *) "string from handler"); } /* handler */ -static bool -handler_throw_test (const jerry_object_t *function_obj_p, /**< function object */ +static jerry_value_t +handler_throw_test (const jerry_value_t func_obj_val, /**< function object */ const jerry_value_t this_val, /**< this value */ const jerry_value_t args_p[], /**< arguments list */ - const jerry_length_t args_cnt, /**< arguments length */ - jerry_value_t *ret_val_p) /**< [out] return value */ + const jerry_length_t args_cnt) /**< arguments length */ { - printf ("ok %p %p %p %d %p\n", function_obj_p, this_val, args_p, args_cnt, ret_val_p); - - jerry_object_t *error_p = jerry_create_error (JERRY_ERROR_TYPE, - (jerry_char_t *) "error"); - - *ret_val_p = jerry_create_object_value (error_p); + printf ("ok %d %d %p %d\n", func_obj_val, this_val, args_p, args_cnt); - return false; + return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "error"); } /* handler_throw_test */ static void @@ -119,14 +109,13 @@ handler_construct_freecb (uintptr_t native_p) test_api_is_free_callback_was_called = true; } /* handler_construct_freecb */ -static bool -handler_construct (const jerry_object_t *function_obj_p, /**< function object */ +static jerry_value_t +handler_construct (const jerry_value_t func_obj_val, /**< function object */ const jerry_value_t this_val, /**< this value */ const jerry_value_t args_p[], /**< arguments list */ - const jerry_length_t args_cnt, /**< arguments length */ - jerry_value_t *ret_val_p) /**< [out] return value */ + const jerry_length_t args_cnt) /**< arguments length */ { - printf ("ok construct %p %p %p %d %p\n", function_obj_p, this_val, args_p, args_cnt, ret_val_p); + printf ("ok construct %d %d %p %d\n", func_obj_val, this_val, args_p, args_cnt); JERRY_ASSERT (jerry_value_is_object (this_val)); @@ -134,24 +123,24 @@ handler_construct (const jerry_object_t *function_obj_p, /**< function object */ JERRY_ASSERT (jerry_value_is_boolean (args_p[0])); JERRY_ASSERT (jerry_get_boolean_value (args_p[0]) == true); - jerry_set_object_field_value (jerry_get_object_value (this_val), - (jerry_char_t *) "value_field", - args_p[0]); + jerry_value_t field_name = jerry_create_string ((jerry_char_t *) "value_field"); + jerry_set_property (this_val, field_name, args_p[0]); + jerry_release_value (field_name); - jerry_set_object_native_handle (jerry_get_object_value (this_val), + jerry_set_object_native_handle (this_val, (uintptr_t) 0x0000000000000000ull, handler_construct_freecb); uintptr_t ptr; - bool is_ok = jerry_get_object_native_handle (jerry_get_object_value (this_val), &ptr); + bool is_ok = jerry_get_object_native_handle (this_val, &ptr); JERRY_ASSERT (is_ok && ptr == (uintptr_t) 0x0000000000000000ull); /* check if setting handle for second time is handled correctly */ - jerry_set_object_native_handle (jerry_get_object_value (this_val), + jerry_set_object_native_handle (this_val, (uintptr_t) 0x0012345678abcdefull, handler_construct_freecb); - return true; + return jerry_create_boolean (true); } /* handler_construct */ /** @@ -190,7 +179,7 @@ const jerry_char_ptr_t magic_string_items[] = }; static bool -foreach (const jerry_string_t *name, /**< field name */ +foreach (const jerry_value_t name, /**< field name */ const jerry_value_t value, /**< field value */ void *user_data) /**< user data */ { @@ -198,6 +187,12 @@ foreach (const jerry_string_t *name, /**< field name */ jerry_size_t sz = jerry_string_to_char_buffer (name, (jerry_char_t *) str_buf_p, 128); str_buf_p[sz] = '\0'; + if (sz == 0) + { + JERRY_ASSERT (!strncmp ((const char *) user_data, "user_data", 9)); + return true; + } + if (!strncmp (str_buf_p, "alpha", (size_t) sz)) { JERRY_ASSERT (jerry_value_is_number (value)); @@ -220,23 +215,19 @@ foreach (const jerry_string_t *name, /**< field name */ else if (!strncmp (str_buf_p, "echo", (size_t) sz)) { JERRY_ASSERT (jerry_value_is_string (value)); - jerry_size_t echo_sz = jerry_string_to_char_buffer (jerry_get_string_value (value), + jerry_size_t echo_sz = jerry_string_to_char_buffer (value, (jerry_char_t *) str_buf_p, 128); str_buf_p[echo_sz] = '\0'; JERRY_ASSERT (!strncmp (str_buf_p, "foobar", (size_t) echo_sz)); } - else - { - JERRY_ASSERT (false); - } - JERRY_ASSERT (!strncmp ((const char *) user_data, "user_data", 9)); - return true; + JERRY_ASSERT (false); + return false; } /* foreach */ static bool -foreach_exception (const jerry_string_t *name, /**< field name */ +foreach_exception (const jerry_value_t name, /**< field name */ const jerry_value_t value, /**< field value */ void *user_data) /**< user data */ { @@ -250,11 +241,12 @@ foreach_exception (const jerry_string_t *name, /**< field name */ { JERRY_ASSERT (false); } + return true; } /* foreach_exception */ static bool -foreach_subset (const jerry_string_t *name, /**< field name */ +foreach_subset (const jerry_value_t name, /**< field name */ const jerry_value_t value, /**< field value */ void *user_data) /**< user data */ { @@ -270,73 +262,109 @@ foreach_subset (const jerry_string_t *name, /**< field name */ return true; } /* foreach_subset */ +static jerry_value_t +get_property (const jerry_value_t obj_val, /**< object value */ + const char *str_p) /**< property name */ +{ + jerry_value_t prop_name_val = jerry_create_string ((const jerry_char_t *) str_p); + jerry_value_t ret_val = jerry_get_property (obj_val, prop_name_val); + jerry_release_value (prop_name_val); + return ret_val; +} /* get_property */ + +static jerry_value_t +set_property (const jerry_value_t obj_val, /**< object value */ + const char *str_p, /**< property name */ + const jerry_value_t val) /**< value to set */ +{ + jerry_value_t prop_name_val = jerry_create_string ((const jerry_char_t *) str_p); + jerry_value_t ret_val = jerry_set_property (obj_val, prop_name_val, val); + jerry_release_value (prop_name_val); + return ret_val; +} /* set_property */ + +static bool +test_run_simple (const char *script_p) /**< source code to run */ +{ + size_t script_size = strlen (script_p); + + return jerry_run_simple ((const jerry_char_t *) script_p, script_size, JERRY_INIT_EMPTY); +} /* test_run_simple */ + int main (void) { TEST_INIT (); - jerry_init (JERRY_FLAG_EMPTY); - bool is_ok; jerry_size_t sz; jerry_value_t val_t, val_foo, val_bar, val_A, val_A_prototype, val_a, val_a_foo, val_value_field, val_p, val_np; - jerry_value_t val_external, val_external_construct, val_call_external; - jerry_object_t *global_obj_p, *obj_p; - jerry_object_t *external_func_p, *external_construct_p; - jerry_object_t *throw_test_handler_p; - jerry_object_t *err_obj_p = NULL; + jerry_value_t val_call_external; + jerry_value_t global_obj_val, obj_val; + jerry_value_t external_func_val, external_construct_val; + jerry_value_t throw_test_handler_val; + jerry_value_t parsed_code_val, proto_val, prim_val; jerry_value_t res, args[2]; char buffer[32]; - is_ok = jerry_parse ((jerry_char_t *) test_source, strlen (test_source), &err_obj_p); - JERRY_ASSERT (is_ok && err_obj_p == NULL); - - is_ok = (jerry_run (&res) == JERRY_COMPLETION_CODE_OK); + is_ok = test_run_simple ("print ('Hello, World!');"); JERRY_ASSERT (is_ok); - JERRY_ASSERT (jerry_value_is_undefined (res)); - global_obj_p = jerry_get_global (); + is_ok = test_run_simple ("throw 'Hello World';"); + JERRY_ASSERT (!is_ok); + + jerry_init (JERRY_INIT_EMPTY); + + parsed_code_val = jerry_parse ((jerry_char_t *) test_source, strlen (test_source), false); + JERRY_ASSERT (!jerry_value_has_error_flag (parsed_code_val)); + + res = jerry_run (parsed_code_val); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + jerry_release_value (res); + jerry_release_value (parsed_code_val); + + global_obj_val = jerry_get_global_object (); // Test corner case for jerry_string_to_char_buffer - args[0] = jerry_create_string_value (jerry_create_string ((jerry_char_t *) "")); - sz = jerry_get_string_size (jerry_get_string_value (args[0])); + args[0] = jerry_create_string ((jerry_char_t *) ""); + sz = jerry_get_string_size (args[0]); JERRY_ASSERT (sz == 0); jerry_release_value (args[0]); // Get global.boo (non-existing field) - val_t = jerry_get_object_field_value (global_obj_p, (jerry_char_t *) "boo"); - JERRY_ASSERT (!jerry_value_is_error (val_t)); + val_t = get_property (global_obj_val, "boo"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_t)); JERRY_ASSERT (jerry_value_is_undefined (val_t)); // Get global.t - val_t = jerry_get_object_field_value (global_obj_p, (jerry_char_t *) "t"); - JERRY_ASSERT (!jerry_value_is_error (val_t)); + val_t = get_property (global_obj_val, "t"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_t)); JERRY_ASSERT (jerry_value_is_number (val_t) && jerry_get_number_value (val_t) == 1.0); jerry_release_value (val_t); // Get global.foo - val_foo = jerry_get_object_field_value (global_obj_p, (jerry_char_t *) "foo"); - JERRY_ASSERT (!jerry_value_is_error (val_foo)); + val_foo = get_property (global_obj_val, "foo"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_foo)); JERRY_ASSERT (jerry_value_is_object (val_foo)); // Call foo (4, 2) - args[0] = jerry_create_number_value (4); - args[1] = jerry_create_number_value (2); - res = jerry_call_function (jerry_get_object_value (val_foo), NULL, args, 2); - JERRY_ASSERT (!jerry_value_is_error (res)); + args[0] = jerry_create_number (4); + args[1] = jerry_create_number (2); + res = jerry_call_function (val_foo, jerry_create_undefined (), args, 2); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_number (res) && jerry_get_number_value (res) == 1.0); jerry_release_value (res); // Get global.bar - val_bar = jerry_get_object_field_value (global_obj_p, (jerry_char_t *) "bar"); - JERRY_ASSERT (!jerry_value_is_error (val_bar)); + val_bar = get_property (global_obj_val, "bar"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_bar)); JERRY_ASSERT (jerry_value_is_object (val_bar)); // Call bar (4, 2) - res = jerry_call_function (jerry_get_object_value (val_bar), NULL, args, 2); - JERRY_ASSERT (!jerry_value_is_error (res)); + res = jerry_call_function (val_bar, jerry_create_undefined (), args, 2); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_number (res) && jerry_get_number_value (res) == 5.0); jerry_release_value (res); @@ -344,17 +372,19 @@ main (void) // Set global.t = "abcd" jerry_release_value (args[0]); - args[0] = jerry_create_string_value (jerry_create_string ((jerry_char_t *) "abcd")); - is_ok = jerry_set_object_field_value (global_obj_p, (jerry_char_t *) "t", args[0]); - JERRY_ASSERT (is_ok); + args[0] = jerry_create_string ((jerry_char_t *) "abcd"); + res = set_property (global_obj_val, "t", args[0]); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + JERRY_ASSERT (jerry_get_boolean_value (res)); + jerry_release_value (res); // Call foo (4, 2) - res = jerry_call_function (jerry_get_object_value (val_foo), NULL, args, 2); - JERRY_ASSERT (!jerry_value_is_error (res)); + res = jerry_call_function (val_foo, jerry_create_undefined (), args, 2); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_string (res)); - sz = jerry_get_string_size (jerry_get_string_value (res)); + sz = jerry_get_string_size (res); JERRY_ASSERT (sz == 4); - sz = jerry_string_to_char_buffer (jerry_get_string_value (res), (jerry_char_t *) buffer, sz); + sz = jerry_string_to_char_buffer (res, (jerry_char_t *) buffer, sz); JERRY_ASSERT (sz == 4); jerry_release_value (res); JERRY_ASSERT (!strncmp (buffer, "abcd", (size_t) sz)); @@ -362,69 +392,64 @@ main (void) jerry_release_value (args[1]); // Get global.A - val_A = jerry_get_object_field_value (global_obj_p, (jerry_char_t *) "A"); - JERRY_ASSERT (!jerry_value_is_error (val_A)); + val_A = get_property (global_obj_val, "A"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_A)); JERRY_ASSERT (jerry_value_is_object (val_A)); // Get A.prototype - is_ok = jerry_is_constructor (jerry_get_object_value (val_A)); + is_ok = jerry_value_is_constructor (val_A); JERRY_ASSERT (is_ok); - val_A_prototype = jerry_get_object_field_value (jerry_get_object_value (val_A), - (jerry_char_t *) "prototype"); - JERRY_ASSERT (!jerry_value_is_error (val_A_prototype)); + val_A_prototype = get_property (val_A, "prototype"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_A_prototype)); JERRY_ASSERT (jerry_value_is_object (val_A_prototype)); jerry_release_value (val_A); // Set A.prototype.foo = global.foo - is_ok = jerry_set_object_field_value (jerry_get_object_value (val_A_prototype), - (jerry_char_t *) "foo", - val_foo); - JERRY_ASSERT (is_ok); + res = set_property (val_A_prototype, "foo", val_foo); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + JERRY_ASSERT (jerry_get_boolean_value (res)); + jerry_release_value (res); jerry_release_value (val_A_prototype); jerry_release_value (val_foo); // Get global.a - val_a = jerry_get_object_field_value (global_obj_p, (jerry_char_t *) "a"); - JERRY_ASSERT (!jerry_value_is_error (val_a)); + val_a = get_property (global_obj_val, "a"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_a)); JERRY_ASSERT (jerry_value_is_object (val_a)); // Get a.t - res = jerry_get_object_field_value (jerry_get_object_value (val_a), (jerry_char_t *) "t"); - JERRY_ASSERT (!jerry_value_is_error (res)); + res = get_property (val_a, "t"); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_number (res) && jerry_get_number_value (res) == 12.0); jerry_release_value (res); // foreach properties - val_p = jerry_get_object_field_value (global_obj_p, (jerry_char_t *) "p"); - is_ok = jerry_foreach_object_field (jerry_get_object_value (val_p), foreach, (void *) "user_data"); + val_p = get_property (global_obj_val, "p"); + is_ok = jerry_foreach_object_property (val_p, foreach, (void *) "user_data"); JERRY_ASSERT (is_ok); // break foreach at third element int count = 0; - is_ok = jerry_foreach_object_field (jerry_get_object_value (val_p), foreach_subset, &count); + is_ok = jerry_foreach_object_property (val_p, foreach_subset, &count); JERRY_ASSERT (is_ok); JERRY_ASSERT (count == 3); jerry_release_value (val_p); // foreach with throw test - val_np = jerry_get_object_field_value (global_obj_p, (jerry_char_t *) "np"); - is_ok = !jerry_foreach_object_field (jerry_get_object_value (val_np), foreach_exception, NULL); + val_np = get_property (global_obj_val, "np"); + is_ok = !jerry_foreach_object_property (val_np, foreach_exception, NULL); JERRY_ASSERT (is_ok); jerry_release_value (val_np); // Get a.foo - val_a_foo = jerry_get_object_field_value (jerry_get_object_value (val_a), - (jerry_char_t *) "foo"); - JERRY_ASSERT (!jerry_value_is_error (val_a_foo)); + val_a_foo = get_property (val_a, "foo"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_a_foo)); JERRY_ASSERT (jerry_value_is_object (val_a_foo)); // Call a.foo () - res = jerry_call_function (jerry_get_object_value (val_a_foo), - jerry_get_object_value (val_a), - NULL, - 0); - JERRY_ASSERT (!jerry_value_is_error (res)); + res = jerry_call_function (val_a_foo, val_a, NULL, 0); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_number (res) && jerry_get_number_value (res) == 12.0); jerry_release_value (res); @@ -433,108 +458,88 @@ main (void) jerry_release_value (val_a); // Create native handler bound function object and set it to 'external' variable - external_func_p = jerry_create_external_function (handler); - JERRY_ASSERT (external_func_p != NULL - && jerry_is_function (external_func_p) - && jerry_is_constructor (external_func_p)); - - val_external = jerry_create_object_value (external_func_p); - is_ok = jerry_set_object_field_value (global_obj_p, - (jerry_char_t *) "external", - val_external); - JERRY_ASSERT (is_ok); - jerry_release_value (val_external); + external_func_val = jerry_create_external_function (handler); + JERRY_ASSERT (jerry_value_is_function (external_func_val) + && jerry_value_is_constructor (external_func_val)); + + res = set_property (global_obj_val, "external", external_func_val); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + JERRY_ASSERT (jerry_get_boolean_value (res)); + jerry_release_value (external_func_val); // Call 'call_external' function that should call external function created above - val_call_external = jerry_get_object_field_value (global_obj_p, - (jerry_char_t *) "call_external"); - JERRY_ASSERT (!jerry_value_is_error (val_call_external)); + val_call_external = get_property (global_obj_val, "call_external"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_call_external)); JERRY_ASSERT (jerry_value_is_object (val_call_external)); - res = jerry_call_function (jerry_get_object_value (val_call_external), - global_obj_p, - NULL, - 0); + res = jerry_call_function (val_call_external, global_obj_val, NULL, 0); jerry_release_value (val_call_external); - JERRY_ASSERT (!jerry_value_is_error (res)); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_string (res)); - sz = jerry_get_string_size (jerry_get_string_value (res)); + sz = jerry_get_string_size (res); JERRY_ASSERT (sz == 19); - sz = jerry_string_to_char_buffer (jerry_get_string_value (res), (jerry_char_t *) buffer, sz); + sz = jerry_string_to_char_buffer (res, (jerry_char_t *) buffer, sz); JERRY_ASSERT (sz == 19); jerry_release_value (res); JERRY_ASSERT (!strncmp (buffer, "string from handler", (size_t) sz)); // Create native handler bound function object and set it to 'external_construct' variable - external_construct_p = jerry_create_external_function (handler_construct); - JERRY_ASSERT (external_construct_p != NULL - && jerry_is_function (external_construct_p) - && jerry_is_constructor (external_construct_p)); - - val_external_construct = jerry_create_object_value (external_construct_p); - is_ok = jerry_set_object_field_value (global_obj_p, - (jerry_char_t *) "external_construct", - val_external_construct); - JERRY_ASSERT (is_ok); + external_construct_val = jerry_create_external_function (handler_construct); + JERRY_ASSERT (jerry_value_is_function (external_construct_val) + && jerry_value_is_constructor (external_construct_val)); + + res = set_property (global_obj_val, "external_construct", external_construct_val); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + JERRY_ASSERT (jerry_get_boolean_value (res)); + jerry_release_value (res); // Call external function created above, as constructor - args[0] = jerry_create_boolean_value (true); - res = jerry_construct_object (external_construct_p, args, 1); - JERRY_ASSERT (!jerry_value_is_error (res)); + args[0] = jerry_create_boolean (true); + res = jerry_construct_object (external_construct_val, args, 1); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_object (res)); - val_value_field = jerry_get_object_field_value (jerry_get_object_value (res), - (jerry_char_t *) "value_field"); + val_value_field = get_property (res, "value_field"); // Get 'value_field' of constructed object - JERRY_ASSERT (!jerry_value_is_error (val_value_field)); + JERRY_ASSERT (!jerry_value_has_error_flag (val_value_field)); JERRY_ASSERT (jerry_value_is_boolean (val_value_field) && jerry_get_boolean_value (val_value_field)); jerry_release_value (val_value_field); - jerry_release_object (external_construct_p); + jerry_release_value (external_construct_val); uintptr_t ptr; - is_ok = jerry_get_object_native_handle (jerry_get_object_value (res), &ptr); + is_ok = jerry_get_object_native_handle (res, &ptr); JERRY_ASSERT (is_ok && ptr == (uintptr_t) 0x0012345678abcdefull); jerry_release_value (res); - // Test: Throwing exception from native handler. - throw_test_handler_p = jerry_create_external_function (handler_throw_test); - JERRY_ASSERT (throw_test_handler_p != NULL - && jerry_is_function (throw_test_handler_p)); - - val_t = jerry_create_object_value (throw_test_handler_p); - is_ok = jerry_set_object_field_value (global_obj_p, - (jerry_char_t *) "throw_test", - val_t); - JERRY_ASSERT (is_ok); - jerry_release_value (val_t); + throw_test_handler_val = jerry_create_external_function (handler_throw_test); + JERRY_ASSERT (jerry_value_is_function (throw_test_handler_val)); - val_t = jerry_get_object_field_value (global_obj_p, (jerry_char_t *) "call_throw_test"); - JERRY_ASSERT (!jerry_value_is_error (val_t)); + res = set_property (global_obj_val, "throw_test", throw_test_handler_val); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + JERRY_ASSERT (jerry_get_boolean_value (res)); + jerry_release_value (res); + jerry_release_value (throw_test_handler_val); + + val_t = get_property (global_obj_val, "call_throw_test"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_t)); JERRY_ASSERT (jerry_value_is_object (val_t)); - res = jerry_call_function (jerry_get_object_value (val_t), - global_obj_p, - NULL, - 0); - JERRY_ASSERT (!jerry_value_is_error (res)); + res = jerry_call_function (val_t, global_obj_val, NULL, 0); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); jerry_release_value (val_t); jerry_release_value (res); // Test: Unhandled exception in called function - val_t = jerry_get_object_field_value (global_obj_p, - (jerry_char_t *) "throw_reference_error"); - JERRY_ASSERT (!jerry_value_is_error (val_t)); + val_t = get_property (global_obj_val, "throw_reference_error"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_t)); JERRY_ASSERT (jerry_value_is_object (val_t)); - res = jerry_call_function (jerry_get_object_value (val_t), - global_obj_p, - NULL, - 0); + res = jerry_call_function (val_t, global_obj_val, NULL, 0); - JERRY_ASSERT (jerry_value_is_error (res)); + JERRY_ASSERT (jerry_value_has_error_flag (res)); jerry_release_value (val_t); // 'res' should contain exception object @@ -542,27 +547,23 @@ main (void) jerry_release_value (res); // Test: Call of non-function - obj_p = jerry_create_object (); - res = jerry_call_function (obj_p, - global_obj_p, - NULL, - 0); - JERRY_ASSERT (jerry_value_is_error (res)); + obj_val = jerry_create_object (); + res = jerry_call_function (obj_val, global_obj_val, NULL, 0); + JERRY_ASSERT (jerry_value_has_error_flag (res)); // 'res' should contain exception object JERRY_ASSERT (jerry_value_is_object (res)); jerry_release_value (res); - jerry_release_object (obj_p); + jerry_release_value (obj_val); // Test: Unhandled exception in function called, as constructor - val_t = jerry_get_object_field_value (global_obj_p, - (jerry_char_t *) "throw_reference_error"); - JERRY_ASSERT (!jerry_value_is_error (val_t)); + val_t = get_property (global_obj_val, "throw_reference_error"); + JERRY_ASSERT (!jerry_value_has_error_flag (val_t)); JERRY_ASSERT (jerry_value_is_object (val_t)); - res = jerry_construct_object (jerry_get_object_value (val_t), NULL, 0); - JERRY_ASSERT (jerry_value_is_error (res)); + res = jerry_construct_object (val_t, NULL, 0); + JERRY_ASSERT (jerry_value_has_error_flag (res)); jerry_release_value (val_t); // 'res' should contain exception object @@ -570,50 +571,122 @@ main (void) jerry_release_value (res); // Test: Call of non-function as constructor - obj_p = jerry_create_object (); - res = jerry_construct_object (obj_p, NULL, 0); - JERRY_ASSERT (jerry_value_is_error (res)); + obj_val = jerry_create_object (); + res = jerry_construct_object (obj_val, NULL, 0); + JERRY_ASSERT (jerry_value_has_error_flag (res)); // 'res' should contain exception object JERRY_ASSERT (jerry_value_is_object (res)); jerry_release_value (res); - jerry_release_object (obj_p); - + jerry_release_value (obj_val); // Test: Array Object API - jerry_object_t *array_obj_p = jerry_create_array_object (10); - JERRY_ASSERT (jerry_is_array (array_obj_p)); - JERRY_ASSERT (jerry_get_array_length (array_obj_p) == 10); + jerry_value_t array_obj_val = jerry_create_array (10); + JERRY_ASSERT (jerry_value_is_array (array_obj_val)); + JERRY_ASSERT (jerry_get_array_length (array_obj_val) == 10); - jerry_value_t v_in = jerry_create_number_value (10.5); - jerry_set_array_index_value (array_obj_p, 5, v_in); - jerry_value_t v_out; - jerry_get_array_index_value (array_obj_p, 5, &v_out); + jerry_value_t v_in = jerry_create_number (10.5); + jerry_set_property_by_index (array_obj_val, 5, v_in); + jerry_value_t v_out = jerry_get_property_by_index (array_obj_val, 5); JERRY_ASSERT (jerry_value_is_number (v_out) && jerry_get_number_value (v_out) == 10.5); jerry_release_value (v_in); jerry_release_value (v_out); - jerry_release_object (array_obj_p); + jerry_release_value (array_obj_val); + + // Test: init property descriptor + jerry_property_descriptor_t prop_desc; + jerry_init_property_descriptor_fields (&prop_desc); + JERRY_ASSERT (prop_desc.is_value_defined == false); + JERRY_ASSERT (jerry_value_is_undefined (prop_desc.value)); + JERRY_ASSERT (prop_desc.is_writable_defined == false); + JERRY_ASSERT (prop_desc.is_writable == false); + JERRY_ASSERT (prop_desc.is_enumerable_defined == false); + JERRY_ASSERT (prop_desc.is_enumerable == false); + JERRY_ASSERT (prop_desc.is_configurable_defined == false); + JERRY_ASSERT (prop_desc.is_configurable == false); + JERRY_ASSERT (prop_desc.is_get_defined == false); + JERRY_ASSERT (jerry_value_is_undefined (prop_desc.getter)); + JERRY_ASSERT (prop_desc.is_set_defined == false); + JERRY_ASSERT (jerry_value_is_undefined (prop_desc.setter)); + + // Test: define own properties + jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "my_defined_property"); + prop_desc.is_value_defined = true; + prop_desc.value = jerry_acquire_value (prop_name); + res = jerry_define_own_property (global_obj_val, prop_name, &prop_desc); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + JERRY_ASSERT (jerry_value_is_boolean (res)); + JERRY_ASSERT (jerry_get_boolean_value (res)); + jerry_release_value (res); + jerry_free_property_descriptor_fields (&prop_desc); + + // Test: get own property descriptor + is_ok = jerry_get_own_property_descriptor (global_obj_val, prop_name, &prop_desc); + JERRY_ASSERT (is_ok); + JERRY_ASSERT (prop_desc.is_value_defined == true); + JERRY_ASSERT (jerry_value_is_string (prop_desc.value)); + JERRY_ASSERT (prop_desc.is_writable == false); + JERRY_ASSERT (prop_desc.is_enumerable == false); + JERRY_ASSERT (prop_desc.is_configurable == false); + JERRY_ASSERT (prop_desc.is_get_defined == false); + JERRY_ASSERT (jerry_value_is_undefined (prop_desc.getter)); + JERRY_ASSERT (prop_desc.is_set_defined == false); + JERRY_ASSERT (jerry_value_is_undefined (prop_desc.setter)); + jerry_release_value (prop_name); + jerry_free_property_descriptor_fields (&prop_desc); + + // Test: object keys + res = jerry_get_object_keys (global_obj_val); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + JERRY_ASSERT (jerry_value_is_array (res)); + jerry_release_value (res); + + // Test: jerry_value_to_primitive + obj_val = jerry_eval ((jerry_char_t *) "new String ('hello')", 20, false); + JERRY_ASSERT (!jerry_value_has_error_flag (obj_val)); + JERRY_ASSERT (jerry_value_is_object (obj_val)); + JERRY_ASSERT (!jerry_value_is_string (obj_val)); + prim_val = jerry_value_to_primitive (obj_val); + JERRY_ASSERT (!jerry_value_has_error_flag (prim_val)); + JERRY_ASSERT (jerry_value_is_string (prim_val)); + jerry_release_value (prim_val); + + // Test: jerry_get_prototype + proto_val = jerry_get_prototype (obj_val); + JERRY_ASSERT (!jerry_value_has_error_flag (proto_val)); + JERRY_ASSERT (jerry_value_is_object (proto_val)); + jerry_release_value (obj_val); + + // Test: jerry_set_prototype + obj_val = jerry_create_object (); + res = jerry_set_prototype (obj_val, jerry_create_null ()); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + JERRY_ASSERT (jerry_value_is_boolean (res)); + JERRY_ASSERT (jerry_get_boolean_value (res)); + + res = jerry_set_prototype (obj_val, jerry_create_object ()); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + JERRY_ASSERT (jerry_value_is_boolean (res)); + JERRY_ASSERT (jerry_get_boolean_value (res)); + proto_val = jerry_get_prototype (obj_val); + JERRY_ASSERT (!jerry_value_has_error_flag (proto_val)); + JERRY_ASSERT (jerry_value_is_object (proto_val)); + jerry_release_value (proto_val); + jerry_release_value (obj_val); // Test: eval const char *eval_code_src_p = "(function () { return 123; })"; - jerry_completion_code_t status = jerry_eval ((jerry_char_t *) eval_code_src_p, - strlen (eval_code_src_p), - false, - true, - &val_t); - JERRY_ASSERT (status == JERRY_COMPLETION_CODE_OK); + val_t = jerry_eval ((jerry_char_t *) eval_code_src_p, strlen (eval_code_src_p), true); + JERRY_ASSERT (!jerry_value_has_error_flag (val_t)); JERRY_ASSERT (jerry_value_is_object (val_t)); - JERRY_ASSERT (jerry_is_function (jerry_get_object_value (val_t))); + JERRY_ASSERT (jerry_value_is_function (val_t)); - res = jerry_call_function (jerry_get_object_value (val_t), - NULL, - NULL, - 0); - JERRY_ASSERT (!jerry_value_is_error (res)); + res = jerry_call_function (val_t, jerry_create_undefined (), NULL, 0); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_number (res) && jerry_get_number_value (res) == 123.0); jerry_release_value (res); @@ -621,7 +694,7 @@ main (void) jerry_release_value (val_t); // cleanup. - jerry_release_object (global_obj_p); + jerry_release_value (global_obj_val); // TEST: run gc. jerry_gc (); @@ -631,20 +704,21 @@ main (void) JERRY_ASSERT (test_api_is_free_callback_was_called); // External Magic String - jerry_init (JERRY_FLAG_SHOW_OPCODES); + jerry_init (JERRY_INIT_SHOW_OPCODES); uint32_t num_magic_string_items = (uint32_t) (sizeof (magic_string_items) / sizeof (jerry_char_ptr_t)); - jerry_register_external_magic_strings (magic_string_items, - num_magic_string_items, - magic_string_lengths); + jerry_register_magic_strings (magic_string_items, + num_magic_string_items, + magic_string_lengths); const char *ms_code_src_p = "var global = {}; var console = [1]; var process = 1;"; - is_ok = jerry_parse ((jerry_char_t *) ms_code_src_p, strlen (ms_code_src_p), &err_obj_p); - JERRY_ASSERT (is_ok && err_obj_p == NULL); + parsed_code_val = jerry_parse ((jerry_char_t *) ms_code_src_p, strlen (ms_code_src_p), false); + JERRY_ASSERT (!jerry_value_has_error_flag (parsed_code_val)); - is_ok = (jerry_run (&res) == JERRY_COMPLETION_CODE_OK); - JERRY_ASSERT (is_ok); - JERRY_ASSERT (jerry_value_is_undefined (res)); + res = jerry_run (parsed_code_val); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); + jerry_release_value (res); + jerry_release_value (parsed_code_val); jerry_cleanup (); @@ -657,45 +731,45 @@ main (void) const char *code_to_snapshot_p = "(function () { return 'string from snapshot'; }) ();"; - jerry_init (JERRY_FLAG_SHOW_OPCODES); + jerry_init (JERRY_INIT_SHOW_OPCODES); size_t global_mode_snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) code_to_snapshot_p, strlen (code_to_snapshot_p), true, + false, global_mode_snapshot_buffer, sizeof (global_mode_snapshot_buffer)); JERRY_ASSERT (global_mode_snapshot_size != 0); jerry_cleanup (); - jerry_init (JERRY_FLAG_SHOW_OPCODES); + jerry_init (JERRY_INIT_SHOW_OPCODES); size_t eval_mode_snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) code_to_snapshot_p, strlen (code_to_snapshot_p), false, + false, eval_mode_snapshot_buffer, sizeof (eval_mode_snapshot_buffer)); JERRY_ASSERT (eval_mode_snapshot_size != 0); jerry_cleanup (); - jerry_init (JERRY_FLAG_SHOW_OPCODES); + jerry_init (JERRY_INIT_SHOW_OPCODES); - is_ok = (jerry_exec_snapshot (global_mode_snapshot_buffer, - global_mode_snapshot_size, - false, - &res) == JERRY_COMPLETION_CODE_OK); + res = jerry_exec_snapshot (global_mode_snapshot_buffer, + global_mode_snapshot_size, + false); - JERRY_ASSERT (is_ok); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_undefined (res)); jerry_release_value (res); - is_ok = (jerry_exec_snapshot (eval_mode_snapshot_buffer, - eval_mode_snapshot_size, - false, - &res) == JERRY_COMPLETION_CODE_OK); + res = jerry_exec_snapshot (eval_mode_snapshot_buffer, + eval_mode_snapshot_size, + false); - JERRY_ASSERT (is_ok); + JERRY_ASSERT (!jerry_value_has_error_flag (res)); JERRY_ASSERT (jerry_value_is_string (res)); - sz = jerry_get_string_size (jerry_get_string_value (res)); + sz = jerry_get_string_size (res); JERRY_ASSERT (sz == 20); - sz = jerry_string_to_char_buffer (jerry_get_string_value (res), (jerry_char_t *) buffer, sz); + sz = jerry_string_to_char_buffer (res, (jerry_char_t *) buffer, sz); JERRY_ASSERT (sz == 20); jerry_release_value (res); JERRY_ASSERT (!strncmp (buffer, "string from snapshot", (size_t) sz)); diff --git a/tests/unit/test-string-to-number.c b/tests/unit/test-string-to-number.c index 5ede32cee2..0e08f3fc64 100644 --- a/tests/unit/test-string-to-number.c +++ b/tests/unit/test-string-to-number.c @@ -16,6 +16,7 @@ #include "ecma-globals.h" #include "ecma-helpers.h" +#include "jerry-api.h" #include "test-common.h"