static int shell_cmd_handler (char *source_buffer) { jerry_value_t ret_val; ret_val = jerry_eval ((jerry_char_t *) source_buffer, strlen (source_buffer), JERRY_PARSE_NO_OPTS); if (jerry_value_is_error (ret_val)) { /* User-friendly error messages require at least "cp" JerryScript profile. Include a message prefix in case "cp_minimal" profile is used. */ printf ("Error executing statement: "); /* Clear error flag, otherwise print call below won't produce any output. */ ret_val = jerry_get_value_from_error (ret_val, true); } if (!jerry_value_is_error (print_function)) { jerry_value_t ret_val_print = jerry_call_function (print_function, jerry_create_undefined (), &ret_val, 1); jerry_release_value (ret_val_print); } jerry_release_value (ret_val); return 0; } /* shell_cmd_handler */
/** * Test ArrayBuffer 'read' api call with various offset values. */ static void test_read_with_offset (uint8_t offset) /**< offset for buffer read. */ { const char *eval_arraybuffer_src_p = ("var array = new Uint8Array (15);" "for (var i = 0; i < array.length; i++) { array[i] = i * 2; };" "array.buffer"); jerry_value_t arraybuffer = jerry_eval ((jerry_char_t *) eval_arraybuffer_src_p, strlen (eval_arraybuffer_src_p), true); TEST_ASSERT (!jerry_value_is_error (arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == 15); uint8_t buffer[20]; memset (buffer, 120, 20); /* Try to copy more than the target buffer size. */ jerry_length_t copied = jerry_arraybuffer_read (arraybuffer, offset, buffer, 20); TEST_ASSERT (copied == (jerry_length_t)(15 - offset)); for (uint8_t i = 0; i < copied; i++) { TEST_ASSERT (buffer[i] == (i + offset) * 2); } TEST_ASSERT (buffer[15 - offset] == 120); jerry_release_value (arraybuffer); } /* test_read_with_offset */
/** * Register a JavaScript function in the global object. */ static void register_js_function (const char *name_p, /**< name of the function */ jerry_external_handler_t handler_p) /**< function callback */ { jerry_value_t result_val = jerryx_handler_register_global ((const jerry_char_t *) name_p, handler_p); if (jerry_value_is_error (result_val)) { jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Warning: failed to register '%s' method.", name_p); } jerry_release_value (result_val); } /* register_js_function */
void jerry_resolve_error (jerry_value_t ret_value) { if (jerry_value_is_error (ret_value)) { jerry_value_clear_error_flag (&ret_value); jerry_value_t err_str_val = jerry_value_to_string (ret_value); jerry_size_t err_str_size = jerry_get_string_size (err_str_val); jerry_char_t *err_str_buf = (jerry_char_t *) balloc (err_str_size, NULL); jerry_size_t sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); err_str_buf[sz] = 0; printk ("Script Error: unhandled exception: %s\n", err_str_buf); bfree(err_str_buf); jerry_release_value (err_str_val); } }
napi_status napi_get_property_names(napi_env env, napi_value object, napi_value* result) { NAPI_TRY_ENV(env); jerry_value_t jval = AS_JERRY_VALUE(object); NAPI_TRY_TYPE(object, jval); jerry_value_t jval_keys = jerry_get_object_keys(jval); jerryx_create_handle(jval_keys); if (jerry_value_is_error(jval_keys)) { jerry_release_value(jval_keys); NAPI_RETURN(napi_invalid_arg, NULL); } return napi_assign_nvalue(jval_keys, result); }
napi_status napi_get_element(napi_env env, napi_value object, uint32_t index, napi_value* result) { NAPI_TRY_ENV(env); jerry_value_t jval_object = AS_JERRY_VALUE(object); NAPI_TRY_TYPE(object, jval_object); jerry_value_t jval_ret = jerry_get_property_by_index(jval_object, index); jerryx_create_handle(jval_ret); if (jerry_value_is_error(jval_ret)) { jerry_release_value(jval_ret); NAPI_RETURN(napi_invalid_arg, NULL); } return napi_assign_nvalue(jval_ret, result); }
napi_status napi_set_element(napi_env env, napi_value object, uint32_t index, napi_value value) { NAPI_TRY_ENV(env); jerry_value_t jval_object = AS_JERRY_VALUE(object); jerry_value_t jval_val = AS_JERRY_VALUE(value); NAPI_TRY_TYPE(object, jval_object); jerry_value_t res = jerry_set_property_by_index(jval_object, index, jval_val); if (jerry_value_is_error(res)) { jerry_release_value(res); NAPI_RETURN(napi_invalid_arg, NULL); } jerry_release_value(res); NAPI_RETURN(napi_ok); }
napi_status napi_define_properties(napi_env env, napi_value object, size_t property_count, const napi_property_descriptor* properties) { NAPI_TRY_ENV(env); jerry_value_t jval_target = AS_JERRY_VALUE(object); NAPI_TRY_TYPE(object, jval_target); NAPI_WEAK_ASSERT(napi_invalid_arg, properties != NULL); napi_status status; jerry_property_descriptor_t prop_desc; for (size_t i = 0; i < property_count; ++i) { jerry_init_property_descriptor_fields(&prop_desc); napi_property_descriptor prop = properties[i]; jerry_value_t jval_prop_name; if (prop.utf8name != NULL) { jval_prop_name = jerry_create_string_from_utf8((jerry_char_t*)prop.utf8name); jerryx_create_handle(jval_prop_name); } else if (prop.name != NULL) { jval_prop_name = AS_JERRY_VALUE(prop.name); NAPI_TRY_TYPE(string, jval_prop_name); } else { NAPI_RETURN(napi_invalid_arg, NULL); } status = iotjs_napi_prop_desc_to_jdesc(env, &prop, &prop_desc); if (status != napi_ok) return status; jerry_value_t return_value = jerry_define_own_property(jval_target, jval_prop_name, &prop_desc); if (jerry_value_is_error(return_value)) { NAPI_RETURN(napi_invalid_arg, NULL); } jerry_release_value(return_value); /** * We don't have to call `jerry_free_property_descriptor_fields` * since most napi values are managed by handle scopes. */ // jerry_free_property_descriptor_fields(&prop_desc); } NAPI_RETURN(napi_ok); }
/** * Test ArrayBuffer 'write' api call with various offset values. */ static void test_write_with_offset (uint8_t offset) /**< offset for buffer write. */ { { jerry_value_t offset_val = jerry_create_number (offset); register_js_value ("offset", offset_val); jerry_release_value (offset_val); } const char *eval_arraybuffer_src_p = "var array = new Uint8Array (15); array.buffer"; jerry_value_t arraybuffer = jerry_eval ((jerry_char_t *) eval_arraybuffer_src_p, strlen (eval_arraybuffer_src_p), true); TEST_ASSERT (!jerry_value_is_error (arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == 15); uint8_t buffer[20]; for (uint8_t i = 0; i < 20; i++) { buffer[i] = (uint8_t) (i * 3); } /* Intentionally copy more than the allowed space. */ jerry_length_t copied = jerry_arraybuffer_write (arraybuffer, offset, buffer, 20); TEST_ASSERT (copied == (jerry_length_t)(15 - offset)); const char *eval_test_arraybuffer_p = ( "for (var i = 0; i < offset; i++)" "{" " assert (array[i] == 0, 'offset check for: ' + i + ' was: ' + array[i] + ' should be: 0');" "};" "for (var i = offset; i < array.length; i++)" "{" " var expected = (i - offset) * 3;" " assert (array[i] == expected, 'calc check for: ' + i + ' was: ' + array[i] + ' should be: ' + expected);" "};" "assert (array[15] === undefined, 'ArrayBuffer out of bounds index should return undefined value');"); jerry_value_t res = jerry_eval ((jerry_char_t *) eval_test_arraybuffer_p, strlen (eval_test_arraybuffer_p), true); jerry_release_value (res); jerry_release_value (arraybuffer); } /* test_write_with_offset */
napi_status napi_get_property(napi_env env, napi_value object, napi_value key, napi_value* result) { NAPI_TRY_ENV(env); jerry_value_t jval_object = AS_JERRY_VALUE(object); jerry_value_t jval_key = AS_JERRY_VALUE(key); NAPI_TRY_TYPE(object, jval_object); NAPI_TRY_TYPE(string, jval_key); jerry_value_t jval_ret = jerry_get_property(jval_object, jval_key); jerryx_create_handle(jval_ret); if (jerry_value_is_error(jval_ret)) { jerry_release_value(jval_ret); NAPI_RETURN(napi_invalid_arg, NULL); } return napi_assign_nvalue(jval_ret, result); }
napi_status napi_set_property(napi_env env, napi_value object, napi_value key, napi_value value) { NAPI_TRY_ENV(env); jerry_value_t jval_object = AS_JERRY_VALUE(object); jerry_value_t jval_key = AS_JERRY_VALUE(key); jerry_value_t jval_val = AS_JERRY_VALUE(value); NAPI_TRY_TYPE(object, jval_object); NAPI_TRY_TYPE(string, jval_key); jerry_value_t ret = jerry_set_property(jval_object, jval_key, jval_val); if (jerry_value_is_error(ret)) { jerry_release_value(ret); NAPI_RETURN(napi_invalid_arg, NULL); } jerry_release_value(ret); NAPI_RETURN(napi_ok); }
napi_status napi_has_element(napi_env env, napi_value object, uint32_t index, bool* result) { NAPI_TRY_ENV(env); jerry_value_t jval_object = AS_JERRY_VALUE(object); NAPI_TRY_TYPE(object, jval_object); char idx_str[17]; sprintf(idx_str, "%d", index); jerry_value_t prop_name = jerry_create_string((const jerry_char_t*)idx_str); jerry_value_t has_prop_val = jerry_has_own_property(jval_object, prop_name); jerry_release_value(prop_name); if (jerry_value_is_error(has_prop_val)) { jerry_release_value(has_prop_val); NAPI_RETURN(napi_generic_failure); } bool has_prop = jerry_get_boolean_value(has_prop_val); return napi_assign_bool(has_prop, result); }
static bool find_test_object_by_property (const jerry_value_t candidate, void *context_p) { jerry_value_t *args_p = (jerry_value_t *) context_p; jerry_value_t result = jerry_has_property (candidate, args_p[0]); bool has_property = (!jerry_value_is_error (result) && jerry_get_boolean_value (result)); /* If the object has the desired property, store a new reference to it in args_p[1]. */ if (has_property) { args_p[1] = jerry_acquire_value (candidate); } jerry_release_value (result); /* Stop iterating if we've found our object. */ return !has_property; } /* find_test_object_by_property */
void main (void) { srand ((unsigned) jerry_port_get_current_time ()); uint32_t zephyr_ver = sys_kernel_version_get (); printf ("JerryScript build: " __DATE__ " " __TIME__ "\n"); printf ("JerryScript API %d.%d\n", JERRY_API_MAJOR_VERSION, JERRY_API_MINOR_VERSION); printf ("Zephyr version %d.%d.%d\n", (int)SYS_KERNEL_VER_MAJOR (zephyr_ver), (int)SYS_KERNEL_VER_MINOR (zephyr_ver), (int)SYS_KERNEL_VER_PATCHLEVEL (zephyr_ver)); zephyr_getline_init (); jerry_init (JERRY_INIT_EMPTY); register_js_function ("print", jerryx_handler_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"); print_function = jerry_get_property (global_obj_val, print_func_name_val); jerry_release_value (print_func_name_val); jerry_release_value (global_obj_val); if (jerry_value_is_error (print_function)) { printf ("Error: could not look up print function, expression results won't be printed\n"); } while (1) { char *s; printf("js> "); fflush(stdout); s = zephyr_getline (); if (*s) { shell_cmd_handler (s); } } /* As we never retturn from REPL above, don't call jerry_cleanup() here. */ } /* main */
int main (void) { jerry_init (JERRY_INIT_EMPTY); if (!jerry_is_feature_enabled (JERRY_FEATURE_TYPEDARRAY)) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "ArrayBuffer is disabled!\n"); jerry_cleanup (); return 0; } jerry_value_t function_val = jerry_create_external_function (assert_handler); register_js_value ("assert", function_val); jerry_release_value (function_val); /* Test array buffer queries */ { const char *eval_arraybuffer_src_p = "new ArrayBuffer (10)"; jerry_value_t eval_arraybuffer = jerry_eval ((jerry_char_t *) eval_arraybuffer_src_p, strlen (eval_arraybuffer_src_p), true); TEST_ASSERT (!jerry_value_is_error (eval_arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (eval_arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (eval_arraybuffer) == 10); jerry_release_value (eval_arraybuffer); } /* Test array buffer creation */ { const uint32_t length = 15; jerry_value_t arraybuffer = jerry_create_arraybuffer (length); TEST_ASSERT (!jerry_value_is_error (arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length); jerry_release_value (arraybuffer); } /* Test array buffer read operations */ for (uint8_t i = 0; i < 15; i++) { test_read_with_offset (i); } /* Test zero length ArrayBuffer read */ { const uint32_t length = 0; jerry_value_t arraybuffer = jerry_create_arraybuffer (length); TEST_ASSERT (!jerry_value_is_error (arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length); uint8_t data[20]; memset (data, 11, 20); jerry_length_t bytes_read = jerry_arraybuffer_read (arraybuffer, 0, data, 20); TEST_ASSERT (bytes_read == 0); for (int i = 0; i < 20; i++) { TEST_ASSERT (data[i] == 11); } jerry_release_value (arraybuffer); } /* Test array buffer write operations */ for (uint8_t i = 0; i < 15; i++) { test_write_with_offset (i); } /* Test zero length ArrayBuffer write */ { const uint32_t length = 0; jerry_value_t arraybuffer = jerry_create_arraybuffer (length); TEST_ASSERT (!jerry_value_is_error (arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length); uint8_t data[20]; memset (data, 11, 20); jerry_length_t bytes_written = jerry_arraybuffer_write (arraybuffer, 0, data, 20); TEST_ASSERT (bytes_written == 0); jerry_release_value (arraybuffer); } /* Test ArrayBuffer with buffer allocated externally */ { const uint32_t buffer_size = 15; const uint8_t base_value = 51; uint8_t buffer_p[buffer_size]; memset (buffer_p, base_value, buffer_size); jerry_value_t arrayb = jerry_create_arraybuffer_external (buffer_size, buffer_p, test_free_cb); uint8_t new_value = 123; jerry_length_t copied = jerry_arraybuffer_write (arrayb, 0, &new_value, 1); TEST_ASSERT (copied == 1); TEST_ASSERT (buffer_p[0] == new_value); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arrayb) == buffer_size); for (uint32_t i = 1; i < buffer_size; i++) { TEST_ASSERT (buffer_p[i] == base_value); } uint8_t test_buffer[buffer_size]; jerry_length_t read = jerry_arraybuffer_read (arrayb, 0, test_buffer, buffer_size); TEST_ASSERT (read == buffer_size); TEST_ASSERT (test_buffer[0] == new_value); for (uint32_t i = 1; i < buffer_size; i++) { TEST_ASSERT (test_buffer[i] == base_value); } TEST_ASSERT (jerry_value_is_arraybuffer (arrayb)); jerry_release_value (arrayb); } /* Test ArrayBuffer external memory map/unmap */ { const uint32_t buffer_size = 20; uint8_t buffer_p[buffer_size]; { jerry_value_t input_buffer = jerry_create_arraybuffer_external (buffer_size, buffer_p, NULL); register_js_value ("input_buffer", input_buffer); jerry_release_value (input_buffer); } const char *eval_arraybuffer_src_p = ( "var array = new Uint8Array(input_buffer);" "for (var i = 0; i < array.length; i++)" "{" " array[i] = i * 2;" "};" "array.buffer"); jerry_value_t buffer = jerry_eval ((jerry_char_t *) eval_arraybuffer_src_p, strlen (eval_arraybuffer_src_p), true); TEST_ASSERT (!jerry_value_is_error (buffer)); TEST_ASSERT (jerry_value_is_arraybuffer (buffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (buffer) == 20); uint8_t *const data = jerry_get_arraybuffer_pointer (buffer); /* test memory read */ for (int i = 0; i < 20; i++) { TEST_ASSERT (data[i] == (uint8_t) (i * 2)); } /* "upload" new data */ double sum = 0; for (int i = 0; i < 20; i++) { data[i] = (uint8_t)(i * 3); sum += data[i]; } jerry_release_value (buffer); const char *eval_test_arraybuffer_p = ( "var sum = 0;" "for (var i = 0; i < array.length; i++)" "{" " var expected = i * 3;" " assert(array[i] == expected, 'Array at index ' + i + ' was: ' + array[i] + ' should be: ' + expected);" " sum += array[i]" "};" "sum"); jerry_value_t res = jerry_eval ((jerry_char_t *) eval_test_arraybuffer_p, strlen (eval_test_arraybuffer_p), true); TEST_ASSERT (jerry_value_is_number (res)); TEST_ASSERT (jerry_get_number_value (res) == sum); jerry_release_value (res); jerry_release_value (buffer); } /* Test ArrayBuffer external with invalid arguments */ { jerry_value_t input_buffer = jerry_create_arraybuffer_external (0, NULL, NULL); TEST_ASSERT (jerry_value_is_error (input_buffer)); TEST_ASSERT (jerry_get_error_type (input_buffer) == JERRY_ERROR_RANGE); jerry_release_value (input_buffer); } jerry_cleanup (); TEST_ASSERT (callback_called == true); return 0; } /* main */
void eval_jerry_script (int argc, char *argv[], struct tcmd_handler_ctx *ctx) { if (argc < 3) { TCMD_RSP_ERROR (ctx, NULL); help (); return; } else { OS_ERR_TYPE err; size_t str_total_length = 0; size_t *str_lens = (size_t *) balloc ((argc - 2) * sizeof(size_t), &err); if (str_lens == NULL || err != E_OS_OK) { printk ("%s: allocate memory failed!", __func__); TCMD_RSP_ERROR (ctx, NULL); return; } for (int i = 2; i < argc; ++i) { str_lens[i - 2] = strlen (argv[i]); str_total_length += str_lens[i - 2] + 1; } err = E_OS_OK; char *buffer = (char *) balloc (str_total_length, &err); if (buffer == NULL || err != E_OS_OK) { printk ("%s: allocate memory failed!", __func__); TCMD_RSP_ERROR (ctx, NULL); return; } char *p = buffer; for (int i = 2; i < argc; ++i) { for (int j =0; j < str_lens[i - 2]; ++j) { *p = argv[i][j]; ++p; } *p = ' '; ++p; } *p = '\0'; jerry_value_t eval_ret = jerry_eval (buffer, str_total_length - 1, false); if (jerry_value_is_error (eval_ret)) { jerry_resolve_error (eval_ret); TCMD_RSP_ERROR (ctx, NULL); } else { jerry_value_t args[] = {eval_ret}; jerry_value_t ret_val_print = jerry_call_function (print_function, jerry_create_undefined (), args, 1); jerry_release_value (ret_val_print); TCMD_RSP_FINAL (ctx, NULL); } jerry_release_value (eval_ret); bfree (buffer); bfree (str_lens); } }
int main (void) { jerry_init (JERRY_INIT_EMPTY); /* Render strict-equal as a function. */ jerry_value_t parse_result = jerry_parse (NULL, 0, strict_equal_source, sizeof (strict_equal_source) - 1, JERRY_PARSE_STRICT_MODE); TEST_ASSERT (!jerry_value_is_error (parse_result)); jerry_value_t strict_equal = jerry_run (parse_result); TEST_ASSERT (!jerry_value_is_error (strict_equal)); jerry_release_value (parse_result); /* Create an object and associate some native data with it. */ jerry_value_t object = jerry_create_object (); jerry_set_object_native_pointer (object, &test_data, &test_info); /* Retrieve the object by its native pointer. */ jerry_value_t found_object; TEST_ASSERT (jerry_objects_foreach_by_native_info (&test_info, find_test_object_by_data, &found_object)); jerry_value_t args[2] = {object, found_object}; /* Assert that the correct object was retrieved. */ jerry_value_t undefined = jerry_create_undefined (); jerry_value_t strict_equal_result = jerry_call_function (strict_equal, undefined, args, 2); TEST_ASSERT (jerry_value_is_boolean (strict_equal_result) && jerry_get_boolean_value (strict_equal_result)); jerry_release_value (strict_equal_result); jerry_release_value (found_object); jerry_release_value (object); /* Collect garbage. */ jerry_gc (JERRY_GC_SEVERITY_LOW); /* Attempt to retrieve the object by its native pointer again. */ TEST_ASSERT (!jerry_objects_foreach_by_native_info (&test_info, find_test_object_by_data, &found_object)); /* Create an object and set a property on it. */ object = jerry_create_object (); jerry_value_t property_name = jerry_create_string ((jerry_char_t *) "xyzzy"); jerry_value_t property_value = jerry_create_number (42); jerry_release_value (jerry_set_property (object, property_name, property_value)); jerry_release_value (property_value); /* Retrieve the object by the presence of its property, placing it at args[1]. */ args[0] = property_name; TEST_ASSERT (jerry_objects_foreach (find_test_object_by_property, args)); /* Assert that the right object was retrieved and release both the original reference to it and the retrieved one. */ args[0] = object; strict_equal_result = jerry_call_function (strict_equal, undefined, args, 2); TEST_ASSERT (jerry_value_is_boolean (strict_equal_result) && jerry_get_boolean_value (strict_equal_result)); jerry_release_value (strict_equal_result); jerry_release_value (args[0]); jerry_release_value (args[1]); /* Collect garbage. */ jerry_gc (JERRY_GC_SEVERITY_LOW); /* Attempt to retrieve the object by the presence of its property again. */ args[0] = property_name; TEST_ASSERT (!jerry_objects_foreach (find_test_object_by_property, args)); jerry_release_value (property_name); jerry_release_value (undefined); jerry_release_value (strict_equal); jerry_cleanup (); } /* main */
/** * Validate the JS arguments and assign them to the native arguments. * * @return jerry undefined: all validators passed, * jerry error: a validator failed. */ jerry_value_t jerryx_arg_transform_args (const jerry_value_t *js_arg_p, /**< points to the array with JS arguments */ const jerry_length_t js_arg_cnt, /**< the count of the `js_arg_p` array */ const jerryx_arg_t *c_arg_p, /**< points to the array of validation/transformation steps */ jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ { jerry_value_t ret = jerry_create_undefined (); jerryx_arg_js_iterator_t iterator = { .js_arg_p = js_arg_p, .js_arg_cnt = js_arg_cnt, .js_arg_idx = 0 }; for (; c_arg_cnt != 0 && !jerry_value_is_error (ret); c_arg_cnt--, c_arg_p++) { ret = c_arg_p->func (&iterator, c_arg_p); } return ret; } /* jerryx_arg_transform_args */ /** * Validate the this value and the JS arguments, * and assign them to the native arguments. * This function is useful to perform input validation inside external * function handlers (see jerry_external_handler_t). * @note this_val is processed as the first value, before the array of arguments. * * @return jerry undefined: all validators passed, * jerry error: a validator failed. */ jerry_value_t jerryx_arg_transform_this_and_args (const jerry_value_t this_val, /**< the this_val for the external function */ const jerry_value_t *js_arg_p, /**< points to the array with JS arguments */ const jerry_length_t js_arg_cnt, /**< the count of the `js_arg_p` array */ const jerryx_arg_t *c_arg_p, /**< points to the array of transformation steps */ jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ { if (c_arg_cnt == 0) { return jerry_create_undefined (); } jerryx_arg_js_iterator_t iterator = { .js_arg_p = &this_val, .js_arg_cnt = 1, .js_arg_idx = 0 }; jerry_value_t ret = c_arg_p->func (&iterator, c_arg_p); if (jerry_value_is_error (ret)) { jerry_release_value (ret); return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "'this' validation failed."); } return jerryx_arg_transform_args (js_arg_p, js_arg_cnt, c_arg_p + 1, c_arg_cnt - 1); } /* jerryx_arg_transform_this_and_args */ /** * Validate the `obj_val`'s properties, * and assign them to the native arguments. * * @return jerry undefined: all validators passed, * jerry error: a validator failed. */ jerry_value_t jerryx_arg_transform_object_properties (const jerry_value_t obj_val,/**< the JS object */ const jerry_char_t **name_p, /**< property name list of the JS object */ const jerry_length_t name_cnt, /**< count of the name list */ const jerryx_arg_t *c_arg_p, /**< points to the array of transformation steps */ jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ { if (!jerry_value_is_object (obj_val)) { return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "Not an object."); } jerry_value_t prop[name_cnt]; for (jerry_length_t i = 0; i < name_cnt; i++, name_p++) { const jerry_value_t name_str = jerry_create_string (*name_p); prop[i] = jerry_get_property (obj_val, name_str); jerry_release_value (name_str); if (jerry_value_is_error (prop[i])) { for (jerry_length_t j = 0; j < i; j++) { jerry_release_value (prop[j]); } return prop[i]; } } const jerry_value_t ret = jerryx_arg_transform_args (prop, name_cnt, c_arg_p, c_arg_cnt); for (jerry_length_t i = 0; i < name_cnt; i++) { jerry_release_value (prop[i]); } return ret; } /* jerryx_arg_transform_object_properties */ /** * Validate the items in the JS array and assign them to the native arguments. * * @return jerry undefined: all validators passed, * jerry error: a validator failed. */ jerry_value_t jerryx_arg_transform_array (const jerry_value_t array_val, /**< points to the JS array */ const jerryx_arg_t *c_arg_p, /**< points to the array of validation/transformation steps */ jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ { if (!jerry_value_is_array (array_val)) { return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "Not an array."); } jerry_value_t arr[c_arg_cnt]; for (jerry_length_t i = 0; i < c_arg_cnt; i++) { arr[i] = jerry_get_property_by_index (array_val, i); if (jerry_value_is_error (arr[i])) { for (jerry_length_t j = 0; j < i; j++) { jerry_release_value (arr[j]); } return arr[i]; } } const jerry_value_t ret = jerryx_arg_transform_args (arr, c_arg_cnt, c_arg_p, c_arg_cnt); for (jerry_length_t i = 0; i < c_arg_cnt; i++) { jerry_release_value (arr[i]); } return ret; } /* jerryx_arg_transform_array */
/** * Provide a 'print' implementation for scripts. * * The routine converts all of its arguments to strings and outputs them * char-by-char using jerryx_port_handler_print_char. * * The NUL character is output as "\u0000", other characters are output * bytewise. * * Note: * This implementation does not use standard C `printf` to print its * output. This allows more flexibility but also extends the core * JerryScript engine port API. Applications that want to use * `jerryx_handler_print` must ensure that their port implementation also * provides `jerryx_port_handler_print_char`. * * @return undefined - if all arguments could be converted to strings, * error - otherwise. */ jerry_value_t jerryx_handler_print (const jerry_value_t func_obj_val, /**< function object */ const jerry_value_t this_p, /**< this arg */ const jerry_value_t args_p[], /**< function arguments */ const jerry_length_t args_cnt) /**< number of function arguments */ { (void) func_obj_val; /* unused */ (void) this_p; /* unused */ static const char *null_str = "\\u0000"; jerry_value_t ret_val = jerry_create_undefined (); for (jerry_length_t arg_index = 0; jerry_value_is_undefined (ret_val) && arg_index < args_cnt; arg_index++) { jerry_value_t str_val = jerry_value_to_string (args_p[arg_index]); if (!jerry_value_is_error (str_val)) { if (arg_index != 0) { jerryx_port_handler_print_char (' '); } jerry_size_t substr_size; jerry_length_t substr_pos = 0; jerry_char_t substr_buf[256]; while ((substr_size = jerry_substring_to_char_buffer (str_val, substr_pos, substr_pos + 256, substr_buf, 256)) != 0) { #ifdef JERRY_DEBUGGER jerry_debugger_send_output (substr_buf, substr_size, JERRY_DEBUGGER_OUTPUT_OK); #endif /* JERRY_DEBUGGER */ for (jerry_size_t chr_index = 0; chr_index < substr_size; chr_index++) { char chr = (char) substr_buf[chr_index]; if (chr == '\0') { for (jerry_size_t null_index = 0; null_str[null_index] != 0; null_index++) { jerryx_port_handler_print_char (null_str[null_index]); } } else { jerryx_port_handler_print_char (chr); } } substr_pos += substr_size; } jerry_release_value (str_val); } else { ret_val = str_val; } } jerryx_port_handler_print_char ('\n'); return ret_val; } /* jerryx_handler_print */
int main (void) { TEST_INIT (); jerry_init (JERRY_INIT_EMPTY); jerry_value_t global = jerry_get_global_object (); jerry_value_t callback_name = jerry_create_string ((jerry_char_t *) "callback"); jerry_value_t func = jerry_create_external_function (callback_func); jerry_value_t res = jerry_set_property (global, callback_name, func); TEST_ASSERT (!jerry_value_is_error (res)); jerry_release_value (res); jerry_release_value (func); jerry_release_value (callback_name); jerry_release_value (global); const char *inf_loop_code_src_p = ("while(true) {\n" " with ({}) {\n" " try {\n" " callback();\n" " } catch (e) {\n" " } finally {\n" " }\n" " }\n" "}"); jerry_value_t parsed_code_val = jerry_parse (NULL, 0, (jerry_char_t *) inf_loop_code_src_p, strlen (inf_loop_code_src_p), JERRY_PARSE_NO_OPTS); TEST_ASSERT (!jerry_value_is_error (parsed_code_val)); res = jerry_run (parsed_code_val); TEST_ASSERT (jerry_value_is_abort (res)); jerry_release_value (res); jerry_release_value (parsed_code_val); inf_loop_code_src_p = ("function f() {" " while(true) {\n" " with ({}) {\n" " try {\n" " callback();\n" " } catch (e) {\n" " } finally {\n" " }\n" " }\n" " }" "}\n" "function g() {\n" " for (a in { x:5 })\n" " f();\n" "}\n" "\n" "with({})\n" " f();\n"); parsed_code_val = jerry_parse (NULL, 0, (jerry_char_t *) inf_loop_code_src_p, strlen (inf_loop_code_src_p), JERRY_PARSE_NO_OPTS); TEST_ASSERT (!jerry_value_is_error (parsed_code_val)); res = jerry_run (parsed_code_val); TEST_ASSERT (jerry_value_is_abort (res)); jerry_release_value (res); jerry_release_value (parsed_code_val); /* Test flag overwrites. */ jerry_value_t value = jerry_create_string ((jerry_char_t *) "Error description"); TEST_ASSERT (!jerry_value_is_abort (value)); TEST_ASSERT (!jerry_value_is_error (value)); jerry_value_set_abort_flag (&value); TEST_ASSERT (jerry_value_is_abort (value)); TEST_ASSERT (jerry_value_is_error (value)); jerry_value_set_error_flag (&value); TEST_ASSERT (!jerry_value_is_abort (value)); TEST_ASSERT (jerry_value_is_error (value)); jerry_value_set_abort_flag (&value); TEST_ASSERT (jerry_value_is_abort (value)); TEST_ASSERT (jerry_value_is_error (value)); jerry_release_value (value); jerry_cleanup (); return 0; } /* main */