void ConnectionPool::EIO_AfterGetConnection(uv_work_t* req) { Nan::HandleScope scope; ConnectionPoolBaton* baton = CONTAINER_OF(req, ConnectionPoolBaton, work_req); Local<Value> argv[2]; if (baton->error) { argv[0] = Nan::Error(baton->error->c_str()); argv[1] = Nan::Undefined(); } else { argv[0] = Nan::Undefined(); Local<FunctionTemplate> ft = Nan::New(Connection::s_ct); Local<Object> connection = ft->GetFunction()->NewInstance(); (Nan::ObjectWrap::Unwrap<Connection>(connection))->setConnection( baton->connectionPool->getEnvironment(), baton->connectionPool, baton->connection); argv[1] = connection; } Nan::TryCatch tryCatch; baton->callback->Call(2, argv); delete baton; if (tryCatch.HasCaught()) { Nan::FatalException(tryCatch); } }
void ILob::Async_AfterWrite(uv_work_t *req) { Nan::HandleScope scope; LobBaton *lobBaton = (LobBaton *)req->data; ILob *iLob = lobBaton->iLob; Nan::TryCatch tc; Local<Value> argv[1]; iLob->state_ = INACTIVE; // mark Lob as inactive as back in main thread if(!(lobBaton->error).empty()) argv[0] = v8::Exception::Error(Nan::New<v8::String>((lobBaton->error).c_str()).ToLocalChecked()); else argv[0] = Nan::Undefined(); Local<Function> callback = Nan::New<Function>(lobBaton->cb); delete lobBaton; Nan::MakeCallback(Nan::GetCurrentContext()->Global(), callback, 1, argv); if(tc.HasCaught()) { Nan::FatalException(tc); } }
/* DESCRIPTION Callback function of close method PARAMETERS: UV queue work block */ void ILob::Async_AfterClose(uv_work_t *req) { Nan::HandleScope scope; LobBaton *lobBaton = ( LobBaton * ) req->data; ILob *iLob = lobBaton->iLob; Nan::TryCatch tc; if ( !lobBaton->errOnActiveOrInvalid ) { iLob->state_ = NJS_INACTIVE; } Local<Value> argv[1]; if( !lobBaton->error.empty () ) argv[0] = v8::Exception::Error( Nan::New<v8::String> ( lobBaton->error ).ToLocalChecked () ); else { argv[0] = Nan::Undefined (); iLob->cleanupNJS (); } Local<Function> callback = Nan::New<Function> ( lobBaton->cb ); delete lobBaton; Nan::MakeCallback( Nan::GetCurrentContext()->Global(), callback, 1, argv ); if( tc.HasCaught () ) { Nan::FatalException ( tc ); } }
/* DESCRIPTION Callback function of terminate PARAMETERS: UV queue work block */ void Pool::Async_AfterTerminate(uv_work_t *req) { Nan::HandleScope scope; poolBaton *terminateBaton = (poolBaton*)req->data; Nan::TryCatch tc; Local<Value> argv[1]; if(!(terminateBaton->error).empty()) { argv[0] = v8::Exception::Error(Nan::New<v8::String>((terminateBaton->error).c_str()).ToLocalChecked()); } else { argv[0] = Nan::Undefined(); // pool is not valid after terminate succeeds. terminateBaton-> njspool-> isValid_ = false; } Local<Function> callback = Nan::New<Function>(terminateBaton->cb); delete terminateBaton; Nan::MakeCallback( Nan::GetCurrentContext()->Global(), callback, 1, argv ); if(tc.HasCaught()) { Nan::FatalException(tc); } }
/* DESCRIPTION Callback function of Get Connection method PARAMETERS: UV queue work block status - expected to be non-zero. NOTES: Connection handle is formed and handed over to JS. */ void Pool::Async_AfterGetConnection(uv_work_t *req) { Nan::HandleScope scope; poolBaton *connBaton = (poolBaton*)req->data; Nan::TryCatch tc; Local<Value> argv[2]; if(!(connBaton->error).empty()) { argv[0] = v8::Exception::Error(Nan::New<v8::String>((connBaton->error).c_str()).ToLocalChecked()); argv[1] = Nan::Undefined(); } else { argv[0] = Nan::Undefined(); Local<FunctionTemplate> lft = Nan::New(Connection::connectionTemplate_s); Local<Object> connection = lft->GetFunction()-> NewInstance(); (Nan::ObjectWrap::Unwrap<Connection> (connection))-> setConnection( connBaton->dpiconn, connBaton->njspool->oracledb_ ); argv[1] = connection; } Local<Function> callback = Nan::New<Function>(connBaton->cb); delete connBaton; Nan::MakeCallback( Nan::GetCurrentContext()->Global(), callback, 2, argv ); if(tc.HasCaught()) { Nan::FatalException(tc); } }
inline v8::Local<v8::Object> node::Function::construct(v8::Isolate* isolate, const v8::Local<v8::Function> &function, size_t argc, const v8::Local<v8::Value> arguments[]) { Nan::TryCatch trycatch; auto result = Nan::NewInstance(function, (int)argc, const_cast<v8::Local<v8::Value>*>(arguments)); if (trycatch.HasCaught()) { throw node::Exception(isolate, trycatch.Exception()); } return result.ToLocalChecked(); }
void ILob::Async_AfterRead(uv_work_t *req) { Nan::HandleScope scope; LobBaton *lobBaton = (LobBaton *)req->data; ILob *iLob = lobBaton->iLob; Nan::TryCatch tc; Local<Value> argv[2]; if ( !lobBaton->errOnActiveOrInvalid ) { iLob->state_ = NJS_INACTIVE; // mark Lob as inactive as back in main thread } if(!(lobBaton->error).empty()) { argv[0] = v8::Exception::Error( Nan::New<v8::String>(lobBaton->error).ToLocalChecked()); argv[1] = Nan::Undefined(); } else { argv[0] = Nan::Undefined(); if (iLob->amountRead_) { if (iLob->dpiLobType_ == DpiClob) { Local<Value> str = Nan::New<v8::String>((char *)iLob->buf_, iLob->amountRead_).ToLocalChecked(); argv[1] = str; } else { // Blobs use buffers rather than strings // TODO: We could use NewBuffer to save memory and CPU, but it gets the ownership of buffer to itself (behaviour changed in Nan 2.0) Local<Value> buffer = Nan::CopyBuffer((char *)iLob->buf_, iLob->amountRead_).ToLocalChecked(); argv[1] = buffer; } } else argv[1] = Nan::Null(); } Local<Function> callback = Nan::New<Function>(lobBaton->cb); delete lobBaton; Nan::MakeCallback(Nan::GetCurrentContext()->Global(), callback, 2, argv); if(tc.HasCaught()) { Nan::FatalException(tc); } }
inline v8::Local<v8::Value> node::Function::callback(v8::Isolate* isolate, const v8::Local<v8::Function> &function, const v8::Local<v8::Object> &this_object, size_t argc, const v8::Local<v8::Value> arguments[]) { Nan::TryCatch trycatch; auto recv = this_object.IsEmpty() ? isolate->GetCurrentContext()->Global() : this_object; auto result = Nan::MakeCallback(recv, function, (int)argc, const_cast<v8::Local<v8::Value>*>(arguments)); if (trycatch.HasCaught()) { throw node::Exception(isolate, trycatch.Exception()); } return result; }
/* DESCRIPTION Callback function of GetRows method PARAMETERS: req - UV queue work block */ void ResultSet::Async_AfterGetRows(uv_work_t *req) { Nan::HandleScope scope; rsBaton *getRowsBaton = (rsBaton*)req->data; Nan::TryCatch tc; Local<Value> argv[2]; if(!(getRowsBaton->error).empty()) { argv[0] = v8::Exception::Error( Nan::New<v8::String>(getRowsBaton->error).ToLocalChecked()); argv[1] = Nan::Undefined(); } else { argv[0] = Nan::Undefined(); eBaton* ebaton = getRowsBaton->ebaton; ebaton->outFormat = getRowsBaton->njsRS->outFormat_; Local<Value> rowsArray = Nan::New<v8::Array>(0), rowsArrayValue = Nan::Null(); if(ebaton->rowsFetched) { rowsArray = Connection::GetRows(ebaton); if(!(ebaton->error).empty()) { argv[0] = v8::Exception::Error( Nan::New<v8::String>(ebaton->error).ToLocalChecked()); argv[1] = Nan::Undefined(); goto exitAsyncAfterGetRows; } rowsArrayValue = Local<Array>::Cast(rowsArray)->Get(0); } argv[1] = (getRowsBaton->fetchMultiple) ? rowsArray : rowsArrayValue; } exitAsyncAfterGetRows: if(!getRowsBaton->errOnActiveOrInvalid) { getRowsBaton->njsRS->state_ = NJS_INACTIVE; } Local<Function> callback = Nan::New(getRowsBaton->ebaton->cb); delete getRowsBaton; Nan::MakeCallback(Nan::GetCurrentContext()->Global(), callback, 2, argv); if(tc.HasCaught()) { Nan::FatalException(tc); } }
/* DESCRIPTION Callback function of close PARAMETERS: req - UV queue work block */ void ResultSet::Async_AfterClose(uv_work_t *req) { Nan::HandleScope scope; rsBaton *closeBaton = (rsBaton*)req->data; Nan::TryCatch tc; Local<Value> argv[1]; if(!(closeBaton->error).empty()) { argv[0] = v8::Exception::Error( Nan::New<v8::String>(closeBaton->error).ToLocalChecked()); if(!closeBaton->errOnActiveOrInvalid) { closeBaton->njsRS->state_ = NJS_INACTIVE; } } else { argv[0] = Nan::Undefined(); // resultset is not valid after close succeeds. closeBaton-> njsRS-> state_ = NJS_INVALID; } /* * When we close the resultSet, we have to clear the reference of * its parent. */ closeBaton->njsRS->jsParent_.Reset (); Local<Function> callback = Nan::New(closeBaton->ebaton->cb); delete closeBaton; Nan::MakeCallback( Nan::GetCurrentContext()->Global(), callback, 1, argv ); if(tc.HasCaught()) { Nan::FatalException(tc); } }
void Connection::EIO_AfterClose(uv_work_t* req) { Nan::HandleScope scope; ConnectionBaton* baton = CONTAINER_OF(req, ConnectionBaton, work_req); baton->connection->Unref(); Nan::TryCatch tryCatch; if (baton->callback != NULL) { Local<Value> argv[2]; if (baton->error) { argv[0] = Nan::Error(baton->error->c_str()); argv[1] = Nan::Undefined(); } else { argv[0] = Nan::Undefined(); argv[1] = Nan::Undefined(); } baton->callback->Call(2, argv); } delete baton; if (tryCatch.HasCaught()) { Nan::FatalException(tryCatch); } }
void EIO_AfterCallJs(uv_work_t* req, int status) { #else void EIO_AfterCallJs(uv_work_t* req) { #endif DynamicProxyData* dynamicProxyData = static_cast<DynamicProxyData*>(req->data); if(!dynamicProxyDataVerify(dynamicProxyData)) { return; } dynamicProxyData->result = NULL; JNIEnv* env; int ret = dynamicProxyData->java->getJvm()->GetEnv((void**)&env, JNI_BEST_VERSION); if (ret != JNI_OK) { dynamicProxyData->throwableClass = "java/lang/IllegalStateException"; dynamicProxyData->throwableMessage = "Could not retrieve JNIEnv: jvm->GetEnv returned " + to_string<int>(ret); dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } Nan::HandleScope scope; v8::Array* v8Args; v8::Function* fn; v8::Handle<v8::Value>* argv; int argc; int i; v8::Local<v8::Value> v8Result; jobject javaResult; v8::Local<v8::Object> dynamicProxyDataFunctions = Nan::New(dynamicProxyData->functions); v8::Local<v8::Value> fnObj = dynamicProxyDataFunctions->Get(Nan::New<v8::String>(dynamicProxyData->methodName.c_str()).ToLocalChecked()); if(fnObj->IsUndefined() || fnObj->IsNull()) { dynamicProxyData->throwableClass = "java/lang/NoSuchMethodError"; dynamicProxyData->throwableMessage = "Could not find js function " + dynamicProxyData->methodName; dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } if(!fnObj->IsFunction()) { dynamicProxyData->throwableClass = "java/lang/IllegalStateException"; dynamicProxyData->throwableMessage = dynamicProxyData->methodName + " is not a function"; dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } fn = v8::Function::Cast(*fnObj); if(dynamicProxyData->args) { v8Args = v8::Array::Cast(*javaArrayToV8(dynamicProxyData->java, env, dynamicProxyData->args)); argc = v8Args->Length(); } else { argc = 0; } argv = new v8::Handle<v8::Value>[argc]; for(i=0; i<argc; i++) { argv[i] = v8Args->Get(i); } Nan::TryCatch tryCatch; tryCatch.SetCaptureMessage(true); v8Result = fn->Call(dynamicProxyDataFunctions, argc, argv); delete[] argv; if (tryCatch.HasCaught()) { dynamicProxyData->throwableClass = "node/NodeJsException"; v8::String::Utf8Value message(tryCatch.Message()->Get()); dynamicProxyData->throwableMessage = std::string(*message); tryCatch.Reset(); dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } if(!dynamicProxyDataVerify(dynamicProxyData)) { return; } javaResult = v8ToJava(env, v8Result); if(javaResult == NULL) { dynamicProxyData->result = NULL; } else { dynamicProxyData->result = env->NewGlobalRef(javaResult); } dynamicProxyData->done = true; }
/* * Tcl proc to embed Javascript */ int jsEval( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ){ v8log("TclBinding::jsEval (interp=%p)\n", interp); // Get handle to the V8 Isolate for this Tcl interpreter Isolate* isolate = v8::Isolate::GetCurrent(); assert(isolate != nullptr); // lock the Isolate for multi-threaded access (not reentrant on its own) Locker locker(isolate); // create a bindings map and store it in the current V8 Isolate TclVariableBindingsMap* varbindings = new TclVariableBindingsMap; isolate->SetData(0, varbindings); v8log("jsEval: created new bindings map at %lp\n", (void*)varbindings ); // validate input params if ( (objc != 3) ) { std::string msg("usage: jsEval [list of tcl vars to add to v8 context] { javascript }"); Tcl_SetObjResult(interp, Tcl_NewStringObj(msg.c_str(), msg.length())); return TCL_ERROR; } // get the argument list Tcl_Obj* arglist = objv[1]; if ( (arglist->typePtr == NULL) || strcmp(arglist->typePtr->name, "list") ) { std::string msg("jsEval: 1st arg not a list"); Tcl_SetObjResult(interp, Tcl_NewStringObj(msg.c_str(), msg.length())); return TCL_ERROR; } // get the JS snippet char* javascript = Tcl_GetString(objv[2]); if ( strlen(javascript) == 0 ) { std::string msg("jsEval: 2nd arg not a string"); Tcl_SetObjResult(interp, Tcl_NewStringObj(msg.c_str(), msg.length())); return TCL_ERROR; } // Create stack-allocated isolate and handle scopes. Isolate::Scope isolate_scope(isolate); HandleScope handle_scope(isolate); // new v8 global template Handle<ObjectTemplate> global_templ = ObjectTemplate::New(isolate); // scrum our F18 Interceptors global_templ->SetNamedPropertyHandler( &TclVariableBinding::GenericNamedPropertyReader, &TclVariableBinding::GenericNamedPropertyWriter ); // Create and Enter a new context for compiling and running the script. Handle<Context> context = Context::New(isolate, NULL, global_templ); context->Enter(); int arglistLength; Tcl_ListObjLength(interp, arglist, &arglistLength); v8log("arg list length == %d\n", arglistLength); for ( int i = 0; i < arglistLength; i++ ) { // get the variable NAME Tcl_Obj* varName; Tcl_ListObjIndex(interp, arglist, i, &varName); char* vn = Tcl_GetString(varName); v8log("binding %s (idx: %d) to V8\n", vn, i); // then create a binding and store it (*varbindings)[vn] = new TclVariableBinding(interp, varName); } // Compile v8log("compiling jsEval'ed script\n"); v8::MaybeLocal<v8::Script> jsSource = v8::Script::Compile(context, Nan::New<String>(javascript).ToLocalChecked()); if (jsSource.IsEmpty()) { v8log("*** jsSource.IsEmpty()\n"); } else { // Run v8log("running jsEval'ed script\n"); Nan::TryCatch tc; Nan::MaybeLocal<v8::Value> retv = jsSource.ToLocalChecked()->Run(); v8log("done running jsEval'ed script\n"); if ( tc.HasCaught() ) { // oops, exception raised from V8 while in JS land Local<Message> msg = tc.Message(); std::string msgtext(*String::Utf8Value(msg->Get())); v8log("*** caught JS exception: %s\n", msgtext.c_str()); } TclVariableBindingsMap::const_iterator it; for (it = varbindings->begin(); it != varbindings->end(); it++) { TclVariableBinding* vb = it->second; v8log("reverse mapping of %s (v8: %p) to Tcl...\n", it->first.c_str(), vb->m_v8val); Tcl_SetVar2Ex(vb->m_interp, it->first.c_str(), NULL, vb->m_tclvar, 0); delete vb; } varbindings->clear(); // handle return value, if there is one if (!retv.IsEmpty()) { Local<Value> rv = retv.ToLocalChecked(); std::string res(*String::Utf8Value(rv)); std::string restype(V8ValueType(rv)); v8log("Tcl_SetObjResult(interp == %lp, result == %s (%s)\n", (void*) interp, res.c_str(), restype.c_str()); Tcl_Obj* tclres = V8ToTcl(interp, rv); Tcl_SetObjResult(interp, tclres); } delete varbindings; } context->Exit(); // TODO: error handling! return TCL_OK; }