diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index 6808239060..332fd18e63 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -196,6 +196,15 @@ typedef void (*jerry_object_native_free_callback_t) (void *native_p); 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. +Typically, one would create a `static const jerry_object_native_info_t` for +each distinct C type for which a pointer is used with +`jerry_set_object_native_pointer ()` and `jerry_get_object_native_pointer ()`. +This way, each `const jerry_object_native_info_t *` pointer address value itself +uniquely identifies the C type of the native pointer. + +See [jerry_get_object_native_pointer](#jerry_get_object_native_pointer) +for a best-practice code example. + **Prototype** ```c @@ -205,6 +214,11 @@ typedef struct } jerry_object_native_info_t; ``` +**See also** + +- [jerry_set_object_native_pointer](#jerry_set_object_native_pointer) +- [jerry_get_object_native_pointer](#jerry_get_object_native_pointer) + ## jerry_object_property_foreach_t **Summary** @@ -3416,7 +3430,18 @@ jerry_set_object_native_handle (const jerry_value_t obj_val, 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. + +*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`. **Prototype** @@ -3437,37 +3462,60 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, **Example** ```c -static void native_freecb (uintptr_t native_p) +typedef struct { + int foo; + bool bar; +} native_obj_t; + +static void native_freecb (void *native_p) { ... // free the native pointer } -static const jerry_object_native_info_t type_info = +// 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 = { .free_cb = native_freecb }; +// Function creating JS object that is "backed" by a native_obj_t *: { - 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); + // 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); ... +} - 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); +// Native method, `this` is expected to be "backed" by a native_obj_t *: +{ + 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); - if (is_there_associated_native) + if (has_p) { - if (out_info_p == &type_info) + // The type_p pointer address itself is used to identify the type: + if (type_p == &native_obj_type_info) + { + // 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! + } + else { - ... // the type of object's native pointer is expected, and then process the native pointer. + // 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. } } + ... } ``` @@ -3503,44 +3551,14 @@ jerry_set_object_native_pointer (const jerry_value_t obj_val, - `obj_val` - object to set native pointer in. - `native_p` - native pointer. -- `info_p` - native pointer's type infomation or NULL. +- `info_p` - native pointer's type infomation or NULL. When used, this should + be a long-lived pointer, usually a pointer to a + `static const jerry_object_native_info_t` makes most sense. **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 [jerry_get_object_native_pointer](#jerry_get_object_native_pointer) for a +best-practice example. **See also**