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. */ 23const char eval_string1[] = "require ('my_custom_module');"; 24 25/* Load a module using a different resolver. */ 26const char eval_string2[] = "require ('differently-handled-module');"; 27 28/* Load a broken module using the built-in resolver. */ 29const 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. */ 43const 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. */ 56const 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. */ 64const 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. */ 73const 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 */ 84static bool 85resolve_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 100static 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 */ 111static bool 112cache_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 127static jerryx_module_resolver_t cache_check_resolver = 128{ 129 NULL, 130 cache_check 131}; 132 133static const jerryx_module_resolver_t *resolvers[3] = 134{ 135 &jerryx_module_native_resolver, 136 &differently_handled_module_resolver, 137 &cache_check_resolver 138}; 139 140static jerry_value_t 141handle_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 156static jerry_value_t 157handle_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 174static void 175assert_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 181static void 182eval_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 192extern void my_broken_module_register (void); 193extern void my_custom_module_register (void); 194#endif /* !ENABLE_INIT_FINI */ 195 196int 197main (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