Dear Leandro, This is very nice commit for elev8 modularization. Thanks.
I have some problems compiling in my machine. Object::HasOwnProperty() is not to be found in v8.h. I did an apt-get update/upgrade and I did not find this in v8.h (version - 3.1.8.22) . The reference API page does provide this API though. Can you tell me which version of libv8 you have used? I would prefer to use the API's provided as part of distro. Regards, Sanjeev On Fri, Mar 2, 2012 at 3:35 AM, Enlightenment SVN < no-re...@enlightenment.org> wrote: > Log: > elev8: Allow loading modules in runtime > > There are now two kinds of modules: native (.so) and JavaScript (.js). > Both > modules can be loaded using the same interface and is completely > transparent > to the application developer, by using the global require() function. For > example, to load the elementary module: > > elm = require('elm'); > > This will try to open 'libelm.so' in the current directory, then > 'libelm.so' > in elev8's module directory. If that fails, it will try to open 'elm.js' > in > the current directory, then 'elm.js' in elev8's directory. Should any of > these attempts work, it will save the module in an internal cache and > return > a reference to an object containing all exported symbols from that module. > The module loading path can be changed by changing the MODPATH environment > variable in the same way one would set the PATH environment variable. > > To create a native module, one should create a > RegisterModule(Handle<ObjectTemplate>target) function, and manually add > exported symbols to the target object. Be sure to ``export "C"'' it or > else > dlsym() will fail. > > JavaScript modules works pretty much the same way: they're created and > executed in a separate context so that they do not mess up with the rest > of > the application (for instance, it is very easy to forget a ``var'' > keyword, > making a variable global -- imagine the mess a for (i = 0; i < 10; i++) > derp() would make). A global (to the module's context) object called > ``exports'' must be used to export functions and globals: > > exports.pi = 3.14159265; > exports.calculate_the_answer = function() { > return Math.ceil((1337 * exports.pi) / 100.0); > } > > Elev8 does not load all modules automatically anymore -- this is now > controlled by the init.js script, which is loaded and interpreted at > startup. This can be used to load other modules, define useful constants, > this sort of thing. Care should be taken when using this file, though, > since > it is compiled and evaluated in the global context. > > Also, support for Eina_Module has been temporarily removed; it will be > back, > don't worry about it. This means that module shutdown functions have been > temporarily removed as well. There are more important cleanups to be made > in Elev8, so this will be postponed until further notice. > > > > Author: acidx > Date: 2012-03-01 10:35:09 -0800 (Thu, 01 Mar 2012) > New Revision: 68583 > Trac: http://trac.enlightenment.org/e/changeset/68583 > > Added: > trunk/PROTO/elev8/src/bin/init.js > trunk/PROTO/elev8/src/modules/elm/elev8_elm.cc > Removed: > trunk/PROTO/elev8/src/bin/module.cc > trunk/PROTO/elev8/src/modules/elm/elev8_elm.cc > Modified: > trunk/PROTO/elev8/src/bin/Makefile.am trunk/PROTO/elev8/src/bin/main.cc > trunk/PROTO/elev8/src/modules/dbus/Makefile.am > trunk/PROTO/elev8/src/modules/dbus/elev8_dbus.cc > trunk/PROTO/elev8/src/modules/elm/Makefile.am > trunk/PROTO/elev8/src/modules/http/Makefile.am > trunk/PROTO/elev8/src/modules/http/elev8_http.cc > > Modified: trunk/PROTO/elev8/src/bin/Makefile.am > =================================================================== > --- trunk/PROTO/elev8/src/bin/Makefile.am 2012-03-01 17:25:54 UTC > (rev 68582) > +++ trunk/PROTO/elev8/src/bin/Makefile.am 2012-03-01 18:35:09 UTC > (rev 68583) > @@ -12,14 +12,15 @@ > -DPACKAGE_TMP_DIR=\"/tmp\" \ > @ELEV8_CFLAGS@ > > - > bin_PROGRAMS = elev8 > > +elev8libdir = $(libdir)/elev8 > +elev8lib_SCRIPTS = init.js > + > elev8_SOURCES = \ > main.cc \ > elev8_utils.cc \ > - downloader.cc \ > - module.cc > + downloader.cc > > elev8_LDADD = @ELEV8_LIBS@ @V8_LIBS@ > > > Modified: trunk/PROTO/elev8/src/bin/main.cc > =================================================================== > --- trunk/PROTO/elev8/src/bin/main.cc 2012-03-01 17:25:54 UTC (rev 68582) > +++ trunk/PROTO/elev8/src/bin/main.cc 2012-03-01 18:35:09 UTC (rev 68583) > @@ -5,7 +5,6 @@ > * then exit > */ > > - > #include <sys/mman.h> > #include <fcntl.h> > #include <downloader.h> > @@ -16,13 +15,25 @@ > using namespace v8; > int elev8_log_domain = -1; > > -/* FIXME */ > -void elm_v8_setup(Handle<ObjectTemplate> global); > -int xmlhttp_v8_setup(Handle<ObjectTemplate> global); > -int dbus_v8_setup(Handle<ObjectTemplate> global); > +#define MODLOAD_ENV "MODPATH" > +#define MODLOAD_ENV_DEFAULT_DIRS ".:" PACKAGE_LIB_DIR > > +static Persistent<Object> module_cache; > + > +static Handle<Value> require(const Arguments& args); > +static Handle<Value> modules(const Arguments& args); > +static Handle<Value> print(const Arguments& args); > + > +static void > +add_symbols_to_context_global(Handle<ObjectTemplate> global) > +{ > + global->Set(String::NewSymbol("require"), > FunctionTemplate::New(require)); > + global->Set(String::NewSymbol("modules"), > FunctionTemplate::New(modules)); > + global->Set(String::NewSymbol("print"), FunctionTemplate::New(print)); > +} > + > Handle<Value> > -Print(const Arguments& args) > +print(const Arguments& args) > { > for (int i = 0; i < args.Length(); i++) > { > @@ -121,44 +132,193 @@ > { > HandleScope handle_scope; > > - if (filename == strstr(filename, "http")) > + if (!strncmp(filename, "http://", 7)) > { > INF("Downloading elev8 Script"); > show_download_ui((void *)filename); > + return; > } > - else > + > + /* load the script and run it */ > + Handle<String> source = string_from_file(filename); > + if (source.IsEmpty()) > { > - /* load the script and run it */ > - //Handle<String> origin = String::New(filename); > - Handle<String> source = string_from_file(filename); > - if (source.IsEmpty()) > + ERR("Failed to read source %s", filename); > + return; > + } > + compile_and_run(source); > +} > + > +static char * > +find_module_file_name(char *module_name, const char *prefix, const char > *type) > +{ > + char *modpath = getenv(MODLOAD_ENV); > + char default_modpath[] = MODLOAD_ENV_DEFAULT_DIRS; > + > + if (!modpath) modpath = default_modpath; > + > + for (char *token, *rest, *ptr = modpath; > + (token = strtok_r(ptr, ":", &rest)); > + ptr = rest) > + { > + char full_path[PATH_MAX]; > + > + if (snprintf(full_path, PATH_MAX - 1, "%s/%s%s.%s", token, > prefix, module_name, type) < 0) > + return NULL; > + > + if (!access(full_path, R_OK)) > + return strdup(full_path); > + } > + > + return NULL; > +} > + > +inline static char * > +find_native_module_file_name(char *module_name) > +{ > + return find_module_file_name(module_name, "lib", "so"); > +} > + > +inline static char * > +find_js_module_file_name(char *module_name) > +{ > + return find_module_file_name(module_name, "", "js"); > +} > + > +static bool > +module_native_load(Handle<String> module_name, Handle<Object> name_space) > +{ > + char *file_name = > find_native_module_file_name(*String::AsciiValue(module_name)); > + > + if (!file_name) return false; > + > + DBG("Loading native module: %s", file_name); > + > + // FIXME: Use Eina_Module here. > + void *handle = dlopen(file_name, RTLD_LAZY); > + if (!handle) > + { > + free(file_name); > + return false; > + } > + > + void (*init_func)(Handle<Object> name_space); > + init_func = (void (*)(Handle<Object>))dlsym(handle, "RegisterModule"); > + if (!init_func) > + { > + free(file_name); > + dlclose(handle); > + return false; > + } > + > + init_func(name_space); > + > + name_space->Set(String::NewSymbol("__dl_handle"), > External::Wrap(handle)); > + name_space->Set(String::NewSymbol("__file_name"), > String::New(file_name)); > + > + free(file_name); > + return true; > +} > + > +static bool > +module_js_load(Handle<String> module_name, Handle<Object> name_space) > +{ > + char *file_name = > find_js_module_file_name(*String::AsciiValue(module_name)); > + > + if (!file_name) return false; > + > + DBG("Loading JavaScript module: %s", file_name); > + > + Handle<Value> mod_source = string_from_file(file_name); > + if (mod_source->IsUndefined()) > + { > + free(file_name); > + return false; > + } > + > + HandleScope handle_scope; > + Handle<ObjectTemplate> mod_global = ObjectTemplate::New(); > + > + mod_global->Set(String::NewSymbol("exports"), name_space); > + add_symbols_to_context_global(mod_global); > + > + Persistent<Context> mod_context = Context::New(NULL, mod_global); > + Context::Scope mod_context_scope(mod_context); > + > + TryCatch try_catch; > + Local<Script> mod_script = Script::Compile(mod_source->ToString()); > + if (try_catch.HasCaught()) > + { > + mod_context.Dispose(); > + free(file_name); > + return false; > + } > + > + mod_script->Run(); > + > + name_space->Set(String::NewSymbol("__file_name"), > String::New(file_name)); > + // FIXME: How to wrap mod_context so that t can be Disposed() properly? > + > + free(file_name); > + return true; > +} > + > +static Handle<Value> > +require(const Arguments& args) > +{ > + HandleScope scope; > + Local<Object> name_space; > + Local<String> module_name; > + > + if (args.Length() < 1) > + return > scope.Close(ThrowException(Exception::Error(String::New("Module name > missing")))); > + > + module_name = args[0]->ToString(); > + > + if (module_cache->HasOwnProperty(module_name)) > I did an apt-get update/upgrade and I did not find this in v8.h (version - 3.1.8.22) . So, my compile fails. The reference API page does provide this API though. Can you tell me which version of libv8 you have used? I would prefer to use the API's provided as part of distro. > + return scope.Close(module_cache->Get(module_name)); > + > + name_space = Object::New(); > + if (!module_native_load(module_name, name_space)) > + { > + if (!module_js_load(module_name, name_space)) > { > - ERR("Failed to read source %s", filename); > - return; > + Local<String> msg = String::Concat(String::New("Cannot load > module: "), module_name); > + return scope.Close(ThrowException(Exception::Error(msg))); > } > - compile_and_run(source); > - } > + } > + > + module_cache->Set(module_name, Persistent<Object>::New(name_space)); > + return scope.Close(name_space); > } > > +static Handle<Value> > +modules(const Arguments&) > +{ > + HandleScope scope; > + return scope.Close(module_cache); > +} > + > void > elev8_run(const char *script) > { > HandleScope handle_scope; > Handle<ObjectTemplate> global = ObjectTemplate::New(); > > - global->Set(String::New("print"), FunctionTemplate::New(Print)); > + add_symbols_to_context_global(global); > > - load_modules(); > - init_modules(global); > - > - /* setup V8 */ > Persistent<Context> context = Context::New(NULL, global); > Context::Scope context_scope(context); > + > + module_cache = Persistent<Object>::New(Object::New()); > + > + run_script(PACKAGE_LIB_DIR "/../init.js"); > run_script(script); > > ecore_main_loop_begin(); > > context.Dispose(); > + module_cache.Dispose(); > } > > static void > > Modified: trunk/PROTO/elev8/src/modules/dbus/Makefile.am > =================================================================== > --- trunk/PROTO/elev8/src/modules/dbus/Makefile.am 2012-03-01 > 17:25:54 UTC (rev 68582) > +++ trunk/PROTO/elev8/src/modules/dbus/Makefile.am 2012-03-01 > 18:35:09 UTC (rev 68583) > @@ -12,10 +12,10 @@ > @ELEV8_CFLAGS@ > > moddir = $(libdir)/$(PACKAGE)/$(MODULE_ARCH) > -mod_LTLIBRARIES = libelev8-dbus.la > +mod_LTLIBRARIES = libdbus.la > > -libelev8_dbus_la_SOURCES = elev8_dbus.cc > +libdbus_la_SOURCES = elev8_dbus.cc > > -libelev8_dbus_la_LIBADD = @ELEV8_LIBS@ @V8_LIBS@ > -libelev8_dbus_la_LDFLAGS = -module -avoid-version -no-undefined > -libelev8_dbus_la_LIBTOOLFLAGS = --tag=disable-static > +libdbus_la_LIBADD = @ELEV8_LIBS@ @V8_LIBS@ > +libdbus_la_LDFLAGS = -module -avoid-version -no-undefined > +libdbus_la_LIBTOOLFLAGS = --tag=disable-static > > Modified: trunk/PROTO/elev8/src/modules/dbus/elev8_dbus.cc > =================================================================== > --- trunk/PROTO/elev8/src/modules/dbus/elev8_dbus.cc 2012-03-01 > 17:25:54 UTC (rev 68582) > +++ trunk/PROTO/elev8/src/modules/dbus/elev8_dbus.cc 2012-03-01 > 18:35:09 UTC (rev 68583) > @@ -640,7 +640,7 @@ > return EINA_TRUE; > } > > -Handle<Value> dbus_method_invoke(const Arguments &args) > +Handle<Value> dbus_method_invoke(const Arguments&) > { > HandleScope scope; > > @@ -848,7 +848,8 @@ > return dbus->obj; > } > > -int dbus_module_init(Handle<ObjectTemplate> global, void *data) > +extern "C" > +void RegisterModule(Handle<ObjectTemplate>) > { > elev8_dbus_log_domain = eina_log_domain_register("elev8-dbus", > EINA_COLOR_ORANGE); > if (!elev8_dbus_log_domain) > @@ -858,29 +859,10 @@ > } > DBUS_INF("elev8-dbus Logging initialized. %d", elev8_dbus_log_domain); > > - if (!e_dbus_init()) > + if (e_dbus_init()) > { > - DBUS_ERR( "Cannot Init to E_DBus"); > - return -1; > + /* Add support for DBus Service Introspection */ > + dbusObj = ObjectTemplate::New(); > + dbusObj->SetInternalFieldCount(1); > } > - > - /* Add support for DBus Service Introspection */ > - dbusObj = ObjectTemplate::New(); > - dbusObj->SetInternalFieldCount(1); > - global->Set(String::New("dbus"), > FunctionTemplate::New(createDBusInstance)); > - return 0; > } > - > -int dbus_module_shutdown(void *data) > -{ > - DBUS_INF("SHUTTING DOWN MODULE DBUS"); > - return 0; > -} > - > -extern "C" > -void setup(module_info *mi) > -{ > - strcpy(mi->name,DBUS_MODULE_NAME); > - mi->init = &dbus_module_init; > - mi->deinit = &dbus_module_shutdown; > -} > > Modified: trunk/PROTO/elev8/src/modules/elm/Makefile.am > =================================================================== > --- trunk/PROTO/elev8/src/modules/elm/Makefile.am 2012-03-01 > 17:25:54 UTC (rev 68582) > +++ trunk/PROTO/elev8/src/modules/elm/Makefile.am 2012-03-01 > 18:35:09 UTC (rev 68583) > @@ -12,10 +12,10 @@ > @ELEV8_CFLAGS@ > > moddir = $(libdir)/$(PACKAGE)/$(MODULE_ARCH) > -mod_LTLIBRARIES = libelev8-elm.la > +mod_LTLIBRARIES = libelm.la > > -libelev8_elm_la_SOURCES = elev8_elm.cc > +libelm_la_SOURCES = elev8_elm.cc > > -libelev8_elm_la_LIBADD = @ELEV8_LIBS@ @V8_LIBS@ > -libelev8_elm_la_LDFLAGS = -module -avoid-version -no-undefined > -libelev8_elm_la_LIBTOOLFLAGS = --tag=disable-static > +libelm_la_LIBADD = @ELEV8_LIBS@ @V8_LIBS@ > +libelm_la_LDFLAGS = -module -avoid-version -no-undefined > +libelm_la_LIBTOOLFLAGS = --tag=disable-static > > Modified: trunk/PROTO/elev8/src/modules/http/Makefile.am > =================================================================== > --- trunk/PROTO/elev8/src/modules/http/Makefile.am 2012-03-01 > 17:25:54 UTC (rev 68582) > +++ trunk/PROTO/elev8/src/modules/http/Makefile.am 2012-03-01 > 18:35:09 UTC (rev 68583) > @@ -12,10 +12,10 @@ > @ELEV8_CFLAGS@ > > moddir = $(libdir)/$(PACKAGE)/$(MODULE_ARCH) > -mod_LTLIBRARIES = libelev8-http.la > +mod_LTLIBRARIES = libhttp.la > > -libelev8_http_la_SOURCES = elev8_http.cc > +libhttp_la_SOURCES = elev8_http.cc > > -libelev8_http_la_LIBADD = @ELEV8_LIBS@ @V8_LIBS@ > -libelev8_http_la_LDFLAGS = -module -avoid-version -no-undefined > -libelev8_http_la_LIBTOOLFLAGS = --tag=disable-static > +libhttp_la_LIBADD = @ELEV8_LIBS@ @V8_LIBS@ > +libhttp_la_LDFLAGS = -module -avoid-version -no-undefined > +libhttp_la_LIBTOOLFLAGS = --tag=disable-static > > Modified: trunk/PROTO/elev8/src/modules/http/elev8_http.cc > =================================================================== > --- trunk/PROTO/elev8/src/modules/http/elev8_http.cc 2012-03-01 > 17:25:54 UTC (rev 68582) > +++ trunk/PROTO/elev8/src/modules/http/elev8_http.cc 2012-03-01 > 18:35:09 UTC (rev 68583) > @@ -367,7 +367,8 @@ > return reqObj->obj; > } > > -int http_module_init(Handle<ObjectTemplate> global, void *data) > +extern "C" > +void RegisterModule(Handle<ObjectTemplate> target) > { > elev8_http_log_domain = eina_log_domain_register("elev8-http", > EINA_COLOR_ORANGE); > if (!elev8_http_log_domain) > @@ -377,32 +378,11 @@ > } > HTTP_INF("elev8-http Logging initialized. %d", elev8_http_log_domain); > > - > - if (!ecore_con_url_init()) > + if (ecore_con_url_init()) > { > - HTTP_ERR( "Cannot Init to ECore_Url"); > - return -1; > + /* Add support for XML HTTP Request */ > + xmlHttpReqObj = ObjectTemplate::New(); > + xmlHttpReqObj->SetInternalFieldCount(1); > + target->Set(String::NewSymbol("XMLHttpRequest"), > FunctionTemplate::New(createXMLHttpReqInstance)->GetFunction()); > } > - > - //HTTP_INF( "Creating XML Http Request Instance"); > - > - /* Add support for XML HTTP Request */ > - xmlHttpReqObj = ObjectTemplate::New(); > - xmlHttpReqObj->SetInternalFieldCount(1); > - global->Set(String::New("XMLHttpRequest"), > FunctionTemplate::New(createXMLHttpReqInstance)); > - return 0; > } > - > -int http_module_shutdown(void *data) > -{ > - HTTP_INF("SHUTTING DOWN MODULE HTTP"); > - return 0; > -} > - > -extern "C" > -void setup(module_info *mi) > -{ > - strcpy(mi->name,HTTP_MODULE_NAME); > - mi->init = &http_module_init; > - mi->deinit = &http_module_shutdown; > -} > > > > ------------------------------------------------------------------------------ > Virtualization & Cloud Management Using Capacity Planning > Cloud computing makes use of virtualization - but cloud computing > also focuses on allowing computing to be delivered as a service. > http://www.accelacomm.com/jaw/sfnl/114/51521223/ > _______________________________________________ > enlightenment-svn mailing list > enlightenment-...@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/enlightenment-svn > ------------------------------------------------------------------------------ Virtualization & Cloud Management Using Capacity Planning Cloud computing makes use of virtualization - but cloud computing also focuses on allowing computing to be delivered as a service. http://www.accelacomm.com/jaw/sfnl/114/51521223/ _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel