SREVER-357 NumberLong support in v8 engine

This commit is contained in:
Aaron 2010-01-20 16:21:19 -08:00
parent 37d6be1908
commit fb093990ac
5 changed files with 101 additions and 4 deletions

View File

@ -521,7 +521,7 @@ namespace JSTests {
Scope * s = globalScriptEngine->newScope();
s->localConnect( "blah" );
BSONObjBuilder b;
long long val = (long long)( 0xdeadbeefbaddULL );
long long val = (long long)( 0xbabadeadbeefbaddULL );
b.append( "a", val );
BSONObj in = b.obj();
s->setObject( "a", in );

View File

@ -162,7 +162,7 @@ namespace mongo {
long long toNumberLongUnsafe( JSObject *o ) {
unsigned long long val =
( (unsigned long long)( getNumber( o , "top" ) ) << 32 ) +
( unsigned long long )( getNumber( o , "bottom" ) );
( unsigned )( getNumber( o , "bottom" ) );
return val;
}

View File

@ -49,6 +49,17 @@ namespace mongo {
return mongo;
}
v8::Handle<v8::FunctionTemplate> getNumberLongFunctionTemplate() {
v8::Local<v8::FunctionTemplate> numberLong = FunctionTemplate::New( numberLongInit );
v8::Local<v8::Template> proto = numberLong->PrototypeTemplate();
proto->Set( v8::String::New( "toString" ) , FunctionTemplate::New( numberLongToString ) );
proto->Set( v8::String::New( "toNumber" ) , FunctionTemplate::New( numberLongToNumber ) );
return numberLong;
}
void installDBTypes( Handle<ObjectTemplate>& global ){
v8::Local<v8::FunctionTemplate> db = FunctionTemplate::New( dbInit );
db->InstanceTemplate()->SetNamedPropertyHandler( collectionFallback );
@ -71,6 +82,8 @@ namespace mongo {
global->Set( v8::String::New("BinData") , FunctionTemplate::New( binDataInit ) );
global->Set( v8::String::New("NumberLong") , getNumberLongFunctionTemplate() );
}
void installDBTypes( Handle<v8::Object>& global ){
@ -95,6 +108,8 @@ namespace mongo {
global->Set( v8::String::New("BinData") , FunctionTemplate::New( binDataInit )->GetFunction() );
global->Set( v8::String::New("NumberLong") , getNumberLongFunctionTemplate()->GetFunction() );
BSONObjBuilder b;
b.appendMaxKey( "" );
b.appendMinKey( "" );
@ -531,6 +546,59 @@ namespace mongo {
return it;
}
v8::Handle<v8::Value> numberLongInit( const v8::Arguments& args ) {
if (args.Length() != 2) {
return v8::ThrowException( v8::String::New( "NumberLong needs 2 arguments" ) );
}
v8::Handle<v8::Object> it = args.This();
if ( it->IsUndefined() || it == v8::Context::GetCurrent()->Global() ){
v8::Function* f = getNamedCons( "NumberLong" );
it = f->NewInstance();
}
it->Set( v8::String::New( "top" ) , args[0] );
it->Set( v8::String::New( "bottom" ) , args[1] );
it->SetHiddenValue( v8::String::New( "__NumberLong" ), v8::Number::New( 1 ) );
return it;
}
v8::Handle<v8::Value> numberLongToString( const v8::Arguments& args ) {
if (args.Length() != 0) {
return v8::ThrowException( v8::String::New( "toString needs 0 arguments" ) );
}
v8::Handle<v8::Object> it = args.This();
unsigned long long val =
( (unsigned long long)( it->Get( v8::String::New( "top" ) )->ToInt32()->Value() ) << 32 ) +
(unsigned)( it->Get( v8::String::New( "bottom" ) )->ToInt32()->Value() );
stringstream ss;
ss << (long long)val;
string ret = ss.str();
return v8::String::New( ret.c_str() );
}
v8::Handle<v8::Value> numberLongToNumber( const v8::Arguments& args ) {
if (args.Length() != 0) {
return v8::ThrowException( v8::String::New( "toNumber needs 0 arguments" ) );
}
v8::Handle<v8::Object> it = args.This();
unsigned long long val =
( (unsigned long long)( it->Get( v8::String::New( "top" ) )->ToInt32()->Value() ) << 32 ) +
(unsigned)( it->Get( v8::String::New( "bottom" ) )->ToInt32()->Value() );
return v8::Number::New( double( (long long)val ) );
}
v8::Handle<v8::Value> bsonsize( const v8::Arguments& args ) {
if (args.Length() != 1 || !args[ 0 ]->IsObject()) {

View File

@ -60,6 +60,9 @@ namespace mongo {
v8::Handle<v8::Value> dbPointerInit( const v8::Arguments& args );
v8::Handle<v8::Value> binDataInit( const v8::Arguments& args );
v8::Handle<v8::Value> numberLongInit( const v8::Arguments& args );
v8::Handle<v8::Value> numberLongToString(const v8::Arguments& args);
v8::Handle<v8::Value> numberLongToNumber(const v8::Arguments& args);
v8::Handle<v8::Value> dbQueryInit( const v8::Arguments& args );
v8::Handle<v8::Value> dbQueryIndexAccess( uint32_t index , const v8::AccessorInfo& info );

View File

@ -149,7 +149,6 @@ namespace mongo {
case mongo::NumberDouble:
case mongo::NumberInt:
case mongo::NumberLong: // may lose information here - just copying sm engine behavior
o->Set( v8::String::New( f.fieldName() ) , v8::Number::New( f.number() ) );
break;
@ -208,6 +207,17 @@ namespace mongo {
break;
}
case mongo::NumberLong: {
Local<v8::Object> sub = readOnly ? readOnlyObjects->NewInstance() : internalFieldObjects->NewInstance();
unsigned long long val = f.numberLong();
v8::Function* numberLong = getNamedCons( "NumberLong" );
v8::Handle<v8::Value> argv[2];
argv[0] = v8::Integer::New( val >> 32 );
argv[1] = v8::Integer::New( (unsigned long)(val & 0x00000000ffffffff) );
o->Set( v8::String::New( f.fieldName() ), numberLong->NewInstance(2, argv) );
break;
}
case mongo::MinKey: {
Local<v8::Object> sub = readOnly ? readOnlyObjects->NewInstance() : internalFieldObjects->NewInstance();
sub->Set( v8::String::New( "$MinKey" ), v8::Boolean::New( true ) );
@ -325,6 +335,16 @@ namespace mongo {
return sub;
}
case mongo::NumberLong: {
Local<v8::Object> sub = internalFieldObjects->NewInstance();
unsigned long long val = f.numberLong();
v8::Function* numberLong = getNamedCons( "NumberLong" );
v8::Handle<v8::Value> argv[2];
argv[0] = v8::Integer::New( val >> 32 );
argv[1] = v8::Integer::New( (unsigned long)(val & 0x00000000ffffffff) );
return numberLong->NewInstance( 2, argv );
}
case mongo::MinKey: {
Local<v8::Object> sub = internalFieldObjects->NewInstance();
@ -431,10 +451,16 @@ namespace mongo {
oid.init( toSTLString( value ) );
b.appendOID( sname.c_str() , &oid );
}
else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__DBPointer" ) ).IsEmpty() ) {
else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__NumberLong" ) ).IsEmpty() ) {
// TODO might be nice to potentially speed this up with an indexed internal
// field, but I don't yet know how to use an ObjectTemplate with a
// constructor.
unsigned long long val =
( (unsigned long long)( value->ToObject()->Get( v8::String::New( "top" ) )->ToInt32()->Value() ) << 32 ) +
(unsigned)( value->ToObject()->Get( v8::String::New( "bottom" ) )->ToInt32()->Value() );
b.append( sname.c_str(), (long long)val );
}
else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__DBPointer" ) ).IsEmpty() ) {
OID oid;
oid.init( toSTLString( value->ToObject()->Get( v8::String::New( "id" ) ) ) );
string ns = toSTLString( value->ToObject()->Get( v8::String::New( "ns" ) ) );