From 469ef4e62261a22f0545000eceff58d380b764bd Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Mon, 6 Apr 2015 15:38:26 +0300 Subject: [PATCH] Implementing API for associating native handle (uintptr_t) values with JS objects. --- jerry-core/ecma/base/ecma-gc.cpp | 1 + jerry-core/ecma/base/ecma-globals.h | 1 + .../base/ecma-helpers-external-pointers.cpp | 64 +++++++++++++++---- jerry-core/ecma/base/ecma-helpers.cpp | 1 + jerry-core/ecma/base/ecma-helpers.h | 7 +- .../ecma/operations/ecma-function-object.cpp | 14 ++-- jerry-core/jerry-api.h | 6 ++ jerry-core/jerry.cpp | 36 +++++++++++ tests/unit/test_api.cpp | 7 ++ 9 files changed, 115 insertions(+), 22 deletions(-) diff --git a/jerry-core/ecma/base/ecma-gc.cpp b/jerry-core/ecma/base/ecma-gc.cpp index 3779361a4..30e72526c 100644 --- a/jerry-core/ecma/base/ecma-gc.cpp +++ b/jerry-core/ecma/base/ecma-gc.cpp @@ -319,6 +319,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */ 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_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */ diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index a7a0bac1e..b8cd21813 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -205,6 +205,7 @@ typedef enum ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP, /**< [[ParametersMap]] */ 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_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 */ diff --git a/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp b/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp index 56315b860..779ff8bf3 100644 --- a/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp +++ b/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp @@ -29,17 +29,35 @@ * * Note: * property identifier should be one of the following: - * - ECMA_INTERNAL_PROPERTY_NATIVE_CODE + * - ECMA_INTERNAL_PROPERTY_NATIVE_CODE; + * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE. + * + * @return true - if property was just created with specified value, + * false - otherwise, if property existed before the call, it's value was updated. */ -void +bool ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to create property in */ ecma_internal_property_id_t id, /**< identifier of internal * property to create */ ecma_external_pointer_t ptr_value) /**< value to store in the property */ { - JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE); + JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE + || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE); + + bool ret_val; + ecma_property_t *prop_p = ecma_find_internal_property (obj_p, id); + + if (prop_p == NULL) + { + prop_p = ecma_create_internal_property (obj_p, id); + + ret_val = true; + } + else + { + ret_val = false; + } - ecma_property_t *prop_p = ecma_create_internal_property (obj_p, id); JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (prop_p->u.internal_property.value)); if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t)) @@ -53,6 +71,8 @@ ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to crea ECMA_SET_NON_NULL_POINTER (prop_p->u.internal_property.value, handler_p); } + + return ret_val; } /* ecma_create_external_pointer_property */ /** @@ -60,30 +80,44 @@ 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_CODE; + * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE. * - * @return value of the external 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). */ -ecma_external_pointer_t +bool ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */ - ecma_internal_property_id_t id) /**< identifier of internal property + ecma_internal_property_id_t id, /**< identifier of internal property * to get value from */ + ecma_external_pointer_t *out_pointer_p) /**< out: value of the external pointer */ { - JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE); + JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE + || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE); + + ecma_property_t* prop_p = ecma_find_internal_property (obj_p, id); + + if (prop_p == NULL) + { + *out_pointer_p = (ecma_external_pointer_t) NULL; + + return false; + } - ecma_property_t* prop_p = ecma_get_internal_property (obj_p, id); JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (prop_p->u.internal_property.value)); if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t)) { - return (ecma_external_pointer_t) prop_p->u.internal_property.value; + *out_pointer_p = (ecma_external_pointer_t) prop_p->u.internal_property.value; } else { ecma_external_pointer_t *handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, prop_p->u.internal_property.value); - return *handler_p; + *out_pointer_p = *handler_p; } + + return true; } /* ecma_get_external_pointer_value */ /** @@ -91,12 +125,14 @@ 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_CODE; + * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE. */ 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); + JERRY_ASSERT (prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_CODE + || prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE); if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t)) { diff --git a/jerry-core/ecma/base/ecma-helpers.cpp b/jerry-core/ecma/base/ecma-helpers.cpp index eaa6694fb..044700f89 100644 --- a/jerry-core/ecma/base/ecma-helpers.cpp +++ b/jerry-core/ecma/base/ecma-helpers.cpp @@ -779,6 +779,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 */ { ecma_free_external_pointer_in_property (property_p); diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index a51367141..cfdaa4fc9 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -309,13 +309,14 @@ extern ecma_property_descriptor_t ecma_make_empty_property_descriptor (void); extern void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p); /* ecma-helpers-external-pointers.c */ -extern void +extern bool ecma_create_external_pointer_property (ecma_object_t *obj_p, ecma_internal_property_id_t id, ecma_external_pointer_t ptr_value); -extern ecma_external_pointer_t +extern bool ecma_get_external_pointer_value (ecma_object_t *obj_p, - ecma_internal_property_id_t id); + ecma_internal_property_id_t id, + ecma_external_pointer_t *out_pointer_p); extern void ecma_free_external_pointer_in_property (ecma_property_t *prop_p); diff --git a/jerry-core/ecma/operations/ecma-function-object.cpp b/jerry-core/ecma/operations/ecma-function-object.cpp index 28f52cb85..4fdbc6408 100644 --- a/jerry-core/ecma/operations/ecma-function-object.cpp +++ b/jerry-core/ecma/operations/ecma-function-object.cpp @@ -308,9 +308,10 @@ ecma_op_create_external_function_object (ecma_external_pointer_t code_p) /**< po ecma_property_t *class_prop_p = ecma_create_internal_property (function_obj_p, ECMA_INTERNAL_PROPERTY_CLASS); class_prop_p->u.internal_property.value = ECMA_MAGIC_STRING_FUNCTION_UL; - ecma_create_external_pointer_property (function_obj_p, - ECMA_INTERNAL_PROPERTY_NATIVE_CODE, - (ecma_external_pointer_t) code_p); + bool is_created = ecma_create_external_pointer_property (function_obj_p, + ECMA_INTERNAL_PROPERTY_NATIVE_CODE, + (ecma_external_pointer_t) code_p); + JERRY_ASSERT (is_created); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { @@ -607,8 +608,11 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ } else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION) { - ecma_external_pointer_t handler_p = ecma_get_external_pointer_value (func_obj_p, - ECMA_INTERNAL_PROPERTY_NATIVE_CODE); + ecma_external_pointer_t handler_p; + bool is_retrieved = ecma_get_external_pointer_value (func_obj_p, + ECMA_INTERNAL_PROPERTY_NATIVE_CODE, + &handler_p); + JERRY_ASSERT (is_retrieved); ret_value = jerry_dispatch_external_function (func_obj_p, handler_p, diff --git a/jerry-core/jerry-api.h b/jerry-core/jerry-api.h index 637b8f751..ed285257c 100644 --- a/jerry-core/jerry-api.h +++ b/jerry-core/jerry-api.h @@ -136,6 +136,12 @@ bool jerry_api_set_object_field_value (jerry_api_object_t *object_p, const char *field_name_p, const jerry_api_value_t *field_value_p); +extern EXTERN_C +bool jerry_api_get_object_native_handle (jerry_api_object_t *object_p, uintptr_t* out_handle_p); + +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_call_function (jerry_api_object_t *function_object_p, jerry_api_object_t *this_arg_p, diff --git a/jerry-core/jerry.cpp b/jerry-core/jerry.cpp index ced63ffa2..34e2f9656 100644 --- a/jerry-core/jerry.cpp +++ b/jerry-core/jerry.cpp @@ -616,6 +616,42 @@ jerry_api_set_object_field_value (jerry_api_object_t *object_p, /**< object */ return is_successful; } /* jerry_api_set_object_field_value */ +/** + * Get native handle, associated with specified object + * + * @return true - if there is associated handle (handle is returned through out_handle_p), + * false - otherwise. + */ +bool +jerry_api_get_object_native_handle (jerry_api_object_t *object_p, /**< object to get handle from */ + uintptr_t* out_handle_p) /**< out: handle value */ +{ + uintptr_t handle_value; + + bool does_exist = ecma_get_external_pointer_value (object_p, + ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, + &handle_value); + + if (does_exist) + { + *out_handle_p = handle_value; + } + + return does_exist; +} /* jerry_api_get_object_native_handle */ + +/** + * Set native handle for the specified object + */ +void +jerry_api_set_object_native_handle (jerry_api_object_t *object_p, /**< object to set handle in */ + uintptr_t handle) /**< handle value */ +{ + ecma_create_external_pointer_property (object_p, + ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, + handle); +} /* jerry_api_set_object_native_handle */ + /** * Call function specified by a function object * diff --git a/tests/unit/test_api.cpp b/tests/unit/test_api.cpp index a65637d02..27b953d47 100644 --- a/tests/unit/test_api.cpp +++ b/tests/unit/test_api.cpp @@ -125,6 +125,8 @@ handler_construct (const jerry_api_object_t *function_obj_p, jerry_api_set_object_field_value (this_p->v_object, "value_field", &args_p [0]); + jerry_api_set_object_native_handle (this_p->v_object, (uintptr_t) 0x0012345678abcdefull); + return true; } /* handler_construct */ @@ -322,6 +324,11 @@ main (void) && val_value_field.v_bool == true); jerry_api_release_value (&val_value_field); + uintptr_t ptr; + is_ok = jerry_api_get_object_native_handle (res.v_object, &ptr); + assert (is_ok + && ptr == (uintptr_t) 0x0012345678abcdefull); + jerry_api_release_value (&res); jerry_cleanup ();