Update the webpage (#1941)
* Add new documents about autorelease values and module support JerryScript-DCO-1.0-Signed-off-by: Zsolt Borbély zsborbely.u-szeged@partner.samsung.com
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
---
|
||||
layout: page
|
||||
title: 'Extension API: Module Support'
|
||||
category: documents
|
||||
permalink: /ext-reference-module/
|
||||
---
|
||||
|
||||
* toc
|
||||
{:toc}
|
||||
|
||||
# Module API
|
||||
|
||||
This is a JerryScript extension that provides a means of loading modules. Fundamentally, a module is a name (stored as
|
||||
a string) that resolves to a `jerry_value_t`. This extension provides the function `jerryx_module_resolve()` which
|
||||
accepts the name of the module being requested as well as an array of so-called "resolvers" - functions which satisfy
|
||||
the signature `jerryx_module_resolver_t`. The resolvers in the list are called in sequence until one of them returns
|
||||
`true` and a `jerry_value_t` in its out parameter. The value is cached if it is not an error, so subsequent requests
|
||||
for the same name will not result in additional calls to the resolvers.
|
||||
|
||||
The purpose of having resolvers is to be able to account for the fact that different types of modules may be structured
|
||||
differently and thus, for each type of module a module resolver must be supplied at the point where an instance of that
|
||||
type of module is requested.
|
||||
|
||||
Additionally, this extension provides a means of easily defining so-called "native" JerryScript modules which can be
|
||||
resolved using the JerryScript native module resolver `jerryx_module_native_resolver()`, which can be passed to
|
||||
`jerryx_module_resolve()`. Note, however, that native JerryScript modules are only supported and
|
||||
`jerryx_module_native_resolver()` is only compiled in if compiler support for `__attribute__` extensions is present. In
|
||||
effect this means that native JerryScript modules are available only when this extension is built with GCC or
|
||||
LLVM/clang. In the absence of such support, you may construct alternative module systems and provide your own resolver
|
||||
to `jerryx_module_resolve()`.
|
||||
|
||||
`jerryscript-ext/module.h` defines the preprocessor directive `JERRYX_NATIVE_MODULES_SUPPORTED` only if support for
|
||||
native JerryScript modules is available.
|
||||
|
||||
## jerryx_module_resolve
|
||||
|
||||
**Summary**
|
||||
|
||||
Load a copy of a module into the current context or return one that was already loaded if it is found.
|
||||
|
||||
Each function in `resolvers_p` will be called in sequence until one returns `true` and fills out its out-parameter with
|
||||
the `jerry_value_t` representing the requested module. If the `jerry_value_t` does not have the error flag set it will
|
||||
be cached. Thus, on subsequent calls with the same value for `name`, none of the functions in `resolvers_p` will be
|
||||
called.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_module_resolve (const jerry_char_t *name,
|
||||
const jerryx_module_resolver_t *resolvers_p,
|
||||
size_t resolver_count);
|
||||
```
|
||||
|
||||
- `name` - the name of the module to load
|
||||
- `resolvers_p` - the list of resolvers to call in sequence
|
||||
- `resolver_count` - the number of resolvers in `resolvers_p`
|
||||
- return value - `jerry_value_t` representing the module that was loaded, or the error that occurred in the process.
|
||||
|
||||
|
||||
## jerryx_module_native_resolver
|
||||
|
||||
**Summary**
|
||||
|
||||
The resolver for JerryScript modules. A pointer to this function can be passed in the second parameter to
|
||||
`jerryx_module_resolve` to search for the module among the JerryScript modules built into the binary. This function is
|
||||
available only if the preprocessor directive `JERRYX_NATIVE_MODULES_SUPPORTED` is defined.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
bool
|
||||
jerryx_module_native_resolver (const jerry_char_t *name,
|
||||
jerry_value_t *result)
|
||||
```
|
||||
- `name` - the name of the module to find
|
||||
- `result` - out - place where to store the resulting module instance
|
||||
- return value - `true` if the module was found and stored in `result`, and `false` otherwise
|
||||
|
||||
|
||||
# Module data types
|
||||
|
||||
## jerryx_native_module_on_resolve_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Function pointer type for a function that will create an instance of a native module. This type is only defined if the
|
||||
preprocessor directive `JERRYX_NATIVE_MODULES_SUPPORTED` is defined.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef jerry_value_t (*jerryx_native_module_on_resolve_t) (void);
|
||||
```
|
||||
|
||||
## jerryx_module_resolver_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Function pointer type for a module resolver
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef bool (*jerryx_module_resolver_t) (const jerry_char_t *name, jerry_value_t *result);
|
||||
```
|
||||
|
||||
**Example**
|
||||
```c
|
||||
bool
|
||||
load_and_evaluate_js_file (const jerry_char_t *name, jerry_value_t *result)
|
||||
{
|
||||
bool return_value = false;
|
||||
char *js_file_contents = NULL;
|
||||
int file_size = 0;
|
||||
FILE *js_file = fopen (name, "r");
|
||||
|
||||
if (js_file)
|
||||
{
|
||||
/* We have successfully opened the file. Now, we establish its size. */
|
||||
file_size = fseek (js_file, 0, SEEK_END);
|
||||
fseek (js_file, 0, SEEK_SET);
|
||||
|
||||
/* We allocate enough memory to store the contents of the file. */
|
||||
js_file_contents = malloc (file_size);
|
||||
if (js_file_contents)
|
||||
{
|
||||
/* We read the file into memory and call jerry_eval (), assigning the result to the out-parameter. */
|
||||
fread (js_file_contents, file_size, 1, js_file);
|
||||
(*result) = jerry_eval (js_file_contents, file_size, false);
|
||||
|
||||
/* We release the memory holding the contents of the file. */
|
||||
free (js_file_contents);
|
||||
return_value = true;
|
||||
}
|
||||
|
||||
/* We close the file. */
|
||||
fclose (js_file);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
```
|
||||
|
||||
We can now load JavaScript files:
|
||||
```c
|
||||
static const jerryx_module_resolver_t resolvers[] =
|
||||
{
|
||||
/* Consult the JerryScript module resolver first, in case the requested module is a compiled-in JerryScript module. */
|
||||
jerryx_module_native_resolver,
|
||||
|
||||
/*
|
||||
* If the requested module is not a JerryScript module, assume it is a JavaScript file on disk and use the above-
|
||||
* defined JavaScript file loader to load it.
|
||||
*/
|
||||
load_and_evaluate_js_file
|
||||
};
|
||||
jerry_value_t js_module = jerryx_module_resolve (requested_module, resolvers, 2);
|
||||
```
|
||||
|
||||
# Module helper macros
|
||||
|
||||
## JERRYX_NATIVE_MODULE
|
||||
|
||||
**Summary**
|
||||
|
||||
Helper macro to define a JerryScript module. Currently stores the name of the module and its initializer in an
|
||||
executable linker section. This macro is available only if the preprocessor directive `JERRYX_NATIVE_MODULES_SUPPORTED`
|
||||
is defined.
|
||||
|
||||
**Note**: The helper macro must appear at the bottom of a source file, and no semicolon must follow it.
|
||||
|
||||
**Prototype**
|
||||
```c
|
||||
#define JERRYX_NATIVE_MODULE(module_name, on_resolve_cb)
|
||||
```
|
||||
|
||||
- `module_name` - the name of the module without quotes
|
||||
- `on_resolve_cb` - the function of type `jerryx_native_module_on_resolve_t` that will be called when the module needs to be
|
||||
loaded.
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/module.h"
|
||||
|
||||
static jerry_value_t
|
||||
my_module_on_resolve (void)
|
||||
{
|
||||
return jerry_create_external_function (very_useful_function);
|
||||
} /* my_module_on_resolve */
|
||||
|
||||
/* Note that there is no semicolon at the end of the next line. This is how it must be. */
|
||||
JERRYX_NATIVE_MODULE (my_module, my_module_on_resolve)
|
||||
```
|
||||
Reference in New Issue
Block a user