Skip to content

Commit 849ea45

Browse files
martijntheLaszloLango
authored andcommitted
Improve documentation for jerry_get_object_native_pointer API (#1769)
Based on feedback I got from people who tried using the new API, it was not immediately clear how to properly use it. Hopefully these doc additions make it more clear how to use it and why it is designed the way it is. Also fixed some mistakes in the example and provided more comments to explain the intent of the code. JerryScript-DCO-1.0-Signed-off-by: Martijn The martijn.the@intel.com
1 parent acf88d2 commit 849ea45

File tree

1 file changed

+67
-49
lines changed

1 file changed

+67
-49
lines changed

docs/02.API-REFERENCE.md

Lines changed: 67 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ typedef void (*jerry_object_native_free_callback_t) (void *native_p);
197197
The type infomation of the native pointer.
198198
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.
199199

200+
Typically, one would create a `static const jerry_object_native_info_t` for
201+
each distinct C type for which a pointer is used with
202+
`jerry_set_object_native_pointer ()` and `jerry_get_object_native_pointer ()`.
203+
This way, each `const jerry_object_native_info_t *` pointer address value itself
204+
uniquely identifies the C type of the native pointer.
205+
206+
See [jerry_get_object_native_pointer](#jerry_get_object_native_pointer)
207+
for a best-practice code example.
208+
200209
**Prototype**
201210

202211
```c
@@ -206,6 +215,11 @@ typedef struct
206215
} jerry_object_native_info_t;
207216
```
208217

218+
**See also**
219+
220+
- [jerry_set_object_native_pointer](#jerry_set_object_native_pointer)
221+
- [jerry_get_object_native_pointer](#jerry_get_object_native_pointer)
222+
209223
## jerry_object_property_foreach_t
210224

211225
**Summary**
@@ -3417,7 +3431,18 @@ jerry_set_object_native_handle (const jerry_value_t obj_val,
34173431

34183432
Get native pointer and its type information.
34193433
The pointer and the type information are previously associated with the object by jerry_set_object_native_pointer.
3420-
Users can check the pointer's type before processing it.
3434+
3435+
*Note*: It is recommended to ensure that the `out_native_info_p` value pointer
3436+
is equal to the native info pointer that is expected, before casting
3437+
and accessing the `out_native_pointer_p`.
3438+
An example of when this is important: external functions that expect
3439+
`this` to have a native pointer of a certain C type.
3440+
It is possible in JavaScript to change `this` at will – using `call()`,
3441+
`apply()` or `bind()`. Therefore, it is possible that the native pointer
3442+
of `this` is not of the expected C type. To handle this safely and
3443+
securely, one must always add type checks to make sure that the
3444+
`out_native_pointer_p` is of the expected type, before casting
3445+
and dereferencing `out_native_pointer_p`.
34213446

34223447
**Prototype**
34233448

@@ -3438,37 +3463,60 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val,
34383463
**Example**
34393464

34403465
```c
3441-
static void native_freecb (uintptr_t native_p)
3466+
typedef struct {
3467+
int foo;
3468+
bool bar;
3469+
} native_obj_t;
3470+
3471+
static void native_freecb (void *native_p)
34423472
{
34433473
... // free the native pointer
34443474
}
34453475

3446-
static const jerry_object_native_info_t type_info =
3476+
// NOTE: The address (!) of type_info acts as a way to uniquely "identify" the
3477+
// C type `native_obj_t *`.
3478+
static const jerry_object_native_info_t native_obj_type_info =
34473479
{
34483480
.free_cb = native_freecb
34493481
};
34503482

3483+
// Function creating JS object that is "backed" by a native_obj_t *:
34513484
{
3452-
jerry_value_t object;
3453-
uintptr_t native_set;
3454-
3455-
... // receive or construct object and native_set value
3485+
...
34563486

3457-
jerry_set_object_native_pointer (object, native_set, &type_info);
3487+
// construct object and native_set value:
3488+
jerry_value_t object = ...;
3489+
native_obj_t *native_obj = malloc(sizeof(*native_obj));
3490+
jerry_set_object_native_pointer (object, native_obj, &native_obj_type_info);
34583491

34593492
...
3493+
}
34603494

3461-
uintptr_t native_get;
3462-
const jerry_object_native_info_t *type_get_p;
3463-
bool is_there_associated_native = jerry_get_object_native_pointer (object, &native_get, &type_get_p);
3495+
// Native method, `this` is expected to be "backed" by a native_obj_t *:
3496+
{
3497+
void *native_p;
3498+
const jerry_object_native_info_t *type_p;
3499+
bool has_p = jerry_get_object_native_pointer (this_val, &native_p, &type_p);
34643500

3465-
if (is_there_associated_native)
3501+
if (has_p)
34663502
{
3467-
if (out_info_p == &type_info)
3503+
// The type_p pointer address itself is used to identify the type:
3504+
if (type_p == &native_obj_type_info)
3505+
{
3506+
// The type of this's native pointer matches what is expected.
3507+
// Only now is it safe to cast to native_obj_t * and dereference the
3508+
// pointer:
3509+
native_obj_t *native_obj = native_p;
3510+
native_obj->bar = ...; // Safe to access now!
3511+
}
3512+
else
34683513
{
3469-
... // the type of object's native pointer is expected, and then process the native pointer.
3514+
// The type of this's native pointer is NOT what we expected!
3515+
// We should not cast to native_obj_t * and dereference because it's unsafe.
3516+
// Handle the error here, for example throw an error.
34703517
}
34713518
}
3519+
...
34723520
}
34733521
```
34743522

@@ -3504,44 +3552,14 @@ jerry_set_object_native_pointer (const jerry_value_t obj_val,
35043552

35053553
- `obj_val` - object to set native pointer in.
35063554
- `native_p` - native pointer.
3507-
- `info_p` - native pointer's type infomation or NULL.
3555+
- `info_p` - native pointer's type infomation or NULL. When used, this should
3556+
be a long-lived pointer, usually a pointer to a
3557+
`static const jerry_object_native_info_t` makes most sense.
35083558

35093559
**Example**
35103560

3511-
```c
3512-
static void native_freecb (uintptr_t native_p)
3513-
{
3514-
... // free the native pointer
3515-
}
3516-
3517-
static const jerry_object_native_info_t type_info =
3518-
{
3519-
.free_cb = native_freecb
3520-
};
3521-
3522-
{
3523-
jerry_value_t object;
3524-
uintptr_t native_set;
3525-
3526-
... // receive or construct object and native_set value
3527-
3528-
jerry_set_object_native_pointer (object, native_set, &type_info);
3529-
3530-
...
3531-
3532-
uintptr_t native_get;
3533-
const jerry_object_native_info_t *type_get_p;
3534-
bool is_there_associated_native = jerry_get_object_native_pointer (object, &native_get, &type_get_p);
3535-
3536-
if (is_there_associated_native)
3537-
{
3538-
if (out_info_p == &type_info)
3539-
{
3540-
... // the type of object's native pointer is expected, and then process the native pointer.
3541-
}
3542-
}
3543-
}
3544-
```
3561+
See [jerry_get_object_native_pointer](#jerry_get_object_native_pointer) for a
3562+
best-practice example.
35453563

35463564
**See also**
35473565

0 commit comments

Comments
 (0)