| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <rtthread.h>
- #include <finsh.h>
- #include "jerry_util.h"
- #include "jerry_module.h"
- #include <jerryscript-ext/module.h>
- #include <ecma-globals.h>
- #ifdef RT_USING_MODULE
- #include <dlfcn.h>
- #endif
- #ifndef PATH_MAX
- #define PATH_MAX 256
- #endif
- char *getcwd(char *buf, size_t size);
- typedef jerry_value_t (*module_init_func_t)(void);
- #ifdef RT_USING_DFS
- char *js_module_dirname(char *path)
- {
- size_t i;
- char *s = NULL;
- if (!path || !*path) return NULL;
- s = rt_strdup(path);
- if (!s) return NULL;
- i = strlen(s)-1;
- for (; s[i]=='/'; i--) if (!i)
- {
- s[0] = '/';
- goto __exit;
- }
- for (; s[i]!='/'; i--) if (!i)
- {
- s[0] = '.';
- goto __exit;
- }
- for (; s[i]=='/'; i--) if (!i)
- {
- s[0] = '/';
- goto __exit;
- }
- __exit:
- s[i+1] = 0;
- return s;
- }
- char *js_module_normalize_path(const char *directory, const char *filename)
- {
- char *fullpath;
- char *dst0, *dst, *src;
- char *cwd = NULL;
- /* check parameters */
- if (filename == NULL) return NULL;
- if (directory == NULL && filename[0] != '/')
- {
- cwd = (char*) malloc (PATH_MAX);
- if (cwd == NULL) return NULL;
- /* get current working directory */
- getcwd(cwd, PATH_MAX);
- directory = cwd;
- }
- if (filename[0] != '/') /* it's a absolute path, use it directly */
- {
- fullpath = malloc(strlen(directory) + strlen(filename) + 2);
- if (fullpath == NULL)
- {
- free(cwd);
- return NULL;
- }
- /* join path and file name */
- snprintf(fullpath, strlen(directory) + strlen(filename) + 2,
- "%s/%s", directory, filename);
- }
- else
- {
- fullpath = rt_strdup(filename); /* copy string */
- if (fullpath == NULL)
- return NULL;
- }
- src = fullpath;
- dst = fullpath;
- dst0 = dst;
- while (1)
- {
- char c = *src;
- if (c == '.')
- {
- if (!src[1]) src ++; /* '.' and ends */
- else if (src[1] == '/')
- {
- /* './' case */
- src += 2;
- while ((*src == '/') && (*src != '\0'))
- src ++;
- continue;
- }
- else if (src[1] == '.')
- {
- if (!src[2])
- {
- /* '..' and ends case */
- src += 2;
- goto up_one;
- }
- else if (src[2] == '/')
- {
- /* '../' case */
- src += 3;
- while ((*src == '/') && (*src != '\0'))
- src ++;
- goto up_one;
- }
- }
- }
- /* copy up the next '/' and erase all '/' */
- while ((c = *src++) != '\0' && c != '/')
- *dst ++ = c;
- if (c == '/')
- {
- *dst ++ = '/';
- while (c == '/')
- c = *src++;
- src --;
- }
- else if (!c)
- break;
- continue;
- up_one:
- dst --;
- if (dst < dst0)
- {
- free(cwd);
- free(fullpath);
- return NULL;
- }
- while (dst0 < dst && dst[-1] != '/')
- dst --;
- }
- *dst = '\0';
- /* remove '/' in the end of path if exist */
- dst --;
- if ((dst != fullpath) && (*dst == '/'))
- *dst = '\0';
- /* final check fullpath is not empty, for the special path of lwext "/.." */
- if ('\0' == fullpath[0])
- {
- fullpath[0] = '/';
- fullpath[1] = '\0';
- }
- free(cwd);
- return fullpath;
- }
- /* load module from file system */
- static bool load_module_from_filesystem(const jerry_value_t module_name, jerry_value_t *result)
- {
- bool ret = false;
- char *str = NULL;
- char *module = js_value_to_string(module_name);
- char *dirname = NULL;
- jerry_value_t dirname_value = ECMA_VALUE_UNDEFINED;
- jerry_value_t filename_value = ECMA_VALUE_UNDEFINED;
- jerry_value_t global_obj = ECMA_VALUE_UNDEFINED;
- char *full_path = NULL;
- char *full_dir = NULL;
- global_obj = jerry_get_global_object();
- dirname_value = js_get_property(global_obj, "__dirname");
- if (jerry_value_is_string(dirname_value))
- {
- dirname = js_value_to_string(dirname_value);
- }
- else
- {
- dirname = NULL;
- }
- if (module[0] != '/') /* is a relative path */
- {
- full_path = js_module_normalize_path(dirname, module);
- }
- else
- {
- full_path = js_module_normalize_path(NULL, module);
- }
- free(dirname);
- uint32_t len = js_read_file(full_path, &str);
- if (len == 0) goto __exit;
- filename_value = js_get_property(global_obj, "__filename");
- /* set new __filename and __dirname */
- full_dir = js_module_dirname(full_path);
- js_set_string_property(global_obj, "__dirname", full_dir);
- js_set_string_property(global_obj, "__filename", full_path);
- (*result) = jerry_eval((jerry_char_t *)str, len, false);
- if (jerry_value_is_error(*result))
- printf("failed to evaluate JS\n");
- else
- ret = true;
- /* restore __filename and __dirname */
- js_set_property(global_obj, "__dirname", dirname_value);
- js_set_property(global_obj, "__filename", filename_value);
- __exit:
- if (full_dir) free(full_dir);
- if (full_path) free(full_path);
- jerry_release_value(global_obj);
- jerry_release_value(dirname_value);
- jerry_release_value(filename_value);
- free(module);
- free(str);
- return ret;
- }
- #endif
- /* load builtin module */
- static bool load_module_from_builtin(const jerry_value_t module_name,
- jerry_value_t *result)
- {
- bool ret = false;
- module_init_func_t module_init;
- char *module = js_value_to_string(module_name);
- #ifdef HOST_BUILD
- {
- extern jerry_value_t js_module_rtthread_init(void);
- if (strcmp(module, "os") == 0)
- {
- module_init = js_module_rtthread_init;
- *result = module_init();
- ret = true;
- }
- }
- #elif defined(RT_USING_FINSH)
- int len = strlen(module) + 7;
- char module_fullname[len];
- snprintf(module_fullname, len, "__jsm_%s", module);
- module_fullname[len - 1] = '\0';
- /* find syscall in shell symbol section */
- struct finsh_syscall* syscall;
- for (syscall = _syscall_table_begin; syscall < _syscall_table_end; FINSH_NEXT_SYSCALL(syscall))
- {
- if (strcmp(syscall->name, module_fullname) == 0)
- break;
- }
- if (syscall < _syscall_table_end)
- {
- module_init = (module_init_func_t)syscall->func;
- *result = module_init();
- ret = true;
- }
- #endif
- free(module);
- return ret;
- }
- #ifdef RT_USING_DFS
- static jerryx_module_resolver_t load_filesystem_resolver =
- {
- NULL,
- load_module_from_filesystem
- };
- #endif
- static jerryx_module_resolver_t load_builtin_resolver =
- {
- NULL,
- load_module_from_builtin
- };
- static const jerryx_module_resolver_t *resolvers[] =
- {
- &load_builtin_resolver,
- #ifdef RT_USING_DFS
- &load_filesystem_resolver
- #endif
- };
- #ifdef RT_USING_MODULE
- typedef jerry_value_t (*FFI_INIT)(void);
- static void js_module_info_free(void *native)
- {
- dlclose(native);
- }
- static const jerry_object_native_info_t js_module_info =
- {
- .free_cb = js_module_info_free
- };
- #endif
- DECLARE_HANDLER(require)
- {
- jerry_value_t result;
- char *module = NULL;
- if (args_cnt == 0)
- {
- printf("No module name supplied\n");
- return jerry_create_undefined();
- }
- if (jerry_value_is_string(args[0]) == 0)
- {
- printf("No module name supplied as string\n");
- return jerry_create_undefined();
- }
- module = js_value_to_string(args[0]);
- /* Try each of the resolvers to see if we can find the requested module */
- #ifdef RT_USING_MODULE
- if (strstr(module, ".so"))
- {
- void* handle;
- FFI_INIT ffi_init;
- jerry_value_t info;
- do
- {
- handle = dlopen(module, RTLD_LAZY);
- if(!handle)
- {
- printf("dlopen %s failed!\n", module);
- result = jerry_create_undefined();
- break;
- }
- ffi_init = (FFI_INIT)dlsym(handle,"ffi_init");
- if(!ffi_init)
- {
- printf("ffi_init not found!\n");
- result = jerry_create_undefined();
- dlclose(handle);
- break;
- }
- result = ffi_init();
- info = jerry_create_object();
- jerry_set_object_native_pointer(info, handle, &js_module_info);
- js_set_property(result, "info", info);
- jerry_release_value(info);
- }
- while(0);
- }
- else
- #endif
- {
- /* make new module.exports */
- jerry_value_t global_obj = jerry_get_global_object();
- jerry_value_t modules_obj = ECMA_VALUE_UNDEFINED;
- jerry_value_t exports_obj = ECMA_VALUE_UNDEFINED;
- modules_obj = js_get_property(global_obj, "module");
- exports_obj = js_get_property(modules_obj, "exports");
- jerry_value_t module_exports_obj = jerry_create_object();
- js_set_property(modules_obj, "exports", module_exports_obj);
- jerry_release_value(module_exports_obj);
- result = jerryx_module_resolve(args[0], resolvers, sizeof(resolvers)/sizeof(resolvers[0]));
- if (jerry_value_is_error(result))
- {
- printf("Couldn't load module %s\n", module);
- jerry_release_value(result);
- /* create result with error */
- result = jerry_create_error(JERRY_ERROR_TYPE,
- (const jerry_char_t *) "Module not found");
- }
- /* restore the parent module.exports */
- js_set_property(modules_obj, "exports", exports_obj);
- jerry_release_value(global_obj);
- jerry_release_value(modules_obj);
- jerry_release_value(exports_obj);
- }
- free(module);
- return result;
- }
- int js_module_init(void)
- {
- jerry_value_t global_obj = jerry_get_global_object();
- jerry_value_t modules_obj = jerry_create_object();
- jerry_value_t exports_obj = jerry_create_object();
- js_set_property(modules_obj, "exports", exports_obj);
- js_set_property(global_obj, "module", modules_obj);
- REGISTER_HANDLER(require);
- jerry_release_value(global_obj);
- jerry_release_value(modules_obj);
- jerry_release_value(exports_obj);
- return 0;
- }
|