diff options
-rw-r--r-- | dbtests/jstests.cpp | 22 | ||||
-rw-r--r-- | scripting/engine_spidermonkey.cpp | 22 |
2 files changed, 36 insertions, 8 deletions
diff --git a/dbtests/jstests.cpp b/dbtests/jstests.cpp index d38081eafd9..e7077707caa 100644 --- a/dbtests/jstests.cpp +++ b/dbtests/jstests.cpp @@ -528,7 +528,7 @@ namespace JSTests { BSONObj out = s->getObject( "a" ); ASSERT_EQUALS( mongo::NumberLong, out.firstElement().type() ); - ASSERT( s->exec( "b = {b:a.a}", "foo", false, true, false ) ); + ASSERT( s->exec( "printjson( a ); b = {b:a.a}", "foo", false, true, false ) ); out = s->getObject( "b" ); ASSERT_EQUALS( mongo::NumberLong, out.firstElement().type() ); ASSERT_EQUALS( val, out.firstElement().numberLong() ); @@ -543,6 +543,26 @@ namespace JSTests { out = s->getObject( "d" ); ASSERT_EQUALS( NumberDouble, out.firstElement().type() ); ASSERT_EQUALS( double( val ), out.firstElement().number() ); + + ASSERT( s->exec( "e = {e:a.a.floatApprox}", "foo", false, true, false ) ); + out = s->getObject( "e" ); + ASSERT_EQUALS( NumberDouble, out.firstElement().type() ); + ASSERT_EQUALS( double( val ), out.firstElement().number() ); + + ASSERT( s->exec( "f = {f:a.a.top}", "foo", false, true, false ) ); + out = s->getObject( "f" ); + ASSERT_EQUALS( NumberDouble, out.firstElement().type() ); + + s->setObject( "z", BSON( "z" << (long long)( 4 ) ) ); + ASSERT( s->exec( "y = {y:z.z.top}", "foo", false, true, false ) ); + out = s->getObject( "y" ); + ASSERT_EQUALS( Undefined, out.firstElement().type() ); + + ASSERT( s->exec( "x = {x:z.z.floatApprox}", "foo", false, true, false ) ); + out = s->getObject( "x" ); + ASSERT_EQUALS( NumberDouble, out.firstElement().type() ); + ASSERT_EQUALS( double( 4 ), out.firstElement().number() ); + } }; diff --git a/scripting/engine_spidermonkey.cpp b/scripting/engine_spidermonkey.cpp index 294431c6e35..51ba1ca1c4f 100644 --- a/scripting/engine_spidermonkey.cpp +++ b/scripting/engine_spidermonkey.cpp @@ -160,9 +160,14 @@ namespace mongo { // NOTE No validation of passed in object long long toNumberLongUnsafe( JSObject *o ) { - boost::uint64_t val = - ( (boost::uint64_t)(boost::uint32_t)getNumber( o , "top" ) << 32 ) + - ( boost::uint32_t)( getNumber( o , "bottom" ) ); + boost::uint64_t val; + if ( hasProperty( o, "top" ) ) { + val = + ( (boost::uint64_t)(boost::uint32_t)getNumber( o , "top" ) << 32 ) + + ( boost::uint32_t)( getNumber( o , "bottom" ) ); + } else { + val = getNumber( o, "floatApprox" ); + } return val; } @@ -566,10 +571,13 @@ namespace mongo { case NumberLong: { boost::uint64_t val = (boost::uint64_t)e.numberLong(); JSObject * o = JS_NewObject( _context , &numberlong_class , 0 , 0 ); - // using 2 doubles here instead of a single double because certain double - // bit patterns represent undefined values and sm might trash them - setProperty( o , "top" , toval( (double)(boost::uint32_t)( val >> 32 ) ) ); - setProperty( o , "bottom" , toval( (double)(boost::uint32_t)( val & 0x00000000ffffffff ) ) ); + setProperty( o , "floatApprox" , toval( (double)(boost::int64_t)( val ) ) ); + if ( val != boost::uint64_t( double( val ) ) ) { + // using 2 doubles here instead of a single double because certain double + // bit patterns represent undefined values and sm might trash them + setProperty( o , "top" , toval( (double)(boost::uint32_t)( val >> 32 ) ) ); + setProperty( o , "bottom" , toval( (double)(boost::uint32_t)( val & 0x00000000ffffffff ) ) ); + } return OBJECT_TO_JSVAL( o ); } case DBRef: { |