Description: Port to Spidermonkey 1.8.5 (Firefox 4.0)
Author: Chris Coulson <chris.coulson@canonical.com>
Author: Krzysztof Klimonda <kklimonda@ubuntu.com>
Forwarded: no
Bug: http://jira.mongodb.org/browse/SERVER-2683

--- mongodb-1.6.3.orig/SConstruct
+++ mongodb-1.6.3/SConstruct
@@ -745,8 +745,9 @@ else:
 
 if nix:
     env.Append( CPPFLAGS="-fPIC -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch" )
-    if linux:
-        env.Append( CPPFLAGS=" -Werror " )
+    #including jsfun.h throws some warnings
+    #if linux:
+    #    env.Append( CPPFLAGS=" -Werror " )
     env.Append( CXXFLAGS=" -Wnon-virtual-dtor " )
     env.Append( LINKFLAGS=" -fPIC -pthread -rdynamic" )
     env.Append( LIBS=[] )
@@ -982,6 +983,13 @@ def doConfigure( myenv , needPcre=True ,
                 print( "no spider monkey headers!" )
                 Exit(1)
 
+    if conf.CheckFunc( 'JS_NewCompartmentAndGlobalObject' ):
+        myenv.Append( CPPDEFINES=[ "HAVE_COMPARTMENTS" ] )
+    if conf.CheckFunc( 'JS_GetStringCharsAndLength' ):
+        myenv.Append( CPPDEFINES=[ "HAVE_JS_GET_STRING_CHARS_AND_LENGTH" ] )
+    if conf.CheckFunc( 'JS_NewRegExpObjectNoStatics' ):
+        myenv.Append( CPPDEFINES=[ "JS_NEW_REG_EXP_OBJECT_NO_STATISTICS" ] )
+
     if usev8:
         if debugBuild:
             myCheckLib( [ "v8_g" , "v8" ] , True )
--- mongodb-1.6.3.orig/scripting/sm_db.cpp
+++ mongodb-1.6.3/scripting/sm_db.cpp
@@ -79,13 +79,25 @@ namespace mongo {
         return holder->get();
     }
     
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool internal_cursor_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
     JSBool internal_cursor_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         uassert( 10236 ,  "no args to internal_cursor_constructor" , argc == 0 );
         assert( JS_SetPrivate( cx , obj , 0 ) ); // just for safety
+#ifdef JSFUN_CONSTRUCTOR
+        JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
         return JS_TRUE;
     }
 
