diff --git a/binding.gyp b/binding.gyp index 2d52e14..195fa89 100644 --- a/binding.gyp +++ b/binding.gyp @@ -4,12 +4,12 @@ "target_name": "nodelua", "variables": { "lua_include": "&1 | grep -oP '\d\.\d')" + "lua_version": "&1 | grep -o '\d\.\d')" }, "sources": [ - "src/utils.cc", - "src/luafunction.cc", - "src/luaobject.cc", + "src/utils.cc", + "src/luafunction.cc", + "src/luastate.cc", "src/nodelua.cc" ], "include_dirs": [ diff --git a/src/luaobject.cc b/src/luaobject.cc index da169e4..12e48de 100644 --- a/src/luaobject.cc +++ b/src/luaobject.cc @@ -16,14 +16,10 @@ void LuaObject::Init(Handle target) { tpl->SetClassName(String::NewSymbol("LuaObject")); tpl->InstanceTemplate()->SetInternalFieldCount(1); // Prototype - tpl->PrototypeTemplate()->Set(String::NewSymbol("doFile"), - FunctionTemplate::New(DoFile)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("doString"), FunctionTemplate::New(DoString)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("getGlobal"), FunctionTemplate::New(GetGlobal)->GetFunction()); - tpl->PrototypeTemplate()->Set(String::NewSymbol("setGlobal"), - FunctionTemplate::New(SetGlobal)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("registerFunction"), FunctionTemplate::New(RegisterFunction)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("status"), @@ -70,13 +66,13 @@ Handle LuaObject::Status(const Arguments& args){ HandleScope scope; LuaObject* obj = ObjectWrap::Unwrap(args.This()); int status = lua_status(obj->lua_); - + return scope.Close(Number::New(status)); } Handle LuaObject::CollectGarbage(const Arguments& args){ HandleScope scope; - + if(args.Length() < 1){ ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); return scope.Close(Undefined()); @@ -86,7 +82,7 @@ Handle LuaObject::CollectGarbage(const Arguments& args){ ThrowException(Exception::TypeError(String::New("Argument 1 must be a number, try nodelua.GC"))); return scope.Close(Undefined()); } - + LuaObject* obj = ObjectWrap::Unwrap(args.This()); int type = (int)args[0]->ToNumber()->Value(); int gc = lua_gc(obj->lua_, type, 0); @@ -94,28 +90,6 @@ Handle LuaObject::CollectGarbage(const Arguments& args){ return scope.Close(Number::New(gc)); } -Handle LuaObject::DoFile(const Arguments& args) { - HandleScope scope; - - if(args.Length() < 1){ - ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); - return scope.Close(Undefined()); - } - - char *file_name = get_str(args[0]); - - LuaObject* obj = ObjectWrap::Unwrap(args.This()); - if(luaL_dofile(obj->lua_, file_name)){ - char buf[1000]; - sprintf(buf, "Execution Of File %s Has Failed:\n%s\n", file_name, lua_tostring(obj->lua_, -1)); - ThrowException(Exception::TypeError(String::New(buf))); - return scope.Close(Undefined()); - } - - return scope.Close(Undefined()); -} - - Handle LuaObject::DoString(const Arguments& args) { HandleScope scope; @@ -157,24 +131,6 @@ Handle LuaObject::GetGlobal(const Arguments& args) { } -Handle LuaObject::SetGlobal(const Arguments& args) { - HandleScope scope; - - if(args.Length() < 2){ - ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); - return scope.Close(Undefined()); - } - - char *global_name = get_str(args[0]); - - LuaObject* obj = ObjectWrap::Unwrap(args.This()); - - push_value_to_lua(obj->lua_, args[1]); - lua_setglobal(obj->lua_, global_name); - - return scope.Close(Undefined()); -} - Handle LuaObject::Push(const Arguments& args) { HandleScope scope; @@ -300,7 +256,7 @@ int LuaObject::CallFunction(lua_State *L){ break; } } - + push_value_to_lua(L, ret_val); return 1; } diff --git a/src/luaobject.h b/src/luaobject.h index 8bb137d..a30411b 100644 --- a/src/luaobject.h +++ b/src/luaobject.h @@ -22,10 +22,8 @@ class LuaObject : public node::ObjectWrap { ~LuaObject(); static v8::Handle New(const v8::Arguments& args); - static v8::Handle DoFile(const v8::Arguments& args); static v8::Handle DoString(const v8::Arguments& args); static v8::Handle GetGlobal(const v8::Arguments& args); - static v8::Handle SetGlobal(const v8::Arguments& args); static v8::Handle RegisterFunction(const v8::Arguments& args); static v8::Handle Status(const v8::Arguments& args); static v8::Handle CollectGarbage(const v8::Arguments& args); diff --git a/src/luastate.cc b/src/luastate.cc new file mode 100644 index 0000000..1424a95 --- /dev/null +++ b/src/luastate.cc @@ -0,0 +1,177 @@ +#define BUILDING_NODELUA +#include "luastate.h" + +using namespace v8; + +uv_async_t async; + +struct do_file_baton{ + Persistent callback; + char* file_name; + bool error; + char msg[1000]; + LuaState* state; +}; + +void do_file(uv_work_t *req){ + do_file_baton* baton = static_cast(req->data); + + if(luaL_dofile(baton->state->lua_, baton->file_name)){ + baton->error = true; + sprintf(baton->msg, "Exception In File %s Has Failed:\n%s\n", baton->file_name, lua_tostring(baton->state->lua_, -1)); + } +} + +void do_file_after(uv_work_t *req){ + HandleScope scope; + + do_file_baton* baton = (do_file_baton *)req->data; + + Local argv[2]; + const int argc = 2; + + if(baton->error){ + argv[0] = String::NewSymbol(baton->msg); + argv[1] = Local::New(Undefined()); + } else{ + argv[0] = Local::New(Undefined()); + if(lua_gettop(baton->state->lua_)){ + argv[1] = lua_to_value(baton->state->lua_, -1); + } else{ + argv[1] = Local::New(Undefined()); + } + } + + TryCatch try_catch; + + baton->callback->Call(Context::GetCurrent()->Global(), argc, argv); + + baton->callback.Dispose(); + delete baton; + delete req; + + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } +} + +LuaState::LuaState(){}; +LuaState::~LuaState(){}; + +void LuaState::Init(Handle target){ + Local tpl = FunctionTemplate::New(New); + tpl->SetClassName(String::NewSymbol("LuaState")); + tpl->InstanceTemplate()->SetInternalFieldCount(2); + + tpl->PrototypeTemplate()->Set(String::NewSymbol("doFileSync"), + FunctionTemplate::New(DoFileSync)->GetFunction()); + tpl->PrototypeTemplate()->Set(String::NewSymbol("doFile"), + FunctionTemplate::New(DoFile)->GetFunction()); + + tpl->PrototypeTemplate()->Set(String::NewSymbol("setGlobal"), + FunctionTemplate::New(SetGlobal)->GetFunction()); + + Persistent constructor = Persistent::New(tpl->GetFunction()); + target->Set(String::NewSymbol("LuaState"), constructor); +} + +Handle LuaState::New(const Arguments& args){ + HandleScope scope; + + if(!args.IsConstructCall()) { + return ThrowException(Exception::TypeError(String::New("Use the new operator to create instances of this object."))); + } + + LuaState* obj = new LuaState(); + obj->lua_ = lua_open(); + luaL_openlibs(obj->lua_); + obj->Wrap(args.This()); + + return args.This(); +} + +Handle LuaState::DoFileSync(const Arguments& args){ + HandleScope scope; + + if(args.Length() < 1){ + ThrowException(Exception::TypeError(String::New("doFileSync Takes Only 1 Argument"))); + return scope.Close(Undefined()); + } + + if(!args[0]->IsString()){ + ThrowException(Exception::TypeError(String::New("doFileSync Argument 1 Must Be A String"))); + return scope.Close(Undefined()); + } + + char* file_name = get_str(args[0]); + + LuaState* obj = ObjectWrap::Unwrap(args.This()); + if(luaL_dofile(obj->lua_, file_name)){ + char buf[1000]; + sprintf(buf, "Exception Of File %s Has Failed:\n%s\n", file_name, lua_tostring(obj->lua_, -1)); + ThrowException(Exception::Error(String::New(buf))); + return scope.Close(Undefined()); + } + + if(lua_gettop(obj->lua_)){ + return scope.Close(lua_to_value(obj->lua_, -1)); + } else{ + return scope.Close(Undefined()); + } +} + +Handle LuaState::DoFile(const Arguments& args){ + HandleScope scope; + + if(args.Length() < 1){ + ThrowException(Exception::TypeError(String::New("doFile Requires At Least 1 Argument"))); + return scope.Close(Undefined()); + } + + if(!args[0]->IsString()){ + ThrowException(Exception::TypeError(String::New("doFile Argument 1 Must Be A String"))); + return scope.Close(Undefined()); + } + + if(args.Length() > 2 && !args[1]->IsFunction()){ + ThrowException(Exception::TypeError(String::New("doFile Argument 2 Must Be A Function"))); + return scope.Close(Undefined()); + } + + char* file_name = get_str(args[0]); + Persistent callback; + if(args.Length() > 1){ + callback = Persistent::New(Local::Cast(args[1])); + } + + LuaState* obj = ObjectWrap::Unwrap(args.This()); + do_file_baton* baton = new do_file_baton(); + baton->file_name = file_name; + baton->callback = callback; + baton->state = obj; + obj->Ref(); + + uv_work_t *req = new uv_work_t; + req->data = baton; + uv_queue_work(uv_default_loop(), req, do_file, do_file_after); + + return scope.Close(Undefined()); +} + +Handle LuaState::SetGlobal(const Arguments& args) { + HandleScope scope; + + if(args.Length() < 2){ + ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); + return scope.Close(Undefined()); + } + + char *global_name = get_str(args[0]); + + LuaState* obj = ObjectWrap::Unwrap(args.This()); + + push_value_to_lua(obj->lua_, args[1]); + lua_setglobal(obj->lua_, global_name); + + return scope.Close(Undefined()); +} diff --git a/src/luastate.h b/src/luastate.h new file mode 100644 index 0000000..61bd22e --- /dev/null +++ b/src/luastate.h @@ -0,0 +1,28 @@ +#ifndef LUASTATE_H +#define LUASTATE_H + +#include + +#include "utils.h" + +extern "C"{ +#include +#include +#include +} + +class LuaState : public node::ObjectWrap{ + public: + static void Init(v8::Handle target); + lua_State* lua_; + + private: + LuaState(); + ~LuaState(); + + static v8::Handle New(const v8::Arguments& args); + static v8::Handle DoFileSync(const v8::Arguments& args); + static v8::Handle DoFile(const v8::Arguments& args); + static v8::Handle SetGlobal(const v8::Arguments& args); +}; +#endif diff --git a/src/nodelua.cc b/src/nodelua.cc index 5b7b700..f8ac4d2 100644 --- a/src/nodelua.cc +++ b/src/nodelua.cc @@ -1,8 +1,7 @@ #include #include -#include "luaobject.h" -#include "luafunction.h" +#include "luastate.h" extern "C"{ #include @@ -43,8 +42,7 @@ void init_gc_constants(Handle target){ } void init(Handle target) { - LuaObject::Init(target); - LuaFunction::Init(target); + LuaState::Init(target); init_gc_constants(target); init_status_constants(target); init_info_constants(target);