Example #1
0
 void operator()() {
     Locker l;
     HandleScope handle_scope;
     Handle< Context > context;
     Handle< v8::Function > fun;
     auto_ptr< V8Scope > scope;
     if ( config_.newScope_ ) {
         scope.reset( dynamic_cast< V8Scope * >( globalScriptEngine->newScope() ) );
         context = scope->context();
         // A v8::Function tracks the context in which it was created, so we have to
         // create a new function in the new context.
         Context::Scope baseScope( baseContext_ );
         string fCode = toSTLString( config_.f_->ToString() );
         Context::Scope context_scope( context );
         fun = scope->__createFunction( fCode.c_str() );
     } else {
         context = baseContext_;
         Context::Scope context_scope( context );
         fun = config_.f_;
     }
     Context::Scope context_scope( context );
     boost::scoped_array< Local< Value > > argv( new Local< Value >[ config_.args_.size() ] );
     for( unsigned int i = 0; i < config_.args_.size(); ++i )
         argv[ i ] = Local< Value >::New( config_.args_[ i ] );
     TryCatch try_catch;
     Handle< Value > ret = fun->Call( context->Global(), config_.args_.size(), argv.get() );
     if ( ret.IsEmpty() ) {
         string e = toSTLString( &try_catch );
         log() << "js thread raised exception: " << e << endl;
         // v8 probably does something sane if ret is empty, but not going to assume that for now
         ret = v8::Undefined();
     }
     config_.returnData_ = Persistent< Value >::New( ret );
 }
Example #2
0
            void operator()() {
                V8Scope* scope = config_._scope.get();
                v8::Isolate::Scope iscope(scope->getIsolate());
                v8::Locker l(scope->getIsolate());
                HandleScope handle_scope;
                Context::Scope context_scope( scope->getContext() );

                BSONObj args = config_.args_;
                Local< v8::Function > f = v8::Function::Cast( *(scope->mongoToV8Element(args.firstElement(), true)) );
                int argc = args.nFields() - 1;

                boost::scoped_array< Local< Value > > argv( new Local< Value >[ argc ] );
                BSONObjIterator it(args);
                it.next();
                for( int i = 0; i < argc; ++i ) {
                    argv[ i ] = Local< Value >::New( scope->mongoToV8Element(*it, true) );
                    it.next();
                }
                TryCatch try_catch;
                Handle< Value > ret = f->Call( scope->getContext()->Global(), argc, argv.get() );
                if ( ret.IsEmpty() ) {
                    string e = toSTLString( &try_catch );
                    log() << "js thread raised exception: " << e << endl;
                    // v8 probably does something sane if ret is empty, but not going to assume that for now
                    ret = v8::Undefined();
                }
                // ret is translated to BSON to switch isolate
                BSONObjBuilder b;
                scope->v8ToMongoElement(b, "ret", ret);
                config_.returnData_ = b.obj();
            }
Example #3
0
    int V8Scope::invoke( ScriptingFunction func , const BSONObj& argsObject, int timeoutMs , bool ignoreReturn ){
        Handle<Value> funcValue = _funcs[func-1];
        
        TryCatch try_catch;        
        int nargs = argsObject.nFields();
        auto_ptr< Handle<Value> > args;
        if ( nargs ){
            args.reset( new Handle<Value>[nargs] );
            BSONObjIterator it( argsObject );
            for ( int i=0; i<nargs; i++ ){
                BSONElement next = it.next();
                args.get()[i] = mongoToV8Element( next );
            }
        }
        Local<Value> result = ((v8::Function*)(*funcValue))->Call( _this , nargs , args.get() );
                
        if ( result.IsEmpty() ){
            stringstream ss;
            ss << "error in invoke: " << toSTLString( &try_catch );
            _error = ss.str();
            log() << _error << endl;
            return 1;
        }

        if ( ! ignoreReturn ){
            _global->Set( v8::String::New( "return" ) , result );
        }

        return 0;
    }
