diff --git a/dbtests/jstests.cpp b/dbtests/jstests.cpp index c56654dc44e..9d721098bec 100644 --- a/dbtests/jstests.cpp +++ b/dbtests/jstests.cpp @@ -550,6 +550,47 @@ namespace JSTests { const char * _a; const char * _b; }; + + class BinDataType { + public: + + void pp( const char * s , BSONElement e ){ + int len; + const char * data = e.binData( len ); + cout << s << ":" << e.binDataType() << "\t" << len << endl; + cout << "\t"; + for ( int i=0; icreateScope(); + s->localConnect( "asd" ); + const char * foo = "asdasdasdasd"; + + + BSONObj in; + { + BSONObjBuilder b; + b.append( "a" , 7 ); + b.appendBinData( "b" , strlen( foo ) , ByteArray , foo ); + in = b.obj(); + s->setObject( "x" , in ); + } + + s->invokeSafe( "myb = x.b; print( myb ); printjson( myb );" , BSONObj() ); + s->invokeSafe( "y = { c : myb };" , BSONObj() ); + + BSONObj out = s->getObject( "y" ); + ASSERT_EQUALS( BinData , out["c"].type() ); + //blah( "in " , in["b"] ); + //blah( "out" , out["c"] ); + ASSERT_EQUALS( 0 , in["b"].woCompare( out["c"] , false ) ); + + delete s; + } + }; class All : public Suite { public: @@ -572,6 +613,7 @@ namespace JSTests { add< LongUtf8String >(); add< CodeTests >(); add< DBRefTest >(); + add< BinDataType >(); } }; diff --git a/scripting/engine_spidermonkey.cpp b/scripting/engine_spidermonkey.cpp index 2c1e647b3bc..05aad830b33 100644 --- a/scripting/engine_spidermonkey.cpp +++ b/scripting/engine_spidermonkey.cpp @@ -335,7 +335,7 @@ namespace mongo { } jsval toval( const BSONElement& e ){ - + switch( e.type() ){ case EOO: case jstNULL: @@ -344,6 +344,7 @@ namespace mongo { case NumberDouble: case NumberInt: return toval( e.number() ); + case Symbol: // TODO: should we make a special class for this case String: return toval( e.valuestr() ); case Bool: @@ -435,12 +436,20 @@ namespace mongo { JSObject * oid = JS_NewObject( _context , &object_id_class , 0 , 0 ); setProperty( oid , "str" , toval( e.dbrefOID().str().c_str() ) ); - + setProperty( o , "id" , OBJECT_TO_JSVAL( oid ) ); return OBJECT_TO_JSVAL( o ); } - default: - log() << "toval can't handle type: " << (int)(e.type()) << endl; + case BinData:{ + JSObject * o = JS_NewObject( _context , &bindata_class , 0 , 0 ); + int len; + void * data = (void*)e.binData( len ); + assert( JS_SetPrivate( _context , o , data ) ); + + setProperty( o , "len" , toval( len ) ); + setProperty( o , "type" , toval( (int)e.binDataType() ) ); + return OBJECT_TO_JSVAL( o ); + } } uassert( "not done: toval" , 0 ); diff --git a/scripting/engine_spidermonkey.h b/scripting/engine_spidermonkey.h index be980ed289f..0c7407793bd 100644 --- a/scripting/engine_spidermonkey.h +++ b/scripting/engine_spidermonkey.h @@ -59,6 +59,7 @@ namespace mongo { extern JSClass object_id_class; extern JSClass dbref_class; + extern JSClass bindata_class; extern JSClass timestamp_class; extern JSClass minkey_class; extern JSClass maxkey_class; diff --git a/scripting/sm_db.cpp b/scripting/sm_db.cpp index aa563c0b8b2..9182be399db 100644 --- a/scripting/sm_db.cpp +++ b/scripting/sm_db.cpp @@ -480,6 +480,26 @@ namespace mongo { { 0 } }; + // BinData + + + JSBool bindata_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){ + JS_ReportError( cx , "can't create a BinData yet" ); + return JS_FALSE; + } + + JSClass bindata_class = { + "BinData" , JSCLASS_HAS_PRIVATE , + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub, + JSCLASS_NO_OPTIONAL_MEMBERS + }; + + JSFunctionSpec bindata_functions[] = { + { 0 } + }; + + // ----- JSClass timestamp_class = { @@ -576,6 +596,7 @@ namespace mongo { assert( JS_InitClass( cx , global , 0 , &internal_cursor_class , internal_cursor_constructor , 0 , 0 , internal_cursor_functions , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , &dbquery_class , dbquery_constructor , 0 , 0 , 0 , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , &dbref_class , dbref_constructor , 0 , 0 , dbref_functions , 0 , 0 ) ); + assert( JS_InitClass( cx , global , 0 , &bindata_class , bindata_constructor , 0 , 0 , bindata_functions , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , ×tamp_class , 0 , 0 , 0 , 0 , 0 , 0 ) ); assert( JS_InitClass( cx , global , 0 , &minkey_class , 0 , 0 , 0 , 0 , 0 , 0 ) ); @@ -613,6 +634,14 @@ namespace mongo { return true; } + if ( JS_InstanceOf( c->_context , o , &bindata_class , 0 ) ){ + b.appendBinData( name.c_str() , + (int)(c->getNumber( o , "len" )) , (BinDataType)(c->getNumber( o , "type" ) ) , + (char*)JS_GetPrivate( c->_context , o ) + 1 + ); + return true; + } + #if defined( SM16 ) || defined( MOZJS ) { jsdouble d = js_DateGetMsecSinceEpoch( c->_context , o ); diff --git a/shell/utils.js b/shell/utils.js index d98c618cf3b..0ffcc4c911c 100644 --- a/shell/utils.js +++ b/shell/utils.js @@ -186,6 +186,10 @@ DBRef.prototype.toString = function(){ return "DBRef " + this.ns + ":" + this.id; } +BinData.prototype.tojson = function(){ + return "BinData type: " + this.type + " len: " + this.len; +} + tojson = function( x ){ if ( x == null || x == undefined ) return "";