3
/* Copyright 2009 10gen Inc.
5
* Licensed under the Apache License, Version 2.0 (the "License");
6
* you may not use this file except in compliance with the License.
7
* You may obtain a copy of the License at
9
* http://www.apache.org/licenses/LICENSE-2.0
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
* See the License for the specific language governing permissions and
15
* limitations under the License.
18
// hacked in right now from engine_spidermonkey.cpp
20
#include "../client/syncclusterconnection.h"
24
bool haveLocalShardingInfo( const string& ns );
26
// ------------ some defs needed ---------------
28
JSObject * doCreateCollection( JSContext * cx , JSObject * db , const string& shortName );
30
// ------------ utils ------------------
33
bool isSpecialName( const string& name ){
34
static set<string> names;
35
if ( names.size() == 0 ){
36
names.insert( "tojson" );
37
names.insert( "toJson" );
38
names.insert( "toString" );
41
if ( name.length() == 0 )
47
return names.count( name ) > 0;
51
// ------ cursor ------
55
CursorHolder( auto_ptr< DBClientCursor > &cursor, const shared_ptr< DBClientWithCommands > &connection ) :
56
connection_( connection ),
58
assert( cursor_.get() );
60
DBClientCursor *get() const { return cursor_.get(); }
62
shared_ptr< DBClientWithCommands > connection_;
63
auto_ptr< DBClientCursor > cursor_;
66
DBClientCursor *getCursor( JSContext *cx, JSObject *obj ) {
67
CursorHolder * holder = (CursorHolder*)JS_GetPrivate( cx , obj );
68
uassert( 10235 , "no cursor!" , holder );
72
JSBool internal_cursor_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
73
uassert( 10236 , "no args to internal_cursor_constructor" , argc == 0 );
74
assert( JS_SetPrivate( cx , obj , 0 ) ); // just for safety
78
void internal_cursor_finalize( JSContext * cx , JSObject * obj ){
79
CursorHolder * holder = (CursorHolder*)JS_GetPrivate( cx , obj );
82
assert( JS_SetPrivate( cx , obj , 0 ) );
86
JSBool internal_cursor_hasNext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
87
DBClientCursor *cursor = getCursor( cx, obj );
88
*rval = cursor->more() ? JSVAL_TRUE : JSVAL_FALSE;
92
JSBool internal_cursor_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
93
DBClientCursor *cursor = getCursor( cx, obj );
94
if ( ! cursor->more() ){
95
JS_ReportError( cx , "cursor at the end" );
100
BSONObj n = cursor->next();
101
*rval = c.toval( &n );
106
JSFunctionSpec internal_cursor_functions[] = {
107
{ "hasNext" , internal_cursor_hasNext , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
108
{ "next" , internal_cursor_next , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
112
JSClass internal_cursor_class = {
113
"InternalCursor" , JSCLASS_HAS_PRIVATE ,
114
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
115
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, internal_cursor_finalize,
116
JSCLASS_NO_OPTIONAL_MEMBERS
120
// ------ mongo stuff ------
122
JSBool mongo_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
123
uassert( 10237 , "mongo_constructor not implemented yet" , 0 );
127
JSBool mongo_local_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
130
shared_ptr< DBClientWithCommands > client( createDirectClient() );
131
assert( JS_SetPrivate( cx , obj , (void*)( new shared_ptr< DBClientWithCommands >( client ) ) ) );
133
jsval host = c.toval( "EMBEDDED" );
134
assert( JS_SetProperty( cx , obj , "host" , &host ) );
139
JSBool mongo_external_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
142
uassert( 10238 , "0 or 1 args to Mongo" , argc <= 1 );
144
string host = "127.0.0.1";
146
host = c.toString( argv[0] );
148
shared_ptr< DBClientWithCommands > conn;
151
if ( host.find( "," ) == string::npos ){
152
DBClientConnection * c = new DBClientConnection( true );
154
if ( ! c->connect( host , errmsg ) ){
155
JS_ReportError( cx , ((string)"couldn't connect: " + errmsg).c_str() );
161
for ( uint i=0; i<host.size(); i++ )
162
if ( host[i] == ',' )
165
assert( numCommas > 0 );
167
if ( numCommas == 1 ){
168
DBClientPaired * c = new DBClientPaired();
170
if ( ! c->connect( host ) ){
171
JS_ReportError( cx , "couldn't connect to pair" );
175
else if ( numCommas == 2 ){
176
conn.reset( new SyncCluterConnection( host ) );
179
JS_ReportError( cx , "1 (paired) or 2(quorum) commas are allowed" );
185
assert( JS_SetPrivate( cx , obj , (void*)( new shared_ptr< DBClientWithCommands >( conn ) ) ) );
186
jsval host_val = c.toval( host.c_str() );
187
assert( JS_SetProperty( cx , obj , "host" , &host_val ) );
192
DBClientWithCommands *getConnection( JSContext *cx, JSObject *obj ) {
193
shared_ptr< DBClientWithCommands > * connHolder = (shared_ptr< DBClientWithCommands >*)JS_GetPrivate( cx , obj );
194
uassert( 10239 , "no connection!" , connHolder && connHolder->get() );
195
return connHolder->get();
198
void mongo_finalize( JSContext * cx , JSObject * obj ){
199
shared_ptr< DBClientWithCommands > * connHolder = (shared_ptr< DBClientWithCommands >*)JS_GetPrivate( cx , obj );
202
assert( JS_SetPrivate( cx , obj , 0 ) );
206
JSClass mongo_class = {
207
"Mongo" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE ,
208
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
209
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, mongo_finalize,
210
JSCLASS_NO_OPTIONAL_MEMBERS
213
JSBool mongo_find(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
214
uassert( 10240 , "mongo_find neesd 5 args" , argc == 5 );
215
shared_ptr< DBClientWithCommands > * connHolder = (shared_ptr< DBClientWithCommands >*)JS_GetPrivate( cx , obj );
216
uassert( 10241 , "no connection!" , connHolder && connHolder->get() );
217
DBClientWithCommands *conn = connHolder->get();
221
string ns = c.toString( argv[0] );
223
BSONObj q = c.toObject( argv[1] );
224
BSONObj f = c.toObject( argv[2] );
226
int nToReturn = (int) c.toNumber( argv[3] );
227
int nToSkip = (int) c.toNumber( argv[4] );
228
bool slaveOk = c.getBoolean( obj , "slaveOk" );
232
auto_ptr<DBClientCursor> cursor = conn->query( ns , q , nToReturn , nToSkip , f.nFields() ? &f : 0 , slaveOk ? QueryOption_SlaveOk : 0 );
233
if ( ! cursor.get() ){
234
JS_ReportError( cx , "error doing query: failed" );
237
JSObject * mycursor = JS_NewObject( cx , &internal_cursor_class , 0 , 0 );
238
assert( JS_SetPrivate( cx , mycursor , new CursorHolder( cursor, *connHolder ) ) );
239
*rval = OBJECT_TO_JSVAL( mycursor );
243
JS_ReportError( cx , "error doing query: unknown" );
248
JSBool mongo_update(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
249
smuassert( cx , "mongo_find needs at elast 3 args" , argc >= 3 );
250
smuassert( cx , "2nd param to update has to be an object" , JSVAL_IS_OBJECT( argv[1] ) );
251
smuassert( cx , "3rd param to update has to be an object" , JSVAL_IS_OBJECT( argv[2] ) );
254
if ( c.getBoolean( obj , "readOnly" ) ){
255
JS_ReportError( cx , "js db in read only mode - mongo_update" );
259
DBClientWithCommands * conn = getConnection( cx, obj );
260
uassert( 10245 , "no connection!" , conn );
262
string ns = c.toString( argv[0] );
264
bool upsert = argc > 3 && c.toBoolean( argv[3] );
265
bool multi = argc > 4 && c.toBoolean( argv[4] );
268
conn->update( ns , c.toObject( argv[1] ) , c.toObject( argv[2] ) , upsert , multi );
272
JS_ReportError( cx , "error doing update" );
277
JSBool mongo_insert(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
278
smuassert( cx , "mongo_insert needs 2 args" , argc == 2 );
279
smuassert( cx , "2nd param to insert has to be an object" , JSVAL_IS_OBJECT( argv[1] ) );
282
if ( c.getBoolean( obj , "readOnly" ) ){
283
JS_ReportError( cx , "js db in read only mode - mongo_insert" );
287
DBClientWithCommands * conn = getConnection( cx, obj );
288
uassert( 10248 , "no connection!" , conn );
291
string ns = c.toString( argv[0] );
292
BSONObj o = c.toObject( argv[1] );
297
conn->insert( ns , o );
300
catch ( std::exception& e ){
302
ss << "error doing insert:" << e.what();
304
JS_ReportError( cx , s.c_str() );
308
JS_ReportError( cx , "error doing insert" );
313
JSBool mongo_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
314
smuassert( cx , "mongo_remove needs 2 arguments" , argc == 2 );
315
smuassert( cx , "2nd param to insert has to be an object" , JSVAL_IS_OBJECT( argv[1] ) );
318
if ( c.getBoolean( obj , "readOnly" ) ){
319
JS_ReportError( cx , "js db in read only mode - mongo_remove" );
323
DBClientWithCommands * conn = getConnection( cx, obj );
324
uassert( 10251 , "no connection!" , conn );
326
string ns = c.toString( argv[0] );
327
BSONObj o = c.toObject( argv[1] );
330
conn->remove( ns , o );
334
JS_ReportError( cx , "error doing remove" );
340
JSFunctionSpec mongo_functions[] = {
341
{ "find" , mongo_find , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
342
{ "update" , mongo_update , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
343
{ "insert" , mongo_insert , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
344
{ "remove" , mongo_remove , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
349
// ------------- db_collection -------------
351
JSBool db_collection_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
352
smuassert( cx , "db_collection_constructor wrong args" , argc == 4 );
353
assert( JS_SetProperty( cx , obj , "_mongo" , &(argv[0]) ) );
354
assert( JS_SetProperty( cx , obj , "_db" , &(argv[1]) ) );
355
assert( JS_SetProperty( cx , obj , "_shortName" , &(argv[2]) ) );
356
assert( JS_SetProperty( cx , obj , "_fullName" , &(argv[3]) ) );
359
if ( haveLocalShardingInfo( c.toString( argv[3] ) ) ){
360
JS_ReportError( cx , "can't use sharded collection from db.eval" );
367
JSBool db_collection_resolve( JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp ){
368
if ( flags & JSRESOLVE_ASSIGNING )
372
string collname = c.toString( id );
374
if ( isSpecialName( collname ) )
377
if ( obj == c.getGlobalPrototype( "DBCollection" ) )
380
JSObject * proto = JS_GetPrototype( cx , obj );
381
if ( c.hasProperty( obj , collname.c_str() ) || ( proto && c.hasProperty( proto , collname.c_str() ) ) )
384
string name = c.toString( c.getProperty( obj , "_shortName" ) );
388
jsval db = c.getProperty( obj , "_db" );
389
if ( ! JSVAL_IS_OBJECT( db ) )
392
JSObject * coll = doCreateCollection( cx , JSVAL_TO_OBJECT( db ) , name );
395
c.setProperty( obj , collname.c_str() , OBJECT_TO_JSVAL( coll ) );
400
JSClass db_collection_class = {
401
"DBCollection" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE ,
402
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
403
JS_EnumerateStub, (JSResolveOp)(&db_collection_resolve) , JS_ConvertStub, JS_FinalizeStub,
404
JSCLASS_NO_OPTIONAL_MEMBERS
408
JSObject * doCreateCollection( JSContext * cx , JSObject * db , const string& shortName ){
411
assert( c.hasProperty( db , "_mongo" ) );
412
assert( c.hasProperty( db , "_name" ) );
414
JSObject * coll = JS_NewObject( cx , &db_collection_class , 0 , 0 );
415
c.setProperty( coll , "_mongo" , c.getProperty( db , "_mongo" ) );
416
c.setProperty( coll , "_db" , OBJECT_TO_JSVAL( db ) );
417
c.setProperty( coll , "_shortName" , c.toval( shortName.c_str() ) );
419
string name = c.toString( c.getProperty( db , "_name" ) );
420
name += "." + shortName;
421
c.setProperty( coll , "_fullName" , c.toval( name.c_str() ) );
423
if ( haveLocalShardingInfo( name ) ){
424
JS_ReportError( cx , "can't use sharded collection from db.eval" );
431
// -------------- DB ---------------
434
JSBool db_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
435
smuassert( cx, "wrong number of arguments to DB" , argc == 2 );
436
assert( JS_SetProperty( cx , obj , "_mongo" , &(argv[0]) ) );
437
assert( JS_SetProperty( cx , obj , "_name" , &(argv[1]) ) );
442
JSBool db_resolve( JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp ){
443
if ( flags & JSRESOLVE_ASSIGNING )
448
if ( obj == c.getGlobalPrototype( "DB" ) )
451
string collname = c.toString( id );
453
if ( isSpecialName( collname ) )
456
JSObject * proto = JS_GetPrototype( cx , obj );
457
if ( proto && c.hasProperty( proto , collname.c_str() ) )
460
JSObject * coll = doCreateCollection( cx , obj , collname );
463
c.setProperty( obj , collname.c_str() , OBJECT_TO_JSVAL( coll ) );
470
"DB" , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE ,
471
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
472
JS_EnumerateStub, (JSResolveOp)(&db_resolve) , JS_ConvertStub, JS_FinalizeStub,
473
JSCLASS_NO_OPTIONAL_MEMBERS
477
// -------------- object id -------------
479
JSBool object_id_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
487
smuassert( cx , "object_id_constructor can't take more than 1 param" , argc == 1 );
488
string s = c.toString( argv[0] );
491
Scope::validateObjectIdString( s );
492
} catch ( const MsgAssertionException &m ) {
493
static string error = m.toString();
494
JS_ReportError( cx, error.c_str() );
500
if ( ! JS_InstanceOf( cx , obj , &object_id_class , 0 ) ){
501
obj = JS_NewObject( cx , &object_id_class , 0 , 0 );
503
*rval = OBJECT_TO_JSVAL( obj );
506
jsval v = c.toval( oid.str().c_str() );
507
assert( JS_SetProperty( cx , obj , "str" , &v ) );
512
JSClass object_id_class = {
513
"ObjectId" , JSCLASS_HAS_PRIVATE ,
514
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
515
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
516
JSCLASS_NO_OPTIONAL_MEMBERS
519
JSBool object_id_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
521
return *rval = c.getProperty( obj , "str" );
524
JSFunctionSpec object_id_functions[] = {
525
{ "toString" , object_id_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
531
JSBool dbpointer_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
536
if ( ! JSVAL_IS_OID( argv[1] ) ){
537
JS_ReportError( cx , "2nd arg to DBPointer needs to be oid" );
541
assert( JS_SetProperty( cx , obj , "ns" , &(argv[0]) ) );
542
assert( JS_SetProperty( cx , obj , "id" , &(argv[1]) ) );
546
JS_ReportError( cx , "DBPointer needs 2 arguments" );
551
JSClass dbpointer_class = {
552
"DBPointer" , JSCLASS_HAS_PRIVATE ,
553
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
554
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
555
JSCLASS_NO_OPTIONAL_MEMBERS
558
JSFunctionSpec dbpointer_functions[] = {
563
JSBool dbref_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
567
assert( JS_SetProperty( cx , obj , "$ref" , &(argv[0]) ) );
568
assert( JS_SetProperty( cx , obj , "$id" , &(argv[1]) ) );
572
JS_ReportError( cx , "DBRef needs 2 arguments" );
577
JSClass dbref_class = {
578
"DBRef" , JSCLASS_HAS_PRIVATE ,
579
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
580
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
581
JSCLASS_NO_OPTIONAL_MEMBERS
584
JSFunctionSpec dbref_functions[] = {
592
JSBool bindata_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
593
JS_ReportError( cx , "can't create a BinData yet" );
597
JSClass bindata_class = {
598
"BinData" , JSCLASS_HAS_PRIVATE ,
599
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
600
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
601
JSCLASS_NO_OPTIONAL_MEMBERS
604
JSFunctionSpec bindata_functions[] = {
610
bool specialMapString( const string& s ){
611
return s == "put" || s == "get" || s == "_get" || s == "values" || s == "_data" || s == "constructor" ;
614
JSBool map_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
616
JS_ReportError( cx , "Map takes no arguments" );
620
JSObject * array = JS_NewObject( cx , 0 , 0 , 0 );
623
jsval a = OBJECT_TO_JSVAL( array );
624
JS_SetProperty( cx , obj , "_data" , &a );
629
JSBool map_prop( JSContext *cx, JSObject *obj, jsval idval, jsval *vp ){
631
if ( specialMapString( c.toString( idval ) ) )
634
log() << "illegal prop access: " << c.toString( idval ) << endl;
635
JS_ReportError( cx , "can't use array access with Map" );
639
JSClass map_class = {
640
"Map" , JSCLASS_HAS_PRIVATE ,
641
map_prop, JS_PropertyStub, map_prop, map_prop,
642
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
643
JSCLASS_NO_OPTIONAL_MEMBERS
646
JSFunctionSpec map_functions[] = {
653
JSClass timestamp_class = {
654
"Timestamp" , JSCLASS_HAS_PRIVATE ,
655
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
656
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
657
JSCLASS_NO_OPTIONAL_MEMBERS
660
JSClass minkey_class = {
661
"MinKey" , JSCLASS_HAS_PRIVATE ,
662
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
663
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
664
JSCLASS_NO_OPTIONAL_MEMBERS
667
JSClass maxkey_class = {
668
"MaxKey" , JSCLASS_HAS_PRIVATE ,
669
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
670
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
671
JSCLASS_NO_OPTIONAL_MEMBERS
676
JSBool dbquery_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
677
smuassert( cx , "DDQuery needs at least 4 args" , argc >= 4 );
680
c.setProperty( obj , "_mongo" , argv[0] );
681
c.setProperty( obj , "_db" , argv[1] );
682
c.setProperty( obj , "_collection" , argv[2] );
683
c.setProperty( obj , "_ns" , argv[3] );
685
if ( argc > 4 && JSVAL_IS_OBJECT( argv[4] ) )
686
c.setProperty( obj , "_query" , argv[4] );
688
c.setProperty( obj , "_query" , OBJECT_TO_JSVAL( JS_NewObject( cx , 0 , 0 , 0 ) ) );
690
if ( argc > 5 && JSVAL_IS_OBJECT( argv[5] ) )
691
c.setProperty( obj , "_fields" , argv[5] );
693
c.setProperty( obj , "_fields" , JSVAL_NULL );
696
if ( argc > 6 && JSVAL_IS_NUMBER( argv[6] ) )
697
c.setProperty( obj , "_limit" , argv[6] );
699
c.setProperty( obj , "_limit" , JSVAL_ZERO );
701
if ( argc > 7 && JSVAL_IS_NUMBER( argv[7] ) )
702
c.setProperty( obj , "_skip" , argv[7] );
704
c.setProperty( obj , "_skip" , JSVAL_ZERO );
706
c.setProperty( obj , "_cursor" , JSVAL_NULL );
707
c.setProperty( obj , "_numReturned" , JSVAL_ZERO );
708
c.setProperty( obj , "_special" , JSVAL_FALSE );
713
JSBool dbquery_resolve( JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp ){
714
if ( flags & JSRESOLVE_ASSIGNING )
717
if ( ! JSVAL_IS_NUMBER( id ) )
720
jsval val = JSVAL_VOID;
721
assert( JS_CallFunctionName( cx , obj , "arrayAccess" , 1 , &id , &val ) );
723
c.setProperty( obj , c.toString( id ).c_str() , val );
728
JSClass dbquery_class = {
729
"DBQuery" , JSCLASS_NEW_RESOLVE ,
730
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
731
JS_EnumerateStub, (JSResolveOp)(&dbquery_resolve) , JS_ConvertStub, JS_FinalizeStub,
732
JSCLASS_NO_OPTIONAL_MEMBERS
735
// ---- other stuff ----
737
void initMongoJS( SMScope * scope , JSContext * cx , JSObject * global , bool local ){
739
assert( JS_InitClass( cx , global , 0 , &mongo_class , local ? mongo_local_constructor : mongo_external_constructor , 0 , 0 , mongo_functions , 0 , 0 ) );
741
assert( JS_InitClass( cx , global , 0 , &object_id_class , object_id_constructor , 0 , 0 , object_id_functions , 0 , 0 ) );
742
assert( JS_InitClass( cx , global , 0 , &db_class , db_constructor , 2 , 0 , 0 , 0 , 0 ) );
743
assert( JS_InitClass( cx , global , 0 , &db_collection_class , db_collection_constructor , 4 , 0 , 0 , 0 , 0 ) );
744
assert( JS_InitClass( cx , global , 0 , &internal_cursor_class , internal_cursor_constructor , 0 , 0 , internal_cursor_functions , 0 , 0 ) );
745
assert( JS_InitClass( cx , global , 0 , &dbquery_class , dbquery_constructor , 0 , 0 , 0 , 0 , 0 ) );
746
assert( JS_InitClass( cx , global , 0 , &dbpointer_class , dbpointer_constructor , 0 , 0 , dbpointer_functions , 0 , 0 ) );
747
assert( JS_InitClass( cx , global , 0 , &dbref_class , dbref_constructor , 0 , 0 , dbref_functions , 0 , 0 ) );
748
assert( JS_InitClass( cx , global , 0 , &bindata_class , bindata_constructor , 0 , 0 , bindata_functions , 0 , 0 ) );
750
assert( JS_InitClass( cx , global , 0 , ×tamp_class , 0 , 0 , 0 , 0 , 0 , 0 ) );
751
assert( JS_InitClass( cx , global , 0 , &minkey_class , 0 , 0 , 0 , 0 , 0 , 0 ) );
752
assert( JS_InitClass( cx , global , 0 , &maxkey_class , 0 , 0 , 0 , 0 , 0 , 0 ) );
754
assert( JS_InitClass( cx , global , 0 , &map_class , map_constructor , 0 , 0 , map_functions , 0 , 0 ) );
756
assert( JS_InitClass( cx , global , 0 , &bson_ro_class , bson_cons , 0 , 0 , bson_functions , 0 , 0 ) );
757
assert( JS_InitClass( cx , global , 0 , &bson_class , bson_cons , 0 , 0 , bson_functions , 0 , 0 ) );
759
scope->exec( jsconcatcode );
762
bool appendSpecialDBObject( Convertor * c , BSONObjBuilder& b , const string& name , jsval val , JSObject * o ){
764
if ( JS_InstanceOf( c->_context , o , &object_id_class , 0 ) ){
766
oid.init( c->getString( o , "str" ) );
767
b.append( name.c_str() , oid );
771
if ( JS_InstanceOf( c->_context , o , &minkey_class , 0 ) ){
772
b.appendMinKey( name.c_str() );
776
if ( JS_InstanceOf( c->_context , o , &maxkey_class , 0 ) ){
777
b.appendMaxKey( name.c_str() );
781
if ( JS_InstanceOf( c->_context , o , ×tamp_class , 0 ) ){
782
b.appendTimestamp( name.c_str() , (unsigned long long)c->getNumber( o , "t" ) , (unsigned int )c->getNumber( o , "i" ) );
786
if ( JS_InstanceOf( c->_context , o , &dbpointer_class , 0 ) ){
787
b.appendDBRef( name.c_str() , c->getString( o , "ns" ).c_str() , c->toOID( c->getProperty( o , "id" ) ) );
791
if ( JS_InstanceOf( c->_context , o , &bindata_class , 0 ) ){
792
b.appendBinData( name.c_str() ,
793
(int)(c->getNumber( o , "len" )) , (BinDataType)((char)(c->getNumber( o , "type" ) ) ) ,
794
(char*)JS_GetPrivate( c->_context , o ) + 1
799
#if defined( SM16 ) || defined( MOZJS )
800
#warning dates do not work in your version of spider monkey
802
jsdouble d = js_DateGetMsecSinceEpoch( c->_context , o );
804
b.appendDate( name.c_str() , Date_t(d) );
808
#elif defined( XULRUNNER )
809
if ( JS_InstanceOf( c->_context , o, globalSMEngine->_dateClass , 0 ) ){
810
jsdouble d = js_DateGetMsecSinceEpoch( c->_context , o );
811
b.appendDate( name.c_str() , Date_t(d) );
815
if ( JS_InstanceOf( c->_context , o, &js_DateClass , 0 ) ){
816
jsdouble d = js_DateGetMsecSinceEpoch( c->_context , o );
818
b.appendDate( name.c_str() , Date_t((unsigned long long)d) );
824
if ( JS_InstanceOf( c->_context , o , &dbquery_class , 0 ) ||
825
JS_InstanceOf( c->_context , o , &mongo_class , 0 ) ||
826
JS_InstanceOf( c->_context , o , &db_collection_class , 0 ) ){
827
b.append( name.c_str() , c->toString( val ) );
831
#if defined( XULRUNNER )
832
if ( JS_InstanceOf( c->_context , o , globalSMEngine->_regexClass , 0 ) ){
833
c->appendRegex( b , name , c->toString( val ) );
836
#elif defined( SM18 )
837
if ( JS_InstanceOf( c->_context , o , &js_RegExpClass , 0 ) ){
838
c->appendRegex( b , name , c->toString( val ) );
846
bool isDate( JSContext * cx , JSObject * o ){
847
#if defined( SM16 ) || defined( MOZJS ) || defined( XULRUNNER )
848
return js_DateGetMsecSinceEpoch( cx , o ) != 0;
850
return JS_InstanceOf( cx , o, &js_DateClass, 0 );