Example #4
0
            void operator()() {
                config_._scope.reset( dynamic_cast< V8Scope * >( globalScriptEngine->newScope() ) );
                v8::Locker v8lock(config_._scope->getIsolate());
                v8::Isolate::Scope iscope(config_._scope->getIsolate());
                HandleScope handle_scope;
                Context::Scope context_scope(config_._scope->getContext());

                BSONObj args = config_.args_;
                Local< v8::Function > f = v8::Function::Cast( *(config_._scope->mongoToV8Element(args.firstElement(), true)) );
                int argc = args.nFields() - 1;

                // TODO SERVER-8016: properly allocate handles on the stack
                Local<Value> argv[24];
                BSONObjIterator it(args);
                it.next();
                for(int i = 0; i < argc && i < 24; ++i) {
                    argv[i] = Local< Value >::New(config_._scope->mongoToV8Element(*it, true));
                    it.next();
                }
                TryCatch try_catch;
                Handle<Value> ret = f->Call(config_._scope->getContext()->Global(), argc, argv);
                if (ret.IsEmpty() || try_catch.HasCaught()) {
                    string e = toSTLString( &try_catch );
                    log() << "js thread raised exception: " << e << endl;
                    // v8 probably does something sane if ret is empty, but not going to assume that for now
                    ret = v8::Undefined();
                }
                // ret is translated to BSON to switch isolate
                BSONObjBuilder b;
                config_._scope->v8ToMongoElement(b, "ret", ret);
                config_.returnData_ = b.obj();
            }
Example #5
0
    BSONObj v8ToMongo( v8::Handle<v8::Object> o ){
        BSONObjBuilder b;

        v8::Handle<v8::String> idName = v8::String::New( "_id" );
        if ( o->HasRealNamedProperty( idName ) ){
            v8ToMongoElement( b , idName , "_id" , o->Get( idName ) );
        }
    
        Local<v8::Array> names = o->GetPropertyNames();
        for ( unsigned int i=0; i<names->Length(); i++ ){
            v8::Local<v8::String> name = names->Get(v8::Integer::New(i) )->ToString();

            if ( o->GetPrototype()->IsObject() &&
                 o->GetPrototype()->ToObject()->HasRealNamedProperty( name ) )
                continue;
        
            v8::Local<v8::Value> value = o->Get( name );
        
            const string sname = toSTLString( name );
            if ( sname == "_id" )
                continue;

            v8ToMongoElement( b , name , sname , value );
        }
        return b.obj();
    }
Example #6
0
    bool V8Scope::exec( const string& code , const string& name , bool printResult , bool reportError , bool assertOnError, int timeoutMs ){

        if ( timeoutMs ){
            static bool t = 1;
            if ( t ){
                log() << "timeoutMs not support for v8 yet" << endl;
                t = 0;
            }
        }
        
        HandleScope handle_scope;
        TryCatch try_catch;
    
        Handle<Script> script = v8::Script::Compile( v8::String::New( code.c_str() ) , 
                                                     v8::String::New( name.c_str() ) );
        if (script.IsEmpty()) {
            stringstream ss;
            ss << "compile error: " << toSTLString( &try_catch );
            _error = ss.str();
            if (reportError)
                log() << _error << endl;
            if ( assertOnError )
                uassert( _error , 0 );
            return false;
        } 
    
        Handle<v8::Value> result = script->Run();
        if ( result.IsEmpty() ){
            _error = (string)"exec error: " + toSTLString( &try_catch );
            if ( reportError )
                log() << _error << endl;
            if ( assertOnError )
                uassert( _error , 0 );
            return false;
        } 
        
        _global->Set( v8::String::New( "__lastres__" ) , result );

        if ( printResult && ! result->IsUndefined() ){
            cout << toSTLString( result ) << endl;
        }
        
        return true;
    }
