Skip to content

Commit

Permalink
Add 'type' argument to set/get native handle API (jerryscript-project…
Browse files Browse the repository at this point in the history
…#1711)

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

Related issue jerryscript-project#1681

JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang [email protected]
  • Loading branch information
jiangzidong authored Apr 10, 2017
1 parent 574dff5 commit e522e74
Show file tree
Hide file tree
Showing 12 changed files with 482 additions and 137 deletions.
180 changes: 178 additions & 2 deletions docs/02.API-REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,44 @@ 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**

```c
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**
Expand Down Expand Up @@ -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**
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion jerry-core/ecma/base/ecma-alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 0 additions & 12 deletions jerry-core/ecma/base/ecma-alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
74 changes: 52 additions & 22 deletions jerry-core/ecma/base/ecma-gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,38 +354,57 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
} /* ecma_gc_mark */

/**
* Free specified object
* Free the native handle/pointer by calling its free callback
*/
void
ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
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 (object_p != NULL
&& !ecma_gc_is_object_visited (object_p)
&& object_p->type_flags_refs < ECMA_OBJECT_REF_ONE);
JERRY_ASSERT (property_p != NULL);

bool obj_is_not_lex_env = !ecma_is_lexical_environment (object_p);
JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);

if (obj_is_not_lex_env)
{
/* if the object provides free callback, invoke it with handle stored in the object */
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;

ecma_external_pointer_t freecb_p;
ecma_external_pointer_t native_p;
package_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, value_p->value);

bool is_retrieved = ecma_get_external_pointer_value (object_p,
LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK,
&freecb_p);
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 (is_retrieved && ((jerry_object_free_callback_t) freecb_p) != NULL)
if ((jerry_object_free_callback_t) free_cb != NULL)
{
is_retrieved = ecma_get_external_pointer_value (object_p,
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
&native_p);
JERRY_ASSERT (is_retrieved);
((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);

jerry_dispatch_object_free_callback (freecb_p, native_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
*/
void
ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
{
JERRY_ASSERT (object_p != NULL
&& !ecma_gc_is_object_visited (object_p)
&& object_p->type_flags_refs < ECMA_OBJECT_REF_ONE);

bool obj_is_not_lex_env = !ecma_is_lexical_environment (object_p);

if (obj_is_not_lex_env
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
Expand All @@ -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);
}
}

Expand Down
22 changes: 22 additions & 0 deletions jerry-core/ecma/base/ecma-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
Loading

0 comments on commit e522e74

Please sign in to comment.