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,没有在导入时做交叉引用的检测,在项目中的话,需要加入检测机制。

posted on 2013-04-16 00:08  盐味  阅读(2193)  评论(1编辑  收藏  举报