whitespace

This commit is contained in:
Mike Dirolf
2009-06-19 15:46:53 -04:00
parent 64e8052961
commit eb95a15752

View File

@@ -12,17 +12,17 @@ namespace mongo {
#define GETHOLDER(x,o) ((BSONHolder*)JS_GetPrivate( x , o ))
class BSONFieldIterator;
class BSONHolder {
public:
BSONHolder( BSONObj obj ){
_obj = obj.getOwned();
_inResolve = false;
_modified = false;
_magic = 17;
}
void check(){
uassert( "holder magic value is wrong" , _magic == 17 );
}
@@ -38,7 +38,7 @@ namespace mongo {
class BSONFieldIterator {
public:
BSONFieldIterator( BSONHolder * holder ){
BSONObjIterator it( holder->_obj );
@@ -46,12 +46,12 @@ namespace mongo {
BSONElement e = it.next();
_names.push_back( e.fieldName() );
}
_names.merge( holder->_extra );
_it = _names.begin();
}
bool more(){
return _it != _names.end();
}
@@ -61,7 +61,7 @@ namespace mongo {
_it++;
return s;
}
private:
list<string> _names;
list<string>::iterator _it;
@@ -77,16 +77,16 @@ namespace mongo {
Convertor( JSContext * cx ){
_context = cx;
}
string toString( JSString * so ){
jschar * s = JS_GetStringChars( so );
size_t srclen = JS_GetStringLength( so );
if( srclen == 0 )
return "";
size_t len = srclen * 6; // we only need *3, but see note on len below
char * dst = (char*)malloc( len );
len /= 2;
// doc re weird JS_EncodeCharacters api claims len expected in 16bit
// units, but experiments suggest 8bit units expected. We allocate
@@ -103,7 +103,7 @@ namespace mongo {
}
string toString( jsval v ){
return toString( JS_ValueToString( _context , v ) );
return toString( JS_ValueToString( _context , v ) );
}
double toNumber( jsval v ){
@@ -127,11 +127,11 @@ namespace mongo {
oid.init( getString( o , "str" ) );
return oid;
}
BSONObj toObject( JSObject * o ){
if ( ! o )
return BSONObj();
if ( JS_InstanceOf( _context , o , &bson_ro_class , 0 ) ){
return GETHOLDER( _context , o )->_obj.getOwned();
}
@@ -143,14 +143,14 @@ namespace mongo {
return holder->_obj;
orig = holder->_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 );
@@ -161,24 +161,24 @@ namespace mongo {
string name = toString( nameval );
if ( name == "_id" )
continue;
append( b , name , getProperty( o , name.c_str() ) , orig[name].type() );
}
JS_DestroyIdArray( _context , properties );
return b.obj();
}
BSONObj toObject( jsval v ){
if ( JSVAL_IS_NULL( v ) ||
if ( JSVAL_IS_NULL( v ) ||
JSVAL_IS_VOID( v ) )
return BSONObj();
uassert( "not an object" , JSVAL_IS_OBJECT( v ) );
return toObject( JSVAL_TO_OBJECT( v ) );
}
string getFunctionCode( JSFunction * func ){
return toString( JS_DecompileFunction( _context , func , 0 ) );
}
@@ -191,10 +191,10 @@ namespace mongo {
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: {
double d = toNumber( val );
if ( oldType == NumberInt && ((int)d) == d )
@@ -231,21 +231,21 @@ namespace mongo {
b.appendRegex( name.c_str() , s.substr( 0 , end ).c_str() , s.substr( end + 1 ).c_str() );
}
else {
b.appendCode( name.c_str() , getFunctionCode( val ).c_str() );
b.appendCode( name.c_str() , getFunctionCode( val ).c_str() );
}
break;
}
default: uassert( (string)"can't append field. name:" + name + " type: " + typeString( val ) , 0 );
}
}
// ---------- to spider monkey ---------
bool hasFunctionIdentifier( const string& code ){
if ( code.size() < 9 || code.find( "function" ) != 0 )
return false;
return code[8] == ' ' || code[8] == '(';
}
@@ -273,7 +273,7 @@ namespace mongo {
addRoot( f );
return f;
}
JSFunction * _compileFunction( const char * code, JSObject * assoc ){
if ( ! hasFunctionIdentifier( code ) ){
string s = code;
@@ -282,7 +282,7 @@ namespace mongo {
}
return JS_CompileFunction( _context , assoc , "anonymous" , 0 , 0 , s.c_str() , strlen( s.c_str() ) , "nofile_a" , 0 );
}
// TODO: there must be a way in spider monkey to do this - this is a total hack
string s = "return ";
@@ -294,7 +294,7 @@ namespace mongo {
cerr << "compile for hack failed" << endl;
return 0;
}
jsval ret;
if ( ! JS_CallFunction( _context , 0 , func , 0 , 0 , &ret ) ){
cerr << "call function for hack failed" << endl;
@@ -307,7 +307,7 @@ namespace mongo {
return JS_ValueToFunction( _context , ret );
}
jsval toval( double d ){
jsval val;
assert( JS_NewNumberValue( _context, d , &val ) );
@@ -326,14 +326,14 @@ namespace mongo {
assert( JS_SetPrivate( _context , o , (void*)(new BSONHolder( obj->getOwned() ) ) ) );
return o;
}
jsval toval( const BSONObj* obj , bool readOnly=false ){
JSObject * o = toJSObject( obj , readOnly );
return OBJECT_TO_JSVAL( o );
}
jsval toval( const BSONElement& e ){
switch( e.type() ){
case EOO:
case jstNULL:
@@ -352,9 +352,9 @@ namespace mongo {
return toval( &embed );
}
case Array:{
BSONObj embed = e.embeddedObject().getOwned();
if ( embed.isEmpty() ){
return OBJECT_TO_JSVAL( JS_NewArrayObject( _context , 0 , 0 ) );
}
@@ -364,14 +364,14 @@ namespace mongo {
JSObject * array = JS_NewArrayObject( _context , embed.nFields() , 0 );
assert( array );
jsval myarray = OBJECT_TO_JSVAL( array );
for ( int i=0; i<n; i++ ){
jsval v = toval( embed[i] );
assert( JS_SetElement( _context , array , i , &v ) );
}
return myarray;
}
case jstOID:{
@@ -393,7 +393,7 @@ namespace mongo {
}
flags++;
}
JSObject * r = JS_NewRegExpObject( _context , (char*)e.regex() , strlen( e.regex() ) , flagNumber );
assert( r );
return OBJECT_TO_JSVAL( r );
@@ -404,7 +404,7 @@ namespace mongo {
}
case CodeWScope:{
JSFunction * func = compileFunction( e.codeWScopeCode() );
BSONObj extraScope = e.codeWScopeObject();
if ( ! extraScope.isEmpty() ){
log() << "warning: CodeWScope doesn't transfer to db.eval" << endl;
@@ -412,9 +412,9 @@ namespace mongo {
return OBJECT_TO_JSVAL( JS_GetFunctionObject( func ) );
}
case Date:
case Date:
return OBJECT_TO_JSVAL( js_NewDateObjectMsec( _context , (jsdouble) e.date() ) );
case MinKey:
return OBJECT_TO_JSVAL( JS_NewObject( _context , &minkey_class , 0 , 0 ) );
@@ -434,7 +434,7 @@ 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 );
}
@@ -443,17 +443,17 @@ namespace mongo {
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 );
return 0;
}
// ------- object helpers ------
JSObject * getJSObject( JSObject * o , const char * name ){
@@ -461,7 +461,7 @@ namespace mongo {
assert( JS_GetProperty( _context , o , name , &v ) );
return JSVAL_TO_OBJECT( v );
}
JSObject * getGlobalObject( const char * name ){
return getJSObject( JS_GetGlobalObject( _context ) , name );
}
@@ -469,7 +469,7 @@ namespace mongo {
JSObject * getGlobalPrototype( const char * name ){
return getJSObject( getGlobalObject( name ) , "prototype" );
}
bool hasProperty( JSObject * o , const char * name ){
JSBool res;
assert( JS_HasProperty( _context , o , name , & res ) );
@@ -486,12 +486,12 @@ namespace mongo {
void setProperty( JSObject * o , const char * field , jsval v ){
assert( JS_SetProperty( _context , o , field , &v ) );
}
string typeString( jsval v ){
JSType t = JS_TypeOfValue( _context , v );
return JS_GetTypeName( _context , t );
}
bool getBoolean( JSObject * o , const char * field ){
return toBoolean( getProperty( o , field ) );
}
@@ -499,7 +499,7 @@ namespace mongo {
double getNumber( JSObject * o , const char * field ){
return toNumber( getProperty( o , field ) );
}
string getString( JSObject * o , const char * field ){
return toString( getProperty( o , field ) );
}
@@ -525,9 +525,9 @@ namespace mongo {
*idp = JSVAL_ZERO;
return JS_TRUE;
}
BSONFieldIterator * it = (BSONFieldIterator*)JSVAL_TO_PRIVATE( *statep );
if ( enum_op == JSENUMERATE_NEXT ){
if ( it->more() ){
string name = it->next();
@@ -540,17 +540,17 @@ namespace mongo {
}
return JS_TRUE;
}
if ( enum_op == JSENUMERATE_DESTROY ){
if ( it )
if ( it )
delete it;
return JS_TRUE;
}
uassert( "don't know what to do with this op" , 0 );
return JS_FALSE;
}
JSBool noaccess( JSContext *cx, JSObject *obj, jsval idval, jsval *vp){
BSONHolder * holder = GETHOLDER( cx , obj );
if ( holder->_inResolve )
@@ -558,9 +558,9 @@ namespace mongo {
JS_ReportError( cx , "doing write op on read only operation" );
return JS_FALSE;
}
JSClass bson_ro_class = {
"bson_ro_object" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE ,
"bson_ro_object" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE ,
noaccess, noaccess, JS_PropertyStub, noaccess,
(JSEnumerateOp)bson_enumerate, (JSResolveOp)(&resolveBSONField) , JS_ConvertStub, bson_finalize ,
JSCLASS_NO_OPTIONAL_MEMBERS
@@ -576,7 +576,7 @@ namespace mongo {
return JS_TRUE;
}
JSBool mark_modified( JSContext *cx, JSObject *obj, jsval idval, jsval *vp){
BSONHolder * holder = GETHOLDER( cx , obj );
if ( holder->_inResolve )
@@ -586,7 +586,7 @@ namespace mongo {
}
JSClass bson_class = {
"bson_object" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE ,
"bson_object" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE ,
bson_add_prop, mark_modified, JS_PropertyStub, mark_modified,
(JSEnumerateOp)bson_enumerate, (JSResolveOp)(&resolveBSONField) , JS_ConvertStub, bson_finalize ,
JSCLASS_NO_OPTIONAL_MEMBERS
@@ -597,7 +597,7 @@ namespace mongo {
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
};
// --- global helpers ---
@@ -624,7 +624,7 @@ namespace mongo {
}
BSONObj out = func( args.obj() );
if ( out.isEmpty() ){
*rval = JSVAL_VOID;
}
@@ -642,27 +642,27 @@ namespace mongo {
return JS_TRUE;
}
JSFunctionSpec globalHelpers[] = {
{ "print" , &native_print , 0 , 0 , 0 } ,
{ "nativeHelper" , &native_helper , 1 , 0 , 0 } ,
{ "load" , &native_load , 1 , 0 , 0 } ,
{ "gc" , &native_gc , 1 , 0 , 0 } ,
{ 0 , 0 , 0 , 0 , 0 }
JSFunctionSpec globalHelpers[] = {
{ "print" , &native_print , 0 , 0 , 0 } ,
{ "nativeHelper" , &native_helper , 1 , 0 , 0 } ,
{ "load" , &native_load , 1 , 0 , 0 } ,
{ "gc" , &native_gc , 1 , 0 , 0 } ,
{ 0 , 0 , 0 , 0 , 0 }
};
// ----END global helpers ----
JSBool resolveBSONField( JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp ){
assert( JS_EnterLocalRootScope( cx ) );
Convertor c( cx );
BSONHolder * holder = GETHOLDER( cx , obj );
holder->check();
string s = c.toString( id );
BSONElement e = holder->_obj[ s.c_str() ];
if ( e.type() == EOO ){
@@ -670,7 +670,7 @@ namespace mongo {
JS_LeaveLocalRootScope( cx );
return JS_TRUE;
}
jsval val = c.toval( e );
assert( ! holder->_inResolve );
@@ -682,13 +682,13 @@ namespace mongo {
JS_LeaveLocalRootScope( cx );
return JS_TRUE;
}
class SMScope;
class SMEngine : public ScriptEngine {
public:
SMEngine(){
_runtime = JS_NewRuntime(8L * 1024L * 1024L);
uassert( "JS_NewRuntime failed" , _runtime );
@@ -703,16 +703,16 @@ namespace mongo {
}
Scope * createScope();
void runTest();
virtual bool utf8Ok() const { return JS_CStringsAreUTF8(); }
private:
JSRuntime * _runtime;
friend class SMScope;
};
SMEngine * globalSMEngine;
@@ -723,58 +723,58 @@ namespace mongo {
// ------ special helpers -------
JSBool object_keyset(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
JSIdArray * properties = JS_Enumerate( cx , obj );
assert( properties );
JSObject * array = JS_NewArrayObject( cx , properties->length , 0 );
assert( array );
for ( jsint i=0; i<properties->length; i++ ){
jsid id = properties->vector[i];
jsval idval;
assert( JS_IdToValue( cx , id , &idval ) );
assert( JS_SetElement( cx , array , i , &idval ) );
}
JS_DestroyIdArray( cx , properties );
*rval = OBJECT_TO_JSVAL( array );
return JS_TRUE;
}
// ------ scope ------
JSBool no_gc(JSContext *cx, JSGCStatus status){
return JS_FALSE;
}
class SMScope : public Scope {
public:
SMScope(){
_context = JS_NewContext( globalSMEngine->_runtime , 8192 );
_convertor = new Convertor( _context );
massert( "JS_NewContext failed" , _context );
JS_SetOptions( _context , JSOPTION_VAROBJFIX);
//JS_SetVersion( _context , JSVERSION_LATEST); TODO
JS_SetErrorReporter( _context , errorReporter );
_global = JS_NewObject( _context , &global_class, NULL, NULL);
massert( "JS_NewObject failed for global" , _global );
JS_SetGlobalObject( _context , _global );
massert( "js init failed" , JS_InitStandardClasses( _context , _global ) );
JS_SetOptions( _context , JS_GetOptions( _context ) | JSOPTION_VAROBJFIX );
JS_DefineFunctions( _context , _global , globalHelpers );
// install my special helpers
assert( JS_DefineFunction( _context , _convertor->getGlobalPrototype( "Object" ) ,
assert( JS_DefineFunction( _context , _convertor->getGlobalPrototype( "Object" ) ,
"keySet" , object_keyset , 0 , JSPROP_READONLY ) );
_this = 0;
@@ -787,7 +787,7 @@ namespace mongo {
for ( list<void*>::iterator i=_roots.begin(); i != _roots.end(); i++ ){
JS_RemoveRoot( _context , *i );
}
if ( _this )
JS_RemoveRoot( _context , &_this );
@@ -801,20 +801,20 @@ namespace mongo {
_context = 0;
}
}
void reset(){
massert( "SMScope::reset() not implemented yet" , 0 );
}
void addRoot( void * root , const char * name ){
JS_AddNamedRoot( _context , root , name );
_roots.push_back( root );
}
void init( BSONObj * data ){
if ( ! data )
return;
BSONObjIterator i( *data );
while ( i.more() ){
BSONElement e = i.next();
@@ -829,18 +829,18 @@ namespace mongo {
void localConnect( const char * dbName ){
initMongoJS( this , _context , _global , true );
exec( "_mongo = new Mongo();" );
exec( ((string)"db = _mongo.getDB( \"" + dbName + "\" ); ").c_str() );
}
// ----- getters ------
double getNumber( const char *field ){
jsval val;
assert( JS_GetProperty( _context , _global , field , &val ) );
return _convertor->toNumber( val );
}
string getString( const char *field ){
jsval val;
assert( JS_GetProperty( _context , _global , field , &val ) );
@@ -851,7 +851,7 @@ namespace mongo {
bool getBoolean( const char *field ){
return _convertor->getBoolean( _global , field );
}
BSONObj getObject( const char *field ){
return _convertor->toObject( _convertor->getProperty( _global , field ) );
}
@@ -863,11 +863,11 @@ namespace mongo {
int type( const char *field ){
jsval val;
assert( JS_GetProperty( _context , _global , field , &val ) );
switch ( JS_TypeOfValue( _context , val ) ){
case JSTYPE_VOID: return Undefined;
case JSTYPE_NULL: return jstNULL;
case JSTYPE_OBJECT: {
case JSTYPE_OBJECT: {
JSObject * o = JSVAL_TO_OBJECT( val );
if ( JS_IsArrayObject( _context , o ) )
return Array;
@@ -884,7 +884,7 @@ namespace mongo {
}
// ----- setters ------
void setNumber( const char *field , double val ){
jsval v = _convertor->toval( val );
assert( JS_SetProperty( _context , _global , field , &v ) );
@@ -902,20 +902,20 @@ namespace mongo {
void setBoolean( const char *field , bool val ){
jsval v = BOOLEAN_TO_JSVAL( val );
assert( JS_SetProperty( _context , _global , field , &v ) );
assert( JS_SetProperty( _context , _global , field , &v ) );
}
void setThis( const BSONObj * obj ){
if ( _this )
JS_RemoveRoot( _context , &_this );
_this = _convertor->toJSObject( obj );
JS_AddNamedRoot( _context , &_this , "scope this" );
}
// ---- functions -----
ScriptingFunction createFunction( const char * code ){
precall();
return (ScriptingFunction)_convertor->compileFunction( code );
@@ -926,7 +926,7 @@ namespace mongo {
boost::posix_time::time_duration timeout;
int count;
};
static JSBool checkTimeout( JSContext *cx, JSScript *script ) {
TimeoutSpec &spec = *(TimeoutSpec *)( JS_GetContextPrivate( cx ) );
if ( ++spec.count % 1000 != 0 )
@@ -947,7 +947,7 @@ namespace mongo {
spec->count = 0;
JS_SetContextPrivate( _context, (void*)spec );
JS_SetBranchCallback( _context, checkTimeout );
}
}
}
void uninstallCheckTimeout( int timeoutMs ) {
@@ -957,32 +957,32 @@ namespace mongo {
JS_SetContextPrivate( _context, 0 );
}
}
void precall(){
_error = "";
currentScope.reset( this );
}
bool exec( const string& code , const string& name = "(anon)" , bool printResult = false , bool reportError = true , bool assertOnError = true, int timeoutMs = 0 ){
precall();
jsval ret = JSVAL_VOID;
installCheckTimeout( timeoutMs );
JSBool worked = JS_EvaluateScript( _context , _global , code.c_str() , strlen( code.c_str() ) , name.c_str() , 0 , &ret );
uninstallCheckTimeout( timeoutMs );
if ( assertOnError )
uassert( name + " exec failed" , worked );
if ( reportError && ! _error.empty() ){
// cout << "exec error: " << _error << endl;
// already printed in reportError, so... TODO
}
if ( worked )
_convertor->setProperty( _global , "__lastres__" , ret );
if ( worked && printResult && ! JSVAL_IS_VOID( ret ) )
cout << _convertor->toString( ret ) << endl;
@@ -992,7 +992,7 @@ namespace mongo {
int invoke( JSFunction * func , const BSONObj& args, int timeoutMs ){
precall();
jsval rval;
int nargs = args.nFields();
auto_ptr<jsval> smargsPtr( new jsval[nargs] );
jsval* smargs = smargsPtr.get();
@@ -1000,13 +1000,13 @@ namespace mongo {
BSONObjIterator it( args );
for ( int i=0; i<nargs; i++ )
smargs[i] = _convertor->toval( it.next() );
setObject( "args" , args , true ); // this is for backwards compatability
installCheckTimeout( timeoutMs );
JSBool ret = JS_CallFunction( _context , _this , func , nargs , smargs , &rval );
uninstallCheckTimeout( timeoutMs );
if ( !ret ) {
return -3;
}
@@ -1022,7 +1022,7 @@ namespace mongo {
void gotError( string s ){
_error = s;
}
string getError(){
return _error;
}
@@ -1030,11 +1030,11 @@ namespace mongo {
void injectNative( const char *field, NativeFunction func ){
string name = field;
_convertor->setProperty( _global , (name + "_").c_str() , PRIVATE_TO_JSVAL( func ) );
stringstream code;
code << field << " = function(){ var a = [ " << field << "_ ]; for ( var i=0; i<arguments.length; i++ ){ a.push( arguments[i] ); } return nativeHelper.apply( null , a ); }";
exec( code.str().c_str() );
}
virtual void gc(){
@@ -1042,7 +1042,7 @@ namespace mongo {
}
JSContext *context() const { return _context; }
private:
JSContext * _context;
Convertor * _convertor;
@@ -1057,11 +1057,11 @@ namespace mongo {
void errorReporter( JSContext *cx, const char *message, JSErrorReport *report ){
stringstream ss;
ss << "JS Error: " << message;
if ( report ){
ss << " " << report->filename << ":" << report->lineno;
}
log() << ss.str() << endl;
if ( currentScope.get() ){
@@ -1077,21 +1077,21 @@ namespace mongo {
for ( uintN i=0; i<argc; i++ ){
string filename = c.toString( argv[i] );
cout << "should load [" << filename << "]" << endl;
if ( ! s->execFile( filename , false , true , false ) ){
JS_ReportError( cx , ((string)"error loading file: " + filename ).c_str() );
return JS_FALSE;
}
}
return JS_TRUE;
}
void SMEngine::runTest(){
SMScope s;
s.localConnect( "foo" );
s.exec( "assert( db.getMongo() )" );
@@ -1120,13 +1120,13 @@ namespace mongo {
void Convertor::addRoot( JSFunction * f ){
if ( ! f )
return;
SMScope * scope = currentScope.get();
uassert( "need a scope" , scope );
scope->addRoot( f , "cf" );
}
}
}
#include "sm_db.cpp"