• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <string.h>
17 
18 #include "jerryscript.h"
19 #include "test-common.h"
20 #include "jerryscript-ext/module.h"
21 
22 /* Load a module. */
23 const char eval_string1[] = "require ('my_custom_module');";
24 
25 /* Load a module using a different resolver. */
26 const char eval_string2[] = "require ('differently-handled-module');";
27 
28 /* Load a broken module using the built-in resolver. */
29 const char eval_string3[] =
30 "(function() {"
31 "  var theError;"
32 "  try {"
33 "    require ('my_broken_module');"
34 "  } catch (anError) {"
35 "    theError = anError;"
36 "  }"
37 "  return (((theError.message === 'Module on_resolve () must not be NULL') &&"
38 "    (theError.moduleName === 'my_broken_module') &&"
39 "    (theError instanceof TypeError)) ? 1 : 0);"
40 "}) ();";
41 
42 /* Load a non-existent module. */
43 const char eval_string4[] =
44 "(function() {"
45 "  var theError;"
46 "  try {"
47 "    require ('some_missing_module_xyzzy');"
48 "  } catch (anError) {"
49 "    theError = anError;"
50 "  }"
51 "  return (((theError.message === 'Module not found') &&"
52 "    (theError.moduleName === 'some_missing_module_xyzzy')) ? 1 : 0);"
53 "}) ();";
54 
55 /* Make sure the result of a module load is cached. */
56 const char eval_string5[] =
57 "(function() {"
58 "  var x = require('cache-check');"
59 "  var y = require('cache-check');"
60 "  return x === y ? 1 : 0;"
61 "}) ();";
62 
63 /* Make sure the result of a module load is removed from the cache. */
64 const char eval_string6[] =
65 "(function() {"
66 "  var x = require('cache-check');"
67 "  clear_require_cache('cache-check');"
68 "  var y = require('cache-check');"
69 "  return x !== y ? 1 : 0;"
70 "}) ();";
71 
72 /* Make sure the entire cache is cleared. */
73 const char eval_string7[] =
74 "(function() {"
75 "  var x = require('cache-check');"
76 "  clear_require_cache(undefined);"
77 "  var y = require('cache-check');"
78 "  return x !== y ? 1 : 0;"
79 "}) ();";
80 
81 /*
82  * Define a resolver for a module named "differently-handled-module" to check that custom resolvers work.
83  */
84 static bool
resolve_differently_handled_module(const jerry_value_t name,jerry_value_t * result)85 resolve_differently_handled_module (const jerry_value_t name,
86                                     jerry_value_t *result)
87 {
88   jerry_size_t name_size = jerry_get_utf8_string_size (name);
89   JERRY_VLA (jerry_char_t, name_string, name_size);
90   jerry_string_to_utf8_char_buffer (name, name_string, name_size);
91 
92   if (!strncmp ((char *) name_string, "differently-handled-module", name_size))
93   {
94     (*result) = jerry_create_number (29);
95     return true;
96   }
97   return false;
98 } /* resolve_differently_handled_module */
99 
100 static jerryx_module_resolver_t differently_handled_module_resolver =
101 {
102   NULL,
103   resolve_differently_handled_module
104 };
105 
106 /*
107  * Define module "cache-check" via its own resolver as an empty object. Since objects are accessible only via references
108  * we can strictly compare the object returned on subsequent attempts at loading "cache-check" with the object returned
109  * on the first attempt and establish that the two are in fact the same object - which in turn shows that caching works.
110  */
111 static bool
cache_check(const jerry_value_t name,jerry_value_t * result)112 cache_check (const jerry_value_t name,
113              jerry_value_t *result)
114 {
115   jerry_size_t name_size = jerry_get_utf8_string_size (name);
116   JERRY_VLA (jerry_char_t, name_string, name_size);
117   jerry_string_to_utf8_char_buffer (name, name_string, name_size);
118 
119   if (!strncmp ((char *) name_string, "cache-check", name_size))
120   {
121     (*result) = jerry_create_object ();
122     return true;
123   }
124   return false;
125 } /* cache_check */
126 
127 static jerryx_module_resolver_t cache_check_resolver =
128 {
129   NULL,
130   cache_check
131 };
132 
133 static const jerryx_module_resolver_t *resolvers[3] =
134 {
135   &jerryx_module_native_resolver,
136   &differently_handled_module_resolver,
137   &cache_check_resolver
138 };
139 
140 static jerry_value_t
handle_clear_require_cache(const jerry_value_t js_function,const jerry_value_t this_val,const jerry_value_t args_p[],const jerry_length_t args_count)141 handle_clear_require_cache (const jerry_value_t js_function,
142                             const jerry_value_t this_val,
143                             const jerry_value_t args_p[],
144                             const jerry_length_t args_count)
145 {
146   (void) js_function;
147   (void) this_val;
148   (void) args_count;
149 
150   TEST_ASSERT (args_count == 1);
151   jerryx_module_clear_cache (args_p[0], resolvers, 3);
152 
153   return 0;
154 } /* handle_clear_require_cache */
155 
156 static jerry_value_t
handle_require(const jerry_value_t js_function,const jerry_value_t this_val,const jerry_value_t args_p[],const jerry_length_t args_count)157 handle_require (const jerry_value_t js_function,
158                 const jerry_value_t this_val,
159                 const jerry_value_t args_p[],
160                 const jerry_length_t args_count)
161 {
162   (void) js_function;
163   (void) this_val;
164   (void) args_count;
165 
166   jerry_value_t return_value = 0;
167 
168   TEST_ASSERT (args_count == 1);
169   return_value = jerryx_module_resolve (args_p[0], resolvers, 3);
170 
171   return return_value;
172 } /* handle_require */
173 
174 static void
assert_number(jerry_value_t js_value,double expected_result)175 assert_number (jerry_value_t js_value, double expected_result)
176 {
177   TEST_ASSERT (!jerry_value_is_error (js_value));
178   TEST_ASSERT (jerry_get_number_value (js_value) == expected_result);
179 } /* assert_number */
180 
181 static void
eval_one(const char * the_string,double expected_result)182 eval_one (const char *the_string, double expected_result)
183 {
184   jerry_value_t js_eval_result = jerry_eval ((const jerry_char_t *) the_string,
185                                              strlen (the_string),
186                                              JERRY_PARSE_STRICT_MODE);
187   assert_number (js_eval_result, expected_result);
188   jerry_release_value (js_eval_result);
189 } /* eval_one */
190 
191 #ifndef ENABLE_INIT_FINI
192 extern void my_broken_module_register (void);
193 extern void my_custom_module_register (void);
194 #endif /* !ENABLE_INIT_FINI */
195 
196 int
main(int argc,char ** argv)197 main (int argc, char **argv)
198 {
199   (void) argc;
200   (void) argv;
201   jerry_value_t js_global = 0, js_function = 0, js_property_name = 0;
202   jerry_value_t res;
203 
204 #ifndef ENABLE_INIT_FINI
205   my_broken_module_register ();
206   my_custom_module_register ();
207 #endif /* !ENABLE_INIT_FINI */
208 
209   jerry_init (JERRY_INIT_EMPTY);
210 
211   js_global = jerry_get_global_object ();
212 
213   js_function = jerry_create_external_function (handle_require);
214   js_property_name = jerry_create_string ((const jerry_char_t *) "require");
215   res = jerry_set_property (js_global, js_property_name, js_function);
216   TEST_ASSERT (!jerry_value_is_error (res));
217   TEST_ASSERT (jerry_value_is_boolean (res) && jerry_get_boolean_value (res));
218   jerry_release_value (res);
219   jerry_release_value (js_property_name);
220   jerry_release_value (js_function);
221 
222   js_function = jerry_create_external_function (handle_clear_require_cache);
223   js_property_name = jerry_create_string ((const jerry_char_t *) "clear_require_cache");
224   res = jerry_set_property (js_global, js_property_name, js_function);
225   TEST_ASSERT (!jerry_value_is_error (res));
226   TEST_ASSERT (jerry_value_is_boolean (res) && jerry_get_boolean_value (res));
227   jerry_release_value (res);
228   jerry_release_value (js_property_name);
229   jerry_release_value (js_function);
230 
231   jerry_release_value (js_global);
232 
233   eval_one (eval_string1, 42);
234   eval_one (eval_string2, 29);
235   eval_one (eval_string3, 1);
236   eval_one (eval_string4, 1);
237   eval_one (eval_string5, 1);
238   eval_one (eval_string6, 1);
239   eval_one (eval_string7, 1);
240 
241   jerry_cleanup ();
242 } /* main */
243