Allow the JS objects to have more than one native pointer data (#2814)
Currently JS objects can only have one native pointer data which could be a limitation in special cases. This patch allows to register multiple native infos, which can be accessed/associated with the corresponding `jerry_object_native_info_t`. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
committed by
László Langó
parent
c818930cdc
commit
b3f4aa6816
+35
-13
@@ -2591,9 +2591,8 @@ jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_i
|
||||
{
|
||||
if (!ecma_is_lexical_environment (iter_p))
|
||||
{
|
||||
native_pointer_p = ecma_get_native_pointer_value (iter_p);
|
||||
native_pointer_p = ecma_get_native_pointer_value (iter_p, (void *) native_info_p);
|
||||
if (native_pointer_p
|
||||
&& ((const jerry_object_native_info_t *) native_pointer_p->info_p) == native_info_p
|
||||
&& !foreach_p (ecma_make_object_value (iter_p), native_pointer_p->data_p, user_data_p))
|
||||
{
|
||||
return true;
|
||||
@@ -2605,11 +2604,10 @@ jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_i
|
||||
} /* jerry_objects_foreach_by_native_info */
|
||||
|
||||
/**
|
||||
* Get native pointer and its type information, associated with specified object.
|
||||
* Get native pointer and its type information, associated with the given native type info.
|
||||
*
|
||||
* Note:
|
||||
* If native pointer is present, its type information is returned
|
||||
* in out_native_pointer_p and out_native_info_p.
|
||||
* If native pointer is present, its type information is returned in out_native_pointer_p
|
||||
*
|
||||
* @return true - if there is an associated pointer,
|
||||
* false - otherwise
|
||||
@@ -2617,8 +2615,8 @@ jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_i
|
||||
bool
|
||||
jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get native pointer from */
|
||||
void **out_native_pointer_p, /**< [out] native pointer */
|
||||
const jerry_object_native_info_t **out_native_info_p) /**< [out] the type info
|
||||
* of the native pointer */
|
||||
const jerry_object_native_info_t *native_info_p) /**< the type info
|
||||
* of the native pointer */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
@@ -2628,7 +2626,7 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get
|
||||
}
|
||||
|
||||
ecma_native_pointer_t *native_pointer_p;
|
||||
native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_val));
|
||||
native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_val), (void *) native_info_p);
|
||||
|
||||
if (native_pointer_p == NULL)
|
||||
{
|
||||
@@ -2640,11 +2638,6 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get
|
||||
*out_native_pointer_p = native_pointer_p->data_p;
|
||||
}
|
||||
|
||||
if (out_native_info_p != NULL)
|
||||
{
|
||||
*out_native_info_p = (const jerry_object_native_info_t *) native_pointer_p->info_p;
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* jerry_get_object_native_pointer */
|
||||
|
||||
@@ -2676,6 +2669,35 @@ jerry_set_object_native_pointer (const jerry_value_t obj_val, /**< object to set
|
||||
}
|
||||
} /* jerry_set_object_native_pointer */
|
||||
|
||||
/**
|
||||
* Delete the previously set native pointer by the native type info from the specified object.
|
||||
*
|
||||
* Note:
|
||||
* If the specified object has no matching native pointer for the given native type info
|
||||
* the function has no effect.
|
||||
*
|
||||
* Note:
|
||||
* This operation cannot throw an exception.
|
||||
*
|
||||
* @return true - if the native pointer has been deleted succesfully
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
jerry_delete_object_native_pointer (const jerry_value_t obj_val, /**< object to delete native pointer from */
|
||||
const jerry_object_native_info_t *native_info_p) /**< object's native type info */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
if (ecma_is_value_object (obj_val))
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
|
||||
|
||||
return ecma_delete_native_pointer_property (object_p, (void *) native_info_p);
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* jerry_delete_object_native_pointer */
|
||||
|
||||
/**
|
||||
* Applies the given function to the every property in the object.
|
||||
*
|
||||
|
||||
@@ -501,17 +501,24 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
|
||||
native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
|
||||
value_p->value);
|
||||
|
||||
if (native_pointer_p->info_p != NULL)
|
||||
while (native_pointer_p != NULL)
|
||||
{
|
||||
ecma_object_native_free_callback_t free_cb = native_pointer_p->info_p->free_cb;
|
||||
|
||||
if (free_cb != NULL)
|
||||
if (native_pointer_p->info_p != NULL)
|
||||
{
|
||||
free_cb (native_pointer_p->data_p);
|
||||
}
|
||||
}
|
||||
ecma_object_native_free_callback_t free_cb = native_pointer_p->info_p->free_cb;
|
||||
|
||||
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
|
||||
if (free_cb != NULL)
|
||||
{
|
||||
free_cb (native_pointer_p->data_p);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_native_pointer_t *next_p = native_pointer_p->next_p;
|
||||
|
||||
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
|
||||
|
||||
native_pointer_p = next_p;
|
||||
}
|
||||
} /* ecma_gc_free_native_pointer */
|
||||
|
||||
/**
|
||||
|
||||
@@ -294,10 +294,11 @@ typedef struct
|
||||
/**
|
||||
* Representation for native pointer data.
|
||||
*/
|
||||
typedef struct
|
||||
typedef struct ecma_native_pointer_t
|
||||
{
|
||||
void *data_p; /**< points to the data of the object */
|
||||
ecma_object_native_info_t *info_p; /**< native info */
|
||||
struct ecma_native_pointer_t *next_p; /**< points to the next ecma_native_pointer_t element */
|
||||
} ecma_native_pointer_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
@@ -42,10 +43,10 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create
|
||||
|
||||
ecma_native_pointer_t *native_pointer_p;
|
||||
|
||||
if (is_new)
|
||||
if (property_p == NULL)
|
||||
{
|
||||
ecma_property_value_t *value_p;
|
||||
value_p = ecma_create_named_data_property (obj_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, &property_p);
|
||||
value_p = ecma_create_named_data_property (obj_p, name_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE, &property_p);
|
||||
|
||||
ECMA_CONVERT_DATA_PROPERTY_TO_INTERNAL_PROPERTY (property_p);
|
||||
|
||||
@@ -57,11 +58,37 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create
|
||||
{
|
||||
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value);
|
||||
ecma_native_pointer_t *iter_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value);
|
||||
|
||||
/* There should be at least 1 native pointer in the chain */
|
||||
JERRY_ASSERT (iter_p != NULL);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (iter_p->info_p == info_p)
|
||||
{
|
||||
/* The native info already exists -> update the corresponding data */
|
||||
iter_p->data_p = native_p;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iter_p->next_p == NULL)
|
||||
{
|
||||
/* The native info does not exist -> append a new element to the chain */
|
||||
break;
|
||||
}
|
||||
|
||||
iter_p = iter_p->next_p;
|
||||
}
|
||||
|
||||
native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t));
|
||||
|
||||
iter_p->next_p = native_pointer_p;
|
||||
}
|
||||
|
||||
native_pointer_p->data_p = native_p;
|
||||
native_pointer_p->info_p = info_p;
|
||||
native_pointer_p->next_p = NULL;
|
||||
|
||||
return is_new;
|
||||
} /* ecma_create_native_pointer_property */
|
||||
@@ -77,7 +104,8 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create
|
||||
* NULL otherwise
|
||||
*/
|
||||
ecma_native_pointer_t *
|
||||
ecma_get_native_pointer_value (ecma_object_t *obj_p) /**< object to get property value from */
|
||||
ecma_get_native_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */
|
||||
void *info_p) /**< native pointer's type info */
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
|
||||
ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p);
|
||||
@@ -89,9 +117,94 @@ ecma_get_native_pointer_value (ecma_object_t *obj_p) /**< object to get property
|
||||
|
||||
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value);
|
||||
ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
|
||||
value_p->value);
|
||||
|
||||
JERRY_ASSERT (native_pointer_p != NULL);
|
||||
|
||||
while (native_pointer_p != NULL)
|
||||
{
|
||||
if (native_pointer_p->info_p == info_p)
|
||||
{
|
||||
return native_pointer_p;
|
||||
}
|
||||
|
||||
native_pointer_p = native_pointer_p->next_p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} /* ecma_get_native_pointer_value */
|
||||
|
||||
/**
|
||||
* Delete the previously set native pointer by the native type info from the specified object.
|
||||
*
|
||||
* Note:
|
||||
* If the specified object has no matching native pointer for the given native type info
|
||||
* the function has no effect.
|
||||
*
|
||||
* @return true - if the native pointer has been deleted succesfully
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
ecma_delete_native_pointer_property (ecma_object_t *obj_p, /**< object to delete property from */
|
||||
void *info_p) /**< native pointer's type info */
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
|
||||
ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p);
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
|
||||
value_p->value);
|
||||
ecma_native_pointer_t *prev_p = NULL;
|
||||
|
||||
JERRY_ASSERT (native_pointer_p != NULL);
|
||||
|
||||
while (native_pointer_p != NULL)
|
||||
{
|
||||
if (native_pointer_p->info_p == info_p)
|
||||
{
|
||||
if (prev_p == NULL)
|
||||
{
|
||||
if (native_pointer_p->next_p == NULL)
|
||||
{
|
||||
/* Only one native pointer property exists, so the property can be deleted as well. */
|
||||
ecma_op_object_delete (obj_p, name_p, false);
|
||||
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There are at least two native pointers and the first one should be deleted.
|
||||
In this case the second element's data is copied to the head of the chain, and freed as well. */
|
||||
ecma_native_pointer_t *next_p = native_pointer_p->next_p;
|
||||
memcpy (native_pointer_p, next_p, sizeof (ecma_native_pointer_t));
|
||||
jmem_heap_free_block (next_p, sizeof (ecma_native_pointer_t));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There are at least two native pointers and not the first element should be deleted.
|
||||
In this case the current element's next element reference is copied to the previous element. */
|
||||
prev_p->next_p = native_pointer_p->next_p;
|
||||
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
prev_p = native_pointer_p;
|
||||
native_pointer_p = native_pointer_p->next_p;
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* ecma_delete_native_pointer_property */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -389,7 +389,8 @@ void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p);
|
||||
|
||||
/* ecma-helpers-external-pointers.c */
|
||||
bool ecma_create_native_pointer_property (ecma_object_t *obj_p, void *native_p, void *info_p);
|
||||
ecma_native_pointer_t *ecma_get_native_pointer_value (ecma_object_t *obj_p);
|
||||
ecma_native_pointer_t *ecma_get_native_pointer_value (ecma_object_t *obj_p, void *info_p);
|
||||
bool ecma_delete_native_pointer_property (ecma_object_t *obj_p, void *info_p);
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -527,10 +527,12 @@ jerry_value_t jerry_set_prototype (const jerry_value_t obj_val, const jerry_valu
|
||||
|
||||
bool jerry_get_object_native_pointer (const jerry_value_t obj_val,
|
||||
void **out_native_pointer_p,
|
||||
const jerry_object_native_info_t **out_pointer_info_p);
|
||||
const jerry_object_native_info_t *native_pointer_info_p);
|
||||
void jerry_set_object_native_pointer (const jerry_value_t obj_val,
|
||||
void *native_pointer_p,
|
||||
const jerry_object_native_info_t *native_info_p);
|
||||
bool jerry_delete_object_native_pointer (const jerry_value_t obj_val,
|
||||
const jerry_object_native_info_t *native_info_p);
|
||||
|
||||
bool jerry_objects_foreach (jerry_objects_foreach_t foreach_p,
|
||||
void *user_data);
|
||||
|
||||
Reference in New Issue
Block a user