-    void internal_cursor_finalize( JSContext * cx , JSObject * obj ){
+    void internal_cursor_finalize( JSContext * cx, JSObject * obj ){
         CursorHolder * holder = (CursorHolder*)JS_GetPrivate( cx , obj );
         if ( holder ){
             delete holder;
@@ -93,10 +105,11 @@ namespace mongo {
         }
     }
 
-    JSBool internal_cursor_hasNext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
+    JSBool internal_cursor_hasNext(JSContext *cx , uintN argc , jsval *vp) {
+        JSObject* obj = JS_THIS_OBJECT( cx , vp );
         DBClientCursor *cursor = getCursor( cx, obj );
         try {
-            *rval = cursor->more() ? JSVAL_TRUE : JSVAL_FALSE;
+            JS_SET_RVAL( cx , vp , cursor->more() ? JSVAL_TRUE : JSVAL_FALSE );
         }
         catch ( std::exception& e ){
             JS_ReportError( cx , e.what() );
@@ -105,14 +118,16 @@ namespace mongo {
         return JS_TRUE;
     }
 
-    JSBool internal_cursor_objsLeftInBatch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
+    JSBool internal_cursor_objsLeftInBatch(JSContext *cx, uintN argc, jsval *vp) {
+        JSObject* obj = JS_THIS_OBJECT( cx , vp );
         DBClientCursor *cursor = getCursor( cx, obj );
         Convertor c(cx);
-        *rval = c.toval((double) cursor->objsLeftInBatch() );
+        JS_SET_RVAL( cx , vp , c.toval((double) cursor->objsLeftInBatch()) );
         return JS_TRUE;
     }
 
-    JSBool internal_cursor_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
+    JSBool internal_cursor_next(JSContext *cx, uintN argc, jsval *vp) {
+        JSObject* obj = JS_THIS_OBJECT( cx , vp );
         DBClientCursor *cursor = getCursor( cx, obj );
 
         BSONObj n;        
@@ -131,20 +146,21 @@ namespace mongo {
         }
 
         Convertor c(cx);
-        *rval = c.toval( &n );
+        JS_SET_RVAL( cx , vp , c.toval( &n ) );
         return JS_TRUE;
     }
 
     JSFunctionSpec internal_cursor_functions[] = {
-        { "hasNext" , internal_cursor_hasNext , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { "objsLeftInBatch" , internal_cursor_objsLeftInBatch , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { "next" , internal_cursor_next , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { 0 }
+        JS_FS( "hasNext" , internal_cursor_hasNext , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "objsLeftInBatch" , internal_cursor_objsLeftInBatch , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "next" , internal_cursor_next , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS_END
     };
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass internal_cursor_class = {
         "InternalCursor" , JSCLASS_HAS_PRIVATE  ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, internal_cursor_finalize,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
@@ -156,8 +172,17 @@ namespace mongo {
         uassert( 10237 ,  "mongo_constructor not implemented yet" , 0 );
         throw -1;
     }
-    
+
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool mongo_local_constructor( JSContext* cx, uintN argc, jsval* vp ){
+    JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+    if( ! obj ) {
+        JS_ReportError( cx , "Failed to create 'this' object" );
+        return JS_FALSE;
+    }
+#else
     JSBool mongo_local_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         Convertor c( cx );
 
         shared_ptr< DBClientWithCommands > client( createDirectClient() );
@@ -166,10 +191,23 @@ namespace mongo {
         jsval host = c.toval( "EMBEDDED" );
         assert( JS_SetProperty( cx , obj , "host" , &host ) );
 
+#ifdef JSFUN_CONSTRUCTOR
+        JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
         return JS_TRUE;
     }
 
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool mongo_external_constructor( JSContext* cx, uintN argc, jsval* vp ){
+    jsval *argv = JS_ARGV( cx , vp );
+    JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+    if( ! obj ) {
+        JS_ReportError( cx , "Failed to create 'this' object" );
+        return JS_FALSE;
+    }
+#else
     JSBool mongo_external_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         Convertor c( cx );
         
         smuassert( cx ,  "0 or 1 args to Mongo" , argc <= 1 );
@@ -197,6 +235,9 @@ namespace mongo {
         assert( JS_SetPrivate( cx , obj , (void*)( new shared_ptr< DBClientWithCommands >( conn ) ) ) );
         jsval host_val = c.toval( host.c_str() );
         assert( JS_SetProperty( cx , obj , "host" , &host_val ) );
+#ifdef JSFUN_CONSTRUCTOR
+        JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
         return JS_TRUE;
 
     }
@@ -215,14 +256,18 @@ namespace mongo {
         }
     }
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass mongo_class = {
         "Mongo" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, mongo_finalize,
         JSCLASS_NO_OPTIONAL_MEMBERS
      };
 
-    JSBool mongo_find(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
+    JSBool mongo_find(JSContext *cx, uintN argc, jsval *vp) {
+        JSObject* obj = JS_THIS_OBJECT( cx , vp );
+        jsval* argv = JS_ARGV( cx , vp );
+
         smuassert( cx , "mongo_find needs 6 args" , argc == 6 );
         shared_ptr< DBClientWithCommands > * connHolder = (shared_ptr< DBClientWithCommands >*)JS_GetPrivate( cx , obj );
         smuassert( cx ,  "no connection!" , connHolder && connHolder->get() );
@@ -251,7 +296,8 @@ namespace mongo {
             JSObject * mycursor = JS_NewObject( cx , &internal_cursor_class , 0 , 0 );
             CHECKNEWOBJECT( mycursor, cx, "internal_cursor_class" );
             assert( JS_SetPrivate( cx , mycursor , new CursorHolder( cursor, *connHolder ) ) );
-            *rval = OBJECT_TO_JSVAL( mycursor );
+            
+            JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( mycursor ));
             return JS_TRUE;
         }
         catch ( ... ){
@@ -260,7 +306,10 @@ namespace mongo {
         }
     }
 
-    JSBool mongo_update(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
+    JSBool mongo_update(JSContext *cx, uintN argc, jsval *vp) {
+        JSObject* obj = JS_THIS_OBJECT( cx , vp );
+        jsval* argv = JS_ARGV( cx , vp );
+
         smuassert( cx ,  "mongo_find needs at elast 3 args" , argc >= 3 );
         smuassert( cx ,  "2nd param to update has to be an object" , JSVAL_IS_OBJECT( argv[1] ) );
         smuassert( cx ,  "3rd param to update has to be an object" , JSVAL_IS_OBJECT( argv[2] ) );
@@ -281,6 +330,7 @@ namespace mongo {
 
         try {
             conn->update( ns , c.toObject( argv[1] ) , c.toObject( argv[2] ) , upsert , multi );
+            JS_SET_RVAL( cx , vp , JSVAL_VOID );
             return JS_TRUE;
         }
         catch ( ... ){
@@ -289,7 +339,10 @@ namespace mongo {
         }
     }
 
-    JSBool mongo_insert(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool mongo_insert(JSContext *cx, uintN argc, jsval *vp) {
+        JSObject* obj = JS_THIS_OBJECT( cx , vp );
+        jsval* argv = JS_ARGV( cx , vp );
+    
         smuassert( cx ,  "mongo_insert needs 2 args" , argc == 2 );
         smuassert( cx ,  "2nd param to insert has to be an object" , JSVAL_IS_OBJECT( argv[1] ) );
 
@@ -310,6 +363,7 @@ namespace mongo {
         
         try {
             conn->insert( ns , o );
+            JS_SET_RVAL( cx, vp, JSVAL_VOID );
             return JS_TRUE;
         }
         catch ( std::exception& e ){
@@ -325,7 +379,10 @@ namespace mongo {
         }
     }
 
-    JSBool mongo_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool mongo_remove(JSContext *cx, uintN argc, jsval *vp) {
+        JSObject* obj = JS_THIS_OBJECT( cx , vp );
+        jsval* argv = JS_ARGV( cx , vp );
+   
         smuassert( cx ,  "mongo_remove needs 2 or 3 arguments" , argc == 2 || argc == 3 );
         smuassert( cx ,  "2nd param to insert has to be an object" , JSVAL_IS_OBJECT( argv[1] ) );
 
@@ -346,6 +403,7 @@ namespace mongo {
         
         try {
             conn->remove( ns , o , justOne );
+            JS_SET_RVAL( cx , vp , JSVAL_VOID );
             return JS_TRUE;
         }
         catch ( ... ){
@@ -356,16 +414,26 @@ namespace mongo {
     }
 
     JSFunctionSpec mongo_functions[] = {
-        { "find" , mongo_find , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { "update" , mongo_update , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { "insert" , mongo_insert , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { "remove" , mongo_remove , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { 0 }
+        JS_FS( "find" , mongo_find , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "update" , mongo_update , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "insert" , mongo_insert , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "remove" , mongo_remove , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS_END
     };
 
      // -------------  db_collection -------------
 
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool db_collection_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        jsval *argv = JS_ARGV( cx , vp );
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
      JSBool db_collection_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){    
+#endif
          smuassert( cx ,  "db_collection_constructor wrong args" , argc == 4 );
          assert( JS_SetProperty( cx , obj , "_mongo" , &(argv[0]) ) );
          assert( JS_SetProperty( cx , obj , "_db" , &(argv[1]) ) );
@@ -377,16 +445,23 @@ namespace mongo {
              JS_ReportError( cx , "can't use sharded collection from db.eval" );
              return JS_FALSE;
          }
-         
+
+#ifdef JSFUN_CONSTRUCTOR
+         JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
          return JS_TRUE;
      }
 
-     JSBool db_collection_resolve( JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp ){
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSResolveOp)
+     JSBool db_collection_resolve( JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp ){
+         jsval idval;
+         JS_IdToValue( cx , id , &idval );
+
          if ( flags & JSRESOLVE_ASSIGNING )
              return JS_TRUE;
          
          Convertor c( cx );
-         string collname = c.toString( id );
+         string collname = c.toString( idval );
 
          if ( isSpecialName( collname ) )
              return JS_TRUE;
@@ -414,10 +489,11 @@ namespace mongo {
          return JS_TRUE;
      }
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp, JSResolveOp)
     JSClass db_collection_class = {
          "DBCollection" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE , 
-         JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
-         JS_EnumerateStub, (JSResolveOp)(&db_collection_resolve) , JS_ConvertStub, JS_FinalizeStub,
+         JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+         JS_EnumerateStub, (JSResolveOp)db_collection_resolve , JS_ConvertStub, JS_FinalizeStub,
          JSCLASS_NO_OPTIONAL_MEMBERS
      };
 
@@ -448,16 +524,32 @@ namespace mongo {
     
     // --------------  DB ---------------
     
-    
+
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool db_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        jsval *argv = JS_ARGV( cx , vp );
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
     JSBool db_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         smuassert( cx,  "wrong number of arguments to DB" , argc == 2 );
         assert( JS_SetProperty( cx , obj , "_mongo" , &(argv[0]) ) );
         assert( JS_SetProperty( cx , obj , "_name" , &(argv[1]) ) );
 
+#ifdef JSFUN_CONSTRUCTOR
+        JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
         return JS_TRUE;
     }
 
-    JSBool db_resolve( JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp ){
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSResolveOp)
+    JSBool db_resolve( JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp ){
+        jsval idval;
+        JS_IdToValue( cx , id , &idval );
         if ( flags & JSRESOLVE_ASSIGNING )
             return JS_TRUE;
 
@@ -466,7 +558,7 @@ namespace mongo {
         if ( obj == c.getGlobalPrototype( "DB" ) )
             return JS_TRUE;
 
-        string collname = c.toString( id );
+        string collname = c.toString( idval );
         
         if ( isSpecialName( collname ) )
              return JS_TRUE;
@@ -484,17 +576,28 @@ namespace mongo {
         return JS_TRUE;
     }
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp, JSResolveOp)
     JSClass db_class = {
         "DB" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE , 
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
-        JS_EnumerateStub, (JSResolveOp)(&db_resolve) , JS_ConvertStub, JS_FinalizeStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+        JS_EnumerateStub, (JSResolveOp)db_resolve , JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
     
 
     // -------------- object id -------------
 
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool object_id_constructor( JSContext* cx, uintN argc, jsval* vp ){
+    jsval *argv = JS_ARGV( cx , vp );
+    JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+    if( ! obj ) {
+        JS_ReportError( cx , "Failed to create 'this' object" );
+        return JS_FALSE;
+    }
+#else
     JSBool object_id_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         Convertor c( cx );
 
         OID oid;
@@ -518,35 +621,48 @@ namespace mongo {
         if ( ! JS_InstanceOf( cx , obj , &object_id_class , 0 ) ){
             obj = JS_NewObject( cx , &object_id_class , 0 , 0 );
             CHECKNEWOBJECT( obj, cx, "object_id_constructor" );
-            *rval = OBJECT_TO_JSVAL( obj );
         }
         
         jsval v = c.toval( oid.str().c_str() );
         assert( JS_SetProperty( cx , obj , "str" , &v  ) );
 
+        JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
         return JS_TRUE;
     }
     
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass object_id_class = {
         "ObjectId" , JSCLASS_HAS_PRIVATE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
 
-    JSBool object_id_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool object_id_tostring(JSContext *cx, uintN argc, jsval *vp){    
+        JSObject *obj = JS_THIS_OBJECT( cx , vp );
         Convertor c(cx);
-        return (JSBool) (*rval = c.getProperty( obj , "str" ));
+        JS_SET_RVAL( cx , vp , c.getProperty( obj , "str" ));
+        return JS_TRUE;
     }
 
     JSFunctionSpec object_id_functions[] = {
-        { "toString" , object_id_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { 0 }
+        JS_FS( "toString" , object_id_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS_END
     };
 
     // dbpointer
 
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool dbpointer_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        jsval *argv = JS_ARGV( cx , vp );
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
     JSBool dbpointer_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         Convertor c( cx );
                 
         if ( argc == 2 ){
@@ -558,6 +674,9 @@ namespace mongo {
             
             assert( JS_SetProperty( cx , obj , "ns" , &(argv[0]) ) );
             assert( JS_SetProperty( cx , obj , "id" , &(argv[1]) ) );
+#ifdef JSFUN_CONSTRUCTOR
+            JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
             return JS_TRUE;
         }
         else {
@@ -566,19 +685,29 @@ namespace mongo {
         }
     }
  
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass dbpointer_class = {
         "DBPointer" , JSCLASS_HAS_PRIVATE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
 
     JSFunctionSpec dbpointer_functions[] = {
-        { 0 }
+        JS_FS_END
     };
 
-
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool dbref_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        jsval *argv = JS_ARGV( cx , vp );
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
     JSBool dbref_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         Convertor c( cx );
 
         if ( argc == 2 ){
@@ -588,6 +717,9 @@ namespace mongo {
             assert( JS_SetProperty( cx, o , "$id" , &argv[ 1 ] ) );
             BSONObj bo = c.toObject( o );
             assert( JS_SetPrivate( cx , obj , (void*)(new BSONHolder( bo.getOwned() ) ) ) );
+#ifdef JSFUN_CONSTRUCTOR
+            JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
             return JS_TRUE;
         }
         else {
@@ -601,7 +733,17 @@ namespace mongo {
 
     // UUID **************************
 
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool uuid_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        jsval *argv = JS_ARGV( cx , vp );
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
     JSBool uuid_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         Convertor c( cx );
         
         if( argc == 0 ) { 
@@ -629,6 +771,9 @@ namespace mongo {
             c.setProperty( obj, "len", c.toval( (double)16 ) );
             c.setProperty( obj, "type", c.toval( (double)3 ) );
 
+#ifdef JSFUN_CONSTRUCTOR
+            JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
             return JS_TRUE;
         }
         else {
@@ -637,7 +782,8 @@ namespace mongo {
         }
     }
  
-  JSBool uuid_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+  JSBool uuid_tostring(JSContext *cx, uintN argc, jsval *vp){    
+        JSObject *obj = JS_THIS_OBJECT( cx , vp );
         Convertor c(cx);
         void *holder = JS_GetPrivate( cx, obj );
         assert( holder );
@@ -646,7 +792,8 @@ namespace mongo {
         ss << "UUID(\"" << toHex(data, 16);
         ss << "\")";
         string ret = ss.str();
-        return *rval = c.toval( ret.c_str() );
+        JS_SET_RVAL( cx , vp , c.toval( ret.c_str() ) );
+        return JS_TRUE;
     }
 
     void uuid_finalize( JSContext * cx , JSObject * obj ){
@@ -658,21 +805,32 @@ namespace mongo {
         }
     }    
     
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass uuid_class = {
         "UUID" , JSCLASS_HAS_PRIVATE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, uuid_finalize,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
 
     JSFunctionSpec uuid_functions[] = {
-        { "toString" , uuid_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { 0 }
+        JS_FS( "toString" , uuid_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS_END
     };
     
     // BinData **************************
 
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool bindata_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        jsval *argv = JS_ARGV( cx , vp );
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
     JSBool bindata_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         Convertor c( cx );
         
         if ( argc == 2 ){
@@ -696,6 +854,9 @@ namespace mongo {
             c.setProperty( obj, "len", c.toval( (double)decoded.length() ) );
             c.setProperty( obj, "type", c.toval( (double)type ) );
 
+#ifdef JSFUN_CONSTRUCTOR
+            JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
             return JS_TRUE;
         }
         else {
@@ -704,7 +865,8 @@ namespace mongo {
         }
     }
  
-    JSBool bindata_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool bindata_tostring(JSContext *cx, uintN argc, jsval *vp){  
+        JSObject *obj = JS_THIS_OBJECT( cx , vp );  
         Convertor c(cx);
         int type = (int)c.getNumber( obj , "type" );
         int len = (int)c.getNumber( obj, "len" );
@@ -716,10 +878,12 @@ namespace mongo {
         base64::encode( ss, (const char *)data, len );
         ss << "\")";
         string ret = ss.str();
-        return *rval = c.toval( ret.c_str() );
+        JS_SET_RVAL( cx , vp , c.toval( ret.c_str() ) );
+        return JS_TRUE;
     }
 
-    JSBool bindataBase64(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool bindataBase64(JSContext *cx, uintN argc, jsval *vp){
+        JSObject *obj = JS_THIS_OBJECT( cx , vp ); 
         Convertor c(cx);
         int len = (int)c.getNumber( obj, "len" );
         void *holder = JS_GetPrivate( cx, obj );
@@ -728,10 +892,12 @@ namespace mongo {
         stringstream ss;
         base64::encode( ss, (const char *)data, len );
         string ret = ss.str();
-        return *rval = c.toval( ret.c_str() );
+        JS_SET_RVAL( cx , vp , c.toval( ret.c_str() ) );
+        return JS_TRUE;
     }
 
-    JSBool bindataAsHex(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool bindataAsHex(JSContext *cx, uintN argc, jsval *vp){   
+        JSObject *obj = JS_THIS_OBJECT( cx , vp ); 
         Convertor c(cx);
         int len = (int)c.getNumber( obj, "len" );
         void *holder = JS_GetPrivate( cx, obj );
@@ -744,19 +910,24 @@ namespace mongo {
             ss << v;
         }
         string ret = ss.str();
-        return *rval = c.toval( ret.c_str() );
+        JS_SET_RVAL( cx , vp , c.toval( ret.c_str() ) );
+        return JS_TRUE;
     }
 
-    JSBool bindataLength(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool bindataLength(JSContext *cx, uintN argc, jsval *vp){
+        JSObject *obj = JS_THIS_OBJECT( cx , vp );  
         Convertor c(cx);
         int len = (int)c.getNumber( obj, "len" );
-        return *rval = c.toval((double) len);
+        JS_SET_RVAL( cx , vp , c.toval((double) len) );
+        return JS_TRUE;
     }
 
-    JSBool bindataSubtype(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool bindataSubtype(JSContext *cx, uintN argc, jsval *vp){
+        JSObject *obj = JS_THIS_OBJECT( cx , vp ); 
         Convertor c(cx);
         int t = (int)c.getNumber( obj, "type" );
-        return *rval = c.toval((double) t);
+        JS_SET_RVAL( cx , vp , c.toval((double) t) );
+        return JS_TRUE;
     }
 
     void bindata_finalize( JSContext * cx , JSObject * obj ){
@@ -768,20 +939,21 @@ namespace mongo {
         }
     }    
     
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass bindata_class = {
         "BinData" , JSCLASS_HAS_PRIVATE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, bindata_finalize,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
 
     JSFunctionSpec bindata_functions[] = {
-        { "toString" , bindata_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { "hex", bindataAsHex, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { "base64", bindataBase64, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { "length", bindataLength, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { "subtype", bindataSubtype, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-        { 0 }
+        JS_FS( "toString" , bindata_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "hex", bindataAsHex, 0, JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "base64", bindataBase64, 0, JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "length", bindataLength, 0, JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "subtype", bindataSubtype, 0, JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS_END
     };
     
     // Map
@@ -790,7 +962,16 @@ namespace mongo {
         return s == "put" || s == "get" || s == "_get" || s == "values" || s == "_data" || s == "constructor" ;
     }
 
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool map_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
     JSBool map_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         if ( argc > 0 ){
             JS_ReportError( cx , "Map takes no arguments" );
             return JS_FALSE;
@@ -802,10 +983,16 @@ namespace mongo {
         jsval a = OBJECT_TO_JSVAL( array );
         JS_SetProperty( cx , obj , "_data" , &a );
 
+#ifdef JSFUN_CONSTRUCTOR
+        JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
         return JS_TRUE;
     }
- 
-    JSBool map_prop( JSContext *cx, JSObject *obj, jsval idval, jsval *vp ){
+
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSPropertyOp)
+    JSBool map_prop( JSContext *cx, JSObject *obj, jsid id, jsval *vp ){
+        jsval idval;
+        JS_IdToValue( cx , id , &idval );
         Convertor c(cx);
         if ( specialMapString( c.toString( idval ) ) )
             return JS_TRUE;
@@ -815,35 +1002,52 @@ namespace mongo {
         return JS_FALSE;
     }
     
+    JSBool strict_map_prop( JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp ){
+        return map_prop( cx , obj , id , vp );
+    }
+
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass map_class = {
         "Map" , JSCLASS_HAS_PRIVATE ,
-        map_prop, JS_PropertyStub, map_prop, map_prop,
+        map_prop, JS_PropertyStub, map_prop, strict_map_prop,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
     
     JSFunctionSpec map_functions[] = {
-        { 0 }
+        JS_FS_END
     };
     
 
     // -----
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass timestamp_class = {
         "Timestamp" , JSCLASS_HAS_PRIVATE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
     
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass numberlong_class = {
         "NumberLong" , JSCLASS_HAS_PRIVATE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
     
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool numberlong_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        jsval *argv = JS_ARGV( cx , vp );
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
     JSBool numberlong_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         smuassert( cx , "NumberLong needs 0 or 1 args" , argc == 0 || argc == 1 );
         
         Convertor c( cx );
@@ -865,19 +1069,25 @@ namespace mongo {
             c.makeLongObj( n, obj );
         }
         
+#ifdef JSFUN_CONSTRUCTOR
+        JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
         return JS_TRUE;
     }
     
-    JSBool numberlong_valueof(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool numberlong_valueof(JSContext *cx, uintN argc, jsval *vp){   
+        JSObject *obj = JS_THIS_OBJECT( cx , vp ); 
         Convertor c(cx);
-        return *rval = c.toval( double( c.toNumberLongUnsafe( obj ) ) );        
+        JS_SET_RVAL( cx , vp , c.toval( double( c.toNumberLongUnsafe( obj ) ) ) );
+        return JS_TRUE;        
     }
     
-    JSBool numberlong_tonumber(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
-        return numberlong_valueof( cx, obj, argc, argv, rval );
+    JSBool numberlong_tonumber(JSContext *cx, uintN argc, jsval *vp){    
+        return numberlong_valueof( cx, argc, vp );
     }
 
-    JSBool numberlong_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    
+    JSBool numberlong_tostring(JSContext *cx, uintN argc, jsval *vp){    
+        JSObject *obj = JS_THIS_OBJECT( cx , vp );
         Convertor c(cx);
         stringstream ss;
         long long val = c.toNumberLongUnsafe( obj );
@@ -889,33 +1099,46 @@ namespace mongo {
             ss << "NumberLong(" << val << ")";
 
         string ret = ss.str();
-        return *rval = c.toval( ret.c_str() );
+        JS_SET_RVAL( cx , vp , c.toval( ret.c_str() ) );
+        return JS_TRUE;
     }
 
     JSFunctionSpec numberlong_functions[] = {
-    { "valueOf" , numberlong_valueof , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-    { "toNumber" , numberlong_tonumber , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-    { "toString" , numberlong_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
-    { 0 }
+        JS_FS( "valueOf" , numberlong_valueof , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "toNumber" , numberlong_tonumber , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS( "toString" , numberlong_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE ) ,
+        JS_FS_END
     };    
     
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass minkey_class = {
         "MinKey" , JSCLASS_HAS_PRIVATE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     JSClass maxkey_class = {
         "MaxKey" , JSCLASS_HAS_PRIVATE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
     
     // dbquery
 
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool dbquery_constructor( JSContext* cx, uintN argc, jsval* vp ){
+        jsval *argv = JS_ARGV( cx , vp );
+        JSObject *obj = JS_NewObjectForConstructor( cx , vp );
+        if( ! obj ) {
+            JS_ReportError( cx , "Failed to create 'this' object" );
+            return JS_FALSE;
+        }
+#else
     JSBool dbquery_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         smuassert( cx ,  "DDQuery needs at least 4 args" , argc >= 4 );
         
         Convertor c(cx);
@@ -957,28 +1180,35 @@ namespace mongo {
         c.setProperty( obj , "_numReturned" , JSVAL_ZERO );
         c.setProperty( obj , "_special" , JSVAL_FALSE );
 
+#ifdef JSFUN_CONSTRUCTOR
+        JS_SET_RVAL( cx , vp , OBJECT_TO_JSVAL( obj ) );
+#endif
         return JS_TRUE;
     }
 
-    JSBool dbquery_resolve( JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp ){
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSResolveOp)
+    JSBool dbquery_resolve( JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp ){
+        jsval idval;
+        JS_IdToValue( cx , id , &idval );
         if ( flags & JSRESOLVE_ASSIGNING )
             return JS_TRUE;
 
-        if ( ! JSVAL_IS_NUMBER( id ) )
+        if ( ! JSVAL_IS_NUMBER( idval ) )
             return JS_TRUE;
 
         jsval val = JSVAL_VOID;
-        assert( JS_CallFunctionName( cx , obj , "arrayAccess" , 1 , &id , &val ) );
+        assert( JS_CallFunctionName( cx , obj , "arrayAccess" , 1 , &idval , &val ) );
         Convertor c(cx);
-        c.setProperty( obj , c.toString( id ).c_str() , val );
+        c.setProperty( obj , c.toString( idval ).c_str() , val );
         *objp = obj;
         return JS_TRUE;
     }
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp, JSResolveOp)
     JSClass dbquery_class = {
         "DBQuery" , JSCLASS_NEW_RESOLVE ,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
-        JS_EnumerateStub, (JSResolveOp)(&dbquery_resolve) , JS_ConvertStub, JS_FinalizeStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+        JS_EnumerateStub, (JSResolveOp)dbquery_resolve , JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
     
--- mongodb-1.6.3.orig/scripting/engine_spidermonkey.cpp
+++ mongodb-1.6.3/scripting/engine_spidermonkey.cpp
@@ -189,8 +189,13 @@ namespace mongo {
         }
 
         string toString( JSString * so ){
+#ifdef HAVE_JS_GET_STRING_CHARS_AND_LENGTH
+            size_t srclen;
+            const jschar * s = JS_GetStringCharsAndLength( _context , so , &srclen );
+#else
             jschar * s = JS_GetStringChars( so );
             size_t srclen = JS_GetStringLength( so );
+#endif
             if( srclen == 0 )
                 return "";
 
@@ -347,7 +352,7 @@ namespace mongo {
 
             case JSTYPE_OBJECT: {
                 JSObject * o = JSVAL_TO_OBJECT( val );
-                if ( ! o || o == JSVAL_NULL ){
+                if ( ! o || o == (JSObject *)JSVAL_NULL ){
                     b.appendNull( name );
                 }
                 else if ( ! appendSpecialDBObject( this , b , name , val , o ) ){
@@ -403,16 +408,15 @@ namespace mongo {
             return true;
         }
 
-        void addRoot( JSFunction * f , const char * name );
+        void addRoot( JSFunction * f );
 
         JSFunction * compileFunction( const char * code, JSObject * assoc = 0 ){
-            const char * gcName = "unknown";
-            JSFunction * f = _compileFunction( code , assoc , gcName );
-            //addRoot( f , gcName );
+            JSFunction * f = _compileFunction( code , assoc );
+            //addRoot( f );
             return f;
         }
 
-        JSFunction * _compileFunction( const char * raw , JSObject * assoc , const char *& gcName ){
+        JSFunction * _compileFunction( const char * raw , JSObject * assoc ){
             if ( ! assoc )
                 assoc = JS_GetGlobalObject( _context );
 
@@ -431,7 +435,6 @@ namespace mongo {
                 if ( isSimpleStatement( s ) ){
                     s = "return " + s;
                 }
-                gcName = "cf anon";
                 fname << "anon";
                 return JS_CompileFunction( _context , assoc , fname.str().c_str() , 0 , 0 , s.c_str() , strlen( s.c_str() ) , "nofile_a" , 0 );
             }
@@ -472,7 +475,6 @@ namespace mongo {
                 log() << "compile failed for: " << raw << endl;
                 return 0;
             }
-            gcName = "cf normal";
             return func;
         }
 
@@ -614,7 +616,11 @@ namespace mongo {
                     flags++;
                 }
 
+#ifdef JS_NEW_REG_EXP_OBJECT_NO_STATISTICS
+                JSObject * r = JS_NewRegExpObjectNoStatics( _context , (char*)e.regex() , strlen( e.regex() ) , flagNumber);
+#else
                 JSObject * r = JS_NewRegExpObject( _context , (char*)e.regex() , strlen( e.regex() ) , flagNumber );
+#endif
                 assert( r );
                 return OBJECT_TO_JSVAL( r );
             }
@@ -775,7 +781,7 @@ namespace mongo {
 
         BSONFieldIterator * it = (BSONFieldIterator*)JSVAL_TO_PRIVATE( *statep );
         if ( ! it ){
-            *statep = 0;
+            *statep = JSVAL_NULL;
             return JS_TRUE;
         }
 
@@ -787,7 +793,7 @@ namespace mongo {
             }
             else {
                 delete it;
-                *statep = 0;
+                *statep = JSVAL_NULL;
             }
             return JS_TRUE;
         }
@@ -802,7 +808,8 @@ namespace mongo {
         return JS_FALSE;
     }
 
-    JSBool noaccess( JSContext *cx, JSObject *obj, jsval idval, jsval *vp){
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSPropertyOp)
+    JSBool noaccess( JSContext *cx, JSObject *obj, jsid id, jsval *vp){
         BSONHolder * holder = GETHOLDER( cx , obj );
         if ( ! holder ){
             // in init code still
@@ -814,24 +821,37 @@ namespace mongo {
         return JS_FALSE;
     }
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
+    JSBool strict_noaccess( JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp){
+        return noaccess( cx , obj , id , vp );
+    }
+
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp, JSResolveOp)
     JSClass bson_ro_class = {
         "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 ,
+        noaccess, noaccess, JS_PropertyStub, strict_noaccess,
+        (JSEnumerateOp)bson_enumerate, (JSResolveOp)resolveBSONField , JS_ConvertStub, bson_finalize ,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
 
+#ifdef JSFUN_CONSTRUCTOR
+    JSBool bson_cons( JSContext* cx, uintN argc, jsval* vp ){
+#else
     JSBool bson_cons( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
+#endif
         cerr << "bson_cons : shouldn't be here!" << endl;
         JS_ReportError( cx , "can't construct bson object" );
         return JS_FALSE;
     }
 
     JSFunctionSpec bson_functions[] = {
-        { 0 }
+        JS_FS_END
     };
     
-    JSBool bson_add_prop( JSContext *cx, JSObject *obj, jsval idval, jsval *vp){
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSPropertyOp)
+    JSBool bson_add_prop( JSContext *cx, JSObject *obj, jsid id, jsval *vp){
+        jsval idval;
+        JS_IdToValue( cx , id , &idval );
         BSONHolder * holder = GETHOLDER( cx , obj );
         if ( ! holder ){
             // static init
@@ -848,8 +868,10 @@ namespace mongo {
         return JS_TRUE;
     }
     
-
-    JSBool mark_modified( JSContext *cx, JSObject *obj, jsval idval, jsval *vp){
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSPropertyOp)
+    JSBool mark_modified( JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp){
+        jsval idval;
+        JS_IdToValue( cx , id , &idval );
         Convertor c(cx);
         BSONHolder * holder = GETHOLDER( cx , obj );
         if ( !holder ) // needed when we're messing with DBRef.prototype
@@ -861,7 +883,10 @@ namespace mongo {
         return JS_TRUE;
     }
     
-    JSBool mark_modified_remove( JSContext *cx, JSObject *obj, jsval idval, jsval *vp){
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSPropertyOp)
+    JSBool mark_modified_remove( JSContext *cx, JSObject *obj, jsid id, jsval *vp){
+        jsval idval;
+        JS_IdToValue( cx , id , &idval );
         Convertor c(cx);
         BSONHolder * holder = GETHOLDER( cx , obj );
         if ( holder->_inResolve )
@@ -871,23 +896,26 @@ namespace mongo {
         return JS_TRUE;
     }
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp, JSResolveOp)
     JSClass bson_class = {
         "bson_object" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE ,
         bson_add_prop, mark_modified_remove, JS_PropertyStub, mark_modified,
-        (JSEnumerateOp)bson_enumerate, (JSResolveOp)(&resolveBSONField) , JS_ConvertStub, bson_finalize ,
+        (JSEnumerateOp)bson_enumerate, (JSResolveOp)resolveBSONField , JS_ConvertStub, bson_finalize ,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
 
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSStrictPropertyOp)
     static JSClass global_class = {
         "global", JSCLASS_GLOBAL_FLAGS,
-        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
         JSCLASS_NO_OPTIONAL_MEMBERS
     };
 
     // --- global helpers ---
 
-    JSBool native_print( JSContext * cx , JSObject * obj , uintN argc, jsval *argv, jsval *rval ){
+    JSBool native_print( JSContext * cx , uintN argc , jsval *vp ){
+        jsval *argv = JS_ARGV( cx , vp);
         stringstream ss;
         Convertor c( cx );
         for ( uintN i=0; i<argc; i++ ){
@@ -897,10 +925,13 @@ namespace mongo {
         }
         ss << "\n";
         Logstream::logLockless( ss.str() );
+        JS_SET_RVAL( cx , vp , JSVAL_VOID );
         return JS_TRUE;
     }
 
-    JSBool native_helper( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval ){
+    JSBool native_helper( JSContext *cx , uintN argc, jsval *vp){
+        jsval *argv = JS_ARGV( cx , vp );
+        JSObject *obj = JS_THIS_OBJECT( cx , vp );
         Convertor c(cx);
         
         NativeFunction func = (NativeFunction)((long long)c.getNumber( obj , "x" ) );
@@ -926,35 +957,37 @@ namespace mongo {
         }
         
         if ( out.isEmpty() ){
-            *rval = JSVAL_VOID;
+            JS_SET_RVAL( cx , vp , JSVAL_VOID );
         }
         else {
-            *rval = c.toval( out.firstElement() );
+            JS_SET_RVAL( cx , vp , c.toval( out.firstElement() ) );
         }
 
         return JS_TRUE;
     }
 
-    JSBool native_load( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval );
+    JSBool native_load( JSContext *cx , uintN argc, jsval *vp );
 
-    JSBool native_gc( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval ){
+    JSBool native_gc( JSContext *cx , uintN argc, jsval *vp ){
         JS_GC( cx );
+        JS_SET_RVAL( cx , vp , JSVAL_VOID );
         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 }
+        JS_FS( "print" , &native_print , 0 , JSFUN_FAST_NATIVE ) ,
+        JS_FS( "nativeHelper" , &native_helper , 1 , JSFUN_FAST_NATIVE ) ,
+        JS_FS( "load" , &native_load , 1 , JSFUN_FAST_NATIVE ) ,
+        JS_FS( "gc" , &native_gc , 1 , JSFUN_FAST_NATIVE ) ,
+        JS_FS_END
     };
 
     // ----END global helpers ----
 
     // Object helpers
     
-    JSBool bson_get_size(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
+    JSBool bson_get_size(JSContext *cx, uintN argc, jsval *vp){
+        jsval *argv = JS_ARGV( cx , vp );
         if ( argc != 1 || !JSVAL_IS_OBJECT( argv[ 0 ] ) ) {
             JS_ReportError( cx , "bsonsize requires one valid object" );
             return JS_FALSE;
@@ -976,19 +1009,22 @@ namespace mongo {
             BSONObj temp = c.toObject( o );
             size = temp.objsize();
         }
-        
-        *rval = c.toval( size );
+
+        JS_SET_RVAL( cx , vp , c.toval( size ) );
         return JS_TRUE;        
     }
     
     JSFunctionSpec objectHelpers[] = {
-    { "bsonsize" , &bson_get_size , 1 , 0 , 0 } ,
-    { 0 , 0 , 0 , 0 , 0 }
+        JS_FS( "bsonsize" , &bson_get_size , 1 , JSFUN_FAST_NATIVE ) ,
+        JS_FS_END
     };
     
     // end Object helpers
 
-    JSBool resolveBSONField( JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp ){
+    // FIXME: This won't build on spidermonkey < 1.8.5 (JSResolveOp)
+    JSBool resolveBSONField( JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp ){
+        jsval idval;
+        JS_IdToValue( cx , id , &idval );
         assert( JS_EnterLocalRootScope( cx ) );
         Convertor c( cx );
 
@@ -1001,7 +1037,7 @@ namespace mongo {
         }
         holder->check();
         
-        string s = c.toString( id );
+        string s = c.toString( idval );
 
         BSONElement e = holder->_obj[ s.c_str() ];
         
@@ -1117,9 +1153,15 @@ namespace mongo {
             //JS_SetVersion( _context , JSVERSION_LATEST); TODO
             JS_SetErrorReporter( _context , errorReporter );
 
+#ifdef HAVE_COMPARTMENTS
+            _global = JS_NewCompartmentAndGlobalObject( _context , &global_class , NULL);
+            massert( 13441 ,  "JS_NewCompartmentAndGlobalObject failed for global" , _global );
+            _call = JS_EnterCrossCompartmentCall( _context , _global);
+#else
             _global = JS_NewObject( _context , &global_class, NULL, NULL);
             massert( 10432 ,  "JS_NewObject failed for global" , _global );
             JS_SetGlobalObject( _context , _global );
+#endif
             massert( 10433 ,  "js init failed" , JS_InitStandardClasses( _context , _global ) );
 
             JS_SetOptions( _context , JS_GetOptions( _context ) | JSOPTION_VAROBJFIX );
@@ -1137,13 +1179,14 @@ namespace mongo {
             smlock;
             uassert( 10223 ,  "deleted SMScope twice?" , _convertor );
 
-            for ( list<void*>::iterator i=_roots.begin(); i != _roots.end(); i++ ){
-                JS_RemoveRoot( _context , *i );
+            for ( list<JSObject*>::iterator i=_roots.begin(); i != _roots.end(); i++ ){
+                JSObject * obj = (JSObject *)*i;
+                JS_RemoveObjectRoot( _context , &obj );
             }
             _roots.clear();
             
             if ( _this ){
-                JS_RemoveRoot( _context , &_this );
+                JS_RemoveObjectRoot( _context , &_this );
                 _this = 0;
             }
 
@@ -1152,6 +1195,13 @@ namespace mongo {
                 _convertor = 0;
             }
             
+#ifdef HAVE_COMPARTMENTS
+            if ( _call ) {
+                JS_LeaveCrossCompartmentCall( _call );
+                _call = 0;
+            }
+#endif
+            
             if ( _context ){
                 JS_DestroyContext( _context );
                 _context = 0;
@@ -1164,16 +1214,16 @@ namespace mongo {
             assert( _convertor );
             return;
             if ( _this ){
-                JS_RemoveRoot( _context , &_this );
+                JS_RemoveObjectRoot( _context , &_this );
                 _this = 0;
             }
             currentScope.reset( this );
             _error = "";
         }
         
-        void addRoot( void * root , const char * name ){
-            JS_AddNamedRoot( _context , root , name );
-            _roots.push_back( root );
+        void addRoot( JSObject * obj ){
+            JS_AddObjectRoot( _context , &obj );
+            _roots.push_back( obj );
         }
 
         void init( BSONObj * data ){
@@ -1313,13 +1363,13 @@ namespace mongo {
         void setThis( const BSONObj * obj ){
             smlock;
             if ( _this ){
-                JS_RemoveRoot( _context , &_this );
+                JS_RemoveObjectRoot( _context , &_this );
                 _this = 0;
             }
             
             if ( obj ){
                 _this = _convertor->toJSObject( obj );
-                JS_AddNamedRoot( _context , &_this , "scope this" );
+                JS_AddObjectRoot( _context , &_this );
             }
         }
 
@@ -1508,9 +1558,12 @@ namespace mongo {
 
         JSObject * _global;
         JSObject * _this;
+#ifdef HAVE_COMPARTMENTS
+        JSCrossCompartmentCall * _call;
+#endif
 
         string _error;
-        list<void*> _roots;
+        list<JSObject*> _roots;
 
         bool _externalSetup;
         bool _localConnect;
@@ -1539,7 +1592,8 @@ namespace mongo {
         }
     }
 
-    JSBool native_load( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval ){
+    JSBool native_load( JSContext *cx , uintN argc, jsval *vp ){
+        jsval *argv = JS_ARGV( cx , vp );
         Convertor c(cx);
 
         Scope * s = currentScope.get();
@@ -1554,6 +1608,7 @@ namespace mongo {
             }
         }
 
+        JS_SET_RVAL( cx , vp , JSVAL_VOID );
         return JS_TRUE;
     }
 
@@ -1593,7 +1648,7 @@ namespace mongo {
         return new SMScope();
     }
 
-    void Convertor::addRoot( JSFunction * f , const char * name ){
+    void Convertor::addRoot( JSFunction * f ){
         if ( ! f )
             return;
 
@@ -1602,7 +1657,7 @@ namespace mongo {
         
         JSObject * o = JS_GetFunctionObject( f );
         assert( o );
-        scope->addRoot( &o , name );
+        scope->addRoot( o );
     }
 
 }
--- mongodb-1.6.3.orig/scripting/engine_spidermonkey.h
+++ mongodb-1.6.3/scripting/engine_spidermonkey.h
@@ -21,6 +21,9 @@
 
 // START inc hacking
 
+#undef malloc
+#undef realloc
+
 #if defined( MOZJS )
 
 #define MOZILLA_1_8_BRANCH
@@ -55,6 +58,9 @@
 
 #endif
 
+#define malloc MONGO_malloc
+#define realloc MONGO_realloc
+
 // END inc hacking
 
 // -- SM 1.6 hacks ---
@@ -81,6 +87,10 @@ JSBool JS_CStringsAreUTF8(){
 #define SM181
 #endif
 
+#ifndef JSFUN_FAST_NATIVE
+#define JSFUN_FAST_NATIVE 0
+#endif
+
 namespace mongo {
 
     class SMScope;
@@ -104,7 +114,7 @@ namespace mongo {
     extern boost::thread_specific_ptr<SMScope> currentScope;
     
     // bson
-    JSBool resolveBSONField( JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp );
+    JSBool resolveBSONField( JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp );
 
 
     // mongo

