1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
#include "js_shell.h"
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef __GNUC__
#ifdef __APPLE__
#define LIBRARY_EXT ".bundle"
#else
#define LIBRARY_EXT ".so"
#endif
#include <dlfcn.h>
#define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY)
#define CLOSE_LIBRARY(handle) dlclose(handle)
#define LIBRARY_ERROR dlerror
#define LIBRARYFILE(name) std::string("lib").append(name).append(LIBRARY_EXT)
#else
#error "implement dll loading"
#endif
JSShell::~JSShell() {
for(std::vector<HANDLE>::iterator it = loaded_modules.begin();
it != loaded_modules.end(); ++it) {
HANDLE handle = *it;
CLOSE_LIBRARY(handle);
}
}
// TODO: this could be done more intelligent...
// - can we achieve source file relative loading?
// - better path resolution
std::string JSShell::LoadModule(const std::string& name, HANDLE* library) {
// works only for posix like OSs
size_t pathIdx = name.find_last_of("/");
std::string lib_name;
std::string module_name;
if (pathIdx == std::string::npos) {
module_name = name;
lib_name = std::string(name).append(LIBRARY_EXT);
} else {
std::string path = name.substr(0, pathIdx+1);
module_name = name.substr(pathIdx+1);
lib_name = path.append(module_name).append(LIBRARY_EXT);
}
std::string lib_path;
HANDLE handle = 0;
for (int i = 0; i < module_path.size(); ++i) {
lib_path = module_path[i] + "/" + lib_name;
if (access( lib_path.c_str(), F_OK ) != -1) {
handle = LOAD_LIBRARY(lib_path.c_str());
}
}
if(handle == 0) {
std::cerr << "Could not find module " << lib_path << ":"
<< std::endl << LIBRARY_ERROR() << std::endl;
return 0;
}
loaded_modules.push_back(handle);
*library = handle;
return module_name;
}
bool JSShell::RunScript(const std::string& scriptPath) {
std::string source = ReadFile(scriptPath);
if(!InitializeEngine()) return false;
// Node.js compatibility: make `print` available as `console.log()`
ExecuteScript("var console = {}; console.log = print;", "<console>");
if(!ExecuteScript(source, scriptPath)) {
return false;
}
return DisposeEngine();
}
bool JSShell::RunShell() {
if(!InitializeEngine()) return false;
static const int kBufferSize = 1024;
while (true) {
char buffer[kBufferSize];
printf("> ");
char* str = fgets(buffer, kBufferSize, stdin);
if (str == NULL) break;
std::string source(str);
ExecuteScript(source, "(shell)");
}
printf("\n");
return true;
}
std::string JSShell::ReadFile(const std::string& fileName)
{
std::string script;
std::ifstream file(fileName.c_str());
if (file.is_open()) {
while ( file.good() ) {
std::string line;
getline(file, line);
script.append(line);
script.append("\n");
}
file.close();
} else {
std::cout << "Unable to open file " << fileName << "." << std::endl;
}
return script;
}
#ifdef ENABLE_JSC
extern JSShell* JSCShell_Create();
#endif
#ifdef ENABLE_V8
extern JSShell* V8Shell_Create();
#endif
typedef JSShell*(*ShellFactory)();
static ShellFactory js_shell_factories[2] = {
#ifdef ENABLE_JSC
JSCShell_Create,
#else
0,
#endif
#ifdef ENABLE_V8
V8Shell_Create,
#else
0,
#endif
};
JSShell *JSShell::Create(Engine engine) {
if(js_shell_factories[engine] == 0) {
throw "Engine not available.";
}
return js_shell_factories[engine]();
}
|