Google v8实现类似nodejs的import加载模块
希望在Cooper中加入模块搭建的机制, 参考了Nodejs中exports,import的机制,觉得他弄得复杂了些, 就自己试着写了个简单的
有这些文件:
makefile
v8test: \ v8test.cpp g++ \ v8test.cpp \ -o v8test \ -I/usr/local/include -L/usr/local/lib -lv8
v8test.cpp
#include <v8.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> using namespace v8; Handle<ObjectTemplate> GetTemplate(); int main(int argc, char* argv[]) { HandleScope handle_scope; Persistent<Context> context = Context::New(NULL, GetTemplate()); Context::Scope context_scope(context); Handle<String> source = String::New("var m = module('script1.js');print(m.name, m.fun(321,456));"); Handle<Script> script = Script::Compile(source); Handle<Value> result = script->Run(); context.Dispose(); return 0; } Handle<Value> ScriptPrint(const Arguments& args) { for(int i = 0; i < args.Length(); ++i) { String::Utf8Value str(args[i]); printf("%s\n", *str); } return v8::Undefined(); } Handle<Value> ScriptImport(const Arguments& args) { HandleScope handle_scope; if (args.Length() == 0) { return ThrowException(String::New("bad args")); } String::Utf8Value file(args[0]); char buff[4096]; memset(buff, 0, 4096); int fd = open(*file, O_RDONLY); int len = read(fd, buff, 4096); close(fd); Handle<Value> result = Undefined(); Persistent<Context> context = Context::New(NULL, GetTemplate()); Context::Scope context_scope(context); Handle<Object> global = context->Global(); global->Set(String::New("public"), Object::New()); Handle<String> source = String::New(buff, len); Handle<Script> script = Script::Compile(source); if(script.IsEmpty()) { result = ThrowException(String::New("module import error: Compile")); } else { result = script->Run(); if(result.IsEmpty()) { result = ThrowException(String::New("module import error: Run")); } else { result = global->Get(String::New("public")); } } context.Dispose(); return handle_scope.Close(result); } Handle<ObjectTemplate> GetTemplate() { HandleScope handle_scope; Handle<ObjectTemplate> global = ObjectTemplate::New(); //print function global->Set(String::New("print"), FunctionTemplate::New(ScriptPrint)); global->Set(String::New("module"), FunctionTemplate::New(ScriptImport)); return handle_scope.Close(global); }
script1.js
var m = module('script2.js'); var s = 'gibbon'; var f = function(a, b) { return a + b; }; public.fun = f; public.name = s + m.version;
script2.js
public.version = '0.0.1';
输出如下,达到了预设的要求。
gibbon@ubt:~/workspace/v8_test$ make g++ \ v8test.cpp \ -o v8test \ -I/usr/local/include -L/usr/local/lib -lv8 gibbon@ubt:~/workspace/v8_test$ ./v8test gibbon0.0.1 777 gibbon@ubt:~/workspace/v8_test$
nodejs中使用exports和require来导出和导入模块,哥为了显得不一样,使用了public和module来导出和导入模块,只是一个demo,没有在导入时做交叉引用的检测,在项目中的话,需要加入检测机制。