1/* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef JERRYX_MODULE_H
17#define JERRYX_MODULE_H
18
19#include "jerryscript.h"
20
21#ifdef __cplusplus
22extern "C"
23{
24#endif /* __cplusplus */
25
26/**
27 * Declare the signature for the module initialization function.
28 */
29typedef jerry_value_t (*jerryx_native_module_on_resolve_t) (void);
30
31/**
32 * Declare the structure used to define a module. One should only make use of this structure via the
33 * JERRYX_NATIVE_MODULE macro declared below.
34 */
35typedef struct jerryx_native_module_t
36{
37  const jerry_char_t *name_p; /**< name of the module */
38  const jerryx_native_module_on_resolve_t on_resolve_p; /**< function that returns a new instance of the module */
39  struct jerryx_native_module_t *next_p; /**< pointer to next module in the list */
40} jerryx_native_module_t;
41
42/**
43 * Declare the constructor and destructor attributes. These evaluate to nothing if this extension is built without
44 * library constructor/destructor support.
45 */
46#ifdef ENABLE_INIT_FINI
47#ifdef _MSC_VER
48#error "`FEATURE_INIT_FINI` build flag isn't supported on Windows, because Microsoft Visual C/C++ Compiler \
49doesn't support library constructors and destructors."
50#endif
51#define JERRYX_MODULE_CONSTRUCTOR_ATTRIBUTE __attribute__((constructor))
52#define JERRYX_MODULE_DESTRUCTOR_ATTRIBUTE __attribute__((destructor))
53#define JERRYX_MODULE_REGISTRATION_QUALIFIER static
54#else /* !ENABLE_INIT_FINI */
55#define JERRYX_MODULE_CONSTRUCTOR_ATTRIBUTE
56#define JERRYX_MODULE_DESTRUCTOR_ATTRIBUTE
57#define JERRYX_MODULE_REGISTRATION_QUALIFIER
58#endif /* ENABLE_INIT_FINI */
59
60/**
61 * Having two levels of macros allows strings to be used unquoted.
62 */
63#define JERRYX_NATIVE_MODULE(module_name, on_resolve_cb)  \
64  JERRYX_NATIVE_MODULE_IMPLEM(module_name, on_resolve_cb)
65
66#define JERRYX_NATIVE_MODULE_IMPLEM(module_name, on_resolve_cb)        \
67  static jerryx_native_module_t _ ## module_name ## _definition =      \
68  {                                                                    \
69    .name_p = (jerry_char_t *) #module_name,                           \
70    .on_resolve_p = (on_resolve_cb),                                   \
71    .next_p = NULL                                                     \
72  };                                                                   \
73                                                                       \
74  JERRYX_MODULE_REGISTRATION_QUALIFIER void                            \
75  module_name ## _register (void) JERRYX_MODULE_CONSTRUCTOR_ATTRIBUTE; \
76  JERRYX_MODULE_REGISTRATION_QUALIFIER void                            \
77  module_name ## _register (void)                                      \
78  {                                                                    \
79    jerryx_native_module_register(&_##module_name##_definition);       \
80  }                                                                    \
81                                                                       \
82  JERRYX_MODULE_REGISTRATION_QUALIFIER void                            \
83  module_name ## _unregister (void)                                    \
84  JERRYX_MODULE_DESTRUCTOR_ATTRIBUTE;                                  \
85  JERRYX_MODULE_REGISTRATION_QUALIFIER void                            \
86  module_name ## _unregister (void)                                    \
87  {                                                                    \
88    jerryx_native_module_unregister(&_##module_name##_definition);     \
89  }
90
91/**
92 * Register a native module. This makes it available for loading via jerryx_module_resolve, when
93 * jerryx_module_native_resolver is passed in as a possible resolver.
94 */
95void jerryx_native_module_register (jerryx_native_module_t *module_p);
96
97/**
98 * Unregister a native module. This removes the module from the list of available native modules, meaning that
99 * subsequent calls to jerryx_module_resolve with jerryx_module_native_resolver will not be able to find it.
100 */
101void jerryx_native_module_unregister (jerryx_native_module_t *module_p);
102
103/**
104 * Declare the function pointer type for canonical name resolution.
105 */
106typedef jerry_value_t (*jerryx_module_get_canonical_name_t) (const jerry_value_t name); /**< The name for which to
107                                                                                         *   compute the canonical
108                                                                                         *   name */
109
110/**
111 * Declare the function pointer type for module resolution.
112 */
113typedef bool (*jerryx_module_resolve_t) (const jerry_value_t canonical_name, /**< The module's canonical name */
114                                         jerry_value_t *result); /**< The resulting module, if the function returns
115                                                                  *   true */
116
117/**
118 * Declare the structure for module resolvers.
119 */
120typedef struct
121{
122  jerryx_module_get_canonical_name_t get_canonical_name_p; /**< function pointer to establish the canonical name of a
123                                                            *   module */
124  jerryx_module_resolve_t resolve_p; /**< function pointer to resolve a module */
125} jerryx_module_resolver_t;
126
127/**
128 * Declare the JerryScript module resolver so that it may be added to an array of jerryx_module_resolver_t items and
129 * thus passed to jerryx_module_resolve.
130 */
131extern jerryx_module_resolver_t jerryx_module_native_resolver;
132
133/**
134 * Load a copy of a module into the current context using the provided module resolvers, or return one that was already
135 * loaded if it is found.
136 */
137jerry_value_t jerryx_module_resolve (const jerry_value_t name,
138                                     const jerryx_module_resolver_t **resolvers,
139                                     size_t count);
140
141/**
142 * Delete a module from the cache or, if name has the JavaScript value of undefined, clear the entire cache.
143 */
144void jerryx_module_clear_cache (const jerry_value_t name,
145                                const jerryx_module_resolver_t **resolvers,
146                                size_t count);
147
148#ifdef __cplusplus
149}
150#endif /* __cplusplus */
151#endif /* !JERRYX_MODULE_H */
152