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:
Robert Fancsik 2019-04-16 07:50:49 +02:00 committed by László Langó
parent c818930cdc
commit b3f4aa6816
14 changed files with 436 additions and 180 deletions

View File

@ -4756,23 +4756,11 @@ jerry_set_prototype (const jerry_value_t obj_val,
**Summary**
Get native pointer and its type information.
Get native pointer by the given type information.
The pointer and the type information are previously associated with the object by jerry_set_object_native_pointer.
*Note*: It is recommended to ensure that the `out_native_info_p` value pointer
is equal to the native info pointer that is expected, before casting
and accessing the `out_native_pointer_p`.
An example of when this is important: external functions that expect
`this` to have a native pointer of a certain C type.
It is possible in JavaScript to change `this` at will using `call()`,
`apply()` or `bind()`. Therefore, it is possible that the native pointer
of `this` is not of the expected C type. To handle this safely and
securely, one must always add type checks to make sure that the
`out_native_pointer_p` is of the expected type, before casting
and dereferencing `out_native_pointer_p`.
*Note*: `out_native_pointer_p` and `out_native_info_p` can be NULL, and it means the
caller doesn't want to get the native_pointer or type information.
*Note*: `out_native_pointer_p` can be NULL, and it means the
caller doesn't want to get the native_pointer.
**Prototype**
@ -4780,73 +4768,185 @@ The pointer and the type information are previously associated with the object b
bool
jerry_get_object_native_pointer (const jerry_value_t obj_val,
void **out_native_pointer_p,
const jerry_object_native_info_t **out_native_info_p)
const jerry_object_native_info_t *native_info_p)
```
- `obj_val` - object value to get native pointer from.
- `out_native_pointer_p` - native pointer (output parameter).
- `out_native_info_p` - native pointer's type information (output parameter).
- `native_info_p` - native pointer's type information.
- return value
- true, if there is native pointer associated with the object
- true, if there is native pointer associated of the specified object with the given native type info
- false, otherwise
**Example**
```c
typedef struct {
int foo;
bool bar;
} native_obj_t;
[doctest]: # ()
static void native_freecb (void *native_p)
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jerryscript.h"
typedef struct
{
... // free the native pointer
char *data_p;
unsigned int length;
} buffer_native_object_t;
typedef struct
{
int area;
int perimeter;
} shape_native_object_t;
#define SECRET_INFO ((void *) 42)
static void
buffer_native_freecb (void *native_p)
{
char *data_p = ((buffer_native_object_t*)native_p)->data_p;
if (data_p != NULL)
{
free (data_p);
}
free (native_p);
}
static void
shape_native_freecb (void *native_p)
{
free (native_p);
}
static void
destructor_freecb (void *native_p)
{
printf("Note: the object has been freed\n");
}
// NOTE: The address (!) of type_info acts as a way to uniquely "identify" the
// C type `native_obj_t *`.
static const jerry_object_native_info_t native_obj_type_info =
// C type `buffer_native_object_t *`.
static const jerry_object_native_info_t buffer_obj_type_info =
{
.free_cb = native_freecb
.free_cb = buffer_native_freecb
};
// Function creating JS object that is "backed" by a native_obj_t *:
// NOTE: The address (!) of type_info acts as a way to uniquely "identify" the
// C type `shape_native_object_t *`.
static const jerry_object_native_info_t shape_obj_type_info =
{
...
.free_cb = shape_native_freecb
};
// construct object and native_set value:
jerry_value_t object = ...;
native_obj_t *native_obj = malloc(sizeof(*native_obj));
jerry_set_object_native_pointer (object, native_obj, &native_obj_type_info);
// NOTE: The address (!) of type_info is the unique "identifier"
static const jerry_object_native_info_t destructor_obj_type_info =
{
.free_cb = destructor_freecb
};
...
static void
print_buffer (char *data_p,
unsigned int length)
{
for (unsigned int i = 0; i < length; ++i)
{
printf("%c", data_p[i]);
}
printf("\n");
}
// Native method, `this` is expected to be "backed" by a native_obj_t *:
static void
do_stuff (jerry_value_t object)
{
void *native_p;
const jerry_object_native_info_t *type_p;
bool has_p = jerry_get_object_native_pointer (this_val, &native_p, &type_p);
bool has_p = jerry_get_object_native_pointer (object, &native_p, &buffer_obj_type_info);
if (has_p)
if (!has_p)
{
// The type_p pointer address itself is used to identify the type:
if (type_p == &native_obj_type_info)
// Process the error
return;
}
// It is safe to cast to buffer_native_object_t * and dereference the pointer:
buffer_native_object_t *buffer_p = (buffer_native_object_t *) native_p;
print_buffer (buffer_p->data_p, buffer_p->length); // Usage of buffer_p
bool need_shape_info = true; // implementation dependent
if (need_shape_info)
{
has_p = jerry_get_object_native_pointer (object, &native_p, &shape_obj_type_info);
if (!has_p)
{
// The type of this's native pointer matches what is expected.
// Only now is it safe to cast to native_obj_t * and dereference the
// pointer:
native_obj_t *native_obj = native_p;
native_obj->bar = ...; // Safe to access now!
// Process the error
return;
}
else
// It is safe to cast to shape_native_object_t * and dereference the pointer:
shape_native_object_t *shape_p = (shape_native_object_t *) native_p;
printf("Area: %d\tPerimeter: %d\n", shape_p->area, shape_p->perimeter); // Usage of shape_p
}
bool need_secret_info = true; // implementation dependent
if (need_secret_info)
{
has_p = jerry_get_object_native_pointer (object, &native_p, NULL);
if (!has_p)
{
// The type of this's native pointer is NOT what we expected!
// We should not cast to native_obj_t * and dereference because it's unsafe.
// Handle the error here, for example throw an error.
// Process the error
return;
}
printf("Secret: %d\n", (int)((uintptr_t) native_p)); // Usage of native_p
bool deleted = jerry_delete_object_native_pointer (object, NULL);
if (deleted)
{
printf("The secret is no longer available\n");
}
}
...
}
int
main (void)
{
jerry_init (JERRY_INIT_EMPTY);
jerry_value_t object = jerry_create_object ();
buffer_native_object_t *buffer_p = (buffer_native_object_t *) malloc (sizeof (buffer_native_object_t));
buffer_p->length = 14;
buffer_p->data_p = (char *) malloc (buffer_p->length * sizeof (char));
memcpy (buffer_p->data_p, "My buffer data", buffer_p->length);
jerry_set_object_native_pointer (object, buffer_p, &buffer_obj_type_info);
shape_native_object_t *shape_p = (shape_native_object_t *) malloc (sizeof (shape_native_object_t));
shape_p->area = 6;
shape_p->perimeter = 12;
jerry_set_object_native_pointer (object, shape_p, &shape_obj_type_info);
// The native pointer can be NULL. This gives possibily to get notified via the native type info's
// free callback when the object has been freed by the GC.
jerry_set_object_native_pointer (object, NULL, &destructor_obj_type_info);
// The native type info can be NULL as well. In this case the registered property is simply freed
// when the object is freed by te GC.
jerry_set_object_native_pointer (object, SECRET_INFO, NULL);
do_stuff (object);
jerry_release_value (object);
jerry_cleanup ();
return 0;
}
```
@ -4897,6 +4997,40 @@ best-practice example.
- [jerry_get_object_native_pointer](#jerry_get_object_native_pointer)
- [jerry_object_native_info_t](#jerry_object_native_info_t)
## jerry_delete_object_native_pointer
**Summary**
Delete the native pointer of the specified object associated with the given native type info.
You can get them by calling jerry_get_object_native_pointer later.
*Note*:
- If the specified object has no matching native pointer for the given native type info the operation has no effect.
- This operation cannot throw an exception.
**Prototype**
```c
bool
jerry_delete_object_native_pointer (const jerry_value_t obj_val,
const jerry_object_native_info_t *info_p)
```
- `obj_val` - object to delete native pointer from.
- `info_p` - native pointer's type information.
**Example**
See [jerry_get_object_native_pointer](#jerry_get_object_native_pointer) for a
best-practice example.
**See also**
- [jerry_create_object](#jerry_create_object)
- [jerry_get_object_native_pointer](#jerry_get_object_native_pointer)
- [jerry_get_object_native_pointer](#jerry_set_object_native_pointer)
- [jerry_object_native_info_t](#jerry_object_native_info_t)
## jerry_foreach_object_property

View File

@ -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.
*

View File

@ -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 */
/**

View File

@ -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;
/**

View File

@ -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 */
/**
* @}
* @}

View File

@ -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);

View File

@ -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);

View File

@ -455,12 +455,11 @@ jerryx_arg_transform_native_pointer (jerryx_arg_js_iterator_t *js_arg_iter_p, /*
}
const jerry_object_native_info_t *expected_info_p;
const jerry_object_native_info_t *out_info_p;
expected_info_p = (const jerry_object_native_info_t *) c_arg_p->extra_info;
void **ptr_p = (void **) c_arg_p->dest;
bool is_ok = jerry_get_object_native_pointer (js_arg, ptr_p, &out_info_p);
bool is_ok = jerry_get_object_native_pointer (js_arg, ptr_p, expected_info_p);
if (!is_ok || out_info_p != expected_info_p)
if (!is_ok)
{
return jerry_create_error (JERRY_ERROR_TYPE,
(jerry_char_t *) "The object has no native pointer or type does not match.");

View File

@ -47,10 +47,9 @@ DECLARE_CLASS_FUNCTION(AnalogIn, read) {
// Extract native AnalogIn pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native AnalogIn pointer");
}
@ -73,10 +72,9 @@ DECLARE_CLASS_FUNCTION(AnalogIn, read_u16) {
// Extract native AnalogIn pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native AnalogIn pointer");
}

View File

@ -50,10 +50,9 @@ DECLARE_CLASS_FUNCTION(DigitalOut, write) {
// Extract native DigitalOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native DigitalOut pointer");
}
@ -78,10 +77,9 @@ DECLARE_CLASS_FUNCTION(DigitalOut, read) {
// Extract native DigitalOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native DigitalOut pointer");
}
@ -103,10 +101,9 @@ DECLARE_CLASS_FUNCTION(DigitalOut, is_connected) {
// Extract native DigitalOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native DigitalOut pointer");
}

View File

@ -49,10 +49,9 @@ DECLARE_CLASS_FUNCTION(I2C, frequency) {
// Unwrap native I2C object
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native I2C pointer");
}
@ -92,10 +91,9 @@ DECLARE_CLASS_FUNCTION(I2C, read) {
if (args_count == 1) {
CHECK_ARGUMENT_TYPE_ALWAYS(I2C, read, 0, number);
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native I2C pointer");
}
@ -114,10 +112,9 @@ DECLARE_CLASS_FUNCTION(I2C, read) {
CHECK_ARGUMENT_TYPE_ON_CONDITION(I2C, read, 3, boolean, (args_count == 4));
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native I2C pointer");
}
@ -189,10 +186,9 @@ DECLARE_CLASS_FUNCTION(I2C, write) {
// Extract native I2C object
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native I2C pointer");
}
@ -213,10 +209,9 @@ DECLARE_CLASS_FUNCTION(I2C, write) {
// Extract native I2C object
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native I2C pointer");
}
@ -254,10 +249,9 @@ DECLARE_CLASS_FUNCTION(I2C, start) {
// Extract native I2C object
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native I2C pointer");
}
@ -278,10 +272,9 @@ DECLARE_CLASS_FUNCTION(I2C, stop) {
// Extract native I2C object
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native I2C pointer");
}

View File

@ -53,10 +53,9 @@ DECLARE_CLASS_FUNCTION(InterruptIn, rise) {
// Detach the rise callback when InterruptIn::rise(null) is called
if (jerry_value_is_null(args[0])) {
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native InterruptIn pointer");
}
@ -83,10 +82,9 @@ DECLARE_CLASS_FUNCTION(InterruptIn, rise) {
CHECK_ARGUMENT_TYPE_ALWAYS(InterruptIn, rise, 0, function);
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native InterruptIn pointer");
}
@ -120,10 +118,9 @@ DECLARE_CLASS_FUNCTION(InterruptIn, fall) {
// Detach the fall callback when InterruptIn::fall(null) is called
if (jerry_value_is_null(args[0])) {
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native InterruptIn pointer");
}
@ -150,10 +147,9 @@ DECLARE_CLASS_FUNCTION(InterruptIn, fall) {
CHECK_ARGUMENT_TYPE_ALWAYS(InterruptIn, fall, 0, function);
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native InterruptIn pointer");
}
@ -186,10 +182,9 @@ DECLARE_CLASS_FUNCTION(InterruptIn, mode) {
CHECK_ARGUMENT_TYPE_ALWAYS(InterruptIn, mode, 0, number);
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native InterruptIn pointer");
}
@ -211,10 +206,9 @@ DECLARE_CLASS_FUNCTION(InterruptIn, disable_irq) {
CHECK_ARGUMENT_COUNT(InterruptIn, disable_irq, (args_count == 0));
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native InterruptIn pointer");
}
@ -234,10 +228,9 @@ DECLARE_CLASS_FUNCTION(InterruptIn, enable_irq) {
CHECK_ARGUMENT_COUNT(InterruptIn, enable_irq, (args_count == 0));
void *void_ptr;
const jerry_object_native_info_t *type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native InterruptIn pointer");
}

View File

@ -52,10 +52,9 @@ DECLARE_CLASS_FUNCTION(PwmOut, write) {
// Extract native PwmOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native PwmOut pointer");
}
@ -86,10 +85,9 @@ DECLARE_CLASS_FUNCTION(PwmOut, read) {
// Extract native PwmOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native PwmOut pointer");
}
@ -115,10 +113,9 @@ DECLARE_CLASS_FUNCTION(PwmOut, period) {
// Extract native PwmOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native PwmOut pointer");
}
@ -142,10 +139,9 @@ DECLARE_CLASS_FUNCTION(PwmOut, period_ms) {
// Extract native PwmOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native PwmOut pointer");
}
@ -169,10 +165,9 @@ DECLARE_CLASS_FUNCTION(PwmOut, period_us) {
// Extract native PwmOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native PwmOut pointer");
}
@ -196,10 +191,9 @@ DECLARE_CLASS_FUNCTION(PwmOut, pulsewidth) {
// Extract native PwmOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native PwmOut pointer");
}
@ -223,10 +217,9 @@ DECLARE_CLASS_FUNCTION(PwmOut, pulsewidth_ms) {
// Extract native PwmOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native PwmOut pointer");
}
@ -250,10 +243,9 @@ DECLARE_CLASS_FUNCTION(PwmOut, pulsewidth_us) {
// Extract native PwmOut pointer
void* void_ptr;
const jerry_object_native_info_t* type_ptr;
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
if (!has_ptr || type_ptr != &native_obj_type_info) {
if (!has_ptr) {
return jerry_create_error(JERRY_ERROR_TYPE,
(const jerry_char_t *) "Failed to get native PwmOut pointer");
}

View File

@ -102,13 +102,22 @@ handler_throw_test (const jerry_value_t func_obj_val, /**< function object */
} /* handler_throw_test */
static void
handler_construct_freecb (void *native_p)
handler_construct_1_freecb (void *native_p)
{
TEST_ASSERT ((uintptr_t) native_p == (uintptr_t) 0x0000000000000000ull);
printf ("ok object free callback\n");
test_api_is_free_callback_was_called = true;
} /* handler_construct_1_freecb */
static void
handler_construct_2_freecb (void *native_p)
{
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 */
} /* handler_construct_2_freecb */
/**
@ -125,8 +134,8 @@ handler_construct_freecb (void *native_p)
.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);
JERRY_DEFINE_NATIVE_HANDLE_INFO (bind1, handler_construct_1_freecb);
JERRY_DEFINE_NATIVE_HANDLE_INFO (bind2, handler_construct_2_freecb);
JERRY_DEFINE_NATIVE_HANDLE_INFO (bind3, NULL);
static jerry_value_t
@ -153,11 +162,9 @@ handler_construct (const jerry_value_t func_obj_val, /**< function object */
&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);
bool is_ok = jerry_get_object_native_pointer (this_val, &ptr, &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind1));
TEST_ASSERT (is_ok
&& (uintptr_t) ptr == (uintptr_t) 0x0000000000000000ull
&& out_info_p == &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind1));
&& (uintptr_t) ptr == (uintptr_t) 0x0000000000000000ull);
/* check if setting handle for second time is handled correctly */
jerry_set_object_native_pointer (this_val,
(void *) 0x0012345678abcdefull,
@ -531,17 +538,14 @@ main (void)
jerry_release_value (external_construct_val);
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
&& (uintptr_t) ptr == (uintptr_t) 0x0012345678abcdefull
&& out_info_p == &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind2));
/* Passing NULL for out_info_p is allowed. */
is_ok = jerry_get_object_native_pointer (res, &ptr, NULL);
is_ok = jerry_get_object_native_pointer (res, &ptr, &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind2));
TEST_ASSERT (is_ok
&& (uintptr_t) ptr == (uintptr_t) 0x0012345678abcdefull);
/* Passing NULL for info_p is allowed. */
is_ok = jerry_get_object_native_pointer (res, &ptr, NULL);
TEST_ASSERT (!is_ok);
jerry_release_value (res);
/* Test: It is ok to set native pointer's free callback as NULL. */