add transform_object_properties in jerryx/arg (#1879)
Add a function in jerryx/arg. jerryx_arg_transform_object_properties, it will validate the properties of a JS object, and convert those properties into native type. JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang zidong.jiang@intel.com
This commit is contained in:
+160
-10
@@ -31,6 +31,30 @@ typedef struct
|
|||||||
- [jerryx_arg_function](#jerryx_arg_function)
|
- [jerryx_arg_function](#jerryx_arg_function)
|
||||||
- [jerryx_arg_native_pointer](#jerryx_arg_native_pointer)
|
- [jerryx_arg_native_pointer](#jerryx_arg_native_pointer)
|
||||||
- [jerryx_arg_ignore](#jerryx_arg_ignore)
|
- [jerryx_arg_ignore](#jerryx_arg_ignore)
|
||||||
|
- [jerryx_arg_object_properties](#jerryx_arg_object_properties)
|
||||||
|
|
||||||
|
## jerryx_arg_object_props_t
|
||||||
|
|
||||||
|
**Summary**
|
||||||
|
|
||||||
|
The structure is used in `jerryx_arg_object_properties`. It provides the properties' names,
|
||||||
|
its corresponding JS-to-C mapping and other related information.
|
||||||
|
|
||||||
|
**Prototype**
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const jerry_char_t **name_p; /**< property name list of the JS object */
|
||||||
|
jerry_length_t name_cnt; /**< count of the name list */
|
||||||
|
const jerryx_arg_t *c_arg_p; /**< points to the array of transformation steps */
|
||||||
|
jerry_length_t c_arg_cnt; /**< the count of the `c_arg_p` array */
|
||||||
|
} jerryx_arg_object_props_t;
|
||||||
|
```
|
||||||
|
|
||||||
|
**See also**
|
||||||
|
|
||||||
|
- [jerryx_arg_object_properties](#jerryx_arg_object_properties)
|
||||||
|
|
||||||
## jerryx_arg_transform_func_t
|
## jerryx_arg_transform_func_t
|
||||||
|
|
||||||
@@ -128,7 +152,7 @@ jerryx_arg_transform_this_and_args (const jerry_value_t this_val,
|
|||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
```c
|
```c
|
||||||
// JS signature: function (requiredBool, requiredString, optionalNumber)
|
/* JS signature: function (requiredBool, requiredString, optionalNumber) */
|
||||||
static jerry_value_t my_external_handler (const jerry_value_t function_obj,
|
static jerry_value_t my_external_handler (const jerry_value_t function_obj,
|
||||||
const jerry_value_t this_val,
|
const jerry_value_t this_val,
|
||||||
const jerry_value_t args_p[],
|
const jerry_value_t args_p[],
|
||||||
@@ -138,10 +162,10 @@ static jerry_value_t my_external_handler (const jerry_value_t function_obj,
|
|||||||
char required_str[16];
|
char required_str[16];
|
||||||
double optional_num = 1234.567; // default value
|
double optional_num = 1234.567; // default value
|
||||||
|
|
||||||
// "mapping" defines the steps to transform input arguments to C variables:
|
/* "mapping" defines the steps to transform input arguments to C variables. */
|
||||||
const jerryx_arg_t mapping[] =
|
const jerryx_arg_t mapping[] =
|
||||||
{
|
{
|
||||||
// `this` is the first value. No checking needed on `this` for this function.
|
/* `this` is the first value. No checking needed on `this` for this function. */
|
||||||
jerryx_arg_ignore (),
|
jerryx_arg_ignore (),
|
||||||
|
|
||||||
jerryx_arg_boolean (&required_bool, JERRYX_ARG_NO_COERCE, JERRYX_ARG_REQUIRED),
|
jerryx_arg_boolean (&required_bool, JERRYX_ARG_NO_COERCE, JERRYX_ARG_REQUIRED),
|
||||||
@@ -149,22 +173,24 @@ static jerry_value_t my_external_handler (const jerry_value_t function_obj,
|
|||||||
jerryx_arg_number (&optional_num, JERRYX_ARG_NO_COERCE, JERRYX_ARG_OPTIONAL),
|
jerryx_arg_number (&optional_num, JERRYX_ARG_NO_COERCE, JERRYX_ARG_OPTIONAL),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Validate and transform:
|
/* Validate and transform. */
|
||||||
const jerry_value_t rv = jerryx_arg_transform_this_and_args (this_val,
|
const jerry_value_t rv = jerryx_arg_transform_this_and_args (this_val,
|
||||||
args_p,
|
args_p,
|
||||||
args_count,
|
args_count,
|
||||||
mapping,
|
mapping,
|
||||||
ARRAY_LENGTH (mapping));
|
4);
|
||||||
|
|
||||||
if (jerry_value_has_error_flag (rv))
|
if (jerry_value_has_error_flag (rv))
|
||||||
{
|
{
|
||||||
// Handle error
|
/* Handle error. */
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validated and tranformed successfully!
|
/*
|
||||||
// required_bool, required_str and optional_num can now be used.
|
* Validated and transformed successfully!
|
||||||
// ...
|
* required_bool, required_str and optional_num can now be used.
|
||||||
|
*/
|
||||||
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -177,6 +203,7 @@ static jerry_value_t my_external_handler (const jerry_value_t function_obj,
|
|||||||
- [jerryx_arg_function](#jerryx_arg_function)
|
- [jerryx_arg_function](#jerryx_arg_function)
|
||||||
- [jerryx_arg_native_pointer](#jerryx_arg_native_pointer)
|
- [jerryx_arg_native_pointer](#jerryx_arg_native_pointer)
|
||||||
- [jerryx_arg_custom](#jerryx_arg_custom)
|
- [jerryx_arg_custom](#jerryx_arg_custom)
|
||||||
|
- [jerryx_arg_object_properties](#jerryx_arg_object_properties)
|
||||||
|
|
||||||
|
|
||||||
## jerryx_arg_transform_args
|
## jerryx_arg_transform_args
|
||||||
@@ -206,6 +233,41 @@ jerryx_arg_transform_args (const jerry_value_t *js_arg_p,
|
|||||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||||
|
|
||||||
|
|
||||||
|
## jerryx_arg_transform_object_properties
|
||||||
|
|
||||||
|
**Summary**
|
||||||
|
|
||||||
|
Validate the properties of a JS object and assign them to the native arguments.
|
||||||
|
|
||||||
|
*Note*: This function transforms properties of a single JS object into native C values.
|
||||||
|
To transform multiple objects in one pass (for example when converting multiple arguments
|
||||||
|
to an external handler), please use `jerryx_arg_object_properties` together with
|
||||||
|
`jerryx_arg_transform_this_and_args` or `jerryx_arg_transform_args`.
|
||||||
|
|
||||||
|
**Prototype**
|
||||||
|
|
||||||
|
```c
|
||||||
|
jerry_value_t
|
||||||
|
jerryx_arg_transform_object_properties (const jerry_value_t obj_val,
|
||||||
|
const jerry_char_t **name_p,
|
||||||
|
const jerry_length_t name_cnt,
|
||||||
|
const jerryx_arg_t *c_arg_p,
|
||||||
|
jerry_length_t c_arg_cnt);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
- `obj_val` - the JS object.
|
||||||
|
- `name_p` - points to the array of property names.
|
||||||
|
- `name_cnt` - the count of the `name_p` array.
|
||||||
|
- `c_arg_p` - points to the array of validation/transformation steps
|
||||||
|
- `c_arg_cnt` - the count of the `c_arg_p` array.
|
||||||
|
- return value - a `jerry_value_t` representing `undefined` if all validators passed or an `Error` if a validator failed.
|
||||||
|
|
||||||
|
**See also**
|
||||||
|
|
||||||
|
- [jerryx_arg_object_properties](#jerryx_arg_object_properties)
|
||||||
|
|
||||||
|
|
||||||
# Helpers for commonly used validations
|
# Helpers for commonly used validations
|
||||||
|
|
||||||
## jerryx_arg_number
|
## jerryx_arg_number
|
||||||
@@ -314,7 +376,7 @@ jerryx_arg_function (jerry_value_t *dest,
|
|||||||
**Summary**
|
**Summary**
|
||||||
|
|
||||||
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||||
consume one `Object` JS argument that is 'backed' with a native pointer with
|
consume one `object` JS argument that is 'backed' with a native pointer with
|
||||||
a given type info. In case the native pointer info matches, the transform
|
a given type info. In case the native pointer info matches, the transform
|
||||||
will succeed and the object's native pointer will be assigned to `*dest`.
|
will succeed and the object's native pointer will be assigned to `*dest`.
|
||||||
|
|
||||||
@@ -335,6 +397,94 @@ jerryx_arg_native_pointer (void **dest,
|
|||||||
|
|
||||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||||
|
|
||||||
|
## jerryx_arg_object_properties
|
||||||
|
|
||||||
|
**Summary**
|
||||||
|
|
||||||
|
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||||
|
consume one `object` JS argument and call `jerryx_arg_transform_object_properties` inside
|
||||||
|
to transform its properties to native arguments.
|
||||||
|
User should prepare the `jerryx_arg_object_props_t` instance, and pass it to this function.
|
||||||
|
|
||||||
|
**Prototype**
|
||||||
|
|
||||||
|
```c
|
||||||
|
static inline jerryx_arg_t
|
||||||
|
jerryx_arg_object_properties (const jerryx_arg_object_props_t *object_props_p,
|
||||||
|
jerryx_arg_optional_t opt_flag);
|
||||||
|
```
|
||||||
|
- return value - the created `jerryx_arg_t` instance.
|
||||||
|
- `object_props_p` - provides information for properties transform.
|
||||||
|
- `opt_flag` - whether the argument is optional.
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
```c
|
||||||
|
/**
|
||||||
|
* The binding function expects args_p[0] is an object, which has 3 properties:
|
||||||
|
* "enable": boolean
|
||||||
|
* "data": number
|
||||||
|
* "extra_data": number, optional
|
||||||
|
*/
|
||||||
|
static jerry_value_t my_external_handler (const jerry_value_t function_obj,
|
||||||
|
const jerry_value_t this_val,
|
||||||
|
const jerry_value_t args_p[],
|
||||||
|
const jerry_length_t args_count)
|
||||||
|
{
|
||||||
|
bool required_bool;
|
||||||
|
double required_num;
|
||||||
|
double optional_num = 1234.567; // default value
|
||||||
|
|
||||||
|
/* "prop_name_p" defines the name list of the expected properties' names. */
|
||||||
|
const char *prop_name_p[] = { "enable", "data", "extra_data" };
|
||||||
|
|
||||||
|
/* "prop_mapping" defines the steps to transform properties to C variables. */
|
||||||
|
const jerryx_arg_t prop_mapping[] =
|
||||||
|
jerryx_arg_boolean (&required_bool, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||||
|
jerryx_arg_number (&required_num, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||||
|
jerryx_arg_number (&optional_num, JERRYX_ARG_COERCE, JERRYX_ARG_OPTIONAL)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Prepare the jerryx_arg_object_props_t instance. */
|
||||||
|
const jerryx_arg_object_props_t prop_info =
|
||||||
|
{
|
||||||
|
.name_p = (const jerry_char_t **) prop_name_p,
|
||||||
|
.name_cnt = 3,
|
||||||
|
.c_arg_p = prop_mapping,
|
||||||
|
.c_arg_cnt = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
/* It is the mapping used in the jerryx_arg_transform_args. */
|
||||||
|
const jerryx_arg_t mapping[] =
|
||||||
|
{
|
||||||
|
jerryx_arg_object_properties (&prop_info, JERRYX_ARG_REQUIRED)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Validate and transform. */
|
||||||
|
const jerry_value_t rv = jerryx_arg_transform_args (args_p,
|
||||||
|
args_count,
|
||||||
|
mapping,
|
||||||
|
1);
|
||||||
|
|
||||||
|
if (jerry_value_has_error_flag (rv))
|
||||||
|
{
|
||||||
|
/* Handle error. */
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validated and transformed successfully!
|
||||||
|
* required_bool, required_num and optional_num can now be used.
|
||||||
|
*/
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
**See also**
|
||||||
|
|
||||||
|
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||||
|
- [jerryx_arg_transform_object_properties](#jerryx_arg_transform_object_properties)
|
||||||
|
|
||||||
# Functions to create custom validations
|
# Functions to create custom validations
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ jerryx_arg_transform_number_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, /**
|
|||||||
} /* jerryx_arg_transform_number_strict */
|
} /* jerryx_arg_transform_number_strict */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tranform a JS argument to a double. Type coercion is allowed.
|
* Transform a JS argument to a double. Type coercion is allowed.
|
||||||
*
|
*
|
||||||
* @return jerry undefined: the transformer passes,
|
* @return jerry undefined: the transformer passes,
|
||||||
* jerry error: the transformer fails.
|
* jerry error: the transformer fails.
|
||||||
@@ -251,7 +251,7 @@ jerryx_arg_transform_native_pointer (jerryx_arg_js_iterator_t *js_arg_iter_p, /*
|
|||||||
if (!jerry_value_is_object (js_arg))
|
if (!jerry_value_is_object (js_arg))
|
||||||
{
|
{
|
||||||
return jerry_create_error (JERRY_ERROR_TYPE,
|
return jerry_create_error (JERRY_ERROR_TYPE,
|
||||||
(jerry_char_t *) "It is not a object.");
|
(jerry_char_t *) "It is not an object.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const jerry_object_native_info_t *expected_info_p;
|
const jerry_object_native_info_t *expected_info_p;
|
||||||
@@ -269,6 +269,27 @@ jerryx_arg_transform_native_pointer (jerryx_arg_js_iterator_t *js_arg_iter_p, /*
|
|||||||
return jerry_create_undefined ();
|
return jerry_create_undefined ();
|
||||||
} /* jerryx_arg_transform_native_pointer */
|
} /* jerryx_arg_transform_native_pointer */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the JS object's properties have expected types, and transform them into native args.
|
||||||
|
*
|
||||||
|
* @return jerry undefined: the transformer passes,
|
||||||
|
* jerry error: the transformer fails.
|
||||||
|
*/
|
||||||
|
jerry_value_t
|
||||||
|
jerryx_arg_transform_object_props (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */
|
||||||
|
const jerryx_arg_t *c_arg_p) /**< the native arg */
|
||||||
|
{
|
||||||
|
jerry_value_t js_arg = jerryx_arg_js_iterator_pop (js_arg_iter_p);
|
||||||
|
|
||||||
|
const jerryx_arg_object_props_t *object_props = (const jerryx_arg_object_props_t *) c_arg_p->extra_info;
|
||||||
|
|
||||||
|
return jerryx_arg_transform_object_properties (js_arg,
|
||||||
|
object_props->name_p,
|
||||||
|
object_props->name_cnt,
|
||||||
|
object_props->c_arg_p,
|
||||||
|
object_props->c_arg_cnt);
|
||||||
|
} /* jerryx_arg_transform_object_props */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define transformer for optional argument.
|
* Define transformer for optional argument.
|
||||||
*/
|
*/
|
||||||
@@ -288,6 +309,7 @@ JERRYX_ARG_TRANSFORM_OPTIONAL (string)
|
|||||||
JERRYX_ARG_TRANSFORM_OPTIONAL (string_strict)
|
JERRYX_ARG_TRANSFORM_OPTIONAL (string_strict)
|
||||||
JERRYX_ARG_TRANSFORM_OPTIONAL (function)
|
JERRYX_ARG_TRANSFORM_OPTIONAL (function)
|
||||||
JERRYX_ARG_TRANSFORM_OPTIONAL (native_pointer)
|
JERRYX_ARG_TRANSFORM_OPTIONAL (native_pointer)
|
||||||
|
JERRYX_ARG_TRANSFORM_OPTIONAL (object_props)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ignore the JS argument.
|
* Ignore the JS argument.
|
||||||
|
|||||||
+49
-1
@@ -81,8 +81,56 @@ jerryx_arg_transform_this_and_args (const jerry_value_t this_val, /**< the this_
|
|||||||
{
|
{
|
||||||
jerry_release_value (ret);
|
jerry_release_value (ret);
|
||||||
|
|
||||||
return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "'this' validation failed");
|
return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "'this' validation failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return jerryx_arg_transform_args (js_arg_p, js_arg_cnt, c_arg_p + 1, c_arg_cnt - 1);
|
return jerryx_arg_transform_args (js_arg_p, js_arg_cnt, c_arg_p + 1, c_arg_cnt - 1);
|
||||||
} /* jerryx_arg_transform_this_and_args */
|
} /* jerryx_arg_transform_this_and_args */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the `obj_val`'s properties,
|
||||||
|
* and assign them to the native arguments.
|
||||||
|
*
|
||||||
|
* @return jerry undefined: all validators passed,
|
||||||
|
* jerry error: a validator failed.
|
||||||
|
*/
|
||||||
|
jerry_value_t
|
||||||
|
jerryx_arg_transform_object_properties (const jerry_value_t obj_val,/**< the JS object */
|
||||||
|
const jerry_char_t **name_p, /**< property name list of the JS object */
|
||||||
|
const jerry_length_t name_cnt, /**< count of the name list */
|
||||||
|
const jerryx_arg_t *c_arg_p, /**< points to the array of transformation steps */
|
||||||
|
jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */
|
||||||
|
{
|
||||||
|
if (!jerry_value_is_object (obj_val))
|
||||||
|
{
|
||||||
|
return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "Not an object.");
|
||||||
|
}
|
||||||
|
|
||||||
|
jerry_value_t prop[name_cnt];
|
||||||
|
|
||||||
|
for (jerry_length_t i = 0; i < name_cnt; i++, name_p++)
|
||||||
|
{
|
||||||
|
const jerry_value_t name_str = jerry_create_string (*name_p);
|
||||||
|
prop[i] = jerry_get_property (obj_val, name_str);
|
||||||
|
jerry_release_value (name_str);
|
||||||
|
|
||||||
|
if (jerry_value_has_error_flag (prop[i]))
|
||||||
|
{
|
||||||
|
for (jerry_length_t j = 0; j < i; j++)
|
||||||
|
{
|
||||||
|
jerry_release_value (prop[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const jerry_value_t ret = jerryx_arg_transform_args (prop, name_cnt, c_arg_p, c_arg_cnt);
|
||||||
|
|
||||||
|
for (jerry_length_t i = 0; i < name_cnt; i++)
|
||||||
|
{
|
||||||
|
jerry_release_value (prop[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
} /* jerryx_arg_transform_object_properties */
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#ifndef JERRYX_ARG_H
|
#ifndef JERRYX_ARG_H
|
||||||
#define JERRYX_ARG_H
|
#define JERRYX_ARG_H
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -43,6 +42,17 @@ typedef struct jerryx_arg_js_iterator_t jerryx_arg_js_iterator_t;
|
|||||||
typedef jerry_value_t (*jerryx_arg_transform_func_t) (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */
|
typedef jerry_value_t (*jerryx_arg_transform_func_t) (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */
|
||||||
const jerryx_arg_t *c_arg_p); /**< native arg */
|
const jerryx_arg_t *c_arg_p); /**< native arg */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The structure used in jerryx_arg_object_properties
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const jerry_char_t **name_p; /**< property name list of the JS object */
|
||||||
|
jerry_length_t name_cnt; /**< count of the name list */
|
||||||
|
const jerryx_arg_t *c_arg_p; /**< points to the array of transformation steps */
|
||||||
|
jerry_length_t c_arg_cnt; /**< the count of the `c_arg_p` array */
|
||||||
|
} jerryx_arg_object_props_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The structure defining a single validation & transformation step.
|
* The structure defining a single validation & transformation step.
|
||||||
*/
|
*/
|
||||||
@@ -64,6 +74,12 @@ jerry_value_t jerryx_arg_transform_args (const jerry_value_t *js_arg_p,
|
|||||||
const jerryx_arg_t *c_arg_p,
|
const jerryx_arg_t *c_arg_p,
|
||||||
jerry_length_t c_arg_cnt);
|
jerry_length_t c_arg_cnt);
|
||||||
|
|
||||||
|
jerry_value_t jerryx_arg_transform_object_properties (const jerry_value_t obj_val,
|
||||||
|
const jerry_char_t **name_p,
|
||||||
|
const jerry_length_t name_cnt,
|
||||||
|
const jerryx_arg_t *c_arg_p,
|
||||||
|
jerry_length_t c_arg_cnt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether an argument is allowed to be coerced into the expected JS type.
|
* Indicates whether an argument is allowed to be coerced into the expected JS type.
|
||||||
*/
|
*/
|
||||||
@@ -105,6 +121,8 @@ static inline jerryx_arg_t
|
|||||||
jerryx_arg_ignore (void);
|
jerryx_arg_ignore (void);
|
||||||
static inline jerryx_arg_t
|
static inline jerryx_arg_t
|
||||||
jerryx_arg_custom (void *dest, uintptr_t extra_info, jerryx_arg_transform_func_t func);
|
jerryx_arg_custom (void *dest, uintptr_t extra_info, jerryx_arg_transform_func_t func);
|
||||||
|
static inline jerryx_arg_t
|
||||||
|
jerryx_arg_object_properties (const jerryx_arg_object_props_t *object_props_p, jerryx_arg_optional_t opt_flag);
|
||||||
|
|
||||||
jerry_value_t
|
jerry_value_t
|
||||||
jerryx_arg_transform_optional (jerryx_arg_js_iterator_t *js_arg_iter_p,
|
jerryx_arg_transform_optional (jerryx_arg_js_iterator_t *js_arg_iter_p,
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ jerry_value_t jerryx_arg_transform_native_pointer_optional (jerryx_arg_js_iterat
|
|||||||
const jerryx_arg_t *c_arg_p);
|
const jerryx_arg_t *c_arg_p);
|
||||||
jerry_value_t jerryx_arg_transform_ignore (jerryx_arg_js_iterator_t *js_arg_iter_p,
|
jerry_value_t jerryx_arg_transform_ignore (jerryx_arg_js_iterator_t *js_arg_iter_p,
|
||||||
const jerryx_arg_t *c_arg_p);
|
const jerryx_arg_t *c_arg_p);
|
||||||
|
jerry_value_t jerryx_arg_transform_object_props (jerryx_arg_js_iterator_t *js_arg_iter_p,
|
||||||
|
const jerryx_arg_t *c_arg_p);
|
||||||
|
jerry_value_t jerryx_arg_transform_object_props_optional (jerryx_arg_js_iterator_t *js_arg_iter_p,
|
||||||
|
const jerryx_arg_t *c_arg_p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
* Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||||
@@ -213,7 +217,7 @@ jerryx_arg_function (jerry_value_t *dest, /**< pointer to the jerry_value_t wher
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
* Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||||
* consume one `Object` JS argument that is 'backed' with a native pointer with
|
* consume one `object` JS argument that is 'backed' with a native pointer with
|
||||||
* a given type info. In case the native pointer info matches, the transform
|
* a given type info. In case the native pointer info matches, the transform
|
||||||
* will succeed and the object's native pointer will be assigned to *dest.
|
* will succeed and the object's native pointer will be assigned to *dest.
|
||||||
*
|
*
|
||||||
@@ -275,4 +279,32 @@ jerryx_arg_custom (void *dest, /**< pointer to the native argument where the res
|
|||||||
};
|
};
|
||||||
} /* jerryx_arg_custom */
|
} /* jerryx_arg_custom */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a jerryx_arg_t instance for object properties.
|
||||||
|
*
|
||||||
|
* @return a jerryx_arg_t instance.
|
||||||
|
*/
|
||||||
|
static inline jerryx_arg_t
|
||||||
|
jerryx_arg_object_properties (const jerryx_arg_object_props_t *object_props, /**< pointer to object property mapping */
|
||||||
|
jerryx_arg_optional_t opt_flag) /**< whether the argument is optional */
|
||||||
|
{
|
||||||
|
jerryx_arg_transform_func_t func;
|
||||||
|
|
||||||
|
if (opt_flag == JERRYX_ARG_OPTIONAL)
|
||||||
|
{
|
||||||
|
func = jerryx_arg_transform_object_props_optional;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
func = jerryx_arg_transform_object_props;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (jerryx_arg_t)
|
||||||
|
{
|
||||||
|
.func = func,
|
||||||
|
.dest = NULL,
|
||||||
|
.extra_info = (uintptr_t) object_props
|
||||||
|
};
|
||||||
|
} /* jerryx_arg_object_properties */
|
||||||
|
|
||||||
#endif /* !JERRYX_ARG_IMPL_H */
|
#endif /* !JERRYX_ARG_IMPL_H */
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "test-common.h"
|
#include "test-common.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <jerryscript-ext/arg.h>
|
||||||
|
|
||||||
const char *test_source = (
|
const char *test_source = (
|
||||||
"var arg1 = true;"
|
"var arg1 = true;"
|
||||||
@@ -40,6 +41,15 @@ const char *test_source = (
|
|||||||
"test_validator2.call(obj_a, 5);"
|
"test_validator2.call(obj_a, 5);"
|
||||||
"test_validator2.call(obj_b, 5);"
|
"test_validator2.call(obj_b, 5);"
|
||||||
"test_validator2.call(obj_a, 1);"
|
"test_validator2.call(obj_a, 1);"
|
||||||
|
"var obj1 = {prop1:true, prop2:'1.5'};"
|
||||||
|
"test_validator_prop1(obj1);"
|
||||||
|
"test_validator_prop2(obj1);"
|
||||||
|
"test_validator_prop2();"
|
||||||
|
"var obj2 = {prop1:true};"
|
||||||
|
"Object.defineProperty(obj2, 'prop2', {"
|
||||||
|
" get: function() { throw new TypeError('prop2 error') }"
|
||||||
|
"});"
|
||||||
|
"test_validator_prop3(obj2);"
|
||||||
);
|
);
|
||||||
|
|
||||||
static const jerry_object_native_info_t thing_a_info =
|
static const jerry_object_native_info_t thing_a_info =
|
||||||
@@ -68,6 +78,8 @@ static my_type_b_t my_thing_b;
|
|||||||
static int validator1_count = 0;
|
static int validator1_count = 0;
|
||||||
static int validator2_count = 0;
|
static int validator2_count = 0;
|
||||||
|
|
||||||
|
static int validator_prop_count = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The handler should have following arguments:
|
* The handler should have following arguments:
|
||||||
* this: Ignore.
|
* this: Ignore.
|
||||||
@@ -211,6 +223,129 @@ test_validator2_handler (const jerry_value_t func_obj_val __attribute__((unused)
|
|||||||
return jerry_create_undefined ();
|
return jerry_create_undefined ();
|
||||||
} /* test_validator2_handler */
|
} /* test_validator2_handler */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calling jerryx_arg_transform_object_properties directly.
|
||||||
|
*/
|
||||||
|
static jerry_value_t
|
||||||
|
test_validator_prop1_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
|
||||||
|
const jerry_value_t this_val __attribute__((unused)), /**< this value */
|
||||||
|
const jerry_value_t args_p[], /**< arguments list */
|
||||||
|
const jerry_length_t args_cnt __attribute__((unused))) /**< arguments length */
|
||||||
|
{
|
||||||
|
bool native1 = false;
|
||||||
|
double native2 = 0;
|
||||||
|
double native3 = 3;
|
||||||
|
|
||||||
|
const char *name_p[] = {"prop1", "prop2", "prop3"};
|
||||||
|
|
||||||
|
jerryx_arg_t mapping[] =
|
||||||
|
{
|
||||||
|
jerryx_arg_boolean (&native1, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||||
|
jerryx_arg_number (&native2, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||||
|
jerryx_arg_number (&native3, JERRYX_ARG_COERCE, JERRYX_ARG_OPTIONAL)
|
||||||
|
};
|
||||||
|
|
||||||
|
jerry_value_t is_ok = jerryx_arg_transform_object_properties (args_p[0],
|
||||||
|
(const jerry_char_t **) name_p,
|
||||||
|
3,
|
||||||
|
mapping,
|
||||||
|
3);
|
||||||
|
|
||||||
|
TEST_ASSERT (!jerry_value_has_error_flag (is_ok));
|
||||||
|
TEST_ASSERT (native1);
|
||||||
|
TEST_ASSERT (native2 == 1.5);
|
||||||
|
TEST_ASSERT (native3 == 3);
|
||||||
|
|
||||||
|
validator_prop_count ++;
|
||||||
|
|
||||||
|
return jerry_create_undefined ();
|
||||||
|
} /* test_validator_prop1_handler */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calling jerryx_arg_transform_object_properties indirectly by
|
||||||
|
* using jerryx_arg_object_properties.
|
||||||
|
*/
|
||||||
|
static jerry_value_t
|
||||||
|
test_validator_prop2_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
|
||||||
|
const jerry_value_t this_val __attribute__((unused)), /**< this value */
|
||||||
|
const jerry_value_t args_p[], /**< arguments list */
|
||||||
|
const jerry_length_t args_cnt __attribute__((unused))) /**< arguments length */
|
||||||
|
{
|
||||||
|
bool native1 = false;
|
||||||
|
double native2 = 0;
|
||||||
|
double native3 = 3;
|
||||||
|
|
||||||
|
jerryx_arg_object_props_t prop_info;
|
||||||
|
|
||||||
|
const char *name_p[] = { "prop1", "prop2", "prop3" };
|
||||||
|
|
||||||
|
jerryx_arg_t prop_mapping[] =
|
||||||
|
{
|
||||||
|
jerryx_arg_boolean (&native1, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||||
|
jerryx_arg_number (&native2, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||||
|
jerryx_arg_number (&native3, JERRYX_ARG_COERCE, JERRYX_ARG_OPTIONAL)
|
||||||
|
};
|
||||||
|
|
||||||
|
prop_info.name_p = (const jerry_char_t **) name_p;
|
||||||
|
prop_info.name_cnt = 3;
|
||||||
|
prop_info.c_arg_p = prop_mapping;
|
||||||
|
prop_info.c_arg_cnt = 3;
|
||||||
|
|
||||||
|
jerryx_arg_t mapping[] =
|
||||||
|
{
|
||||||
|
jerryx_arg_object_properties (&prop_info, JERRYX_ARG_OPTIONAL),
|
||||||
|
};
|
||||||
|
|
||||||
|
jerry_value_t is_ok = jerryx_arg_transform_args (args_p, 1, mapping, 1);
|
||||||
|
|
||||||
|
|
||||||
|
TEST_ASSERT (!jerry_value_has_error_flag (is_ok));
|
||||||
|
|
||||||
|
if (validator_prop_count == 1)
|
||||||
|
{
|
||||||
|
TEST_ASSERT (native1);
|
||||||
|
TEST_ASSERT (native2 == 1.5);
|
||||||
|
TEST_ASSERT (native3 == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
validator_prop_count ++;
|
||||||
|
|
||||||
|
return jerry_create_undefined ();
|
||||||
|
} /* test_validator_prop2_handler */
|
||||||
|
|
||||||
|
static jerry_value_t
|
||||||
|
test_validator_prop3_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
|
||||||
|
const jerry_value_t this_val __attribute__((unused)), /**< this value */
|
||||||
|
const jerry_value_t args_p[], /**< arguments list */
|
||||||
|
const jerry_length_t args_cnt __attribute__((unused))) /**< arguments length */
|
||||||
|
{
|
||||||
|
bool native1 = false;
|
||||||
|
bool native2 = true;
|
||||||
|
|
||||||
|
const char *name_p[] = { "prop1", "prop2" };
|
||||||
|
|
||||||
|
jerryx_arg_t mapping[] =
|
||||||
|
{
|
||||||
|
jerryx_arg_boolean (&native1, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||||
|
jerryx_arg_boolean (&native2, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||||
|
};
|
||||||
|
|
||||||
|
jerry_value_t is_ok = jerryx_arg_transform_object_properties (args_p[0],
|
||||||
|
(const jerry_char_t **) name_p,
|
||||||
|
2,
|
||||||
|
mapping,
|
||||||
|
2);
|
||||||
|
|
||||||
|
TEST_ASSERT (jerry_value_has_error_flag (is_ok));
|
||||||
|
TEST_ASSERT (!native1);
|
||||||
|
TEST_ASSERT (native2);
|
||||||
|
|
||||||
|
validator_prop_count ++;
|
||||||
|
jerry_release_value (is_ok);
|
||||||
|
|
||||||
|
return jerry_create_undefined ();
|
||||||
|
} /* test_validator_prop3_handler */
|
||||||
|
|
||||||
static jerry_value_t
|
static jerry_value_t
|
||||||
create_object_a_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
|
create_object_a_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
|
||||||
const jerry_value_t this_val, /**< this value */
|
const jerry_value_t this_val, /**< this value */
|
||||||
@@ -272,6 +407,9 @@ main (void)
|
|||||||
register_js_function ("test_validator2", test_validator2_handler);
|
register_js_function ("test_validator2", test_validator2_handler);
|
||||||
register_js_function ("MyObjectA", create_object_a_handler);
|
register_js_function ("MyObjectA", create_object_a_handler);
|
||||||
register_js_function ("MyObjectB", create_object_b_handler);
|
register_js_function ("MyObjectB", create_object_b_handler);
|
||||||
|
register_js_function ("test_validator_prop1", test_validator_prop1_handler);
|
||||||
|
register_js_function ("test_validator_prop2", test_validator_prop2_handler);
|
||||||
|
register_js_function ("test_validator_prop3", test_validator_prop3_handler);
|
||||||
|
|
||||||
jerry_value_t parsed_code_val = jerry_parse ((jerry_char_t *) test_source, strlen (test_source), false);
|
jerry_value_t parsed_code_val = jerry_parse ((jerry_char_t *) test_source, strlen (test_source), false);
|
||||||
TEST_ASSERT (!jerry_value_has_error_flag (parsed_code_val));
|
TEST_ASSERT (!jerry_value_has_error_flag (parsed_code_val));
|
||||||
@@ -280,6 +418,7 @@ main (void)
|
|||||||
TEST_ASSERT (!jerry_value_has_error_flag (res));
|
TEST_ASSERT (!jerry_value_has_error_flag (res));
|
||||||
TEST_ASSERT (validator1_count == 4);
|
TEST_ASSERT (validator1_count == 4);
|
||||||
TEST_ASSERT (validator2_count == 3);
|
TEST_ASSERT (validator2_count == 3);
|
||||||
|
TEST_ASSERT (validator_prop_count == 4);
|
||||||
|
|
||||||
jerry_release_value (res);
|
jerry_release_value (res);
|
||||||
jerry_release_value (parsed_code_val);
|
jerry_release_value (parsed_code_val);
|
||||||
|
|||||||
Reference in New Issue
Block a user