Support parsing of scripts / functions stored in string values (#4728)

Function arguments must be passed as string values.
Snapshots are generated from compiled code rather than source code.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2021-08-11 17:37:12 +02:00
committed by GitHub
parent b7dead7b05
commit 3ed93cfb51
24 changed files with 601 additions and 696 deletions
+146 -256
View File
@@ -243,6 +243,7 @@ Option bits for [jerry_parse_options_t](#jerry_parse_options_t).
- JERRY_PARSE_NO_OPTS - No options passed
- JERRY_PARSE_STRICT_MODE - Enable strict mode
- JERRY_PARSE_MODULE - Parse source as an ECMAScript module
- JERRY_PARSE_HAS_ARGUMENT_LIST - `argument_list` field is valid
- JERRY_PARSE_HAS_RESOURCE - `resource_name` field is valid
- JERRY_PARSE_HAS_START - `start_line` and `start_column` fields are valid
- JERRY_PARSE_HAS_USER_VALUE - `user_value` field is valid
@@ -278,8 +279,7 @@ List of backtrace frame types returned by
## jerry_generate_snapshot_opts_t
Flags for [jerry_generate_snapshot](#jerry_generate_snapshot) and
[jerry_generate_function_snapshot](#jerry_generate_function_snapshot) functions:
Flags for [jerry_generate_snapshot](#jerry_generate_snapshot):
- JERRY_SNAPSHOT_SAVE_STATIC - generate static snapshot (see below)
@@ -540,8 +540,7 @@ Enum that contains the flags of property descriptors.
**Summary**
Various configuration options for parsing functions such as [jerry_parse](#jerry_parse)
or [jerry_parse_function](#jerry_parse_function)
Various configuration options for parsing functions such as [jerry_parse](#jerry_parse).
**Prototype**
@@ -549,9 +548,11 @@ or [jerry_parse_function](#jerry_parse_function)
typedef struct
{
uint32_t options; /**< combination of jerry_parse_option_enable_feature_t values */
jerry_value_t argument_list; /**< function argument list if JERRY_PARSE_HAS_ARGUMENT_LIST is set in options
* Note: must be string value */
jerry_value_t resource_name; /**< resource name string (usually a file name)
* if JERRY_PARSE_HAS_RESOURCE is set in options
* Note: non-string values are ignored */
* Note: must be string value */
uint32_t start_line; /**< start line of the source code if JERRY_PARSE_HAS_START is set in options */
uint32_t start_column; /**< start column of the source code if JERRY_PARSE_HAS_START is set in options */
jerry_value_t user_value; /**< user value assigned to all functions created by this script including eval
@@ -564,9 +565,7 @@ typedef struct
**See also**
- [jerry_parse](#jerry_parse)
- [jerry_parse_function](#jerry_parse_function)
- [jerry_generate_snapshot](#jerry_generate_snapshot)
- [jerry_generate_function_snapshot](#jerry_generate_function_snapshot)
- [jerry_exec_snapshot](#jerry_exec_snapshot)
- [jerry_parse_option_enable_feature_t](#jerry_parse_option_enable_feature_t)
@@ -1696,9 +1695,7 @@ main (void)
**Summary**
Parse script and construct an EcmaScript function. The lexical environment is
set to the global lexical environment. The resource name can be used by
debugging systems to provide line / backtrace info.
Parse a script, module, or function and create a compiled code using a character string.
*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
@@ -1734,6 +1731,7 @@ main (void)
{
jerry_init (JERRY_INIT_EMPTY);
/* Parsing a script. */
const jerry_char_t script[] = "print ('Hello, World!');";
jerry_parse_options_t parse_options;
@@ -1745,6 +1743,89 @@ main (void)
jerry_value_t parsed_code = jerry_parse (script, sizeof (script) - 1, &parse_options);
jerry_release_value (parse_options.resource_name);
jerry_release_value (jerry_run (parsed_code));
jerry_release_value (parsed_code);
/* Parsing a function. */
parse_options.options = JERRY_PARSE_HAS_ARGUMENT_LIST;
parse_options.argument_list = jerry_create_string ((const jerry_char_t *) "a, b");
const jerry_char_t function_code[] = "return a + b;";
jerry_value_t parsed_function = jerry_parse (function_code, sizeof (function_code) - 1, &parse_options);
jerry_release_value (parse_options.argument_list);
jerry_value_t args[] = {
jerry_create_number (3),
jerry_create_number (4),
};
jerry_size_t argc = sizeof (args) / sizeof (args[0]);
jerry_release_value (jerry_call_function (parsed_function,
jerry_create_undefined(),
args,
argc));
jerry_release_value (parsed_function);
jerry_cleanup ();
return 0;
}
```
**See also**
- [jerry_parse_value](#jerry_parse_value)
- [jerry_run](#jerry_run)
- [jerry_parse_options_t](#jerry_parse_options_t)
## jerry_parse_value
**Summary**
Parse a script, module, or function and create a compiled code using a string value.
*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
**Prototype**
```c
jerry_value_t
jerry_parse_value (const jerry_value_t source_value,
const jerry_parse_options_t *options_p);
```
- `source_value` - string value, containing source code to parse (only string values are accepted).
- `options_p` - additional parsing options, can be NULL if not used
- return value
- function object value, if script was parsed successfully,
- thrown error, otherwise
*New in version [[NEXT_RELEASE]]*.
**Example**
[doctest]: # ()
```c
#include "jerryscript.h"
int
main (void)
{
jerry_init (JERRY_INIT_EMPTY);
jerry_value_t script_value = jerry_create_string ((const jerry_char_t *) "print ('Hello, World!');");
jerry_parse_options_t parse_options;
parse_options.options = JERRY_PARSE_STRICT_MODE | JERRY_PARSE_HAS_RESOURCE | JERRY_PARSE_HAS_START;
parse_options.resource_name = jerry_create_string ((const jerry_char_t *) "hello.js");
/* This example script is extracted from the middle of a file. */
parse_options.start_line = 10;
parse_options.start_column = 1;
jerry_value_t parsed_code = jerry_parse_value (script_value, &parse_options);
jerry_release_value (parse_options.resource_name);
jerry_release_value (script_value);
jerry_release_value (parsed_code);
jerry_cleanup ();
@@ -1754,120 +1835,10 @@ main (void)
**See also**
- [jerry_parse](#jerry_parse)
- [jerry_run](#jerry_run)
- [jerry_parse_function](#jerry_parse_function)
- [jerry_parse_options_t](#jerry_parse_options_t)
## jerry_parse_function
**Summary**
Parse function source code and construct an ECMAScript
function. The function arguments and function body are
passed as separated arguments. The lexical environment
is set to the global lexical environment. The resource
name (usually a file name) is also passed to this function
which is used by the debugger to find the source code.
*Note*: The returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
**Prototype**
```c
jerry_value_t
jerry_parse_function (const jerry_char_t *arg_list_p,
size_t arg_list_size,
const jerry_char_t *source_p,
size_t source_size,
const jerry_parse_options_t *options_p);
```
- `arg_list_p` - argument list of the function (must be a valid UTF8 string).
- `arg_list_size` - size of the argument list, in bytes.
- `source_p` - string, containing source code to parse (must be a valid UTF8 string).
- `source_size` - size of the string, in bytes.
- `options_p` - additional parsing options, can be NULL if not used
- return value
- function object value, if script was parsed successfully,
- thrown error, otherwise
*New in version 2.0*.
*Changed in version [[NEXT_RELEASE]]*: The `resource_name_p`, `resource_name_length`, and `parse_opts` arguments are replaced by `options_p`.
**Example**
[doctest]: # (name="02.API-REFERENCE-parse-func.c")
```c
#include <stdio.h>
#include <string.h>
#include "jerryscript.h"
int
main (void)
{
int return_value = 1;
/* Initialize engine */
jerry_init (JERRY_INIT_EMPTY);
/* Parse the 'function (a,b) { return a + b; }' function */
const char function_args[] = "a, b";
const char function_source[] = "return a + b";
jerry_value_t parsed_function = jerry_parse_function ((const jerry_char_t *) function_args,
strlen (function_args),
(const jerry_char_t *) function_source,
strlen (function_source),
NULL);
if (!jerry_value_is_error (parsed_function))
{
/* Run the parsed function */
jerry_value_t args[] = {
jerry_create_number (3),
jerry_create_number (55),
};
jerry_size_t argc = sizeof (args) / sizeof (args[0]);
jerry_value_t ret_value = jerry_call_function (parsed_function,
jerry_create_undefined(),
args,
argc);
/* Process result value */
if (jerry_value_is_number (ret_value)) {
double value = jerry_get_number_value (ret_value);
printf ("Function result: %lf\n", value);
return_value = !(value == (3 + 55));
}
/* Release the function arguments */
for (jerry_size_t idx = 0; idx < argc; idx++) {
jerry_release_value (args[idx]);
}
/* Returned value must be freed */
jerry_release_value (ret_value);
}
/* Parsed function must be freed */
jerry_release_value (parsed_function);
/* Cleanup engine */
jerry_cleanup ();
return return_value;
}
```
**See also**
- [jerry_call_function](#jerry_call_function)
- [jerry_parse_options_t](#jerry_parse_options_t)
## jerry_run
**Summary**
@@ -10429,17 +10400,13 @@ Generate snapshot from the specified source code.
```c
jerry_value_t
jerry_generate_snapshot (const jerry_char_t *source_p,
size_t source_size,
const jerry_parse_options_t *options_p,
jerry_generate_snapshot (jerry_value_t compiled_code,
uint32_t generate_snapshot_opts,
uint32_t *buffer_p,
size_t buffer_size);
```
- `source_p` - script source, it must be a valid utf8 string.
- `source_size` - script source size, in bytes.
- `options_p` - additional parsing options, can be NULL if not used
- `compiled_code` - compiled script or function (see: [jerry_parse](#jerry_parse)).
- `generate_snapshot_opts` - any combination of [jerry_generate_snapshot_opts_t](#jerry_generate_snapshot_opts_t) flags.
- `buffer_p` - output buffer (aligned to 4 bytes) to save snapshot to.
- `buffer_size` - the output buffer's size in bytes.
@@ -10450,7 +10417,10 @@ jerry_generate_snapshot (const jerry_char_t *source_p,
- thrown error, otherwise.
*New in version 2.0*.
*Changed in version [[NEXT_RELEASE]]*: The `resource_name_p`, and `resource_name_length` arguments are replaced by `options_p`.
*Changed in version [[NEXT_RELEASE]]*: The `source_p`, `source_size`, `resource_name_p`,
and `resource_name_length` arguments are replaced by `compiled_code`
which should contain a compiled ECMAScript script / function.
**Example**
@@ -10467,13 +10437,16 @@ main (void)
static uint32_t global_mode_snapshot_buffer[256];
const jerry_char_t script_to_snapshot[] = "(function () { return 'string from snapshot'; }) ();";
jerry_value_t generate_result;
generate_result = jerry_generate_snapshot (script_to_snapshot,
sizeof (script_to_snapshot) - 1,
NULL,
0,
global_mode_snapshot_buffer,
sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t));
jerry_value_t parse_result = jerry_parse (script_to_snapshot,
sizeof (script_to_snapshot) - 1,
NULL);
size_t buffer_size = sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t);
jerry_value_t generate_result = jerry_generate_snapshot (parse_result,
0,
global_mode_snapshot_buffer,
buffer_size);
jerry_release_value (parse_result);
if (!jerry_value_is_error (generate_result))
{
@@ -10489,107 +10462,12 @@ main (void)
**See also**
- [jerry_init](#jerry_init)
- [jerry_cleanup](#jerry_cleanup)
- [jerry_generate_function_snapshot](#jerry_generate_function_snapshot)
- [jerry_parse](#jerry_parse)
- [jerry_parse_value](#jerry_parse_value)
- [jerry_exec_snapshot](#jerry_exec_snapshot)
- [jerry_parse_options_t](#jerry_parse_options_t)
## jerry_generate_function_snapshot
**Summary**
Generate function snapshot from the specified source code
with the given arguments.
The function arguments and function body are
passed as separated arguments.
*Notes*:
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
- This API depends on a build option (`JERRY_SNAPSHOT_SAVE`) and can be checked in runtime with
the `JERRY_FEATURE_SNAPSHOT_SAVE` feature enum value, see [jerry_is_feature_enabled](#jerry_is_feature_enabled).
If the feature is not enabled the function will return an error.
**Prototype**
```c
jerry_value_t
jerry_generate_function_snapshot (const jerry_char_t *source_p,
size_t source_size,
const jerry_char_t *args_p,
size_t args_size,
const jerry_parse_options_t *options_p,
uint32_t generate_snapshot_opts,
uint32_t *buffer_p,
size_t buffer_size)
```
- `source_p` - script source, it must be a valid utf8 string.
- `source_size` - script source size, in bytes.
- `args_p` - function arguments, it must be a valid utf8 string.
- `args_size` - function argument size, in bytes.
- `options_p` - additional parsing options, can be NULL if not used
- `generate_snapshot_opts` - any combination of [jerry_generate_snapshot_opts_t](#jerry_generate_snapshot_opts_t) flags.
- `buffer_p` - buffer (aligned to 4 bytes) to save snapshot to.
- `buffer_size` - the buffer's size in bytes.
- return value
- the size of the generated snapshot in bytes as number value, if it was generated succesfully (i.e. there
are no syntax errors in source code, buffer size is sufficient, and snapshot support is enabled in
current configuration through JERRY_SNAPSHOT_SAVE)
- thrown error, otherwise.
*New in version 2.0*.
*Changed in version [[NEXT_RELEASE]]*: The `resource_name_p`, and `resource_name_length` arguments are replaced by `options_p`.
**Example**
[doctest]: # ()
```c
#include "jerryscript.h"
int
main (void)
{
jerry_init (JERRY_INIT_EMPTY);
static uint32_t func_snapshot_buffer[256];
const jerry_char_t args[] = "a, b";
const jerry_char_t src[] = "return a + b;";
jerry_value_t generate_result;
generate_result = jerry_generate_function_snapshot (src,
sizeof (src) - 1,
args,
sizeof (args) - 1,
NULL,
0,
func_snapshot_buffer,
sizeof (func_snapshot_buffer) / sizeof (uint32_t));
if (!jerry_value_is_error (generate_result))
{
size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
}
jerry_release_value (generate_result);
jerry_cleanup ();
return 0;
}
```
**See also**
- [jerry_init](#jerry_init)
- [jerry_cleanup](#jerry_cleanup)
- [jerry_generate_snapshot](#jerry_generate_snapshot)
- [jerry_parse_options_t](#jerry_parse_options_t)
## jerry_exec_snapshot
**Summary**
@@ -10645,13 +10523,17 @@ main (void)
const jerry_char_t script_to_snapshot[] = "(function () { return 'string from snapshot'; }) ();";
jerry_value_t generate_result;
generate_result = jerry_generate_snapshot (script_to_snapshot,
sizeof (script_to_snapshot) - 1,
NULL,
0,
snapshot_buffer,
sizeof (snapshot_buffer) / sizeof (uint32_t));
jerry_value_t parse_result = jerry_parse (script_to_snapshot,
sizeof (script_to_snapshot) - 1,
NULL);
size_t buffer_size = sizeof (snapshot_buffer) / sizeof (uint32_t);
jerry_value_t generate_result = jerry_generate_snapshot (parse_result,
0,
snapshot_buffer,
buffer_size);
jerry_release_value (parse_result);
/* 'generate_result' variable should be checked whether it contains an error. */
size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
@@ -10689,18 +10571,24 @@ main (void)
/* 2nd example: function snapshot. */
jerry_init (JERRY_INIT_EMPTY);
const jerry_char_t function_to_snapshot_args[] = "a, b";
const jerry_char_t function_to_snapshot[] = "return a + b;";
jerry_value_t generate_result;
generate_result = jerry_generate_function_snapshot (function_to_snapshot,
sizeof (function_to_snapshot) - 1,
function_to_snapshot_args,
sizeof (function_to_snapshot_args) - 1,
NULL,
0,
snapshot_buffer,
sizeof (snapshot_buffer) / sizeof (uint32_t));
jerry_parse_options_t parse_options;
parse_options.options = JERRY_PARSE_HAS_ARGUMENT_LIST;
parse_options.argument_list = jerry_create_string ((const jerry_char_t *) "a, b");
jerry_value_t parse_result = jerry_parse (function_to_snapshot,
sizeof (function_to_snapshot) - 1,
&parse_options);
size_t buffer_size = sizeof (snapshot_buffer) / sizeof (uint32_t);
jerry_value_t generate_result = jerry_generate_snapshot (parse_result,
0,
snapshot_buffer,
buffer_size);
jerry_release_value (parse_result);
jerry_release_value (parse_options.argument_list);
/* 'generate_result' variable should be checked whether it contains an error. */
size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
@@ -10740,7 +10628,6 @@ main (void)
- [jerry_init](#jerry_init)
- [jerry_cleanup](#jerry_cleanup)
- [jerry_generate_snapshot](#jerry_generate_snapshot)
- [jerry_generate_function_snapshot](#jerry_generate_function_snapshot)
## jerry_get_literals_from_snapshot
@@ -10795,12 +10682,17 @@ main (void)
static uint32_t snapshot_buffer[256];
const jerry_char_t script_for_literal_save[] = "var obj = { a:'aa', bb:'Bb' }";
jerry_value_t generate_result = jerry_generate_snapshot (script_for_literal_save,
sizeof (script_for_literal_save) - 1,
NULL,
jerry_value_t parse_result = jerry_parse (script_for_literal_save,
sizeof (script_for_literal_save) - 1,
NULL);
size_t buffer_size = sizeof (snapshot_buffer) / sizeof (uint32_t);
jerry_value_t generate_result = jerry_generate_snapshot (parse_result,
0,
snapshot_buffer,
256);
buffer_size);
jerry_release_value (parse_result);
size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
jerry_release_value (generate_result);
@@ -11667,9 +11559,7 @@ main (void)
**See also**
- [jerry_parse](#jerry_parse)
- [jerry_parse_function](#jerry_parse_function)
- [jerry_generate_snapshot](#jerry_generate_snapshot)
- [jerry_generate_function_snapshot](#jerry_generate_function_snapshot)
- [jerry_exec_snapshot](#jerry_exec_snapshot)