Implement vm_throw callback (#4726)
Slightly improve the description of vm_exec_stop callback. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
+106
-10
@@ -153,6 +153,7 @@ Possible compile time enabled feature types:
|
||||
- JERRY_FEATURE_SNAPSHOT_EXEC - executing snapshot files
|
||||
- JERRY_FEATURE_DEBUGGER - debugging
|
||||
- JERRY_FEATURE_VM_EXEC_STOP - stopping ECMAScript execution
|
||||
- JERRY_FEATURE_VM_THROW - capturing ECMAScript throws
|
||||
- JERRY_FEATURE_JSON - JSON support
|
||||
- JERRY_FEATURE_PROMISE - promise support
|
||||
- JERRY_FEATURE_TYPEDARRAY - Typedarray support
|
||||
@@ -1122,6 +1123,32 @@ typedef jerry_value_t (*jerry_vm_exec_stop_callback_t) (void *user_p);
|
||||
|
||||
- [jerry_set_vm_exec_stop_callback](#jerry_set_vm_exec_stop_callback)
|
||||
|
||||
## jerry_vm_throw_callback_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Callback which is called when a value is thrown in an ECMAScript code. The callback
|
||||
should not change the `error_value`. The callback is not called again until the value
|
||||
is caught.
|
||||
|
||||
Note:
|
||||
- The engine considers errors thrown by external functions as never caught. The
|
||||
application can maintain a status flag to ignore the next call of the callback
|
||||
if necessary.
|
||||
See: [jerry_create_external_function](#jerry_create_external_function)
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef void (*jerry_vm_throw_callback_t) (const jerry_value_t error_value, void *user_p);
|
||||
```
|
||||
|
||||
*New in [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_set_vm_throw_callback](#jerry_set_vm_throw_callback)
|
||||
|
||||
## jerry_promise_state_t
|
||||
|
||||
Enum which describes the state of a Promise.
|
||||
@@ -11329,8 +11356,7 @@ backtrace_callback (jerry_backtrace_frame_t *frame_p,
|
||||
|
||||
**Summary**
|
||||
|
||||
When JERRY_FEATURE_VM_EXEC_STOP is enabled a callback function can be
|
||||
specified by this function. This callback is periodically called when
|
||||
The callback passed to this function is periodically called when
|
||||
JerryScript executes an ECMAScript program.
|
||||
|
||||
If the callback returns with undefined value the ECMAScript execution
|
||||
@@ -11345,6 +11371,10 @@ or an exception is caught. Setting the `frequency` to a greater
|
||||
than `1` value reduces this overhead further. If its value is N
|
||||
only every Nth event (backward jump, etc.) trigger the next check.
|
||||
|
||||
*Notes*:
|
||||
- This API depends on a build option (`JERRY_VM_EXEC_STOP`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_VM_EXEC_STOP` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
|
||||
**Prototype**
|
||||
|
||||
@@ -11368,14 +11398,14 @@ jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb,
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
|
||||
static int countdown = 10;
|
||||
|
||||
static jerry_value_t
|
||||
vm_exec_stop_callback (void *user_p)
|
||||
{
|
||||
while (countdown > 0)
|
||||
int *countdown_p = (int *) user_p;
|
||||
|
||||
while (*countdown_p > 0)
|
||||
{
|
||||
countdown--;
|
||||
(*countdown_p)--;
|
||||
return jerry_create_undefined ();
|
||||
}
|
||||
|
||||
@@ -11388,6 +11418,7 @@ main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
int countdown = 10;
|
||||
jerry_set_vm_exec_stop_callback (vm_exec_stop_callback, &countdown, 16);
|
||||
|
||||
// Infinite loop.
|
||||
@@ -11402,12 +11433,77 @@ main (void)
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_init](#jerry_init)
|
||||
- [jerry_cleanup](#jerry_cleanup)
|
||||
- [jerry_parse](#jerry_parse)
|
||||
- [jerry_run](#jerry_run)
|
||||
- [jerry_vm_exec_stop_callback_t](#jerry_vm_exec_stop_callback_t)
|
||||
|
||||
## jerry_set_vm_throw_callback
|
||||
|
||||
**Summary**
|
||||
|
||||
The callback passed to this function is called when an error is thrown
|
||||
in ECMAScript code. The callback is not called again until the value is
|
||||
caught. See: [jerry_vm_throw_callback_t](#jerry_vm_throw_callback_t).
|
||||
|
||||
*Notes*:
|
||||
- This API depends on a build option (`JERRY_VM_THROW`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_VM_THROW` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb,
|
||||
void *user_p);
|
||||
```
|
||||
|
||||
- `throw_cb` - callback which is called on throws (passing NULL disables this feature)
|
||||
- `user_p` - user pointer passed to the `throw_cb` function
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
|
||||
static void
|
||||
vm_throw_callback (const jerry_value_t error_value, /**< captured error */
|
||||
void *user_p) /**< user pointer */
|
||||
{
|
||||
(void) error_value;
|
||||
|
||||
/* Counts the number of throws. */
|
||||
int *counter_p = (int *) user_p;
|
||||
(*counter_p)++;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
int counter = 0;
|
||||
jerry_set_vm_throw_callback (vm_throw_callback, &counter);
|
||||
|
||||
const jerry_char_t script[] = "try { throw new Error('1') } catch (e) { throw new Error('2') }";
|
||||
|
||||
jerry_value_t parsed_code = jerry_parse (script, sizeof (script) - 1, NULL);
|
||||
jerry_release_value (jerry_run (parsed_code));
|
||||
jerry_release_value (parsed_code);
|
||||
|
||||
/* The counter contains 2. */
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_vm_throw_callback_t](#jerry_vm_throw_callback_t)
|
||||
|
||||
## jerry_get_resource_name
|
||||
|
||||
**Summary**
|
||||
|
||||
@@ -37,7 +37,8 @@ set(JERRY_SNAPSHOT_EXEC OFF CACHE BOOL "Enable executing
|
||||
set(JERRY_SNAPSHOT_SAVE OFF CACHE BOOL "Enable saving snapshot files?")
|
||||
set(JERRY_SYSTEM_ALLOCATOR OFF CACHE BOOL "Enable system allocator?")
|
||||
set(JERRY_VALGRIND OFF CACHE BOOL "Enable Valgrind support?")
|
||||
set(JERRY_VM_EXEC_STOP OFF CACHE BOOL "Enable VM execution stopping?")
|
||||
set(JERRY_VM_EXEC_STOP OFF CACHE BOOL "Enable VM execution stop callback?")
|
||||
set(JERRY_VM_THROW OFF CACHE BOOL "Enable VM throw callback?")
|
||||
set(JERRY_GLOBAL_HEAP_SIZE "(512)" CACHE STRING "Size of memory heap, in kilobytes")
|
||||
set(JERRY_GC_LIMIT "(0)" CACHE STRING "Heap usage limit to trigger garbage collection")
|
||||
set(JERRY_STACK_LIMIT "(0)" CACHE STRING "Maximum stack usage size, in kilobytes")
|
||||
@@ -96,6 +97,7 @@ message(STATUS "JERRY_SNAPSHOT_SAVE " ${JERRY_SNAPSHOT_SAVE} ${JERRY_
|
||||
message(STATUS "JERRY_SYSTEM_ALLOCATOR " ${JERRY_SYSTEM_ALLOCATOR})
|
||||
message(STATUS "JERRY_VALGRIND " ${JERRY_VALGRIND})
|
||||
message(STATUS "JERRY_VM_EXEC_STOP " ${JERRY_VM_EXEC_STOP})
|
||||
message(STATUS "JERRY_VM_THROW " ${JERRY_VM_THROW})
|
||||
message(STATUS "JERRY_GLOBAL_HEAP_SIZE " ${JERRY_GLOBAL_HEAP_SIZE})
|
||||
message(STATUS "JERRY_GC_LIMIT " ${JERRY_GC_LIMIT})
|
||||
message(STATUS "JERRY_STACK_LIMIT " ${JERRY_STACK_LIMIT})
|
||||
@@ -627,9 +629,12 @@ if(JERRY_VALGRIND)
|
||||
set(INCLUDE_CORE_PRIVATE ${INCLUDE_CORE_PRIVATE} ${INCLUDE_THIRD_PARTY_VALGRIND})
|
||||
endif()
|
||||
|
||||
# Enable VM execution stopping
|
||||
# Enable VM execution stop callback
|
||||
jerry_add_define01(JERRY_VM_EXEC_STOP)
|
||||
|
||||
# Enable VM throw callback
|
||||
jerry_add_define01(JERRY_VM_THROW)
|
||||
|
||||
# Size of heap
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_GLOBAL_HEAP_SIZE=${JERRY_GLOBAL_HEAP_SIZE})
|
||||
|
||||
|
||||
+22
-3
@@ -1800,6 +1800,9 @@ jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check *
|
||||
#if JERRY_VM_EXEC_STOP
|
||||
|| feature == JERRY_FEATURE_VM_EXEC_STOP
|
||||
#endif /* JERRY_VM_EXEC_STOP */
|
||||
#if JERRY_VM_THROW
|
||||
|| feature == JERRY_FEATURE_VM_THROW
|
||||
#endif /* JERRY_VM_THROW */
|
||||
#if JERRY_BUILTIN_JSON
|
||||
|| feature == JERRY_FEATURE_JSON
|
||||
#endif /* JERRY_BUILTIN_JSON */
|
||||
@@ -5202,8 +5205,8 @@ jerry_create_context (uint32_t heap_size, /**< the size of heap */
|
||||
} /* jerry_create_context */
|
||||
|
||||
/**
|
||||
* If JERRY_VM_EXEC_STOP is enabled the callback passed to this function is
|
||||
* periodically called with the user_p argument. If frequency is greater
|
||||
* When JERRY_VM_EXEC_STOP is enabled, the callback passed to this function
|
||||
* is periodically called with the user_p argument. If frequency is greater
|
||||
* than 1, the callback is only called at every frequency ticks.
|
||||
*/
|
||||
void
|
||||
@@ -5219,8 +5222,8 @@ jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, /**< per
|
||||
|
||||
JERRY_CONTEXT (vm_exec_stop_frequency) = frequency;
|
||||
JERRY_CONTEXT (vm_exec_stop_counter) = frequency;
|
||||
JERRY_CONTEXT (vm_exec_stop_user_p) = user_p;
|
||||
JERRY_CONTEXT (vm_exec_stop_cb) = stop_cb;
|
||||
JERRY_CONTEXT (vm_exec_stop_user_p) = user_p;
|
||||
#else /* !JERRY_VM_EXEC_STOP */
|
||||
JERRY_UNUSED (stop_cb);
|
||||
JERRY_UNUSED (user_p);
|
||||
@@ -5228,6 +5231,22 @@ jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, /**< per
|
||||
#endif /* JERRY_VM_EXEC_STOP */
|
||||
} /* jerry_set_vm_exec_stop_callback */
|
||||
|
||||
/**
|
||||
* When JERRY_VM_THROW is enabled, the callback passed to this
|
||||
* function is called when an error is thrown in ECMAScript code.
|
||||
*/
|
||||
void jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb, /**< callback which is called on throws */
|
||||
void *user_p) /**< pointer passed to the function */
|
||||
{
|
||||
#if JERRY_VM_THROW
|
||||
JERRY_CONTEXT (vm_throw_callback_p) = throw_cb;
|
||||
JERRY_CONTEXT (vm_throw_callback_user_p) = user_p;
|
||||
#else /* !JERRY_VM_THROW */
|
||||
JERRY_UNUSED (throw_cb);
|
||||
JERRY_UNUSED (user_p);
|
||||
#endif /* JERRY_VM_THROW */
|
||||
} /* jerry_set_vm_throw_callback */
|
||||
|
||||
/**
|
||||
* Get backtrace. The backtrace is an array of strings where
|
||||
* each string contains the position of the corresponding frame.
|
||||
|
||||
+17
-2
@@ -430,13 +430,24 @@
|
||||
* Enable/Disable the vm execution stop callback function.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable vm exec stop callbacks.
|
||||
* 1: Enable vm exec stop callback functionality.
|
||||
* 0: Disable vm exec stop callback support.
|
||||
* 1: Enable vm exec stop callback support.
|
||||
*/
|
||||
#ifndef JERRY_VM_EXEC_STOP
|
||||
# define JERRY_VM_EXEC_STOP 0
|
||||
#endif /* !defined (JERRY_VM_EXEC_STOP) */
|
||||
|
||||
/**
|
||||
* Enable/Disable the vm throw callback function.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable vm throw callback support.
|
||||
* 1: Enable vm throw callback support.
|
||||
*/
|
||||
#ifndef JERRY_VM_THROW
|
||||
# define JERRY_VM_THROW 0
|
||||
#endif /* !defined (JERRY_VM_THROW) */
|
||||
|
||||
/**
|
||||
* Advanced section configurations.
|
||||
*/
|
||||
@@ -680,6 +691,10 @@
|
||||
|| ((JERRY_VM_EXEC_STOP != 0) && (JERRY_VM_EXEC_STOP != 1))
|
||||
# error "Invalid value for 'JERRY_VM_EXEC_STOP' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_VM_THROW) \
|
||||
|| ((JERRY_VM_THROW != 0) && (JERRY_VM_THROW != 1))
|
||||
# error "Invalid value for 'JERRY_VM_THROW' macro."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Cross component requirements check.
|
||||
|
||||
@@ -63,6 +63,9 @@ typedef enum
|
||||
ECMA_STATUS_EXCEPTION = (1u << 3), /**< last exception is a normal exception */
|
||||
ECMA_STATUS_ABORT = (1u << 4), /**< last exception is an abort */
|
||||
ECMA_STATUS_ERROR_UPDATE = (1u << 5), /**< the error_object_created_callback_p is called */
|
||||
#if JERRY_VM_THROW
|
||||
ECMA_STATUS_ERROR_THROWN = (1u << 6), /**< the vm_throw_callback_p is called */
|
||||
#endif /* JERRY_VM_THROW */
|
||||
} ecma_status_flag_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -360,6 +360,7 @@ bool jerry_backtrace_is_strict (jerry_backtrace_frame_t *frame_p);
|
||||
* Miscellaneous functions.
|
||||
*/
|
||||
void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, void *user_p, uint32_t frequency);
|
||||
void jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb, void *user_p);
|
||||
jerry_value_t jerry_get_resource_name (const jerry_value_t value);
|
||||
jerry_value_t jerry_get_user_value (const jerry_value_t value);
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ typedef enum
|
||||
JERRY_FEATURE_SNAPSHOT_EXEC, /**< executing snapshot files */
|
||||
JERRY_FEATURE_DEBUGGER, /**< debugging */
|
||||
JERRY_FEATURE_VM_EXEC_STOP, /**< stopping ECMAScript execution */
|
||||
JERRY_FEATURE_VM_THROW, /**< capturing ECMAScript throws */
|
||||
JERRY_FEATURE_JSON, /**< JSON support */
|
||||
JERRY_FEATURE_PROMISE, /**< promise support */
|
||||
JERRY_FEATURE_TYPEDARRAY, /**< Typedarray support */
|
||||
@@ -306,6 +307,15 @@ typedef void (*jerry_error_object_created_callback_t) (const jerry_value_t error
|
||||
*/
|
||||
typedef jerry_value_t (*jerry_vm_exec_stop_callback_t) (void *user_p);
|
||||
|
||||
/**
|
||||
* Callback function which is called when an error is thrown in an ECMAScript code.
|
||||
* The callback should not change the error_value. The callback is not called again
|
||||
* until the value is caught.
|
||||
*
|
||||
* Note: the engine considers errors thrown by external functions as never caught.
|
||||
*/
|
||||
typedef void (*jerry_vm_throw_callback_t) (const jerry_value_t error_value, void *user_p);
|
||||
|
||||
/**
|
||||
* Function type applied for each data property of an object.
|
||||
*/
|
||||
|
||||
@@ -113,8 +113,11 @@ jcontext_take_exception (void)
|
||||
{
|
||||
JERRY_ASSERT (jcontext_has_pending_exception ());
|
||||
|
||||
jcontext_set_abort_flag (false);
|
||||
jcontext_set_exception_flag (false);
|
||||
JERRY_CONTEXT (status_flags) &= (uint32_t) ~(ECMA_STATUS_EXCEPTION
|
||||
#if JERRY_VM_THROW
|
||||
| ECMA_STATUS_ERROR_THROWN
|
||||
#endif /* JERRY_VM_THROW */
|
||||
| ECMA_STATUS_ABORT);
|
||||
return JERRY_CONTEXT (error_value);
|
||||
} /* jcontext_take_exception */
|
||||
|
||||
|
||||
@@ -200,6 +200,11 @@ struct jerry_context_t
|
||||
* ECMAScript execution should be stopped */
|
||||
#endif /* JERRY_VM_EXEC_STOP */
|
||||
|
||||
#if JERRY_VM_THROW
|
||||
void *vm_throw_callback_user_p; /**< user pointer for vm_throw_callback_p */
|
||||
jerry_vm_throw_callback_t vm_throw_callback_p; /**< callback for capturing throws */
|
||||
#endif /* JERRY_VM_THROW */
|
||||
|
||||
#if (JERRY_STACK_LIMIT != 0)
|
||||
uintptr_t stack_base; /**< stack base marker */
|
||||
#endif /* (JERRY_STACK_LIMIT != 0) */
|
||||
|
||||
@@ -4457,6 +4457,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
if (context_type == VM_CONTEXT_FINALLY_THROW)
|
||||
{
|
||||
jcontext_raise_exception (*stack_top_p);
|
||||
#if JERRY_VM_THROW
|
||||
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ERROR_THROWN;
|
||||
#endif /* JERRY_VM_THROW */
|
||||
result = ECMA_VALUE_ERROR;
|
||||
|
||||
#if JERRY_DEBUGGER
|
||||
@@ -4789,6 +4792,20 @@ error:
|
||||
ecma_fast_free_value (stack_item);
|
||||
}
|
||||
|
||||
#if JERRY_VM_THROW
|
||||
if (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_ERROR_THROWN))
|
||||
{
|
||||
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ERROR_THROWN;
|
||||
|
||||
jerry_vm_throw_callback_t vm_throw_callback_p = JERRY_CONTEXT (vm_throw_callback_p);
|
||||
|
||||
if (vm_throw_callback_p != NULL)
|
||||
{
|
||||
vm_throw_callback_p (JERRY_CONTEXT (error_value), JERRY_CONTEXT (vm_throw_callback_user_p));
|
||||
}
|
||||
}
|
||||
#endif /* JERRY_VM_THROW */
|
||||
|
||||
#if JERRY_DEBUGGER
|
||||
const uint32_t dont_stop = (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION
|
||||
| JERRY_DEBUGGER_VM_IGNORE
|
||||
|
||||
@@ -48,7 +48,6 @@ set(SOURCE_UNIT_TEST_MAIN_MODULES
|
||||
test-context-data.c
|
||||
test-dataview.c
|
||||
test-date-helpers.c
|
||||
test-exec-stop.c
|
||||
test-external-string.c
|
||||
test-from-property-descriptor.c
|
||||
test-get-own-property.c
|
||||
@@ -91,6 +90,8 @@ set(SOURCE_UNIT_TEST_MAIN_MODULES
|
||||
test-to-property-descriptor.c
|
||||
test-typedarray.c
|
||||
test-unicode.c
|
||||
test-vm-exec-stop.c
|
||||
test-vm-throw.c
|
||||
)
|
||||
|
||||
# jerry_heap_stats_t.size == 0 if system allocator is used.
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "jerryscript.h"
|
||||
|
||||
#include "test-common.h"
|
||||
|
||||
static int mode = 0;
|
||||
static int counter = 0;
|
||||
|
||||
static void
|
||||
vm_throw_callback (const jerry_value_t error_value, /**< captured error */
|
||||
void *user_p) /**< user pointer */
|
||||
{
|
||||
TEST_ASSERT (user_p == (void *) &mode);
|
||||
counter++;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
TEST_ASSERT (counter == 1);
|
||||
TEST_ASSERT (jerry_value_is_number (error_value) && jerry_get_number_value (error_value) == -5.6);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
TEST_ASSERT (counter == 1);
|
||||
TEST_ASSERT (jerry_value_is_null (error_value));
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
jerry_char_t string_buf[2];
|
||||
jerry_size_t size = sizeof (string_buf);
|
||||
|
||||
string_buf[0] = '\0';
|
||||
string_buf[1] = '\0';
|
||||
|
||||
TEST_ASSERT (counter >= 1 && counter <= 3);
|
||||
TEST_ASSERT (jerry_value_is_string (error_value));
|
||||
TEST_ASSERT (jerry_get_string_size (error_value) == size);
|
||||
TEST_ASSERT (jerry_string_to_char_buffer (error_value, string_buf, size) == size);
|
||||
TEST_ASSERT (string_buf[0] == 'e' && string_buf[1] == (char) ('0' + counter));
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
TEST_ASSERT (counter == 1);
|
||||
TEST_ASSERT (jerry_get_error_type (error_value) == JERRY_ERROR_RANGE);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
TEST_ASSERT (mode == 4);
|
||||
TEST_ASSERT (counter >= 1 && counter <= 2);
|
||||
|
||||
jerry_error_t error = (counter == 1) ? JERRY_ERROR_REFERENCE : JERRY_ERROR_TYPE;
|
||||
TEST_ASSERT (jerry_get_error_type (error_value) == error);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
TEST_ASSERT (counter >= 1 && counter <= 2);
|
||||
TEST_ASSERT (jerry_value_is_false (error_value));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
TEST_ASSERT (mode == 6 || mode == 7);
|
||||
TEST_ASSERT (counter == 1);
|
||||
TEST_ASSERT (jerry_value_is_true (error_value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* vm_throw_callback */
|
||||
|
||||
static jerry_value_t
|
||||
native_handler (const jerry_call_info_t *call_info_p, /**< call info */
|
||||
const jerry_value_t args_p[], /**< arguments */
|
||||
const jerry_length_t args_count) /**< arguments length */
|
||||
{
|
||||
(void) call_info_p;
|
||||
(void) args_p;
|
||||
TEST_ASSERT (args_count == 0);
|
||||
|
||||
jerry_char_t source[] = TEST_STRING_LITERAL ("throw false");
|
||||
return jerry_eval (source, sizeof (source) - 1, JERRY_PARSE_NO_OPTS);
|
||||
} /* native_handler */
|
||||
|
||||
static void
|
||||
do_eval (const char *script_p, /**< script to evaluate */
|
||||
bool should_throw) /**< script throws an error */
|
||||
{
|
||||
jerry_value_t result = jerry_eval ((const jerry_char_t *) script_p, strlen (script_p), JERRY_PARSE_NO_OPTS);
|
||||
TEST_ASSERT (jerry_value_is_error (result) == should_throw);
|
||||
jerry_release_value (result);
|
||||
} /* do_eval */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
TEST_INIT ();
|
||||
|
||||
/* Test stopping an infinite loop. */
|
||||
if (!jerry_is_feature_enabled (JERRY_FEATURE_VM_THROW))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_set_vm_throw_callback (vm_throw_callback, (void *) &mode);
|
||||
|
||||
mode = 0;
|
||||
counter = 0;
|
||||
do_eval (TEST_STRING_LITERAL ("throw -5.6"),
|
||||
true);
|
||||
TEST_ASSERT (counter == 1);
|
||||
|
||||
mode = 1;
|
||||
counter = 0;
|
||||
do_eval (TEST_STRING_LITERAL ("function f() { throw null }\n"
|
||||
"function g() { f() }\n"
|
||||
"g()\n"),
|
||||
true);
|
||||
TEST_ASSERT (counter == 1);
|
||||
|
||||
mode = 2;
|
||||
counter = 0;
|
||||
do_eval (TEST_STRING_LITERAL ("function f() { throw 'e1' }\n"
|
||||
"function g() { try { f() } catch (e) { throw 'e2' } }\n"
|
||||
"try { g() } catch (e) { throw 'e3' }\n"),
|
||||
true);
|
||||
TEST_ASSERT (counter == 3);
|
||||
|
||||
mode = 3;
|
||||
counter = 0;
|
||||
do_eval (TEST_STRING_LITERAL ("function f() { throw new RangeError() }\n"
|
||||
"function g() { try { f() } finally { } }\n"
|
||||
"try { g() } finally { }\n"),
|
||||
true);
|
||||
TEST_ASSERT (counter == 1);
|
||||
|
||||
mode = 4;
|
||||
counter = 0;
|
||||
do_eval (TEST_STRING_LITERAL ("function f() { unresolved }\n"
|
||||
"function g() { try { f() } finally { null.member } }\n"
|
||||
"try { g() } finally { }\n"),
|
||||
true);
|
||||
TEST_ASSERT (counter == 2);
|
||||
|
||||
/* Native functions may trigger the call twice: */
|
||||
jerry_value_t global_object_value = jerry_get_global_object ();
|
||||
jerry_value_t function_value = jerry_create_external_function (native_handler);
|
||||
jerry_value_t function_name_value = jerry_create_string ((const jerry_char_t *) "native");
|
||||
|
||||
jerry_release_value (jerry_set_property (global_object_value, function_name_value, function_value));
|
||||
jerry_release_value (function_name_value);
|
||||
jerry_release_value (function_value);
|
||||
jerry_release_value (global_object_value);
|
||||
|
||||
mode = 5;
|
||||
counter = 0;
|
||||
do_eval (TEST_STRING_LITERAL ("native()\n"),
|
||||
true);
|
||||
TEST_ASSERT (counter == 2);
|
||||
|
||||
/* Built-in functions should not trigger the call twice: */
|
||||
mode = 6;
|
||||
counter = 0;
|
||||
do_eval (TEST_STRING_LITERAL ("function f() { eval('eval(\\'throw true\\')') }\n"
|
||||
"f()\n"),
|
||||
true);
|
||||
TEST_ASSERT (counter == 1);
|
||||
|
||||
mode = 7;
|
||||
counter = 0;
|
||||
do_eval (TEST_STRING_LITERAL ("function f() { [1].map(function() { throw true }) }\n"
|
||||
"f()\n"),
|
||||
true);
|
||||
TEST_ASSERT (counter == 1);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
} /* main */
|
||||
+4
-1
@@ -155,7 +155,9 @@ def get_arguments():
|
||||
coregrp.add_argument('--valgrind', metavar='X', choices=['ON', 'OFF'], type=str.upper,
|
||||
help=devhelp('enable Valgrind support (%(choices)s)'))
|
||||
coregrp.add_argument('--vm-exec-stop', metavar='X', choices=['ON', 'OFF'], type=str.upper,
|
||||
help='enable VM execution stopping (%(choices)s)')
|
||||
help='enable VM execution stop callback (%(choices)s)')
|
||||
coregrp.add_argument('--vm-throw', metavar='X', choices=['ON', 'OFF'], type=str.upper,
|
||||
help='enable VM throw callback (%(choices)s)')
|
||||
|
||||
maingrp = parser.add_argument_group('jerry-main options')
|
||||
maingrp.add_argument('--link-map', metavar='X', choices=['ON', 'OFF'], type=str.upper,
|
||||
@@ -223,6 +225,7 @@ def generate_build_options(arguments):
|
||||
build_options_append('JERRY_SYSTEM_ALLOCATOR', arguments.system_allocator)
|
||||
build_options_append('JERRY_VALGRIND', arguments.valgrind)
|
||||
build_options_append('JERRY_VM_EXEC_STOP', arguments.vm_exec_stop)
|
||||
build_options_append('JERRY_VM_THROW', arguments.vm_throw)
|
||||
|
||||
if arguments.gc_mark_limit is not None:
|
||||
build_options.append('-D%s=%s' % ('JERRY_GC_MARK_LIMIT', arguments.gc_mark_limit))
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ OPTIONS_DEBUG = ['--debug']
|
||||
OPTIONS_SNAPSHOT = ['--snapshot-save=on', '--snapshot-exec=on', '--jerry-cmdline-snapshot=on']
|
||||
OPTIONS_UNITTESTS = ['--unittests=on', '--jerry-cmdline=off', '--error-messages=on',
|
||||
'--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on',
|
||||
'--line-info=on', '--mem-stats=on']
|
||||
'--vm-throw=on', '--line-info=on', '--mem-stats=on']
|
||||
OPTIONS_DOCTESTS = ['--doctests=on', '--jerry-cmdline=off', '--error-messages=on',
|
||||
'--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on']
|
||||
|
||||
|
||||
Reference in New Issue
Block a user