Example #7
0
    ScriptingFunction V8Scope::_createFunction( const char * raw ){
        
        string code = raw;
        if ( code.find( "function" ) == string::npos ){
            if ( code.find( "\n" ) == string::npos && 
                 code.find( "return" ) == string::npos &&
                 ( code.find( ";" ) == string::npos || code.find( ";" ) == code.size() - 1 ) ){
                code = "return " + code;
            }
            code = "function(){ " + code + "}";
        }
        
        int num = _funcs.size() + 1;

        string fn;
        {
            stringstream ss;
            ss << "_funcs" << num;
            fn = ss.str();
        }
        
        code = fn + " = " + code;

        TryCatch try_catch;
        Handle<Script> script = v8::Script::Compile( v8::String::New( code.c_str() ) , 
                                                     v8::String::New( fn.c_str() ) );
        if ( script.IsEmpty() ){
            _error = (string)"compile error: " + toSTLString( &try_catch );
            log() << _error << endl;
            return 0;
        }
        
        Local<Value> result = script->Run();
        if ( result.IsEmpty() ){
            _error = (string)"compile error: " + toSTLString( &try_catch );
            log() << _error << endl;
            return 0;
        }        
        
        Handle<Value> f = _global->Get( v8::String::New( fn.c_str() ) );
        uassert( "not a func" , f->IsFunction() );
        _funcs.push_back( f );
        return num;
    }
Example #8
0
    Handle< Value > V8Scope::loadCallback( const Arguments &args ) {
        HandleScope scope;
        Handle<External> field = Handle<External>::Cast(args.Data());
        void* ptr = field->Value();
        V8Scope* self = static_cast<V8Scope*>(ptr);

        Context::Scope context_scope(self->_context);
        for (int i = 0; i < args.Length(); ++i) {
            std::string filename(toSTLString(args[i]));
            if (!self->execFile(filename, false , true , false)) {
                return v8::ThrowException(v8::String::New((std::string("error loading file: ") + filename).c_str()));
            }
        }
        return v8::True();
    }
Example #9
0
	virtual void serialize(std::stringstream& ss, size_t sz) const
	{
		ss << toSTLString();
	}
Example #10
0
 string V8Scope::getString( const char *field ){ 
     return toSTLString( get( field ) );
 }
Example #11
0
 v8::Handle<v8::Value> get( v8::Local<v8::String> name ) {
     const string& s = toSTLString( name );
     const BSONElement& e = _o->getField( s );
     return _scope->mongoToV8Element(e);
 }
Example #12
0
    void v8ToMongoElement( BSONObjBuilder & b , v8::Handle<v8::String> name , const string sname , v8::Handle<v8::Value> value ){
        
        if ( value->IsString() ){
            if ( sname == "$where" )
                b.appendCode( sname.c_str() , toSTLString( value ).c_str() );
            else
                b.append( sname.c_str() , toSTLString( value ).c_str() );
            return;
        }
        
        if ( value->IsFunction() ){
            b.appendCode( sname.c_str() , toSTLString( value ).c_str() );
            return;
        }
    
        if ( value->IsNumber() ){
            b.append( sname.c_str() , value->ToNumber()->Value() );
            return;
        }
    
        if ( value->IsArray() ){
            BSONObj sub = v8ToMongo( value->ToObject() );
            b.appendArray( sname.c_str() , sub );
            return;
        }
    
        if ( value->IsDate() ){
            b.appendDate( sname.c_str() , Date_t(v8::Date::Cast( *value )->NumberValue()) );
            return;
        }
    
        if ( value->IsObject() ){
            string s = toSTLString( value );
            if ( s.size() && s[0] == '/' ){
                s = s.substr( 1 );
                string r = s.substr( 0 , s.find( "/" ) );
                string o = s.substr( s.find( "/" ) + 1 );
                b.appendRegex( sname.c_str() , r.c_str() , o.c_str() );
            }
            else if ( value->ToObject()->GetPrototype()->IsObject() &&
                      value->ToObject()->GetPrototype()->ToObject()->HasRealNamedProperty( v8::String::New( "isObjectId" ) ) ){
                OID oid;
                oid.init( toSTLString( value ) );
                b.appendOID( sname.c_str() , &oid );
            }
            else {
                BSONObj sub = v8ToMongo( value->ToObject() );
                b.append( sname.c_str() , sub );
            }
            return;
        }
    
        if ( value->IsBoolean() ){
            b.appendBool( sname.c_str() , value->ToBoolean()->Value() );
            return;
        }
    
        else if ( value->IsUndefined() ){
            return;
        }
    
        else if ( value->IsNull() ){
            b.appendNull( sname.c_str() );
            return;
        }

        cout << "don't know how to convert to mongo field [" << name << "]\t" << value << endl;
    }