mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Native callback in embedding jerry when object is to be freed.
JerryScript-DCO-1.0-Signed-off-by: SaeHie Park saehie.park@samsung.com
This commit is contained in:
parent
17036c854e
commit
5ec3e2f59a
@ -34,6 +34,9 @@
|
||||
#include "jrt-libc-includes.h"
|
||||
#include "jrt-bit-fields.h"
|
||||
|
||||
#define JERRY_INTERNAL
|
||||
#include "jerry-internal.h"
|
||||
|
||||
/**
|
||||
* An object's GC color
|
||||
*
|
||||
@ -320,6 +323,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
case ECMA_INTERNAL_PROPERTY_CODE: /* an integer */
|
||||
case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */
|
||||
case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
|
||||
case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */
|
||||
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */
|
||||
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */
|
||||
case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */
|
||||
@ -357,6 +361,27 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
||||
&& !ecma_gc_is_object_visited (object_p)
|
||||
&& ecma_gc_get_object_refs (object_p) == 0);
|
||||
|
||||
if (!ecma_is_lexical_environment (object_p))
|
||||
{
|
||||
/* if the object provides free callback, invoke it with handle stored in the object */
|
||||
|
||||
ecma_external_pointer_t freecb_p;
|
||||
ecma_external_pointer_t native_p;
|
||||
|
||||
bool is_retrieved = ecma_get_external_pointer_value (object_p,
|
||||
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK,
|
||||
&freecb_p);
|
||||
if (is_retrieved)
|
||||
{
|
||||
is_retrieved = ecma_get_external_pointer_value (object_p,
|
||||
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE,
|
||||
&native_p);
|
||||
JERRY_ASSERT (is_retrieved);
|
||||
|
||||
jerry_dispatch_object_free_callback (freecb_p, native_p);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ecma_is_lexical_environment (object_p) ||
|
||||
ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND)
|
||||
{
|
||||
|
||||
@ -206,6 +206,7 @@ typedef enum
|
||||
ECMA_INTERNAL_PROPERTY_CODE, /**< [[Code]] */
|
||||
ECMA_INTERNAL_PROPERTY_NATIVE_CODE, /**< native handler location descriptor */
|
||||
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, /**< native handle associated with an object */
|
||||
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, /**< object's native free callback */
|
||||
ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS, /**< [[FormalParameters]] */
|
||||
ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE, /**< [[Primitive value]] for String objects */
|
||||
ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE, /**< [[Primitive value]] for Number objects */
|
||||
|
||||
@ -30,7 +30,8 @@
|
||||
* Note:
|
||||
* property identifier should be one of the following:
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_CODE;
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE.
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
|
||||
* - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
|
||||
*
|
||||
* @return true - if property was just created with specified value,
|
||||
* false - otherwise, if property existed before the call, it's value was updated.
|
||||
@ -42,7 +43,8 @@ ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to crea
|
||||
ecma_external_pointer_t ptr_value) /**< value to store in the property */
|
||||
{
|
||||
JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE
|
||||
|| id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE);
|
||||
|| id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
|
||||
|| id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);
|
||||
|
||||
bool ret_val;
|
||||
ecma_property_t *prop_p = ecma_find_internal_property (obj_p, id);
|
||||
@ -81,7 +83,8 @@ ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to crea
|
||||
* Note:
|
||||
* property identifier should be one of the following:
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_CODE;
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE.
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
|
||||
* - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
|
||||
*
|
||||
* @return true - if property exists and it's value is returned through out_pointer_p,
|
||||
* false - otherwise (value returned through out_pointer_p is NULL).
|
||||
@ -93,7 +96,8 @@ ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get proper
|
||||
ecma_external_pointer_t *out_pointer_p) /**< out: value of the external pointer */
|
||||
{
|
||||
JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE
|
||||
|| id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE);
|
||||
|| id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
|
||||
|| id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);
|
||||
|
||||
ecma_property_t* prop_p = ecma_find_internal_property (obj_p, id);
|
||||
|
||||
@ -126,13 +130,15 @@ ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get proper
|
||||
* Note:
|
||||
* property identifier should be one of the following:
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_CODE;
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE.
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
|
||||
* - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
|
||||
*/
|
||||
void
|
||||
ecma_free_external_pointer_in_property (ecma_property_t *prop_p) /**< internal property */
|
||||
{
|
||||
JERRY_ASSERT (prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_CODE
|
||||
|| prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE);
|
||||
|| prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
|
||||
|| prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);
|
||||
|
||||
if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t))
|
||||
{
|
||||
|
||||
@ -780,6 +780,7 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */
|
||||
case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
|
||||
case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an external pointer */
|
||||
{
|
||||
ecma_free_external_pointer_in_property (property_p);
|
||||
|
||||
|
||||
@ -100,6 +100,11 @@ typedef bool (*jerry_external_handler_t) (const jerry_api_object_t *function_obj
|
||||
const jerry_api_value_t args_p [],
|
||||
const uint16_t args_count);
|
||||
|
||||
/**
|
||||
* An object's native free callback
|
||||
*/
|
||||
typedef void (*jerry_object_free_callback_t) (const uintptr_t native_p);
|
||||
|
||||
extern EXTERN_C ssize_t
|
||||
jerry_api_string_to_char_buffer (const jerry_api_string_t *string_p,
|
||||
char *buffer_p,
|
||||
@ -152,6 +157,10 @@ bool jerry_api_get_object_native_handle (jerry_api_object_t *object_p, uintptr_t
|
||||
extern EXTERN_C
|
||||
void jerry_api_set_object_native_handle (jerry_api_object_t *object_p, uintptr_t handle);
|
||||
|
||||
extern EXTERN_C
|
||||
bool jerry_api_set_object_free_callback (jerry_api_object_t *object_p,
|
||||
jerry_object_free_callback_t freecb_p);
|
||||
|
||||
extern EXTERN_C
|
||||
bool jerry_api_call_function (jerry_api_object_t *function_object_p,
|
||||
jerry_api_object_t *this_arg_p,
|
||||
|
||||
@ -30,4 +30,8 @@ jerry_dispatch_external_function (ecma_object_t *function_object_p,
|
||||
const ecma_value_t args_p [],
|
||||
ecma_length_t args_count);
|
||||
|
||||
extern void
|
||||
jerry_dispatch_object_free_callback (ecma_external_pointer_t freecb_p,
|
||||
ecma_external_pointer_t native_p);
|
||||
|
||||
#endif /* !JERRY_INTERNAL_H */
|
||||
|
||||
@ -499,6 +499,25 @@ jerry_dispatch_external_function (ecma_object_t *function_object_p, /**< externa
|
||||
return completion_value;
|
||||
} /* jerry_dispatch_external_function */
|
||||
|
||||
/**
|
||||
* Dispatch call to object's native free callback function
|
||||
*
|
||||
* Note:
|
||||
* the callback is called during critical GC phase,
|
||||
* so, should not perform any requests to engine
|
||||
*/
|
||||
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_make_api_unavailable ();
|
||||
|
||||
((jerry_object_free_callback_t) freecb_p) ((uintptr_t) native_p);
|
||||
|
||||
jerry_make_api_available ();
|
||||
} /* jerry_dispatch_object_free_callback */
|
||||
|
||||
/**
|
||||
* Check if the specified object is a function object.
|
||||
*
|
||||
@ -743,6 +762,32 @@ jerry_api_set_object_native_handle (jerry_api_object_t *object_p, /**< object to
|
||||
handle);
|
||||
} /* jerry_api_set_object_native_handle */
|
||||
|
||||
/**
|
||||
* Set object free callback for the specified object
|
||||
*
|
||||
* @return true - if callback was set successfully,
|
||||
* false - otherwise (there is no native handle, associated with the object).
|
||||
*/
|
||||
bool
|
||||
jerry_api_set_object_free_callback (jerry_api_object_t *object_p, /**< object to set callback for */
|
||||
jerry_object_free_callback_t freecb_p) /**< object free callback */
|
||||
{
|
||||
uintptr_t handle_value;
|
||||
bool is_native_handle_associated = jerry_api_get_object_native_handle (object_p,
|
||||
&handle_value);
|
||||
|
||||
if (!is_native_handle_associated)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ecma_create_external_pointer_property (object_p,
|
||||
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK,
|
||||
(uintptr_t) freecb_p);
|
||||
|
||||
return true;
|
||||
} /* jerry_api_set_object_free_callback */
|
||||
|
||||
/**
|
||||
* Invoke function specified by a function object
|
||||
*
|
||||
@ -1019,7 +1064,6 @@ jerry_init (jerry_flag_t flags) /**< combination of Jerry flags */
|
||||
|
||||
jerry_flags = flags;
|
||||
|
||||
jerry_make_api_unavailable (); /* TODO remove this line when it's called somewhere else */
|
||||
jerry_make_api_available ();
|
||||
|
||||
mem_init ();
|
||||
|
||||
@ -40,6 +40,8 @@ const char *test_source = (
|
||||
"}"
|
||||
);
|
||||
|
||||
bool test_api_is_free_callback_was_called = false;
|
||||
|
||||
/**
|
||||
* Initialize Jerry API value with specified boolean value
|
||||
*/
|
||||
@ -115,6 +117,15 @@ handler (const jerry_api_object_t *function_obj_p,
|
||||
return true;
|
||||
} /* handler */
|
||||
|
||||
static void
|
||||
handler_construct_freecb (uintptr_t native_p)
|
||||
{
|
||||
assert (native_p == (uintptr_t) 0x0012345678abcdefull);
|
||||
printf ("ok object free callback\n");
|
||||
|
||||
test_api_is_free_callback_was_called = true;
|
||||
} /* handler_construct_freecb */
|
||||
|
||||
static bool
|
||||
handler_construct (const jerry_api_object_t *function_obj_p,
|
||||
const jerry_api_value_t *this_p,
|
||||
@ -135,6 +146,9 @@ handler_construct (const jerry_api_object_t *function_obj_p,
|
||||
|
||||
jerry_api_set_object_native_handle (this_p->v_object, (uintptr_t) 0x0012345678abcdefull);
|
||||
|
||||
bool is_set = jerry_api_set_object_free_callback (this_p->v_object, handler_construct_freecb);
|
||||
assert (is_set);
|
||||
|
||||
return true;
|
||||
} /* handler_construct */
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user