Introduce new jerry-ext methods to ease property registration (#2715)
New methods
* jerryx_set_properties: Allows multiple property registration for via a single call
* jerryx_set_property_str: Allows property registration without the need to
create the property name JS value. The property name can be directly passed
as a `const char*` value and must be zero terminated.
* jerryx_get_property_str: Allows getting a property value on a given object.
The property name can be directly passed as a `const char*` value.
* jerryx_has_property_str: Allows checking if a property exists on a given object.
JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
This commit is contained in:
committed by
Robert Fancsik
parent
3e12738037
commit
c64ee882da
@@ -1,3 +1,418 @@
|
||||
# Common methods to handle properties
|
||||
|
||||
The `jerryscript-ext/handler.h` header defines a set of convenience methods
|
||||
which makes the property access a bit straightforward.
|
||||
|
||||
## jerryx_set_property_str
|
||||
|
||||
**Summary**
|
||||
|
||||
Set a property on a target object with a given name.
|
||||
|
||||
*Note*:
|
||||
- The property name must be a zero terminated UTF-8 string.
|
||||
- There should be no '\0' (NULL) character in the name excluding the string terminator.
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
|
||||
is no longer needed.
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_set_property_str (const jerry_value_t target_object,
|
||||
const char *name,
|
||||
const jerry_value_t value);
|
||||
```
|
||||
|
||||
- `target_object` - the object where the property should be set
|
||||
- `name` - name of the property
|
||||
- `value` - property value to be set
|
||||
- return value
|
||||
- JS true value, if success
|
||||
- thrown error, if there was a problem setting the property
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
|
||||
jerry_value_t value = jerry_create_number (3.3);
|
||||
jerry_value_t result = jerryx_set_property_str (global, "value", value);
|
||||
if (jerry_value_is_error (result))
|
||||
{
|
||||
/* The error type/reason can be extracted via the `jerry_get_value_from_error` method */
|
||||
printf ("Error during property configuration\r\n");
|
||||
}
|
||||
|
||||
jerry_release_value (result);
|
||||
jerry_release_value (value);
|
||||
jerry_release_value (global);
|
||||
jerry_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## jerryx_get_property_str
|
||||
|
||||
**Summary**
|
||||
|
||||
Get the value of a property from the specified object with the given name.
|
||||
|
||||
*Notes*:
|
||||
- The property name must be a zero terminated UTF-8 string.
|
||||
- There should be no '\0' (NULL) character in the name excluding the string terminator.
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
|
||||
is no longer needed.
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```
|
||||
jerry_value_t
|
||||
jerryx_get_property_str (const jerry_value_t target_object,
|
||||
const char *name);
|
||||
```
|
||||
|
||||
- `target_object` - object on which the property name is accessed
|
||||
- `name` - property name as an UTF-8 `char*`
|
||||
- return value
|
||||
- value of property, if success
|
||||
- thrown error, if there was a problem accessing the property
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
|
||||
jerry_value_t math_object = jerryx_get_property_str (global, "Math");
|
||||
|
||||
/* use math_object */
|
||||
|
||||
jerry_release_value (math_object);
|
||||
jerry_release_value (global);
|
||||
jerry_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## jerryx_has_property_str
|
||||
|
||||
**Summary**
|
||||
|
||||
Check if a property exists on an object.
|
||||
|
||||
*Notes*:
|
||||
- The operation performed is the same as what the `jerry_has_property` method.
|
||||
- The property name must be a zero terminated UTF-8 string.
|
||||
- There should be no '\0' (NULL) character in the name excluding the string terminator.
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```
|
||||
bool
|
||||
jerryx_has_property_str (const jerry_value_t target_object,
|
||||
const char *name);
|
||||
```
|
||||
|
||||
- `target_object` - object on which the property name is accessed
|
||||
- `name` - property name as an UTF-8 `char*`
|
||||
- return value
|
||||
- true, if the given property name exsits on the object
|
||||
- false, if there is no such property name or there was an error accessing the property
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
|
||||
bool have_math = jerryx_has_property_str (global, "Math");
|
||||
|
||||
jerry_release_value (global);
|
||||
jerry_cleanup();
|
||||
|
||||
return have_math ? 0 : 1;
|
||||
}
|
||||
```
|
||||
|
||||
# Utility to register multiple properties in bulk
|
||||
|
||||
In some cases it is useful to register multiple properties for a given object
|
||||
for this the following utility structures and methods are provided.
|
||||
|
||||
## jerryx_property_entry
|
||||
|
||||
**Summary**
|
||||
|
||||
Structure to define an array of properties with `name` and `value` fields which
|
||||
can be registered to a target object.
|
||||
|
||||
The engine must be initialied before specifying the `jerry_value_t` in the struct.
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
const char *name;
|
||||
jerry_value_t value;
|
||||
} jerryx_function_list_entry;
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_set_properties](#jerryx_set_properties)
|
||||
|
||||
|
||||
## jerryx_register_result
|
||||
|
||||
**Summary**
|
||||
|
||||
Structure returned as the result of the [jerryx_set_properties](#jerryx_set_properties) operation.
|
||||
The `result` field will either be a JavaScript undefined value or an error object.
|
||||
In every case the `registered` field is used to indicated the number of
|
||||
successfully registered methods.
|
||||
|
||||
This must be passed for the [jerryx_release_property_entry](#jerryx_release_property_entry) method
|
||||
after the property registration.
|
||||
|
||||
If any error occured during the property registration the `result` field of the structure
|
||||
must be manually released after processing the error value.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
jerry_value_t result;
|
||||
uint32_t registered;
|
||||
} jerryx_register_result;
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_set_properties](#jerryx_set_properties)
|
||||
- [jerryx_release_property_entry](#jerryx_release_property_entry)
|
||||
|
||||
|
||||
## jerryx_set_properties
|
||||
|
||||
**Summary**
|
||||
|
||||
Set multiple properties on a target object.
|
||||
|
||||
The properties are an array of (name, jerry_value_t) pairs and
|
||||
this list must end with a (NULL, 0) entry.
|
||||
|
||||
Important notes:
|
||||
* Each property value in the input array is released after a successful property registration.
|
||||
* The method [jerryx_release_property_entry](#jerryx_release_property_entry) must be called if there is any failed registration
|
||||
to release the values in the entries array.
|
||||
It is safe to call this cleanup method in every case not just in case of failure.
|
||||
* If the error value is reported via the result it must be freed manually.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerryx_register_result
|
||||
jerryx_set_properties (const jerry_value_t target_object,
|
||||
const jerryx_property_entry entries[]);
|
||||
```
|
||||
|
||||
- `target_object` - object on which the entries will be set.
|
||||
- `entries` - array of (name, jerry_value_t) pairs.
|
||||
- return a [jerryx_register_result](#jerryx_register_result).
|
||||
- if everything is ok, the struct's `result` field is set to a JS undefined value.
|
||||
- otherwise the `result` field is an error object indicating the problem.
|
||||
- in every case the `registered` field contains the number of successfully registered properties.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
static jerry_value_t
|
||||
handler (const jerry_value_t function_obj,
|
||||
const jerry_value_t this_val,
|
||||
const jerry_value_t args_p[],
|
||||
const jerry_length_t args_cnt)
|
||||
{
|
||||
printf ("native handler called!\n");
|
||||
|
||||
return jerry_create_boolean (true);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerryx_property_entry methods[] =
|
||||
{
|
||||
{ "demo", jerry_create_external_function (handler) },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
jerryx_register_result reg = jerryx_set_properties (global, methods);
|
||||
/* if `reg.result` is undefined all methods are registered */
|
||||
if (jerry_value_is_error (reg.result))
|
||||
{
|
||||
printf ("Only registered %d properties\r\n", reg.registered);
|
||||
/* clean up not registered property values */
|
||||
jerryx_release_property_entry (methods, reg);
|
||||
|
||||
/* clean up the error */
|
||||
jerry_release_value (reg.result);
|
||||
}
|
||||
|
||||
jerry_release_value (global);
|
||||
|
||||
jerry_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**Convenience macros**
|
||||
|
||||
To make property registration convenient, there are a set of macros to use
|
||||
when setting a property entry:
|
||||
|
||||
* `JERRYX_PROPERTY_NUMBER(NAME, NUMBER)` - creates a number entry.
|
||||
* `JERRYX_PROPERTY_STRING(NAME, STR)` - creates an UTF-8 string entry. This string must be zero terminated.
|
||||
* `JERRYX_PROPERTY_STRING_SZ(NAME, STR, SIZE)` - creates an UTF-8 string entry using only `SIZE` bytes from the string.
|
||||
* `JERRYX_PROPERTY_BOOLEAN(NAME, VALUE)` - creates a boolean entry.
|
||||
* `JERRYX_PROPERTY_FUNCTION(NAME, NATIVE)` - creates a native C function entry.
|
||||
* `JERRYX_PROPERTY_UNDEFINED(NAME)` - creates an undefined property entry.
|
||||
* `JERRYX_PROPERTY_LIST_END()` - indicates the end of the property list.
|
||||
|
||||
**Example usage of Convenience macros**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
static jerry_value_t
|
||||
handler (const jerry_value_t function_obj,
|
||||
const jerry_value_t this_val,
|
||||
const jerry_value_t args_p[],
|
||||
const jerry_length_t args_cnt)
|
||||
{
|
||||
printf ("native handler called!\n");
|
||||
|
||||
return jerry_create_boolean (true);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
/**
|
||||
* Create a array of properties to be registered.
|
||||
* This must be done after initializing the engine as creating `jerry_value_t`
|
||||
* elements are invalid before `jerry_init`.
|
||||
*/
|
||||
jerryx_property_entry methods[] =
|
||||
{
|
||||
JERRYX_PROPERTY_FUNCTION ("demo", handler),
|
||||
JERRYX_PROPERTY_NUMBER ("test_num", 2.3),
|
||||
JERRYX_PROPERTY_UNDEFINED ("this_is_undefined"),
|
||||
JERRYX_PROPERTY_LIST_END(),
|
||||
};
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
jerryx_register_result reg = jerryx_set_properties (global, methods);
|
||||
/* if `reg.result` is undefined all methods are registered */
|
||||
if (jerry_value_is_error (reg.result))
|
||||
{
|
||||
printf ("Only registered %d properties\r\n", reg.registered);
|
||||
/* clean up not registered property values */
|
||||
jerryx_release_property_entry (methods, reg);
|
||||
|
||||
/* clean up the error */
|
||||
jerry_release_value (reg.result);
|
||||
}
|
||||
|
||||
jerry_release_value (global);
|
||||
|
||||
jerry_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_property_entry](#jerryx_property_entry)
|
||||
- [jerryx_release_property_entry](#jerryx_release_property_entry)
|
||||
- [jerryx_register_result](#jerryx_register_result)
|
||||
|
||||
## jerryx_release_property_entry
|
||||
|
||||
**Summary**
|
||||
|
||||
Release all `jerry_value_t` in a `jerryx_property_entry` array based on a previous [jerryx_set_properties](#jerryx_set_properties) call
|
||||
and also the error value (if any) in the `jerryx_register_result` structure.
|
||||
In case of a successful registration it is safe to call this method.
|
||||
|
||||
After the method call the `ęntries` array should not be used as all values are released.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```
|
||||
void
|
||||
jerryx_release_property_entry (const jerryx_property_entry entries[],
|
||||
const jerryx_register_result register_result);
|
||||
```
|
||||
|
||||
- `entires` - array of [jerryx_property_entry](#jerryx_property_entry).
|
||||
- `register_result` - result of a previous [jerryx_set_properties](#jerryx_set_properties) call.
|
||||
|
||||
**Example**
|
||||
|
||||
For example usage see [jerryx_set_properties](#jerryx_set_properties).
|
||||
|
||||
|
||||
# Common external function handlers
|
||||
|
||||
## jerryx_handler_assert_fatal
|
||||
|
||||
Reference in New Issue
Block a user