1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include <string.h>
17425bb815Sopenharmony_ci
18425bb815Sopenharmony_ci#include "jerryscript.h"
19425bb815Sopenharmony_ci#include "test-common.h"
20425bb815Sopenharmony_ci#include "jerryscript-ext/module.h"
21425bb815Sopenharmony_ci
22425bb815Sopenharmony_ci/* Load a module. */
23425bb815Sopenharmony_ciconst char eval_string1[] = "require ('my_custom_module');";
24425bb815Sopenharmony_ci
25425bb815Sopenharmony_ci/* Load a module using a different resolver. */
26425bb815Sopenharmony_ciconst char eval_string2[] = "require ('differently-handled-module');";
27425bb815Sopenharmony_ci
28425bb815Sopenharmony_ci/* Load a broken module using the built-in resolver. */
29425bb815Sopenharmony_ciconst char eval_string3[] =
30425bb815Sopenharmony_ci"(function() {"
31425bb815Sopenharmony_ci"  var theError;"
32425bb815Sopenharmony_ci"  try {"
33425bb815Sopenharmony_ci"    require ('my_broken_module');"
34425bb815Sopenharmony_ci"  } catch (anError) {"
35425bb815Sopenharmony_ci"    theError = anError;"
36425bb815Sopenharmony_ci"  }"
37425bb815Sopenharmony_ci"  return (((theError.message === 'Module on_resolve () must not be NULL') &&"
38425bb815Sopenharmony_ci"    (theError.moduleName === 'my_broken_module') &&"
39425bb815Sopenharmony_ci"    (theError instanceof TypeError)) ? 1 : 0);"
40425bb815Sopenharmony_ci"}) ();";
41425bb815Sopenharmony_ci
42425bb815Sopenharmony_ci/* Load a non-existent module. */
43425bb815Sopenharmony_ciconst char eval_string4[] =
44425bb815Sopenharmony_ci"(function() {"
45425bb815Sopenharmony_ci"  var theError;"
46425bb815Sopenharmony_ci"  try {"
47425bb815Sopenharmony_ci"    require ('some_missing_module_xyzzy');"
48425bb815Sopenharmony_ci"  } catch (anError) {"
49425bb815Sopenharmony_ci"    theError = anError;"
50425bb815Sopenharmony_ci"  }"
51425bb815Sopenharmony_ci"  return (((theError.message === 'Module not found') &&"
52425bb815Sopenharmony_ci"    (theError.moduleName === 'some_missing_module_xyzzy')) ? 1 : 0);"
53425bb815Sopenharmony_ci"}) ();";
54425bb815Sopenharmony_ci
55425bb815Sopenharmony_ci/* Make sure the result of a module load is cached. */
56425bb815Sopenharmony_ciconst char eval_string5[] =
57425bb815Sopenharmony_ci"(function() {"
58425bb815Sopenharmony_ci"  var x = require('cache-check');"
59425bb815Sopenharmony_ci"  var y = require('cache-check');"
60425bb815Sopenharmony_ci"  return x === y ? 1 : 0;"
61425bb815Sopenharmony_ci"}) ();";
62425bb815Sopenharmony_ci
63425bb815Sopenharmony_ci/* Make sure the result of a module load is removed from the cache. */
64425bb815Sopenharmony_ciconst char eval_string6[] =
65425bb815Sopenharmony_ci"(function() {"
66425bb815Sopenharmony_ci"  var x = require('cache-check');"
67425bb815Sopenharmony_ci"  clear_require_cache('cache-check');"
68425bb815Sopenharmony_ci"  var y = require('cache-check');"
69425bb815Sopenharmony_ci"  return x !== y ? 1 : 0;"
70425bb815Sopenharmony_ci"}) ();";
71425bb815Sopenharmony_ci
72425bb815Sopenharmony_ci/* Make sure the entire cache is cleared. */
73425bb815Sopenharmony_ciconst char eval_string7[] =
74425bb815Sopenharmony_ci"(function() {"
75425bb815Sopenharmony_ci"  var x = require('cache-check');"
76425bb815Sopenharmony_ci"  clear_require_cache(undefined);"
77425bb815Sopenharmony_ci"  var y = require('cache-check');"
78425bb815Sopenharmony_ci"  return x !== y ? 1 : 0;"
79425bb815Sopenharmony_ci"}) ();";
80425bb815Sopenharmony_ci
81425bb815Sopenharmony_ci/*
82425bb815Sopenharmony_ci * Define a resolver for a module named "differently-handled-module" to check that custom resolvers work.
83425bb815Sopenharmony_ci */
84425bb815Sopenharmony_cistatic bool
85425bb815Sopenharmony_ciresolve_differently_handled_module (const jerry_value_t name,
86425bb815Sopenharmony_ci                                    jerry_value_t *result)
87425bb815Sopenharmony_ci{
88425bb815Sopenharmony_ci  jerry_size_t name_size = jerry_get_utf8_string_size (name);
89425bb815Sopenharmony_ci  JERRY_VLA (jerry_char_t, name_string, name_size);
90425bb815Sopenharmony_ci  jerry_string_to_utf8_char_buffer (name, name_string, name_size);
91425bb815Sopenharmony_ci
92425bb815Sopenharmony_ci  if (!strncmp ((char *) name_string, "differently-handled-module", name_size))
93425bb815Sopenharmony_ci  {
94425bb815Sopenharmony_ci    (*result) = jerry_create_number (29);
95425bb815Sopenharmony_ci    return true;
96425bb815Sopenharmony_ci  }
97425bb815Sopenharmony_ci  return false;
98425bb815Sopenharmony_ci} /* resolve_differently_handled_module */
99425bb815Sopenharmony_ci
100425bb815Sopenharmony_cistatic jerryx_module_resolver_t differently_handled_module_resolver =
101425bb815Sopenharmony_ci{
102425bb815Sopenharmony_ci  NULL,
103425bb815Sopenharmony_ci  resolve_differently_handled_module
104425bb815Sopenharmony_ci};
105425bb815Sopenharmony_ci
106425bb815Sopenharmony_ci/*
107425bb815Sopenharmony_ci * Define module "cache-check" via its own resolver as an empty object. Since objects are accessible only via references
108425bb815Sopenharmony_ci * we can strictly compare the object returned on subsequent attempts at loading "cache-check" with the object returned
109425bb815Sopenharmony_ci * on the first attempt and establish that the two are in fact the same object - which in turn shows that caching works.
110425bb815Sopenharmony_ci */
111425bb815Sopenharmony_cistatic bool
112425bb815Sopenharmony_cicache_check (const jerry_value_t name,
113425bb815Sopenharmony_ci             jerry_value_t *result)
114425bb815Sopenharmony_ci{
115425bb815Sopenharmony_ci  jerry_size_t name_size = jerry_get_utf8_string_size (name);
116425bb815Sopenharmony_ci  JERRY_VLA (jerry_char_t, name_string, name_size);
117425bb815Sopenharmony_ci  jerry_string_to_utf8_char_buffer (name, name_string, name_size);
118425bb815Sopenharmony_ci
119425bb815Sopenharmony_ci  if (!strncmp ((char *) name_string, "cache-check", name_size))
120425bb815Sopenharmony_ci  {
121425bb815Sopenharmony_ci    (*result) = jerry_create_object ();
122425bb815Sopenharmony_ci    return true;
123425bb815Sopenharmony_ci  }
124425bb815Sopenharmony_ci  return false;
125425bb815Sopenharmony_ci} /* cache_check */
126425bb815Sopenharmony_ci
127425bb815Sopenharmony_cistatic jerryx_module_resolver_t cache_check_resolver =
128425bb815Sopenharmony_ci{
129425bb815Sopenharmony_ci  NULL,
130425bb815Sopenharmony_ci  cache_check
131425bb815Sopenharmony_ci};
132425bb815Sopenharmony_ci
133425bb815Sopenharmony_cistatic const jerryx_module_resolver_t *resolvers[3] =
134425bb815Sopenharmony_ci{
135425bb815Sopenharmony_ci  &jerryx_module_native_resolver,
136425bb815Sopenharmony_ci  &differently_handled_module_resolver,
137425bb815Sopenharmony_ci  &cache_check_resolver
138425bb815Sopenharmony_ci};
139425bb815Sopenharmony_ci
140425bb815Sopenharmony_cistatic jerry_value_t
141425bb815Sopenharmony_cihandle_clear_require_cache (const jerry_value_t js_function,
142425bb815Sopenharmony_ci                            const jerry_value_t this_val,
143425bb815Sopenharmony_ci                            const jerry_value_t args_p[],
144425bb815Sopenharmony_ci                            const jerry_length_t args_count)
145425bb815Sopenharmony_ci{
146425bb815Sopenharmony_ci  (void) js_function;
147425bb815Sopenharmony_ci  (void) this_val;
148425bb815Sopenharmony_ci  (void) args_count;
149425bb815Sopenharmony_ci
150425bb815Sopenharmony_ci  TEST_ASSERT (args_count == 1);
151425bb815Sopenharmony_ci  jerryx_module_clear_cache (args_p[0], resolvers, 3);
152425bb815Sopenharmony_ci
153425bb815Sopenharmony_ci  return 0;
154425bb815Sopenharmony_ci} /* handle_clear_require_cache */
155425bb815Sopenharmony_ci
156425bb815Sopenharmony_cistatic jerry_value_t
157425bb815Sopenharmony_cihandle_require (const jerry_value_t js_function,
158425bb815Sopenharmony_ci                const jerry_value_t this_val,
159425bb815Sopenharmony_ci                const jerry_value_t args_p[],
160425bb815Sopenharmony_ci                const jerry_length_t args_count)
161425bb815Sopenharmony_ci{
162425bb815Sopenharmony_ci  (void) js_function;
163425bb815Sopenharmony_ci  (void) this_val;
164425bb815Sopenharmony_ci  (void) args_count;
165425bb815Sopenharmony_ci
166425bb815Sopenharmony_ci  jerry_value_t return_value = 0;
167425bb815Sopenharmony_ci
168425bb815Sopenharmony_ci  TEST_ASSERT (args_count == 1);
169425bb815Sopenharmony_ci  return_value = jerryx_module_resolve (args_p[0], resolvers, 3);
170425bb815Sopenharmony_ci
171425bb815Sopenharmony_ci  return return_value;
172425bb815Sopenharmony_ci} /* handle_require */
173425bb815Sopenharmony_ci
174425bb815Sopenharmony_cistatic void
175425bb815Sopenharmony_ciassert_number (jerry_value_t js_value, double expected_result)
176425bb815Sopenharmony_ci{
177425bb815Sopenharmony_ci  TEST_ASSERT (!jerry_value_is_error (js_value));
178425bb815Sopenharmony_ci  TEST_ASSERT (jerry_get_number_value (js_value) == expected_result);
179425bb815Sopenharmony_ci} /* assert_number */
180425bb815Sopenharmony_ci
181425bb815Sopenharmony_cistatic void
182425bb815Sopenharmony_cieval_one (const char *the_string, double expected_result)
183425bb815Sopenharmony_ci{
184425bb815Sopenharmony_ci  jerry_value_t js_eval_result = jerry_eval ((const jerry_char_t *) the_string,
185425bb815Sopenharmony_ci                                             strlen (the_string),
186425bb815Sopenharmony_ci                                             JERRY_PARSE_STRICT_MODE);
187425bb815Sopenharmony_ci  assert_number (js_eval_result, expected_result);
188425bb815Sopenharmony_ci  jerry_release_value (js_eval_result);
189425bb815Sopenharmony_ci} /* eval_one */
190425bb815Sopenharmony_ci
191425bb815Sopenharmony_ci#ifndef ENABLE_INIT_FINI
192425bb815Sopenharmony_ciextern void my_broken_module_register (void);
193425bb815Sopenharmony_ciextern void my_custom_module_register (void);
194425bb815Sopenharmony_ci#endif /* !ENABLE_INIT_FINI */
195425bb815Sopenharmony_ci
196425bb815Sopenharmony_ciint
197425bb815Sopenharmony_cimain (int argc, char **argv)
198425bb815Sopenharmony_ci{
199425bb815Sopenharmony_ci  (void) argc;
200425bb815Sopenharmony_ci  (void) argv;
201425bb815Sopenharmony_ci  jerry_value_t js_global = 0, js_function = 0, js_property_name = 0;
202425bb815Sopenharmony_ci  jerry_value_t res;
203425bb815Sopenharmony_ci
204425bb815Sopenharmony_ci#ifndef ENABLE_INIT_FINI
205425bb815Sopenharmony_ci  my_broken_module_register ();
206425bb815Sopenharmony_ci  my_custom_module_register ();
207425bb815Sopenharmony_ci#endif /* !ENABLE_INIT_FINI */
208425bb815Sopenharmony_ci
209425bb815Sopenharmony_ci  jerry_init (JERRY_INIT_EMPTY);
210425bb815Sopenharmony_ci
211425bb815Sopenharmony_ci  js_global = jerry_get_global_object ();
212425bb815Sopenharmony_ci
213425bb815Sopenharmony_ci  js_function = jerry_create_external_function (handle_require);
214425bb815Sopenharmony_ci  js_property_name = jerry_create_string ((const jerry_char_t *) "require");
215425bb815Sopenharmony_ci  res = jerry_set_property (js_global, js_property_name, js_function);
216425bb815Sopenharmony_ci  TEST_ASSERT (!jerry_value_is_error (res));
217425bb815Sopenharmony_ci  TEST_ASSERT (jerry_value_is_boolean (res) && jerry_get_boolean_value (res));
218425bb815Sopenharmony_ci  jerry_release_value (res);
219425bb815Sopenharmony_ci  jerry_release_value (js_property_name);
220425bb815Sopenharmony_ci  jerry_release_value (js_function);
221425bb815Sopenharmony_ci
222425bb815Sopenharmony_ci  js_function = jerry_create_external_function (handle_clear_require_cache);
223425bb815Sopenharmony_ci  js_property_name = jerry_create_string ((const jerry_char_t *) "clear_require_cache");
224425bb815Sopenharmony_ci  res = jerry_set_property (js_global, js_property_name, js_function);
225425bb815Sopenharmony_ci  TEST_ASSERT (!jerry_value_is_error (res));
226425bb815Sopenharmony_ci  TEST_ASSERT (jerry_value_is_boolean (res) && jerry_get_boolean_value (res));
227425bb815Sopenharmony_ci  jerry_release_value (res);
228425bb815Sopenharmony_ci  jerry_release_value (js_property_name);
229425bb815Sopenharmony_ci  jerry_release_value (js_function);
230425bb815Sopenharmony_ci
231425bb815Sopenharmony_ci  jerry_release_value (js_global);
232425bb815Sopenharmony_ci
233425bb815Sopenharmony_ci  eval_one (eval_string1, 42);
234425bb815Sopenharmony_ci  eval_one (eval_string2, 29);
235425bb815Sopenharmony_ci  eval_one (eval_string3, 1);
236425bb815Sopenharmony_ci  eval_one (eval_string4, 1);
237425bb815Sopenharmony_ci  eval_one (eval_string5, 1);
238425bb815Sopenharmony_ci  eval_one (eval_string6, 1);
239425bb815Sopenharmony_ci  eval_one (eval_string7, 1);
240425bb815Sopenharmony_ci
241425bb815Sopenharmony_ci  jerry_cleanup ();
242425bb815Sopenharmony_ci} /* main */
243