module: Re-implement using library constructors/destructors (#2018)
By using constructors/destructors we unify the case of static linking with that of dynamic linking, and we reuse the build flag FEATURE_INIT_FINI. Using constructors/destructors also allows us to cover the case where library constructor/destructor functionality is unavailable, because we can expose the module registration/unregistration functions as global symbols, to be called explicitly from within the application. Fixes https://github.com/jerryscript-project/jerryscript/issues/1952 JerryScript-DCO-1.0-Signed-off-by: Gabriel Schulhof gabriel.schulhof@intel.com
This commit is contained in:
committed by
Zoltan Herczeg
parent
8d916a44f1
commit
81952f3cd0
@@ -13,14 +13,10 @@ 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()`. Native modules are registered during application startup and by calling `dlopen()` by means
|
||||
of library constructors, support for which can be turned on using the `FEATURE_INIT_FINI` build flag. In the absence of
|
||||
such a flag, the module registration and unregistration functions are exposed as global symbols which can be called
|
||||
explicitly.
|
||||
|
||||
## jerryx_module_resolve
|
||||
|
||||
@@ -52,9 +48,8 @@ jerryx_module_resolve (const jerry_char_t *name,
|
||||
|
||||
**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.
|
||||
The resolver for native 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 native JerryScript modules loaded so far.
|
||||
|
||||
**Prototype**
|
||||
|
||||
@@ -74,8 +69,7 @@ jerryx_module_native_resolver (const jerry_char_t *name,
|
||||
|
||||
**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.
|
||||
Function pointer type for a function that will create an instance of a native module.
|
||||
|
||||
**Prototype**
|
||||
|
||||
@@ -136,12 +130,15 @@ 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. */
|
||||
/*
|
||||
* Consult the JerryScript native module resolver first, in case the requested module is a native 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.
|
||||
* If the requested module is not a native 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
|
||||
};
|
||||
@@ -154,9 +151,11 @@ jerry_value_t js_module = jerryx_module_resolve (requested_module, resolvers, 2)
|
||||
|
||||
**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.
|
||||
Helper macro to define a native JerryScript module. Currently declares a global static structure of type
|
||||
`jerryx_native_module_t` and a constructor/destructor pair that calls `jerryx_native_module_register()` resp.
|
||||
`jerryx_native_module_unregister()`. If the extension is built without the FEATURE_INIT_FINI flag, indicating that
|
||||
support for library constructors and destructors is absent, the constructor and destructor are declared as global
|
||||
symbols so that they may be called explicitly from within the application.
|
||||
|
||||
**Note**: The helper macro must appear at the bottom of a source file, and no semicolon must follow it.
|
||||
|
||||
@@ -165,7 +164,8 @@ is defined.
|
||||
#define JERRYX_NATIVE_MODULE(module_name, on_resolve_cb)
|
||||
```
|
||||
|
||||
- `module_name` - the name of the module without quotes
|
||||
- `module_name` - the name of the module without quotes. This value is used as the prefix for the registration and unregistration funtions. For example, when `module_name` is `example_module`, this results in the declaration of two functions `example_module_register()` and `example_module_unregister()`. These functions are declared global if support for library constructors/destructors is absent, allowing you to call them from other parts of the code by
|
||||
first forward-declaring them.
|
||||
- `on_resolve_cb` - the function of type `jerryx_native_module_on_resolve_t` that will be called when the module needs to be
|
||||
loaded.
|
||||
|
||||
@@ -184,3 +184,38 @@ my_module_on_resolve (void)
|
||||
/* 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)
|
||||
```
|
||||
|
||||
**Example Usage When Library Constructors Are Unavailable**
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/module.h"
|
||||
|
||||
/**
|
||||
* Forward-declare the module registration and unregistration function.
|
||||
*/
|
||||
extern void my_module_register (void);
|
||||
extern void my_module_unregister (void);
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerryx_module_resolver_t resolvers[] =
|
||||
{
|
||||
jerryx_native_module_resolver
|
||||
};
|
||||
|
||||
/* This plays the role of the library constructor. */
|
||||
my_module_register ();
|
||||
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
...
|
||||
jerry_value_t my_module = jerryx_module_resolve ("my_module", resolvers, 1);
|
||||
...
|
||||
jerry_cleanup ();
|
||||
|
||||
/* This plays the role of the library destructor */
|
||||
my_module_unregister();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user