summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2009-05-22 10:48:05 -0400
committerEliot Horowitz <eliot@10gen.com>2009-05-22 10:48:05 -0400
commit2eddff58bb98e81a7cb34d193a16354bf1e17eb3 (patch)
tree035164e46cc80f35ae91a37f97618865afb540f4
parenta8d140ae7985551b73ea3a2b660f517b1bfc7cc0 (diff)
downloadmongo-2eddff58bb98e81a7cb34d193a16354bf1e17eb3.tar.gz
conserver types when doing bson -> js -> bson as much as possible
-rw-r--r--dbtests/jstests.cpp51
-rw-r--r--scripting/engine_spidermonkey.cpp29
2 files changed, 74 insertions, 6 deletions
diff --git a/dbtests/jstests.cpp b/dbtests/jstests.cpp
index 300b69a69fd..3e2c6c63a78 100644
--- a/dbtests/jstests.cpp
+++ b/dbtests/jstests.cpp
@@ -315,7 +315,57 @@ namespace JSTests {
delete s;
}
};
+
+ class TypeConservation {
+ public:
+ void run(){
+ Scope * s = globalScriptEngine->createScope();
+
+ // -- A --
+
+ BSONObj o;
+ {
+ BSONObjBuilder b ;
+ b.append( "a" , (int)5 );
+ b.append( "b" , 5.6 );
+ o = b.obj();
+ }
+ ASSERT_EQUALS( NumberInt , o["a"].type() );
+ ASSERT_EQUALS( NumberDouble , o["b"].type() );
+
+ s->setObject( "z" , o );
+ s->invoke( "return z" , BSONObj() );
+ BSONObj out = s->getObject( "return" );
+ ASSERT_EQUALS( 5 , out["a"].number() );
+ ASSERT_EQUALS( 5.6 , out["b"].number() );
+ ASSERT_EQUALS( NumberDouble , out["b"].type() );
+ ASSERT_EQUALS( NumberInt , out["a"].type() );
+
+ // -- B --
+
+ {
+ BSONObjBuilder b ;
+ b.append( "a" , (int)5 );
+ b.append( "b" , 5.6 );
+ o = b.obj();
+ }
+
+ s->setObject( "z" , o , false );
+ s->invoke( "return z" , BSONObj() );
+ out = s->getObject( "return" );
+ ASSERT_EQUALS( 5 , out["a"].number() );
+ ASSERT_EQUALS( 5.6 , out["b"].number() );
+
+ ASSERT_EQUALS( NumberDouble , out["b"].type() );
+ ASSERT_EQUALS( NumberInt , out["a"].type() );
+
+
+
+ delete s;
+ }
+
+ };
class All : public Suite {
public:
@@ -330,6 +380,7 @@ namespace JSTests {
add< ObjectModTests >();
add< OtherJSTypes >();
add< SpecialDBTypes >();
+ add< TypeConservation >();
}
};
diff --git a/scripting/engine_spidermonkey.cpp b/scripting/engine_spidermonkey.cpp
index 06e224a0070..13fd44845f4 100644
--- a/scripting/engine_spidermonkey.cpp
+++ b/scripting/engine_spidermonkey.cpp
@@ -113,13 +113,22 @@ namespace mongo {
if ( ! o )
return BSONObj();
+ if ( JS_InstanceOf( _context , o , &bson_ro_class , 0 ) ){
+ return GETHOLDER( _context , o )->_obj.getOwned();
+ }
+
+ BSONObj orig;
+ if ( JS_InstanceOf( _context , o , &bson_class , 0 ) ){
+ orig = GETHOLDER(_context,o)->_obj;
+ }
+
BSONObjBuilder b;
jsval theid = getProperty( o , "_id" );
if ( ! JSVAL_IS_VOID( theid ) ){
append( b , "_id" , theid );
}
-
+
JSIdArray * properties = JS_Enumerate( _context , o );
assert( properties );
@@ -130,7 +139,8 @@ namespace mongo {
string name = toString( nameval );
if ( name == "_id" )
continue;
- append( b , name , getProperty( o , name.c_str() ) );
+
+ append( b , name , getProperty( o , name.c_str() ) , orig[name].type() );
}
return b.obj();
@@ -154,14 +164,21 @@ namespace mongo {
return getFunctionCode( JS_ValueToFunction( _context , v ) );
}
- void append( BSONObjBuilder& b , string name , jsval val ){
- //cout << "name: " << name << "\t" << typeString( val ) << endl;
+ void append( BSONObjBuilder& b , string name , jsval val , BSONType oldType = EOO ){
+ //cout << "name: " << name << "\t" << typeString( val ) << " oldType: " << oldType << endl;
switch ( JS_TypeOfValue( _context , val ) ){
-
+
case JSTYPE_VOID: b.appendUndefined( name.c_str() ); break;
case JSTYPE_NULL: b.appendNull( name.c_str() ); break;
- case JSTYPE_NUMBER: b.append( name.c_str() , toNumber( val ) ); break;
+ case JSTYPE_NUMBER: {
+ double d = toNumber( val );
+ if ( oldType == NumberInt && ((int)d) == d )
+ b.append( name.c_str() , (int)d );
+ else
+ b.append( name.c_str() , d );
+ break;
+ }
case JSTYPE_STRING: b.append( name.c_str() , toString( val ) ); break;
case JSTYPE_BOOLEAN: b.appendBool( name.c_str() , toBoolean( val ) ); break;