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:
Gabriel "_|Nix|_" Schulhof
2017-09-22 13:35:38 +03:00
committed by Zoltan Herczeg
parent 8d916a44f1
commit 81952f3cd0
11 changed files with 172 additions and 124 deletions
+58 -21
View File
@@ -18,13 +18,6 @@
#include "jerryscript.h"
#ifdef __GNUC__
#define JERRYX_NATIVE_MODULES_SUPPORTED
#endif /* __GNUC__ */
#ifdef JERRYX_NATIVE_MODULES_SUPPORTED
#include "jerryscript-ext/section.impl.h"
/**
* Declare the signature for the module initialization function.
*/
@@ -34,23 +27,69 @@ typedef jerry_value_t (*jerryx_native_module_on_resolve_t) (void);
* Declare the structure used to define a module. One should only make use of this structure via the
* JERRYX_NATIVE_MODULE macro declared below.
*/
typedef struct
typedef struct jerryx_native_module_t
{
jerry_char_t *name; /**< name of the module */
jerryx_native_module_on_resolve_t on_resolve; /**< function that returns a new instance of the module */
const jerry_char_t *name_p; /**< name of the module */
const jerryx_native_module_on_resolve_t on_resolve; /**< function that returns a new instance of the module */
struct jerryx_native_module_t *next_p; /**< pointer to next module in the list */
} jerryx_native_module_t;
/**
* Declare a helper macro that expands to the declaration of a variable of type jerryx_native_module_t placed into the
* specially-named linker section "jerryx_modules" where the JerryScript module resolver
* jerryx_module_native_resolver () will look for it.
* Declare the constructor and destructor attributes. These evaluate to nothing if this extension is built without
* library constructor/destructor support.
*/
#define JERRYX_NATIVE_MODULE(module_name, on_resolve_cb) \
static const jerryx_native_module_t _module JERRYX_SECTION_ATTRIBUTE(jerryx_modules) = \
{ \
.name = ((jerry_char_t *) #module_name), \
.on_resolve = (on_resolve_cb) \
};
#ifdef ENABLE_INIT_FINI
#define JERRYX_MODULE_CONSTRUCTOR_ATTRIBUTE __attribute__((constructor))
#define JERRYX_MODULE_DESTRUCTOR_ATTRIBUTE __attribute__((destructor))
#define JERRYX_MODULE_REGISTRATION_QUALIFIER static
#else /* !ENABLE_INIT_FINI */
#define JERRYX_MODULE_CONSTRUCTOR_ATTRIBUTE
#define JERRYX_MODULE_DESTRUCTOR_ATTRIBUTE
#define JERRYX_MODULE_REGISTRATION_QUALIFIER
#endif /* ENABLE_INIT_FINI */
/**
* Having two levels of macros allows strings to be used unquoted.
*/
#define JERRYX_NATIVE_MODULE(module_name, on_resolve_cb) \
JERRYX_NATIVE_MODULE_IMPLEM(module_name, on_resolve_cb)
#define JERRYX_NATIVE_MODULE_IMPLEM(module_name, on_resolve_cb) \
static jerryx_native_module_t _ ## module_name ## _definition = \
{ \
.name_p = (jerry_char_t *) #module_name, \
.on_resolve = (on_resolve_cb), \
.next_p = NULL \
}; \
\
JERRYX_MODULE_REGISTRATION_QUALIFIER void \
module_name ## _register (void) JERRYX_MODULE_CONSTRUCTOR_ATTRIBUTE; \
JERRYX_MODULE_REGISTRATION_QUALIFIER void \
module_name ## _register (void) \
{ \
jerryx_native_module_register(&_##module_name##_definition); \
} \
\
JERRYX_MODULE_REGISTRATION_QUALIFIER void \
module_name ## _unregister (void) \
JERRYX_MODULE_DESTRUCTOR_ATTRIBUTE; \
JERRYX_MODULE_REGISTRATION_QUALIFIER void \
module_name ## _unregister (void) \
{ \
jerryx_native_module_unregister(&_##module_name##_definition); \
}
/**
* Register a native module. This makes it available for loading via jerryx_module_resolve, when
* jerryx_module_native_resolver is passed in as a possible resolver.
*/
void jerryx_native_module_register (jerryx_native_module_t *module_p);
/**
* Unregister a native module. This removes the module from the list of available native modules, meaning that
* subsequent calls to jerryx_module_resolve with jerryx_module_native_resolver will not be able to find it.
*/
void jerryx_native_module_unregister (jerryx_native_module_t *module_p);
/**
* Declare the JerryScript module resolver so that it may be added to an array of jerryx_module_resolver_t items and
@@ -58,8 +97,6 @@ typedef struct
*/
bool jerryx_module_native_resolver (const jerry_char_t *name, jerry_value_t *result);
#endif /* JERRYX_NATIVE_MODULES_SUPPORTED */
/**
* Declare the function pointer type for module resolvers.
*/