From 6b0b669c14f4085eac9b6daa10f3f65c650cf79a Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Wed, 25 Mar 2015 18:32:38 +0300 Subject: [PATCH] Support passing of string and object arguments to plugins' bound functions. --- jerry-core/ecma/base/ecma-globals.h | 4 +- jerry-core/ecma/base/ecma-helpers-string.cpp | 4 +- .../builtin-objects/ecma-builtin-jerry.cpp | 57 ++++++++++++++-- jerry-core/jerry-extension.h | 44 ++++++++++--- jerry-core/jerry-extension.inc.h | 6 +- jerry-core/jerry.cpp | 66 +++++++++++++++++++ plugins/io/init.cpp | 28 +++++++- plugins/io/io-extension-description.inc.h | 5 +- tests/jerry/extensions.js | 13 ++++ 9 files changed, 202 insertions(+), 25 deletions(-) diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index b38adf5b5..8a712570b 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -387,7 +387,7 @@ typedef enum * Description of ECMA-object or lexical environment * (depending on is_lexical_environment). */ -typedef struct +typedef struct ecma_object_t { /* Common part for objects and lexical environments */ @@ -763,7 +763,7 @@ typedef uint8_t ecma_string_hash_t; /** * ECMA string-value descriptor */ -typedef struct +typedef struct ecma_string_t { /** Reference counter for the string */ unsigned int refs : CONFIG_ECMA_REFERENCE_COUNTER_WIDTH; diff --git a/jerry-core/ecma/base/ecma-helpers-string.cpp b/jerry-core/ecma/base/ecma-helpers-string.cpp index f0bc4209e..da84d6663 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.cpp +++ b/jerry-core/ecma/base/ecma-helpers-string.cpp @@ -866,9 +866,7 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */ } /* ecma_string_to_number */ /** - * Copy ecma-string's contents to a buffer. - * - * Buffer will contain length of string, in characters, followed by string's characters. + * Convert ecma-string's contents to a zero-terminated string and put it to the buffer. * * @return number of bytes, actually copied to the buffer - if string's content was copied successfully; * otherwise (in case size of buffer is insuficcient) - negative number, which is calculated diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-jerry.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-jerry.cpp index c591dbdd9..ed8c358de 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-jerry.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-jerry.cpp @@ -193,19 +193,35 @@ ecma_builtin_jerry_dispatch_routine (uint16_t builtin_routine_id, /**< built-in } } } + else if (arg_p->type == JERRY_EXTENSION_FIELD_TYPE_STRING) + { + if (!ecma_is_value_string (arg_value)) + { + break; + } + else + { + arg_p->v_string = ecma_get_string_from_value (arg_value); + } + } else { - JERRY_ASSERT (arg_p->type == JERRY_EXTENSION_FIELD_TYPE_STRING); + JERRY_ASSERT (arg_p->type == JERRY_EXTENSION_FIELD_TYPE_OBJECT); -#if CONFIG_ECMA_CHAR_ENCODING != CONFIG_ECMA_CHAR_ASCII - JERRY_UNIMPLEMENTED ("Only ASCII encoding support is implemented."); -#else /* CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_ASCII */ - JERRY_UNIMPLEMENTED ("String arguments are not implemented"); -#endif /* CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_ASCII */ + if (!ecma_is_value_object (arg_value)) + { + break; + } + else + { + arg_p->v_object = ecma_get_object_from_value (arg_value); + } } } - if (arg_index != function_p->args_number) + uint32_t initialized_args_count = arg_index; + + if (initialized_args_count != function_p->args_number) { throw_type_error = true; } @@ -213,6 +229,29 @@ ecma_builtin_jerry_dispatch_routine (uint16_t builtin_routine_id, /**< built-in { function_p->function_wrapper_p (function_p); } + + for (arg_index = 0; + arg_index < initialized_args_count; + arg_index++) + { + jerry_extension_function_arg_t *arg_p = &function_p->args_p [arg_index]; + + if (arg_p->type == JERRY_EXTENSION_FIELD_TYPE_STRING) + { + arg_p->v_string = NULL; + } + else if (arg_p->type == JERRY_EXTENSION_FIELD_TYPE_OBJECT) + { + arg_p->v_object = NULL; + } + else + { + JERRY_ASSERT (arg_p->type == JERRY_EXTENSION_FIELD_TYPE_BOOLEAN + || arg_p->type == JERRY_EXTENSION_FIELD_TYPE_FLOAT32 + || arg_p->type == JERRY_EXTENSION_FIELD_TYPE_FLOAT64 + || arg_p->type == JERRY_EXTENSION_FIELD_TYPE_UINT32); + } + } } if (throw_type_error) @@ -444,6 +483,10 @@ ecma_op_extension_object_get_own_property (ecma_object_t *obj_p, /**< the extens break; } + case JERRY_EXTENSION_FIELD_TYPE_OBJECT: + { + JERRY_UNREACHABLE (); + } } ecma_named_data_property_assign_value (obj_p, prop_p, value); diff --git a/jerry-core/jerry-extension.h b/jerry-core/jerry-extension.h index b117e9e3a..ce18de4f4 100644 --- a/jerry-core/jerry-extension.h +++ b/jerry-core/jerry-extension.h @@ -19,6 +19,13 @@ #include #include #include +#include + +#ifdef __cplusplus +# define EXTERN_C "C" +#else /* !__cplusplus */ +# define EXTERN_C +#endif /* !__cplusplus */ /** \addtogroup jerry Jerry engine extension interface * @{ @@ -33,9 +40,20 @@ typedef enum JERRY_EXTENSION_FIELD_TYPE_FLOAT32, /**< 32-bit float */ JERRY_EXTENSION_FIELD_TYPE_FLOAT64, /**< 64-bit float */ JERRY_EXTENSION_FIELD_TYPE_UINT32, /**< number converted to 32-bit unsigned integer*/ - JERRY_EXTENSION_FIELD_TYPE_STRING /**< chars buffer */ + JERRY_EXTENSION_FIELD_TYPE_STRING, /**< string */ + JERRY_EXTENSION_FIELD_TYPE_OBJECT /**< object */ } jerry_extension_data_type_t; +/** + * An interface for Jerry's string value + */ +typedef struct ecma_string_t jerry_string_t; + +/** + * An interface for Jerry's object value + */ +typedef struct ecma_object_t jerry_object_t; + /** * Description of an extension object's fields */ @@ -43,7 +61,7 @@ typedef struct { const char *field_name_p; /**< field name */ - jerry_extension_data_type_t type; /**< field data type */ + const jerry_extension_data_type_t type; /**< field data type */ /** * Value description @@ -63,7 +81,7 @@ typedef struct */ typedef struct { - jerry_extension_data_type_t type; /**< argument data type */ + const jerry_extension_data_type_t type; /**< argument data type */ union { @@ -74,12 +92,11 @@ typedef struct uint32_t v_uint32; /**< number converted 32-bit unsigned integer */ - /** String copied to external characters buffer (not zero-terminated) */ - struct + union { - char* chars_p; /**< pointer to the string's chars in characters buffer */ - size_t length; /**< number of characters */ - } v_string; + jerry_string_t *v_string; /**< pointer to a JS string */ + jerry_object_t *v_object; /**< pointer to a JS object */ + }; }; } jerry_extension_function_arg_t; @@ -117,9 +134,18 @@ typedef struct jerry_extension_descriptor_t uint32_t index; /**< global index of the extension among registered exceptions */ } jerry_extension_descriptor_t; -extern bool +extern EXTERN_C bool jerry_extend_with (jerry_extension_descriptor_t *desc_p); +extern EXTERN_C ssize_t +jerry_string_to_char_buffer (const jerry_string_t *string_p, + char *buffer_p, + ssize_t buffer_size); +extern EXTERN_C jerry_string_t* jerry_acquire_string (jerry_string_t *string_p); +extern EXTERN_C void jerry_release_string (jerry_string_t *string_p); +extern EXTERN_C jerry_object_t* jerry_acquire_object (jerry_object_t *object_p); +extern EXTERN_C void jerry_release_object (jerry_object_t *object_p); + /** * @} */ diff --git a/jerry-core/jerry-extension.inc.h b/jerry-core/jerry-extension.inc.h index c3de1f723..26ab23d5c 100644 --- a/jerry-core/jerry-extension.inc.h +++ b/jerry-core/jerry-extension.inc.h @@ -54,8 +54,9 @@ static const jerry_extension_field_t jerry_extension_fields [JERRY_EXTENSION_FIE #define EXTENSION_ARG_PASS_UINT32(_arg_index) \ args_p [_arg_index].v_uint32 #define EXTENSION_ARG_PASS_STRING(_arg_index) \ - (const char*) args_p [_arg_index].v_string.chars_p, \ - args_p [_arg_index].v_string.length + args_p [_arg_index].v_string +#define EXTENSION_ARG_PASS_OBJECT(_arg_index) \ + args_p [_arg_index].v_object #define EXTENSION_ARG(_arg_index, _type) EXTENSION_ARG_PASS_ ## _type(_arg_index) #define EXTENSION_FUNCTION(_function_name, _function_to_call, _args_number, ...) \ static void jerry_extension_ ## _function_name ## _wrapper (const jerry_extension_function_t *function_block_p) \ @@ -66,6 +67,7 @@ static const jerry_extension_field_t jerry_extension_fields [JERRY_EXTENSION_FIE # include EXTENSION_DESCRIPTION_HEADER #undef EXTENSION_FUNCTION #undef EXTENSION_ARG +#undef EXTENSION_ARG_PASS_OBJECT #undef EXTENSION_ARG_PASS_STRING #undef EXTENSION_ARG_PASS_UINT32 #undef EXTENSION_ARG_PASS_FLOAT64 diff --git a/jerry-core/jerry.cpp b/jerry-core/jerry.cpp index fd7f49006..f9a618964 100644 --- a/jerry-core/jerry.cpp +++ b/jerry-core/jerry.cpp @@ -15,6 +15,8 @@ #include "deserializer.h" #include "ecma-extension.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" #include "ecma-init-finalize.h" #include "jerry.h" #include "jrt.h" @@ -63,6 +65,70 @@ jerry_extend_with (jerry_extension_descriptor_t *desc_p) /**< description of the return ecma_extension_register (desc_p); } /* jerry_extend_with */ +/** + * Copy string characters to specified buffer, append zero character at end of the buffer. + * + * @return number of bytes, actually copied to the buffer - if string's content was copied successfully; + * otherwise (in case size of buffer is insuficcient) - negative number, which is calculated + * as negation of buffer size, that is required to hold the string's content. + */ +ssize_t +jerry_string_to_char_buffer (const jerry_string_t *string_p, /**< string descriptor */ + char *buffer_p, /**< output characters buffer */ + ssize_t buffer_size) /**< size of output buffer */ +{ + return ecma_string_to_zt_string (string_p, (ecma_char_t*) buffer_p, buffer_size); +} /* jerry_string_to_char_buffer */ + +/** + * Acquire string pointer for usage outside of the engine + * + * Warning: + * acquired pointer should be released with jerry_release_string + * + * @return pointer that may be used outside of the engine + */ +jerry_string_t* +jerry_acquire_string (jerry_string_t *string_p) /**< pointer passed to function */ +{ + return ecma_copy_or_ref_ecma_string (string_p); +} /* jerry_acquire_string */ + +/** + * Release string pointer acquired through jerry_acquire_string. + */ +void +jerry_release_string (jerry_string_t *string_p) /**< pointer acquired through jerry_acquire_string */ +{ + ecma_deref_ecma_string (string_p); +} /* jerry_release_string */ + +/** + * Acquire object pointer for usage outside of the engine + * + * Warning: + * acquired pointer should be released with jerry_release_object + * + * @return pointer that may be used outside of the engine + */ +jerry_object_t* +jerry_acquire_object (jerry_object_t *object_p) /**< pointer passed to function */ +{ + ecma_ref_object (object_p); + + return object_p; +} /* jerry_acquire_object */ + +/** + * Release object pointer acquired through jerry_acquire_object. + */ +void +jerry_release_object (jerry_object_t *object_p) /**< pointer acquired through jerry_acquire_object */ +{ + ecma_deref_object (object_p); +} /* jerry_release_object */ + + /** * @} */ diff --git a/plugins/io/init.cpp b/plugins/io/init.cpp index 51845aaf9..bf0525864 100644 --- a/plugins/io/init.cpp +++ b/plugins/io/init.cpp @@ -19,6 +19,7 @@ #include "jerry.h" static void plugin_io_print_uint32 (uint32_t); +static void plugin_io_print_string (jerry_string_t *string_p); #include "io-extension-description.inc.h" @@ -35,4 +36,29 @@ static void plugin_io_print_uint32 (uint32_t num) /**< uint32 to print */ { printf ("%lu", num); -} /* print_uint32 */ +} /* plugin_io_print_uint32 */ + +/** + * Print a string without new-line to standard output + * + * Note: + * Currently, only strings that require up to 32 bytes with zero character at the end, are supported. + * If string is too long for the function, then nothing will be printed. + */ +static void +plugin_io_print_string (jerry_string_t *string_p) /**< string to print */ +{ + char buffer [32]; + + ssize_t req_size = jerry_string_to_char_buffer (string_p, buffer, (ssize_t) sizeof (buffer)); + + if (req_size < 0) + { + /* not enough buffer size */ + return; + } + else + { + printf ("%s", buffer); + } +} /* plugin_io_print_string */ diff --git a/plugins/io/io-extension-description.inc.h b/plugins/io/io-extension-description.inc.h index 56c4c23ff..11ddf18a6 100644 --- a/plugins/io/io-extension-description.inc.h +++ b/plugins/io/io-extension-description.inc.h @@ -27,12 +27,15 @@ EXTENSION_FUNCTION (print_uint32, plugin_io_print_uint32, 1, EXTENSION_ARG (0, UINT32)) +EXTENSION_FUNCTION (print_string, plugin_io_print_string, + 1, + EXTENSION_ARG (0, STRING)) #elif defined (EXTENSION_FIELD) #if defined (__TARGET_HOST) EXTENSION_FIELD (platform, STRING, "linux") #elif defined (__TARGET_MCU_STM32F3) EXTENSION_FIELD (platform, STRING, "mcu_stm32f3") -#elif defined (__TARGET_MCU_STM32F3) +#elif defined (__TARGET_MCU_STM32F4) EXTENSION_FIELD (platform, STRING, "mcu_stm32f4") #endif /* !__TARGET_MCU_STM32F3 && __TARGET_MCU_STM32F4 */ #endif /* !EXTENSION_FUNCTION && !EXTENSION_FIELD */ diff --git a/tests/jerry/extensions.js b/tests/jerry/extensions.js index 25803aeed..10ccea156 100644 --- a/tests/jerry/extensions.js +++ b/tests/jerry/extensions.js @@ -18,6 +18,7 @@ assert(Jerry.io.platform === "linux"); Jerry.io.print_uint32 (1); +Jerry.io.print_string (Jerry.io.platform); try { @@ -30,3 +31,15 @@ catch (e) { assert (e instanceof TypeError); } + +try +{ + // Argument type mismatch + Jerry.io.print_string (1); + + assert (false); +} +catch (e) +{ + assert (e instanceof TypeError); +}