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; }
Handle< Value > V8Scope::nativeCallback( const Arguments &args ) { Local< External > f = External::Cast( *args.Callee()->Get( v8::String::New( "_native_function" ) ) ); NativeFunction function = ( NativeFunction )( f->Value() ); BSONObjBuilder b; for( int i = 0; i < args.Length(); ++i ) { stringstream ss; ss << i; v8ToMongoElement( b, v8::String::New( "foo" ), ss.str(), args[ i ] ); } BSONObj ret; try { ret = function( b.done() ); } catch( const std::exception &e ) { return v8::ThrowException(v8::String::New(e.what())); } catch( ... ) { return v8::ThrowException(v8::String::New("unknown exception")); } return mongoToV8Element( ret.firstElement() ); }
void V8Scope::setElement( const char *field , const BSONElement& e ){ V8_SIMPLE_HEADER _global->Set( v8::String::New( field ) , mongoToV8Element( e ) ); }
v8::Handle<v8::Value> get( v8::Local<v8::String> name ){ const string& s = toSTLString( name ); const BSONElement& e = _o->getField( s ); return mongoToV8Element(e); }
Local<v8::Object> mongoToV8( const BSONObj& m , bool array ){ // handle DBRef. needs to come first. isn't it? (metagoto) static string ref = "$ref"; if ( ref == m.firstElement().fieldName() ) { const BSONElement& id = m["$id"]; if (!id.eoo()) { // there's no check on $id exitence in sm implementation. risky ? v8::Function* dbRef = getNamedCons( "DBRef" ); v8::Handle<v8::Value> argv[2]; argv[0] = mongoToV8Element(m.firstElement()); argv[1] = mongoToV8Element(m["$id"]); return dbRef->NewInstance(2, argv); } } Local<v8::Object> o; if ( array ) o = v8::Array::New(); else o = v8::Object::New(); mongo::BSONObj sub; for ( BSONObjIterator i(m); i.more(); ) { const BSONElement& f = i.next(); Local<Value> v; switch ( f.type() ){ case mongo::Code: cout << "warning, code saved in database just turned into string right now" << endl; case mongo::String: o->Set( v8::String::New( f.fieldName() ) , v8::String::New( f.valuestr() ) ); break; case mongo::jstOID: { v8::Function * idCons = getObjectIdCons(); v8::Handle<v8::Value> argv[1]; argv[0] = v8::String::New( f.__oid().str().c_str() ); o->Set( v8::String::New( f.fieldName() ) , idCons->NewInstance( 1 , argv ) ); break; } case mongo::NumberDouble: case mongo::NumberInt: o->Set( v8::String::New( f.fieldName() ) , v8::Number::New( f.number() ) ); break; case mongo::Array: case mongo::Object: sub = f.embeddedObject(); o->Set( v8::String::New( f.fieldName() ) , mongoToV8( sub , f.type() == mongo::Array ) ); break; case mongo::Date: o->Set( v8::String::New( f.fieldName() ) , v8::Date::New( f.date() ) ); break; case mongo::Bool: o->Set( v8::String::New( f.fieldName() ) , v8::Boolean::New( f.boolean() ) ); break; case mongo::jstNULL: o->Set( v8::String::New( f.fieldName() ) , v8::Null() ); break; case mongo::RegEx: { v8::Function * regex = getNamedCons( "RegExp" ); v8::Handle<v8::Value> argv[2]; argv[0] = v8::String::New( f.regex() ); argv[1] = v8::String::New( f.regexFlags() ); o->Set( v8::String::New( f.fieldName() ) , regex->NewInstance( 2 , argv ) ); break; } case mongo::BinData: { Local<v8::Object> b = v8::Object::New(); int len; f.binData( len ); b->Set( v8::String::New( "subtype" ) , v8::Number::New( f.binDataType() ) ); b->Set( v8::String::New( "length" ) , v8::Number::New( len ) ); o->Set( v8::String::New( f.fieldName() ) , b ); break; }; case mongo::Timestamp: { Local<v8::Object> sub = v8::Object::New(); sub->Set( v8::String::New( "time" ) , v8::Date::New( f.timestampTime() ) ); sub->Set( v8::String::New( "i" ) , v8::Number::New( f.timestampInc() ) ); o->Set( v8::String::New( f.fieldName() ) , sub ); break; } case mongo::MinKey: // TODO: make a special type o->Set( v8::String::New( f.fieldName() ) , v8::String::New( "MinKey" ) ); break; case mongo::MaxKey: // TODO: make a special type o->Set( v8::String::New( f.fieldName() ) , v8::String::New( "MaxKey" ) ); break; default: cout << "can't handle type: "; cout << f.type() << " "; cout << f.toString(); cout << endl; break; } } return o; }