Example #1
0
/*
 * 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;
}
Example #2
0
void* worker_routine(void *vdbc) {

    struct dbcontext * dbc = (struct dbcontext *) vdbc;
    
    //allocate array for objects that will be automatically removed after 
    th_alloc_array(1000);
    
    //  Socket to talk to dispatcher
    void *receiver = zmq_socket (dbc->context, ZMQ_REP);
    zmq_connect (receiver, "inproc://workers");

    //Initialize our Isoloate
    Isolate *isolate = Isolate::New();
    if(!isolate)
    {
        cout << "Failed to initialize Isolate, we can't work";
        return 0;
    }
    
    Locker lock(isolate);
    Isolate::Scope isolateScope(isolate);
    HandleScope scope;
    
    Local<ObjectTemplate> globals = ObjectTemplate::New();
    
#define SETGLOB(name) globals->Set(String::New(""#name), FunctionTemplate::New(name));

    globals->Set(String::New("addnum"), FunctionTemplate::New(addnum));
    SETGLOB(print)
    
    globals->Set(String::New("put"), FunctionTemplate::New(put));
    globals->Set(String::New("get"), FunctionTemplate::New(get));
    globals->Set(String::New("del"), FunctionTemplate::New(del));
    
    //iterator
    globals->Set(String::New("it_del"), FunctionTemplate::New(it_del));
    globals->Set(String::New("it_new"), FunctionTemplate::New(it_new));
    globals->Set(String::New("it_first"), FunctionTemplate::New(it_first));
    globals->Set(String::New("it_last"), FunctionTemplate::New(it_last));
    globals->Set(String::New("it_seek"), FunctionTemplate::New(it_seek));
    globals->Set(String::New("it_next"), FunctionTemplate::New(it_next));
    globals->Set(String::New("it_prev"), FunctionTemplate::New(it_prev));
    globals->Set(String::New("it_valid"), FunctionTemplate::New(it_valid));
    globals->Set(String::New("it_key"), FunctionTemplate::New(it_key));
    globals->Set(String::New("it_val"), FunctionTemplate::New(it_val));

    //BITSET
    SETGLOB(bs_new)
    SETGLOB(bs_reset)
    SETGLOB(bs_set)
    SETGLOB(bs_logicalor)
    SETGLOB(bs_logicalnot)
    SETGLOB(bs_inplace_logicalnot)
    SETGLOB(bs_logicaland)
    SETGLOB(bs_sparselogicaland)
    SETGLOB(bs_tostring)
    SETGLOB(bs_makeSameSize)
    SETGLOB(bs_eq)
    SETGLOB(putbs)
    SETGLOB(getbs)
    SETGLOB(bs_it_new)
    SETGLOB(bs_it_end)
    SETGLOB(bs_it_isend)
    SETGLOB(bs_it_next)
    SETGLOB(bs_it_val)
    SETGLOB(bs_it_end)
    SETGLOB(bs_it_eq)
    
    
    Handle<Context> context = Context::New(NULL, globals);
    context->Enter();
    
    //Running init script with library functions
 
    if (dbc->init_code != NULL) {
        TryCatch try_catch;
        
        Local<String> source = String::New(dbc->init_code);
        Local<Script> script = Script::Compile(source);
        
        if(script.IsEmpty())
        {
            ReportException(&try_catch);
        } else {        
            // Run the function once and catch the error to generate machine code
            Local<Value> result = script->Run();
        }
        
    }
        
    while (1) {
        
        zmq_msg_t req;
        int rc = zmq_msg_init (&req);
        assert (rc == 0);
        rc = zmq_recv (receiver, &req, 0);
        assert (rc == 0);
        
        zmq_msg_t reply;
        //rc = zmq_msg_init_size (&reply, 200);
        //assert (rc == 0);

//test mq speed only
#if 0
        
        rc = zmq_msg_init_size (&reply, 200);
        assert (rc == 0);
        rc = zmq_msg_copy (&reply, &req);
        assert (rc == 0);
        rc = zmq_send (receiver, &reply, 0); 
        assert (rc == 0);
        
        //s_sleep(1);
        
        zmq_msg_close (&req);
        zmq_msg_close (&reply);
        continue;
#endif

        //std::cout << "thread: " << pthread_self() << " Received script: " << (char*) zmq_msg_data(&req) << std::endl;

        //leveldb::Status s;
 
 #if 1
        Context::Scope contextScope(context);
        
        // Compile a function which will keep using the stack until v8 cuts it off
        
        //Local<Script> script = Local<Script>::New(Script::Compile(String::New( (char*) zmq_msg_data(&req) )));
        
        TryCatch try_catch;
        
        Local<String> source = String::New((char*) zmq_msg_data(&req));
        Local<Script> script = Script::Compile(source);
        
        if(script.IsEmpty())
        {
            ReportException(&try_catch);
            
            String::Utf8Value error(try_catch.Exception());
            v8::Handle<v8::Message> message = try_catch.Message();
            int line_num = 0;
            int col_num = 0;
            
            if (message.IsEmpty()) {
                
            }else {
                line_num = message->GetLineNumber();
                col_num = message->GetStartColumn();
            }
            
            int mess_size = error.length()+100;
            rc = zmq_msg_init_size (&reply, mess_size);
            assert (rc == 0);

            //cerr << "compile error line: " << " message: " << *error << endl;
            snprintf ((char*) zmq_msg_data (&reply), mess_size, "2; {res: 'COMPILE ERROR', line: %d, col: %d, message: '%s'}", line_num, col_num, *error);
        }
        else {        

            // Run the function once and catch the error to generate machine code
            Local<Value> result = script->Run();
                    
            if (try_catch.HasCaught()) {
                //TODO: escape string
                String::Utf8Value message(try_catch.Exception());
                int mess_size = message.length()+100;
                rc = zmq_msg_init_size (&reply, mess_size);
                assert (rc == 0);

                std::cout <<"exception->" <<*message <<"\n";
                snprintf ((char*) zmq_msg_data (&reply), mess_size, "1; {res: 'ERROR', message: '%s'}", *message);
            }
            else {
                //TODO: escape string
                String::Utf8Value message(result->ToString());
                int mess_size = message.length()+2;
                rc = zmq_msg_init_size (&reply, mess_size);
                assert (rc == 0);

                snprintf ((char*) zmq_msg_data (&reply), mess_size, " %s", *message);
            }
        }        

#endif
                
        
        /* Send the message to the socket */
        rc = zmq_send (receiver, &reply, 0); 
        assert (rc == 0);
        
        //s_sleep(1);
        
        zmq_msg_close (&req);
        zmq_msg_close (&reply);
        
        free_objects();
    }
    
    context->Exit();    
    //printf("Iter: %d , Result: %ld ; from thread: %ld \n", i, res, tid);
        
    //context.Dispose();
    
    //script.Dispose();
    
    Unlocker unlock(isolate);
    
    //isolate->Exit();
    //isolate->Dispose();

    zmq_close (receiver);
    return NULL;
}
Example #3
0
File: context.cpp Project: sol/v8
void c_contextEnter(Handle<Context> context) {
  context->Enter();
}