diff --git a/plugins/v8/uwsgiplugin.py b/plugins/v8/uwsgiplugin.py index e49fc83c..78004673 100644 --- a/plugins/v8/uwsgiplugin.py +++ b/plugins/v8/uwsgiplugin.py @@ -1,6 +1,11 @@ +import os NAME='v8' CFLAGS = ['-Wno-deprecated-declarations'] LDFLAGS = [] LIBS = ['-lv8'] +engine = os.environ.get('UWSGI_V8_ENGINE', '') +if engine == 'teajs': + CFLAGS.append('-DUWSGI_V8_TEAJS -fexceptions') + LIBS.append('-lteajs') GCC_LIST = ['plugin', 'v8_uwsgi.cc', 'v8_commonjs.cc', 'v8_jsgi.cc'] diff --git a/plugins/v8/v8_commonjs.cc b/plugins/v8/v8_commonjs.cc index a046c743..8ffa1432 100644 --- a/plugins/v8/v8_commonjs.cc +++ b/plugins/v8/v8_commonjs.cc @@ -1,119 +1,141 @@ #include "v8_uwsgi.h" +extern struct uwsgi_server uwsgi; + +#ifdef UWSGI_V8_TEAJS +#include "app.h" +class TeaJS_uWSGI : public TeaJS_App { +public: + void init() { + TeaJS_App::init(); + v8::HandleScope handle_scope; + this->mainfile = ""; + this->create_context(); + this->mainModule = v8::Object::New(); + this->prepare(uwsgi.environ); + } + v8::Persistent getContext() { + return this->context; + } +private: + const char *instanceType() { + return "uWSGI"; + } + + const char *executableName() { + return uwsgi.binary_path; + } + +}; +#else +static v8::Handle < v8::Value > uwsgi_v8_commonjs_require(const v8::Arguments &); +static v8::Handle < v8::Value > uwsgi_v8_commonjs_require_do(char *); +#endif + extern struct uwsgi_v8 uv8; extern struct uwsgi_server uwsgi; +v8::Persistent uwsgi_v8_setup_context() { +#ifdef UWSGI_V8_TEAJS + TeaJS_uWSGI app; + try { + app.init(); + //app.execute(uwsgi.environ); + return app.getContext(); + } + catch (std::string e) { + uwsgi_log("%s\n", e.c_str()); + exit(1); + } +} +#else + // create a new context + v8::Persistent context = v8::Context::New(); + context->Enter(); + + v8::Handle global = context->Global(); + + v8::Handle < v8::Object > system = v8::Object::New(); + v8::Handle < v8::Array > args = v8::Array::New(); + int i; + for (i = 0; i < uwsgi.argc; i++) { + args->Set(v8::Integer::New(i), v8::String::New(uwsgi.argv[i])); + } + system->Set(v8::String::New("args"), args); + v8::Handle < v8::Object > env = v8::Object::New(); + system->Set(v8::String::New("env"), env); + global->Set(v8::String::New("require"), v8::FunctionTemplate::New(uwsgi_v8_commonjs_require)->GetFunction()); + global->Set(v8::String::New("system"), system); + return context; +} + + /* - support .js - support .so files (TeaJS) +uWSGI native "require" support */ -static void uwsgi_v8_commonjs_require_do(char *filename, v8::Local exports, v8::Local module) { + +static v8::Handle < v8::Value > uwsgi_v8_commonjs_require_do(char *filename) { size_t len = 0; - char *code = uwsgi_open_and_read(filename, &len, 1, NULL); + char *code = uwsgi_open_and_read(filename, &len, 1, NULL); - // we do not use TryCatch as we directly use stderr and simply exit with error code 1 - v8::Handle script = v8::Script::Compile( v8::String::New(code), v8::String::New(filename) ); - free(code); - if (script.IsEmpty()) { - return; - } - script->Run(); + // we re-create every time an "exports" object to emulate a local object + v8::Local < v8::Object > exports = v8::Object::New(); + v8::Context::GetCurrent()->Global()->Set(v8::String::New("exports"), exports); + + // we do not use TryCatch as we directly use stderr and simply exit with error code 1 + v8::Handle < v8::Script > script = v8::Script::Compile(v8::String::New(code), v8::String::New(filename)); + free(code); + if (script.IsEmpty()) { + exit(1); + } + + v8::Handle < v8::Value > result = script->Run(); + if (result.IsEmpty()) { + return v8::Undefined(); + } + + return exports; } -static void uwsgi_v8_commonjs_require_teajs_do(char *filename, v8::Local exports, v8::Local module) { - - void *handle = dlopen(filename, RTLD_LAZY); - if (!handle) { - uwsgi_log("error opening teajs module %s: %s\n", filename, dlerror()); - return; - } - typedef void (*init_t)(v8::Handle, v8::Handle, v8::Handle); - init_t func = (init_t) dlsym(handle, "init"); - if (!func) { - uwsgi_log("unable to find teajs module init function\n"); - return; - } - func(v8::Handle::Cast(v8::Context::GetCurrent()->Global()->Get(v8::String::New("require"))), exports, module); -} - - -static v8::Handle uwsgi_v8_commonjs_require(const v8::Arguments& args) { +static v8::Handle < v8::Value > uwsgi_v8_commonjs_require(const v8::Arguments & args) { if (args.Length() > 0) { v8::String::Utf8Value module_name(args[0]->ToString()); - char *id = (char *)"pippo"; - // we re-create every time an "exports" object to emulate a local object - v8::Local exports = v8::Object::New(); - v8::Context::GetCurrent()->Global()->Set(v8::String::New("exports"), exports); - v8::Local module = v8::Object::New(); - v8::Context::GetCurrent()->Global()->Set(v8::String::New("module"), module); - module->Set(v8::String::New("id"), v8::String::New(id)); // ok lets start searching the module if (uwsgi_is_file(*module_name)) { - if (!uwsgi_endswith(*module_name, (char *)".js")) { - uwsgi_v8_commonjs_require_do(*module_name, exports, module); - return exports; - } - else if (!uwsgi_endswith(*module_name, (char *)".so")) { - uwsgi_v8_commonjs_require_teajs_do(*module_name, exports, module); - return exports; - } - return v8::Undefined(); + return uwsgi_v8_commonjs_require_do(*module_name); } - // try appending .js/.so extension - if (!uwsgi_endswith(*module_name, (char *)".js") && !uwsgi_endswith(*module_name, (char *)".so")) { - char *tmp_filename = uwsgi_concat2(*module_name, (char *)".so"); - if (uwsgi_is_file(tmp_filename)) { - uwsgi_v8_commonjs_require_teajs_do(tmp_filename, exports, module); - free(tmp_filename); - return exports; - } - free(tmp_filename); - tmp_filename = uwsgi_concat2(*module_name, (char *)".js"); + // try appending .js extension + if (!uwsgi_endswith(*module_name, (char *) ".js")) { + char *tmp_filename = uwsgi_concat2(*module_name, (char *) ".js"); if (uwsgi_is_file(tmp_filename)) { - uwsgi_v8_commonjs_require_do(tmp_filename, exports, module); + v8::Handle < v8::Value > ret = uwsgi_v8_commonjs_require_do(tmp_filename); free(tmp_filename); - return exports; + return ret; } free(tmp_filename); - } + } // let's start searching in the modules search path struct uwsgi_string_list *usl = uv8.module_paths; - while(usl) { - char *tmp_filename = uwsgi_concat3(usl->value, (char *)"/", *module_name); + while (usl) { + char *tmp_filename = uwsgi_concat3(usl->value, (char *) "/", *module_name); if (uwsgi_is_file(tmp_filename)) { - if (!uwsgi_endswith(tmp_filename, (char *)".js")) { - uwsgi_v8_commonjs_require_do(tmp_filename, exports, module); - } - else if (!uwsgi_endswith(tmp_filename, (char *)".so")) { - uwsgi_v8_commonjs_require_teajs_do(tmp_filename, exports, module); - } - else { - free(tmp_filename); - return v8::Undefined(); - } + v8::Handle < v8::Value > ret = uwsgi_v8_commonjs_require_do(tmp_filename); free(tmp_filename); - return exports; - } + return ret; + } free(tmp_filename); - if (!uwsgi_endswith(*module_name, (char *)".js") && !uwsgi_endswith(*module_name, (char *)".so")) { - tmp_filename = uwsgi_concat4(usl->value, (char *)"/", *module_name, (char *)".so"); - if (uwsgi_is_file(tmp_filename)) { - uwsgi_v8_commonjs_require_teajs_do(tmp_filename, exports, module); - free(tmp_filename); - return exports; - } - tmp_filename = uwsgi_concat4(usl->value, (char *)"/", *module_name, (char *)".js"); + if (!uwsgi_endswith(*module_name, (char *) ".js")) { + tmp_filename = uwsgi_concat4(usl->value, (char *) "/", *module_name, (char *) ".js"); if (uwsgi_is_file(tmp_filename)) { - uwsgi_v8_commonjs_require_do(tmp_filename, exports, module); - free(tmp_filename); - return exports; - } - free(tmp_filename); + v8::Handle < v8::Value > ret = uwsgi_v8_commonjs_require_do(tmp_filename); + free(tmp_filename); + return ret; + } } free(tmp_filename); usl = usl->next; @@ -121,24 +143,4 @@ static v8::Handle uwsgi_v8_commonjs_require(const v8::Arguments& args } return v8::Undefined(); } - -void uwsgi_v8_fill_commonjs(v8::Persistent context) { - context->Enter(); - v8::Handle system = context->Global()->Get(v8::String::New("system"))->ToObject(); - v8::Handle args = v8::Array::New(); - int i; - for(i=0;iSet(v8::Integer::New(i), v8::String::New(uwsgi.argv[i])); - } - system->Set(v8::String::New("args"), args); - v8::Handle env = v8::Object::New(); - system->Set(v8::String::New("env"), env); -} - -void uwsgi_v8_add_commonjs(v8::Handle global) { - // the require function (Modules/1.1) - global->Set(v8::String::New("require"), v8::FunctionTemplate::New(uwsgi_v8_commonjs_require)); - // the system namespace (System/1.0) - v8::Handle system = v8::ObjectTemplate::New(); - global->Set(v8::String::New("system"), system); -} +#endif diff --git a/plugins/v8/v8_uwsgi.cc b/plugins/v8/v8_uwsgi.cc index 37427b24..25df7198 100644 --- a/plugins/v8/v8_uwsgi.cc +++ b/plugins/v8/v8_uwsgi.cc @@ -134,8 +134,7 @@ static v8::Handle uwsgi_v8_api_log(const v8::Arguments& args) { return v8::Undefined(); } -void uwsgi_v8_add_commonjs(v8::Handle); -void uwsgi_v8_fill_commonjs(v8::Persistent); +v8::Persistent uwsgi_v8_setup_context(); static v8::Persistent uwsgi_v8_new_isolate(int core_id) { // create a new isolate @@ -145,23 +144,19 @@ static v8::Persistent uwsgi_v8_new_isolate(int core_id) { uv8.isolates[core_id] = v8::Isolate::GetCurrent(); + v8::Persistent context = uwsgi_v8_setup_context(); + uwsgi_log("context at %p\n", context); + context->Enter(); + v8::HandleScope handle_scope; // uWSGI api - v8::Handle uwsgi_api = v8::ObjectTemplate::New(); - uwsgi_api->Set(v8::String::New("log"), v8::FunctionTemplate::New(uwsgi_v8_api_log)); - uwsgi_api->Set(v8::String::New("register_rpc"), v8::FunctionTemplate::New(uwsgi_v8_api_register_rpc)); - uwsgi_api->Set(v8::String::New("register_signal"), v8::FunctionTemplate::New(uwsgi_v8_api_register_signal)); + v8::Handle uwsgi_api = v8::Object::New(); + uwsgi_api->Set(v8::String::New("log"), v8::FunctionTemplate::New(uwsgi_v8_api_log)->GetFunction()); + uwsgi_api->Set(v8::String::New("register_rpc"), v8::FunctionTemplate::New(uwsgi_v8_api_register_rpc)->GetFunction()); + uwsgi_api->Set(v8::String::New("register_signal"), v8::FunctionTemplate::New(uwsgi_v8_api_register_signal)->GetFunction()); - v8::Handle global = v8::ObjectTemplate::New(); - global->Set(v8::String::New("uwsgi"), uwsgi_api); - - uwsgi_v8_add_commonjs(global); - - // create a new context - v8::Persistent context = v8::Context::New(NULL, global); - - uwsgi_v8_fill_commonjs(context); + context->Global()->Set(v8::String::New("uwsgi"), uwsgi_api); return context; }