| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- /*
- * This file is part of Espruino, a JavaScript interpreter for Microcontrollers
- *
- * Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * ----------------------------------------------------------------------------
- * This file is designed to be parsed during the build process
- *
- * JavaScript Functions for handling Modules
- * ----------------------------------------------------------------------------
- */
- #include "jswrap_functions.h"
- #include "jslex.h"
- #include "jsvar.h"
- #include "jsparse.h"
- #include "jsinteractive.h"
- #include "jswrapper.h"
- #ifdef USE_FILESYSTEM
- #include "../libs/jswrap_fat.h"
- #endif
- static JsVar *jswrap_modules_getModuleList() {
- JsVar *moduleListName = jsvFindChildFromString(jsiGetParser()->root, JSPARSE_MODULE_CACHE_NAME, true);
- if (!moduleListName) return 0; // out of memory
- JsVar *moduleList = jsvSkipName(moduleListName);
- if (!moduleList) {
- moduleList = jsvNewWithFlags(JSV_OBJECT);
- if (!moduleList) { jsvUnLock(moduleListName); return 0; } // out of memory
- jsvSetValueOfName(moduleListName, moduleList); // no need to unlock
- }
- jsvUnLock(moduleListName);
- return moduleList;
- }
- /*JSON{ "type":"function", "name" : "require",
- "description" : "Load the given module, and return the exported functions",
- "generate" : "jswrap_require",
- "params" : [ [ "moduleName", "JsVar", "A String containing the name of the given module"] ],
- "return" : ["JsVar", "The result of evaluating the string"]
- }*/
- JsVar *jswrap_require(JsVar *moduleName) {
- if (!jsvIsString(moduleName)) {
- jsWarn("Expecting a module name as a string, but got %t", moduleName);
- return 0;
- }
- // Search to see if we have already loaded this module
- JsVar *moduleList = jswrap_modules_getModuleList();
- if (!moduleList) return 0; // out of memory
- JsVar *moduleExportName = jsvFindChildFromVar(moduleList, moduleName, true);
- jsvUnLock(moduleList);
- if (!moduleExportName) return 0; // out of memory
- JsVar *moduleExport = jsvSkipName(moduleExportName);
- if (moduleExport) {
- // Found the module!
- jsvUnLock(moduleExportName);
- return moduleExport;
- }
- // Now check if it is built-in
- char moduleNameBuf[32];
- jsvGetString(moduleName, moduleNameBuf, sizeof(moduleNameBuf));
- if (jswIsBuiltInLibrary(moduleNameBuf)) {
- // create a 'fake' module that Espruino can use to map its built-in functions against
- moduleExport = jspNewBuiltin(moduleNameBuf);
- } else {
- // Now try and load it
- JsVar *fileContents = 0;
- //if (jsvIsStringEqual(moduleName,"http")) {}
- //if (jsvIsStringEqual(moduleName,"fs")) {}
- #ifdef USE_FILESYSTEM
- JsVar *modulePath = jsvNewFromString(
- #ifdef LINUX
- "node_modules/"
- #else
- "NODE_M~1/"
- #endif
- );
- if (!modulePath) { jsvUnLock(moduleExportName); return 0; } // out of memory
- jsvAppendStringVarComplete(modulePath, moduleName);
- jsvAppendString(modulePath,".js");
- fileContents = wrap_fat_readFile(modulePath);
- jsvUnLock(modulePath);
- #endif
- if (!fileContents || jsvIsStringEqual(fileContents,"")) {
- jsvUnLock(moduleExportName);
- jsvUnLock(fileContents);
- jsWarn("Module not found");
- return 0;
- }
- moduleExport = jspEvaluateModule(jsiGetParser(), fileContents);
- jsvUnLock(fileContents);
- }
- assert(moduleExport);
- jsvSetValueOfName(moduleExportName, moduleExport); // save in cache
- jsvUnLock(moduleExportName);
- return moduleExport;
- }
- /*JSON{ "type":"staticmethod",
- "class" : "Modules", "name" : "getCached",
- "description" : "Return an array of module names that have been cached",
- "generate" : "jswrap_modules_getCached",
- "return" : ["JsVar", "An array of module names"]
- }*/
- JsVar *jswrap_modules_getCached() {
- JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
- if (!arr) return 0; // out of memory
- JsVar *moduleList = jswrap_modules_getModuleList();
- if (!moduleList) return arr; // out of memory
- JsObjectIterator it;
- jsvObjectIteratorNew(&it, moduleList);
- while (jsvObjectIteratorHasElement(&it)) {
- JsVar *idx = jsvObjectIteratorGetKey(&it);
- JsVar *idxCopy = jsvCopyNameOnly(idx, false, false);
- jsvArrayPushAndUnLock(arr, idxCopy);
- jsvUnLock(idx);
- jsvObjectIteratorNext(&it);
- }
- jsvObjectIteratorFree(&it);
- jsvUnLock(moduleList);
- return arr;
- }
- /*JSON{ "type":"staticmethod",
- "class" : "Modules", "name" : "removeCached",
- "description" : "Remove the given module from the list of cached modules",
- "generate" : "jswrap_modules_removeCached",
- "params" : [ [ "id", "JsVar", "The module name to remove"] ]
- }*/
- void jswrap_modules_removeCached(JsVar *id) {
- if (!jsvIsString(id)) {
- jsError("The argument to removeCached must be a string");
- return;
- }
- JsVar *moduleList = jswrap_modules_getModuleList();
- if (!moduleList) return; // out of memory
- JsVar *moduleExportName = jsvFindChildFromVar(moduleList, id, false);
- if (!moduleExportName) {
- jsWarn("Module not found");
- } else {
- jsvRemoveChild(moduleList, moduleExportName);
- jsvUnLock(moduleExportName);
- }
- jsvUnLock(moduleList);
- }
- /*JSON{ "type":"staticmethod",
- "class" : "Modules", "name" : "removeAllCached",
- "description" : "Remove all cached modules",
- "generate" : "jswrap_modules_removeAllCached"
- }*/
- void jswrap_modules_removeAllCached() {
- JsVar *moduleList = jswrap_modules_getModuleList();
- if (!moduleList) return; // out of memory
- jsvRemoveAllChildren(moduleList);
- jsvUnLock(moduleList);
- }
- /*JSON{ "type":"staticmethod",
- "class" : "Modules", "name" : "addCached",
- "description" : "Add the given module to the cache",
- "generate" : "jswrap_modules_addCached",
- "params" : [ [ "id", "JsVar", "The module name to add" ],
- [ "sourcecode", "JsVar", "The module's sourcecode" ] ]
- }*/
- void jswrap_modules_addCached(JsVar *id, JsVar *sourceCode) {
- if (!jsvIsString(id) || !jsvIsString(sourceCode)) {
- jsError("Both arguments to addCached must be strings");
- return;
- }
- JsVar *moduleList = jswrap_modules_getModuleList();
- if (!moduleList) return; // out of memory
- JsVar *moduleExport = jspEvaluateModule(jsiGetParser(), sourceCode);
- if (!moduleExport) {
- jsWarn("Unable to load module");
- } else {
- JsVar *moduleName = jsvFindChildFromVar(moduleList, id, true);
- if (moduleName) jsvSetValueOfName(moduleName, moduleExport);
- jsvUnLock(moduleExport);
- }
- jsvUnLock(moduleList);
- }
|