Add 'type' argument to set/get native handle API (#1711)

Ecma-object have native handle type inside, and binding code could use
type info to validate native handle's type.

Related issue #1681

JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang zidong.jiang@intel.com
This commit is contained in:
Zidong Jiang 2017-04-10 16:51:37 +08:00 committed by GitHub
parent 574dff512e
commit e522e740a7
12 changed files with 486 additions and 141 deletions

View File

@ -167,7 +167,9 @@ typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_
**Summary**
Native free callback of an object
**Deprecated: Please use jerry_object_native_free_callback_t instead.**
Native free callback of an object.
**Prototype**
@ -175,6 +177,34 @@ Native free callback of an object
typedef void (*jerry_object_free_callback_t) (const uintptr_t native_p);
```
## jerry_object_native_free_callback_t
**Summary**
Native free callback of an object. It is used in jerry_object_native_info_t.
**Prototype**
```c
typedef void (*jerry_object_native_free_callback_t) (void *native_p);
```
## jerry_object_native_info_t
**Summary**
The type infomation of the native pointer.
It includes the free callback that will be called when associated JavaScript object is garbage collected. It can be left NULL in case it is not needed.
**Prototype**
```c
typedef struct
{
jerry_object_native_free_callback_t free_cb;
} jerry_object_native_info_t;
```
## jerry_object_property_foreach_t
**Summary**
@ -3173,6 +3203,8 @@ jerry_set_prototype (const jerry_value_t obj_val,
**Summary**
**Deprecated: Please use jerry_get_object_native_pointer instead.**
Get native handle, previously associated with specified object.
**Prototype**
@ -3211,12 +3243,16 @@ jerry_get_object_native_handle (const jerry_value_t obj_val,
- [jerry_create_object](#jerry_create_object)
- [jerry_set_object_native_handle](#jerry_set_object_native_handle)
- [jerry_get_object_native_pointer](#jerry_get_object_native_pointer)
## jerry_set_object_native_handle
**Summary**
Set native handle and an optional free callback for the specified object
**Deprecated: Please use jerry_set_object_native_pointer instead.**
Set native handle and an optional free callback for the specified object.
*Note*: If native handle was already set for the object, its value is updated.
@ -3260,6 +3296,146 @@ jerry_set_object_native_handle (const jerry_value_t obj_val,
- [jerry_create_object](#jerry_create_object)
- [jerry_get_object_native_handle](#jerry_get_object_native_handle)
- [jerry_set_object_native_pointer](#jerry_set_object_native_pointer)
## jerry_get_object_native_pointer
**Summary**
Get native pointer and its type information.
The pointer and the type information are previously associated with the object by jerry_set_object_native_pointer.
Users can check the pointer's type before processing it.
**Prototype**
```c
bool
jerry_get_object_native_pointer (const jerry_value_t obj_val,
void **out_native_p,
const jerry_object_native_info_t **out_info_p)
```
- `obj_val` - object value to get native pointer from.
- `out_native_p` - native pointer (output parameter).
- `out_info_p` - native pointer's type infomation (output parameter).
- return value
- true, if there is native pointer associated with the object
- false, otherwise
**Example**
```c
static void native_freecb (uintptr_t native_p)
{
... // free the native pointer
}
static const jerry_object_native_info_t type_info =
{
.free_cb = native_freecb
};
{
jerry_value_t object;
uintptr_t native_set;
... // receive or construct object and native_set value
jerry_set_object_native_pointer (object, native_set, &type_info);
...
uintptr_t native_get;
const jerry_object_native_info_t *type_get_p;
bool is_there_associated_native = jerry_get_object_native_pointer (object, &native_get, &type_get_p);
if (is_there_associated_native)
{
if (out_info_p == &type_info)
{
... // the type of object's native pointer is expected, and then process the native pointer.
}
}
}
```
**See also**
- [jerry_create_object](#jerry_create_object)
- [jerry_set_object_native_pointer](#jerry_set_object_native_pointer)
- [jerry_object_native_info_t](#jerry_object_native_info_t)
## jerry_set_object_native_pointer
**Summary**
Set native pointer and an optional type information for the specified object.
You can get them by calling jerry_get_object_native_pointer later.
*Note*: If native pointer was already set for the object, its value is updated.
*Note*: If a non-NULL free callback is specified in the native type information,
it will be called by the garbage collector when the object is freed.
The type info is always overwrites the previous value, so passing
a NULL value deletes the current type info.
**Prototype**
```c
bool
jerry_set_object_native_pointer (const jerry_value_t obj_val,
void *native_p,
const jerry_object_native_info_t *info_p)
```
- `obj_val` - object to set native pointer in.
- `native_p` - native pointer.
- `info_p` - native pointer's type infomation or NULL.
**Example**
```c
static void native_freecb (uintptr_t native_p)
{
... // free the native pointer
}
static const jerry_object_native_info_t type_info =
{
.free_cb = native_freecb
};
{
jerry_value_t object;
uintptr_t native_set;
... // receive or construct object and native_set value
jerry_set_object_native_pointer (object, native_set, &type_info);
...
uintptr_t native_get;
const jerry_object_native_info_t *type_get_p;
bool is_there_associated_native = jerry_get_object_native_pointer (object, &native_get, &type_get_p);
if (is_there_associated_native)
{
if (out_info_p == &type_info)
{
... // the type of object's native pointer is expected, and then process the native pointer.
}
}
}
```
**See also**
- [jerry_create_object](#jerry_create_object)
- [jerry_get_object_native_pointer](#jerry_get_object_native_pointer)
- [jerry_object_native_info_t](#jerry_object_native_info_t)
## jerry_foreach_object_property

View File

@ -86,7 +86,6 @@ DECLARE_ROUTINES_FOR (collection_header)
DECLARE_ROUTINES_FOR (collection_chunk)
DECLARE_ROUTINES_FOR (string)
DECLARE_ROUTINES_FOR (getter_setter_pointers)
DECLARE_ROUTINES_FOR (external_pointer)
/**
* Allocate memory for extended object

View File

@ -97,18 +97,6 @@ ecma_getter_setter_pointers_t *ecma_alloc_getter_setter_pointers (void);
*/
void ecma_dealloc_getter_setter_pointers (ecma_getter_setter_pointers_t *getter_setter_pointers_p);
/**
* Allocate memory for external pointer
*
* @return pointer to allocated memory
*/
ecma_external_pointer_t *ecma_alloc_external_pointer (void);
/**
* Dealloc memory from external pointer
*/
void ecma_dealloc_external_pointer (ecma_external_pointer_t *external_pointer_p);
/*
* Allocate memory for extended object
*

View File

@ -353,6 +353,47 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
}
} /* ecma_gc_mark */
/**
* Free the native handle/pointer by calling its free callback
*/
static void
ecma_gc_free_native_pointer (ecma_property_t *property_p, /**< property */
lit_magic_string_id_t id) /**< identifier of internal property */
{
JERRY_ASSERT (property_p != NULL);
JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
ecma_external_pointer_t native_p;
ecma_external_pointer_t free_cb;
void *package_p;
package_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, value_p->value);
if (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE)
{
native_p = ((ecma_native_handle_package_t *) package_p)->handle_p;
free_cb = ((ecma_native_handle_package_t *) package_p)->free_cb;
if ((jerry_object_free_callback_t) free_cb != NULL)
{
((jerry_object_free_callback_t) free_cb) ((uintptr_t) native_p);
}
}
else
{
native_p = ((ecma_native_pointer_package_t *) package_p)->native_p;
free_cb = *(ecma_external_pointer_t *) (((ecma_native_pointer_package_t *) package_p)->info_p);
if ((jerry_object_native_free_callback_t) free_cb != NULL)
{
((jerry_object_native_free_callback_t) free_cb) ((void *) native_p);
}
}
} /* ecma_gc_free_native_pointer */
/**
* Free specified object
*/
@ -365,28 +406,6 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
bool obj_is_not_lex_env = !ecma_is_lexical_environment (object_p);
if (obj_is_not_lex_env)
{
/* 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,
LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK,
&freecb_p);
if (is_retrieved && ((jerry_object_free_callback_t) freecb_p) != NULL)
{
is_retrieved = ecma_get_external_pointer_value (object_p,
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
&native_p);
JERRY_ASSERT (is_retrieved);
jerry_dispatch_object_free_callback (freecb_p, native_p);
}
}
if (obj_is_not_lex_env
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
@ -410,9 +429,20 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
{
ecma_property_t *property_p = (ecma_property_t *) (prop_iter_p->types + i);
jmem_cpointer_t name_cp = prop_pair_p->names_cp[i];
/* Call the native's free callback. */
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_STRING_CONTAINER_MAGIC_STRING
&& (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER))
{
ecma_gc_free_native_pointer (property_p, (lit_magic_string_id_t) name_cp);
}
if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED)
{
ecma_free_property (object_p, prop_pair_p->names_cp[i], prop_iter_p->types + i);
ecma_free_property (object_p, name_cp, property_p);
}
}

View File

@ -195,6 +195,28 @@ typedef int32_t ecma_integer_value_t;
*/
typedef uintptr_t ecma_external_pointer_t;
/**
* Representation for native handle package.
*
* Note: It is for the deprecated api:
* jerry_get_object_native_handle and jerry_set_object_native_handle
*/
typedef struct
{
ecma_external_pointer_t handle_p; /**< points to the external native object */
ecma_external_pointer_t free_cb; /**< free callback of the native handle */
} ecma_native_handle_package_t;
/**
* Representation of the native pointer package.
*/
typedef struct
{
ecma_external_pointer_t native_p; /**< points to the external native object */
ecma_external_pointer_t info_p; /**< type info of the native pointer */
} ecma_native_pointer_package_t;
/**
* Special property identifiers.
*/

View File

@ -25,24 +25,24 @@
*/
/**
* Create internal property with specified identifier and store external pointer in the property.
* Create internal property with specified identifier and store native handle/pointer of the object.
*
* Note:
* property identifier should be one of the following:
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
* - LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER
*
* @return true - if property was just created with specified value,
* false - otherwise, if property existed before the call, it's value was updated
*/
bool
ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to create property in */
lit_magic_string_id_t id, /**< identifier of internal
* property to create */
ecma_external_pointer_t ptr_value) /**< value to store in the property */
static bool
ecma_create_native_property (ecma_object_t *obj_p, /**< object to create property in */
lit_magic_string_id_t id, /**< identifier of internal
* property to create */
void *package_p) /**< value to store in the property */
{
JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| id == LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK);
|| id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
ecma_string_t name;
ecma_init_ecma_magic_string (&name, id);
@ -58,6 +58,7 @@ ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to crea
else
{
value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
ecma_free_native_package_property (property_p, id);
}
JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (&name));
@ -65,51 +66,72 @@ ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to crea
JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (value_p->value),
size_of_internal_property_value_must_be_greater_than_or_equal_to_4_bytes);
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
value_p->value = (ecma_value_t) ptr_value;
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
ecma_external_pointer_t *handler_p;
if (is_new)
{
handler_p = ecma_alloc_external_pointer ();
ECMA_SET_NON_NULL_POINTER (value_p->value, handler_p);
}
else
{
handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, value_p->value);
}
*handler_p = ptr_value;
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, package_p);
return is_new;
} /* ecma_create_external_pointer_property */
} /* ecma_create_native_property */
/**
* Get value of external pointer stored in the object's property with specified identifier
* Create a native handle property to store the native handle and its 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
*/
bool
ecma_create_native_handle_property (ecma_object_t *obj_p, /**< object to create property in */
ecma_external_pointer_t handle_p, /**< native handle */
ecma_external_pointer_t free_cb) /**< native handle's free callback*/
{
ecma_native_handle_package_t *package_p;
package_p = jmem_heap_alloc_block (sizeof (ecma_native_handle_package_t));
package_p->handle_p = handle_p;
package_p->free_cb = free_cb;
return ecma_create_native_property (obj_p,
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
package_p);
} /* ecma_create_native_handle_property */
/**
* Create a native pointer property to store the native pointer and its type info.
*
* @return true - if property was just created with specified value,
* false - otherwise, if property existed before the call, it's value was updated
*/
bool
ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create property in */
ecma_external_pointer_t native_p, /**< native pointer */
ecma_external_pointer_t info_p) /**< native pointer's type info */
{
ecma_native_pointer_package_t *package_p;
package_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_package_t));
package_p->native_p = native_p;
package_p->info_p = info_p;
return ecma_create_native_property (obj_p,
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER,
package_p);
} /* ecma_create_native_pointer_property */
/**
* Get value of native package stored in the object's property with specified identifier
*
* Note:
* property identifier should be one of the following:
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
* - LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER
*
* @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)
*/
bool
ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */
lit_magic_string_id_t id, /**< identifier of internal property
* to get value from */
ecma_external_pointer_t *out_pointer_p) /**< [out] value of the external pointer */
ecma_get_native_package_value (ecma_object_t *obj_p, /**< object to get property value from */
lit_magic_string_id_t id, /**< identifier of internal property
* to get value from */
void **out_pointer_p) /**< [out] value of the native package */
{
JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| id == LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK);
|| id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
ecma_string_t name;
ecma_init_ecma_magic_string (&name, id);
@ -120,51 +142,46 @@ ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get proper
if (property_p == NULL)
{
*out_pointer_p = (ecma_external_pointer_t) NULL;
*out_pointer_p = NULL;
return false;
}
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
*out_pointer_p = value_p->value;
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
*out_pointer_p = *ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, value_p->value);
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
*out_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, value_p->value);
return true;
} /* ecma_get_external_pointer_value */
} /* ecma_get_native_package_value */
/**
* Free memory associated with external pointer stored in the property
* Free the allocated native package struct.
*
* Note:
* property identifier should be one of the following:
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
* - LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER
*/
void
ecma_free_external_pointer_in_property (ecma_property_t *prop_p) /**< internal property */
ecma_free_native_package_property (ecma_property_t *prop_p, /**< native property */
lit_magic_string_id_t id) /**< identifier of internal */
{
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
/* no additional memory was allocated for the pointer storage */
JERRY_UNUSED (prop_p);
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
void *package_p;
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
package_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, value_p->value);
ecma_external_pointer_t *handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t,
ECMA_PROPERTY_VALUE_PTR (prop_p)->value);
if (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE)
{
jmem_heap_free_block (package_p, sizeof (ecma_native_handle_package_t));
return;
}
ecma_dealloc_external_pointer (handler_p);
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
} /* ecma_free_external_pointer_in_property */
jmem_heap_free_block (package_p, sizeof (ecma_native_pointer_package_t));
} /* ecma_free_native_package_property */
/**
* @}

View File

@ -731,9 +731,9 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_STRING_CONTAINER_MAGIC_STRING)
{
if (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| name_cp == LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK)
|| name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER)
{
ecma_free_external_pointer_in_property (property_p);
ecma_free_native_package_property (property_p, (lit_magic_string_id_t) name_cp);
break;
}
}

View File

@ -341,11 +341,17 @@ void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p);
void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p);
/* ecma-helpers-external-pointers.c */
bool ecma_create_external_pointer_property (ecma_object_t *obj_p, lit_magic_string_id_t id,
ecma_external_pointer_t ptr_value);
bool ecma_get_external_pointer_value (ecma_object_t *obj_p, lit_magic_string_id_t id,
ecma_external_pointer_t *out_pointer_p);
void ecma_free_external_pointer_in_property (ecma_property_t *prop_p);
bool ecma_create_native_handle_property (ecma_object_t *obj_p,
ecma_external_pointer_t handle_p,
ecma_external_pointer_t free_cb);
bool ecma_create_native_pointer_property (ecma_object_t *obj_p,
ecma_external_pointer_t native_p,
ecma_external_pointer_t info_p);
bool ecma_get_native_package_value (ecma_object_t *obj_p,
lit_magic_string_id_t id,
void **out_pointer_p);
void ecma_free_native_package_property (ecma_property_t *prop_p,
lit_magic_string_id_t id);
/* ecma-helpers-conversion.c */
ecma_number_t ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, lit_utf8_size_t str_size);

View File

@ -1902,7 +1902,9 @@ jerry_set_prototype (const jerry_value_t obj_val, /**< object value */
} /* jerry_set_prototype */
/**
* Get native handle, associated with specified object
* Get native handle, associated with specified object.
*
* Note: This API is deprecated, please use jerry_get_object_native_pointer instaed.
*
* @return true - if there is an associated handle (handle is returned through out_handle_p),
* false - otherwise
@ -1913,22 +1915,53 @@ jerry_get_object_native_handle (const jerry_value_t obj_val, /**< object to get
{
jerry_assert_api_available ();
uintptr_t handle_value;
ecma_native_handle_package_t *package_p;
bool does_exist = ecma_get_external_pointer_value (ecma_get_object_from_value (obj_val),
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
&handle_value);
bool does_exist = ecma_get_native_package_value (ecma_get_object_from_value (obj_val),
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
(void **) &package_p);
if (does_exist)
{
*out_handle_p = handle_value;
*out_handle_p = package_p->handle_p;
}
return does_exist;
} /* jerry_get_object_native_handle */
/**
* Set native handle and an optional free callback for the specified object
* Get native pointer and its type information, associated with specified object.
*
* @return true - if there is an associated pointer (pointer is returned through out_handle_p),
* false - otherwise
*/
bool
jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get native pointer from */
void **out_native_p, /**< [out] native pointer */
const jerry_object_native_info_t **out_info_p) /**< [out] the type info
* of the native pointer */
{
jerry_assert_api_available ();
ecma_native_pointer_package_t *package_p;
bool does_exist = ecma_get_native_package_value (ecma_get_object_from_value (obj_val),
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER,
(void **) &package_p);
if (does_exist)
{
*out_native_p = (void *) package_p->native_p;
*out_info_p = (const jerry_object_native_info_t *) package_p->info_p;
}
return does_exist;
} /* jerry_get_object_native_pointer */
/**
* Set native handle and an optional free callback for the specified object.
*
* Note: This API is deprecated, please use jerry_set_object_native_pointer instaed.
*
* Note:
* If native handle was already set for the object, its value is updated.
@ -1948,15 +1981,40 @@ jerry_set_object_native_handle (const jerry_value_t obj_val, /**< object to set
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
ecma_create_external_pointer_property (object_p,
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
handle_p);
ecma_create_external_pointer_property (object_p,
LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK,
(uintptr_t) freecb_p);
ecma_create_native_handle_property (object_p,
handle_p,
(ecma_external_pointer_t) freecb_p);
} /* jerry_set_object_native_handle */
/**
* Set native pointer and an optional type info for the specified object.
*
*
* Note:
* If native pointer was already set for the object, its value is updated.
*
* Note:
* If a non-NULL free callback is specified in the native type info,
* it will be called by the garbage collector when the object is freed.
* The type info is always overwrites the previous value, so passing
* a NULL value deletes the current type info.
*/
void
jerry_set_object_native_pointer (const jerry_value_t obj_val, /**< object to set native pointer in */
void *native_p, /**< native pointer */
const jerry_object_native_info_t *info_p) /**< object's native type info */
{
jerry_assert_api_available ();
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
ecma_create_native_pointer_property (object_p,
(ecma_external_pointer_t) native_p,
(ecma_external_pointer_t) info_p);
} /* jerry_set_object_native_pointer */
/**
* Applies the given function to the every property in the object.
*

View File

@ -25,6 +25,12 @@ extern "C"
{
#endif /* __cplusplus */
#ifdef __GNUC__
#define JERRY_DEPRECATED_API __attribute__((deprecated))
#else /* !__GNUC__ */
/* TODO: for other compilers */
#define JERRY_DEPRECATED_API
#endif /* __GNUC__ */
/** \addtogroup jerry Jerry engine interface
* @{
*/
@ -156,16 +162,28 @@ typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_
const jerry_length_t args_count);
/**
* Native free callback of an object
* Native free callback of an object (deprecated)
*/
typedef void (*jerry_object_free_callback_t) (const uintptr_t native_p);
/**
* Native free callback of an object
*/
typedef void (*jerry_object_native_free_callback_t) (void *native_p);
/**
* Function type applied for each data property of an object
*/
typedef bool (*jerry_object_property_foreach_t) (const jerry_value_t property_name,
const jerry_value_t property_value,
void *user_data_p);
/**
* Type information of a native pointer.
*/
typedef struct
{
jerry_object_native_free_callback_t free_cb; /**< the free callback of the native pointer */
} jerry_object_native_info_t;
/**
* General engine functions
@ -322,9 +340,19 @@ jerry_value_t jerry_get_object_keys (const jerry_value_t obj_val);
jerry_value_t jerry_get_prototype (const jerry_value_t obj_val);
jerry_value_t jerry_set_prototype (const jerry_value_t obj_val, const jerry_value_t proto_obj_val);
JERRY_DEPRECATED_API
bool jerry_get_object_native_handle (const jerry_value_t obj_val, uintptr_t *out_handle_p);
JERRY_DEPRECATED_API
void jerry_set_object_native_handle (const jerry_value_t obj_val, uintptr_t handle_p,
jerry_object_free_callback_t freecb_p);
bool jerry_get_object_native_pointer (const jerry_value_t obj_val,
void **out_native_p,
const jerry_object_native_info_t **out_info_p);
void jerry_set_object_native_pointer (const jerry_value_t obj_val,
void *native_p,
const jerry_object_native_info_t *info_p);
bool jerry_foreach_object_property (const jerry_value_t obj_val, jerry_object_property_foreach_t foreach_p,
void *user_data_p);

View File

@ -36,10 +36,9 @@ typedef enum
#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE
LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< number of non-internal magic strings */
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE = LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< native handle associated
* with an object */
LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK, /**< object's native free callback */
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE = LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< native handle package
* associated with an object */
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER, /**< native pointer package associated with an object */
LIT_MAGIC_STRING__COUNT /**< number of magic strings */
} lit_magic_string_id_t;

View File

@ -107,14 +107,32 @@ handler_throw_test (const jerry_value_t func_obj_val, /**< function object */
} /* handler_throw_test */
static void
handler_construct_freecb (uintptr_t native_p)
handler_construct_freecb (void *native_p)
{
TEST_ASSERT (native_p == (uintptr_t) 0x0012345678abcdefull);
TEST_ASSERT ((uintptr_t) native_p == (uintptr_t) 0x0012345678abcdefull);
printf ("ok object free callback\n");
test_api_is_free_callback_was_called = true;
} /* handler_construct_freecb */
/**
* The name of the jerry_object_native_info_t struct.
*/
#define JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE(c_type) _jerry_object_native_info_##c_type
/**
* Define a native pointer's type based on the C type and free callback.
*/
#define JERRY_DEFINE_NATIVE_HANDLE_INFO(c_type, native_free_cb) \
static const jerry_object_native_info_t JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (c_type) = \
{ \
.free_cb = (jerry_object_native_free_callback_t) native_free_cb \
}
JERRY_DEFINE_NATIVE_HANDLE_INFO (bind1, handler_construct_freecb);
JERRY_DEFINE_NATIVE_HANDLE_INFO (bind2, handler_construct_freecb);
static jerry_value_t
handler_construct (const jerry_value_t func_obj_val, /**< function object */
const jerry_value_t this_val, /**< this value */
@ -134,18 +152,20 @@ handler_construct (const jerry_value_t func_obj_val, /**< function object */
jerry_set_property (this_val, field_name, args_p[0]);
jerry_release_value (field_name);
jerry_set_object_native_handle (this_val,
(uintptr_t) 0x0000000000000000ull,
handler_construct_freecb);
uintptr_t ptr = (uintptr_t) NULL;
bool is_ok = jerry_get_object_native_handle (this_val, &ptr);
TEST_ASSERT (is_ok && ptr == (uintptr_t) 0x0000000000000000ull);
jerry_set_object_native_pointer (this_val,
(void *) 0x0000000000000000ull,
&JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind1));
void *ptr = NULL;
const jerry_object_native_info_t *out_info_p;
bool is_ok = jerry_get_object_native_pointer (this_val, &ptr, &out_info_p);
TEST_ASSERT (is_ok
&& (uintptr_t) ptr == (uintptr_t) 0x0000000000000000ull
&& out_info_p == &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind1));
/* check if setting handle for second time is handled correctly */
jerry_set_object_native_handle (this_val,
(uintptr_t) 0x0012345678abcdefull,
handler_construct_freecb);
jerry_set_object_native_pointer (this_val,
(void *) 0x0012345678abcdefull,
&JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind2));
return jerry_create_boolean (true);
} /* handler_construct */
@ -734,10 +754,12 @@ main (void)
jerry_release_value (val_value_field);
jerry_release_value (external_construct_val);
uintptr_t ptr = (uintptr_t) NULL;
is_ok = jerry_get_object_native_handle (res, &ptr);
void *ptr = NULL;
const jerry_object_native_info_t *out_info_p;
is_ok = jerry_get_object_native_pointer (res, &ptr, &out_info_p);
TEST_ASSERT (is_ok
&& ptr == (uintptr_t) 0x0012345678abcdefull);
&& (uintptr_t) ptr == (uintptr_t) 0x0012345678abcdefull
&& out_info_p == &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind2));
jerry_release_value (res);