diff options
author | Ben Becker <ben.becker@10gen.com> | 2013-01-18 14:15:28 -0800 |
---|---|---|
committer | Ben Becker <ben.becker@10gen.com> | 2013-01-18 14:15:43 -0800 |
commit | 41c1110326ae00fc7fb279b3bfeabadc3a82bc5a (patch) | |
tree | 646e122504532957a3517ea1b3e82070c629d091 /src/mongo/scripting | |
parent | 98d2e5d364e01581a4ba1b2e7df25f79ebd836b2 (diff) | |
download | mongo-41c1110326ae00fc7fb279b3bfeabadc3a82bc5a.tar.gz |
SERVER-8104: clean up js global object
Diffstat (limited to 'src/mongo/scripting')
-rw-r--r-- | src/mongo/scripting/bench.cpp | 17 | ||||
-rw-r--r-- | src/mongo/scripting/bench.h | 5 | ||||
-rw-r--r-- | src/mongo/scripting/engine.cpp | 11 | ||||
-rw-r--r-- | src/mongo/scripting/engine.h | 2 | ||||
-rw-r--r-- | src/mongo/scripting/engine_v8.cpp | 135 | ||||
-rw-r--r-- | src/mongo/scripting/engine_v8.h | 8 | ||||
-rw-r--r-- | src/mongo/scripting/utils.cpp | 4 | ||||
-rw-r--r-- | src/mongo/scripting/v8_db.cpp | 88 | ||||
-rw-r--r-- | src/mongo/scripting/v8_db.h | 9 | ||||
-rw-r--r-- | src/mongo/scripting/v8_utils.cpp | 8 | ||||
-rw-r--r-- | src/mongo/scripting/v8_utils.h | 1 |
11 files changed, 165 insertions, 123 deletions
diff --git a/src/mongo/scripting/bench.cpp b/src/mongo/scripting/bench.cpp index 234550586e6..f0256574afa 100644 --- a/src/mongo/scripting/bench.cpp +++ b/src/mongo/scripting/bench.cpp @@ -347,7 +347,7 @@ namespace mongo { bool check = ! e["check"].eoo(); if( check ){ if ( e["check"].type() == CodeWScope || e["check"].type() == Code || e["check"].type() == String ) { - scope = globalScriptEngine->getPooledScope( ns ); + scope = globalScriptEngine->getPooledScope( ns + "benchrun" ); verify( scope.get() ); if ( e.type() == CodeWScope ) { @@ -790,7 +790,7 @@ namespace mongo { /** * benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 } */ - BSONObj benchRunSync( const BSONObj& argsFake, void* data ) { + BSONObj BenchRunner::benchRunSync( const BSONObj& argsFake, void* data ) { BSONObj start = benchStart( argsFake, data ); @@ -804,7 +804,7 @@ namespace mongo { /** * benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 } */ - BSONObj benchStart( const BSONObj& argsFake, void* data ) { + BSONObj BenchRunner::benchStart( const BSONObj& argsFake, void* data ) { verify( argsFake.firstElement().isABSONObj() ); BSONObj args = argsFake.firstElement().Obj(); @@ -819,7 +819,7 @@ namespace mongo { /** * benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 } */ - BSONObj benchFinish( const BSONObj& argsFake, void* data ) { + BSONObj BenchRunner::benchFinish( const BSONObj& argsFake, void* data ) { OID oid = OID( argsFake.firstElement().String() ); @@ -831,11 +831,4 @@ namespace mongo { return BSON( "" << finalObj ); } - void installBenchmarkSystem( Scope& scope ) { - scope.injectNative( "benchRun" , benchRunSync ); - scope.injectNative( "benchRunSync" , benchRunSync ); - scope.injectNative( "benchStart" , benchStart ); - scope.injectNative( "benchFinish" , benchFinish ); - } - -} +} // namespace mongo diff --git a/src/mongo/scripting/bench.h b/src/mongo/scripting/bench.h index 7ae7d642f53..b3a644c7765 100644 --- a/src/mongo/scripting/bench.h +++ b/src/mongo/scripting/bench.h @@ -395,6 +395,11 @@ namespace mongo { const BenchRunConfig &config() const { return *_config; } // TODO: Remove this function. + // JS bindings + static BSONObj benchFinish(const BSONObj& argsFake, void* data); + static BSONObj benchStart(const BSONObj& argsFake, void* data); + static BSONObj benchRunSync(const BSONObj& argsFake, void* data); + private: // TODO: Same as for createWithConfig. static boost::mutex _staticMutex; diff --git a/src/mongo/scripting/engine.cpp b/src/mongo/scripting/engine.cpp index 0124b45b45c..5017f40a4ed 100644 --- a/src/mongo/scripting/engine.cpp +++ b/src/mongo/scripting/engine.cpp @@ -24,6 +24,7 @@ #include "mongo/client/dbclientcursor.h" #include "mongo/client/dbclientinterface.h" +#include "mongo/scripting/bench.h" #include "mongo/util/file.h" namespace mongo { @@ -230,7 +231,6 @@ namespace mongo { } void Scope::execCoreFiles() { - // keeping same order as in SConstruct execSetup(JSFiles::utils); execSetup(JSFiles::utils_sh); execSetup(JSFiles::db); @@ -240,6 +240,14 @@ namespace mongo { execSetup(JSFiles::collection); } + /** install BenchRunner suite */ + void Scope::installBenchRun() { + injectNative("benchRun", BenchRunner::benchRunSync); + injectNative("benchRunSync", BenchRunner::benchRunSync); + injectNative("benchStart", BenchRunner::benchStart); + injectNative("benchFinish", BenchRunner::benchFinish); + } + typedef map<string, list<Scope*> > PoolToScopes; class ScopeCache { @@ -378,6 +386,7 @@ namespace mongo { Scope* _real; }; + /** Get a scope from the pool of scopes matching the supplied pool name */ auto_ptr<Scope> ScriptEngine::getPooledScope(const string& pool) { if (!scopeCache.get()) scopeCache.reset(new ScopeCache()); diff --git a/src/mongo/scripting/engine.h b/src/mongo/scripting/engine.h index e9d388145c0..160ba077962 100644 --- a/src/mongo/scripting/engine.h +++ b/src/mongo/scripting/engine.h @@ -71,6 +71,8 @@ namespace mongo { virtual bool hasOutOfMemoryException() = 0; + virtual void installBenchRun(); + virtual bool isKillPending() const = 0; virtual void gc() = 0; diff --git a/src/mongo/scripting/engine_v8.cpp b/src/mongo/scripting/engine_v8.cpp index 88be725567c..534a74197f6 100644 --- a/src/mongo/scripting/engine_v8.cpp +++ b/src/mongo/scripting/engine_v8.cpp @@ -25,6 +25,12 @@ using namespace mongoutils; namespace mongo { + // Generated symbols for JS files + namespace JSFiles { + extern const JSFile types; + extern const JSFile assert; + } + /** * Unwraps a BSONObj from the JS wrapper */ @@ -501,17 +507,20 @@ namespace mongo { internalFieldObjects->SetInternalFieldCount(1); injectV8Function("print", Print); - injectV8Function("version", Version); - injectV8Function("load", load); + injectV8Function("version", Version); // TODO: remove injectV8Function("gc", GCV8); - injectV8Function("startCpuProfiler", startCpuProfiler); - injectV8Function("stopCpuProfiler", stopCpuProfiler); - injectV8Function("getCpuProfile", getCpuProfile); + // injectV8Function("startCpuProfiler", startCpuProfiler); + // injectV8Function("stopCpuProfiler", stopCpuProfiler); + // injectV8Function("getCpuProfile", getCpuProfile); - // install db and bson types in the global scope - installDBTypes(this, _global); + // install BSON functions in the global object + installBSONTypes(); - // install db/shell-specific utilities in the global scope + // load JS helpers (dependancy: installBSONTypes) + execSetup(JSFiles::assert); + execSetup(JSFiles::types); + + // install process-specific utilities in the global scope (dependancy: types.js, assert.js) if (_engine->_scopeInitCallback) _engine->_scopeInitCallback(*this); @@ -730,6 +739,40 @@ namespace mongo { return v8ToMongo(v->ToObject()); } + v8::Handle<v8::FunctionTemplate> getNumberLongFunctionTemplate(V8Scope* scope) { + v8::Handle<v8::FunctionTemplate> numberLong = scope->createV8Function(numberLongInit); + v8::Local<v8::Template> proto = numberLong->PrototypeTemplate(); + scope->injectV8Function("valueOf", numberLongValueOf, proto); + scope->injectV8Function("toNumber", numberLongToNumber, proto); + scope->injectV8Function("toString", numberLongToString, proto); + return numberLong; + } + + v8::Handle<v8::FunctionTemplate> getNumberIntFunctionTemplate(V8Scope* scope) { + v8::Handle<v8::FunctionTemplate> numberInt = scope->createV8Function(numberIntInit); + v8::Local<v8::Template> proto = numberInt->PrototypeTemplate(); + scope->injectV8Function("valueOf", numberIntValueOf, proto); + scope->injectV8Function("toNumber", numberIntToNumber, proto); + scope->injectV8Function("toString", numberIntToString, proto); + return numberInt; + } + + v8::Handle<v8::FunctionTemplate> getBinDataFunctionTemplate(V8Scope* scope) { + v8::Handle<v8::FunctionTemplate> binData = scope->createV8Function(binDataInit); + binData->InstanceTemplate()->SetInternalFieldCount(1); + v8::Local<v8::Template> proto = binData->PrototypeTemplate(); + scope->injectV8Function("toString", binDataToString, proto); + scope->injectV8Function("base64", binDataToBase64, proto); + scope->injectV8Function("hex", binDataToHex, proto); + return binData; + } + + v8::Handle<v8::FunctionTemplate> getTimestampFunctionTemplate(V8Scope* scope) { + v8::Handle<v8::FunctionTemplate> ts = scope->createV8Function(dbTimestampInit); + ts->InstanceTemplate()->SetInternalFieldCount(1); + return ts; + } + // --- functions ----- bool hasFunctionIdentifier(const string& code) { @@ -1012,14 +1055,17 @@ namespace mongo { return; uassert(12511, "localConnect previously called with a different name", false); } - _global->ForceSet(v8StringData("Mongo"), - getMongoFunctionTemplate(this, true)->GetFunction()); - execCoreFiles(); - exec("_mongo = new Mongo();", "local connect 2", false, true, true, 0); - exec((string)"db = _mongo.getDB(\"" + dbName + "\");", "local connect 3", - false, true, true, 0); - _connectState = LOCAL; - _localDBName = dbName; + + // NOTE: order is important here. the following methods must be called after + // the above conditional statements. + + // install db access functions in the global object + installDBAccess(); + + // add global load() helper + injectV8Function("load", load); + + // install the Mongo function object and instantiate the 'db' global _global->ForceSet(v8StringData("Mongo"), getMongoFunctionTemplate(this, true)->GetFunction()); execCoreFiles(); @@ -1038,13 +1084,70 @@ namespace mongo { return; if (_connectState == LOCAL) uassert(12512, "localConnect already called, can't call externalSetup", false); + + // install db access functions in the global object + installDBAccess(); + + // install thread-related functions (e.g. _threadInject) installFork(this, _global, _context); + + // install 'load' helper function + injectV8Function("load", load); + + // install the Mongo function object _global->ForceSet(v8StringData("Mongo"), getMongoFunctionTemplate(this, false)->GetFunction()); execCoreFiles(); _connectState = EXTERNAL; } + void V8Scope::installDBAccess() { + v8::Handle<v8::FunctionTemplate> db = createV8Function(dbInit); + db->InstanceTemplate()->SetNamedPropertyHandler(collectionGetter, collectionSetter); + _global->ForceSet(v8StringData("DB"), db->GetFunction()); + v8::Handle<v8::FunctionTemplate> dbCollection = createV8Function(collectionInit); + dbCollection->InstanceTemplate()->SetNamedPropertyHandler(collectionGetter, + collectionSetter); + _global->ForceSet(v8StringData("DBCollection"), dbCollection->GetFunction()); + + v8::Handle<v8::FunctionTemplate> dbQuery = createV8Function(dbQueryInit); + dbQuery->InstanceTemplate()->SetIndexedPropertyHandler(dbQueryIndexAccess); + _global->ForceSet(v8StringData("DBQuery"), dbQuery->GetFunction()); + } + + void V8Scope::installBSONTypes() { + injectV8Function("ObjectId", objectIdInit, _global); + injectV8Function("DBRef", dbRefInit, _global); + injectV8Function("DBPointer", dbPointerInit, _global); + + _global->ForceSet(v8StringData("BinData"), + getBinDataFunctionTemplate(this)->GetFunction()); + _global->ForceSet(v8StringData("UUID"), + createV8Function(uuidInit)->GetFunction()); + _global->ForceSet(v8StringData("MD5"), + createV8Function(md5Init)->GetFunction()); + _global->ForceSet(v8StringData("HexData"), + createV8Function(hexDataInit)->GetFunction()); + _global->ForceSet(v8StringData("NumberLong"), + getNumberLongFunctionTemplate(this)->GetFunction()); + _global->ForceSet(v8StringData("NumberInt"), + getNumberIntFunctionTemplate(this)->GetFunction()); + _global->ForceSet(v8StringData("Timestamp"), + getTimestampFunctionTemplate(this)->GetFunction()); + + BSONObjBuilder b; + b.appendMaxKey(""); + b.appendMinKey(""); + BSONObj o = b.obj(); + BSONObjIterator i(o); + _global->ForceSet(v8StringData("MaxKey"), mongoToV8Element(i.next())); + _global->ForceSet(v8StringData("MinKey"), mongoToV8Element(i.next())); + _global->Get(v8StringData("Object"))->ToObject()->ForceSet( + v8StringData("bsonsize"), + createV8Function(bsonsize)->GetFunction()); + } + + // ----- internal ----- void V8Scope::reset() { diff --git a/src/mongo/scripting/engine_v8.h b/src/mongo/scripting/engine_v8.h index 2ece1eab79d..991e2f63fcd 100644 --- a/src/mongo/scripting/engine_v8.h +++ b/src/mongo/scripting/engine_v8.h @@ -91,10 +91,18 @@ namespace mongo { /** check if there is a pending killOp request */ bool isKillPending() const; + /** + * Connect to a local database, create a Mongo object instance, and load any + * server-side js into the global object + */ virtual void localConnect(const char* dbName); virtual void externalSetup(); + virtual void installDBAccess(); + + virtual void installBSONTypes(); + virtual string getError() { return _error; } virtual bool hasOutOfMemoryException(); diff --git a/src/mongo/scripting/utils.cpp b/src/mongo/scripting/utils.cpp index f3ae976d019..0ba7e900bcb 100644 --- a/src/mongo/scripting/utils.cpp +++ b/src/mongo/scripting/utils.cpp @@ -21,8 +21,6 @@ namespace mongo { - void installBenchmarkSystem( Scope& scope ); - static BSONObj native_hex_md5( const BSONObj& args, void* data ) { uassert( 10261, "hex_md5 takes a single string argument -- hex_md5(string)", @@ -61,8 +59,6 @@ namespace mongo { scope.injectNative( "hex_md5" , native_hex_md5 ); scope.injectNative( "version" , native_version ); scope.injectNative( "sleep" , native_sleep ); - - installBenchmarkSystem( scope ); } } diff --git a/src/mongo/scripting/v8_db.cpp b/src/mongo/scripting/v8_db.cpp index a0a8c8e58c6..e056dfbe206 100644 --- a/src/mongo/scripting/v8_db.cpp +++ b/src/mongo/scripting/v8_db.cpp @@ -102,94 +102,6 @@ namespace mongo { return mongo; } - v8::Handle<v8::FunctionTemplate> getNumberLongFunctionTemplate(V8Scope* scope) { - v8::Handle<v8::FunctionTemplate> numberLong = scope->createV8Function(numberLongInit); - v8::Local<v8::Template> proto = numberLong->PrototypeTemplate(); - scope->injectV8Function("valueOf", numberLongValueOf, proto); - scope->injectV8Function("toNumber", numberLongToNumber, proto); - scope->injectV8Function("toString", numberLongToString, proto); - return numberLong; - } - - v8::Handle<v8::FunctionTemplate> getNumberIntFunctionTemplate(V8Scope* scope) { - v8::Handle<v8::FunctionTemplate> numberInt = scope->createV8Function(numberIntInit); - v8::Local<v8::Template> proto = numberInt->PrototypeTemplate(); - scope->injectV8Function("valueOf", numberIntValueOf, proto); - scope->injectV8Function("toNumber", numberIntToNumber, proto); - scope->injectV8Function("toString", numberIntToString, proto); - return numberInt; - } - - v8::Handle<v8::FunctionTemplate> getBinDataFunctionTemplate(V8Scope* scope) { - v8::Handle<v8::FunctionTemplate> binData = scope->createV8Function(binDataInit); - binData->InstanceTemplate()->SetInternalFieldCount(1); - v8::Local<v8::Template> proto = binData->PrototypeTemplate(); - scope->injectV8Function("toString", binDataToString, proto); - scope->injectV8Function("base64", binDataToBase64, proto); - scope->injectV8Function("hex", binDataToHex, proto); - return binData; - } - - v8::Handle<v8::FunctionTemplate> getUUIDFunctionTemplate(V8Scope* scope) { - v8::Handle<v8::FunctionTemplate> templ = scope->createV8Function(uuidInit); - return templ; - } - - v8::Handle<v8::FunctionTemplate> getMD5FunctionTemplate(V8Scope* scope) { - v8::Handle<v8::FunctionTemplate> templ = scope->createV8Function(md5Init); - return templ; - } - - v8::Handle<v8::FunctionTemplate> getHexDataFunctionTemplate(V8Scope* scope) { - v8::Handle<v8::FunctionTemplate> templ = scope->createV8Function(hexDataInit); - return templ; - } - - v8::Handle<v8::FunctionTemplate> getTimestampFunctionTemplate(V8Scope* scope) { - v8::Handle<v8::FunctionTemplate> ts = scope->createV8Function(dbTimestampInit); - ts->InstanceTemplate()->SetInternalFieldCount(1); - return ts; - } - - void installDBTypes(V8Scope* scope, v8::Handle<v8::Object>& global) { - v8::Handle<v8::FunctionTemplate> db = scope->createV8Function(dbInit); - db->InstanceTemplate()->SetNamedPropertyHandler(collectionGetter, collectionSetter); - global->ForceSet(scope->v8StringData("DB"), db->GetFunction()); - v8::Handle<v8::FunctionTemplate> dbCollection = scope->createV8Function(collectionInit); - dbCollection->InstanceTemplate()->SetNamedPropertyHandler(collectionGetter, - collectionSetter); - global->ForceSet(scope->v8StringData("DBCollection"), dbCollection->GetFunction()); - - v8::Handle<v8::FunctionTemplate> dbQuery = scope->createV8Function(dbQueryInit); - dbQuery->InstanceTemplate()->SetIndexedPropertyHandler(dbQueryIndexAccess); - global->ForceSet(scope->v8StringData("DBQuery"), dbQuery->GetFunction()); - - scope->injectV8Function("ObjectId", objectIdInit, global); - scope->injectV8Function("DBRef", dbRefInit, global); - scope->injectV8Function("DBPointer", dbPointerInit, global); - - global->ForceSet(scope->v8StringData("BinData"), getBinDataFunctionTemplate(scope)->GetFunction()); - global->ForceSet(scope->v8StringData("UUID"), getUUIDFunctionTemplate(scope)->GetFunction()); - global->ForceSet(scope->v8StringData("MD5"), getMD5FunctionTemplate(scope)->GetFunction()); - global->ForceSet(scope->v8StringData("HexData"), getHexDataFunctionTemplate(scope)->GetFunction()); - global->ForceSet(scope->v8StringData("NumberLong"), - getNumberLongFunctionTemplate(scope)->GetFunction()); - global->ForceSet(scope->v8StringData("NumberInt"), - getNumberIntFunctionTemplate(scope)->GetFunction()); - global->ForceSet(scope->v8StringData("Timestamp"), - getTimestampFunctionTemplate(scope)->GetFunction()); - - BSONObjBuilder b; - b.appendMaxKey(""); - b.appendMinKey(""); - BSONObj o = b.obj(); - BSONObjIterator i(o); - global->ForceSet(scope->v8StringData("MaxKey"), scope->mongoToV8Element(i.next())); - global->ForceSet(scope->v8StringData("MinKey"), scope->mongoToV8Element(i.next())); - global->Get(scope->v8StringData("Object"))->ToObject()->ForceSet(scope->v8StringData("bsonsize"), - scope->createV8Function(bsonsize)->GetFunction()); - } - void destroyConnection(v8::Persistent<v8::Value> self, void* parameter) { delete static_cast<DBClientBase*>(parameter); self.Dispose(); diff --git a/src/mongo/scripting/v8_db.h b/src/mongo/scripting/v8_db.h index 6e8924465e4..2f747fd9714 100644 --- a/src/mongo/scripting/v8_db.h +++ b/src/mongo/scripting/v8_db.h @@ -27,9 +27,14 @@ namespace mongo { class DBClientBase; /** - * install the db related functions and objects in the given scope + * install database access functions */ - void installDBTypes(V8Scope* scope, v8::Handle<v8::Object>& global); + void installDBAccess(V8Scope* scope); + + /** + * install BSON types and helpers + */ + void installBSONTypes(V8Scope* scope); /** * get the DBClientBase connection from JS args diff --git a/src/mongo/scripting/v8_utils.cpp b/src/mongo/scripting/v8_utils.cpp index 23f8f8e8980..de20f0713e1 100644 --- a/src/mongo/scripting/v8_utils.cpp +++ b/src/mongo/scripting/v8_utils.cpp @@ -41,6 +41,14 @@ namespace mongo { return s; } + /** Get the properties of an object (and it's prototype) as a comma-delimited string */ + std::string v8objectToString(const v8::Handle<v8::Object>& o) { + v8::Local<v8::Array> properties = o->GetPropertyNames(); + v8::String::Utf8Value str(properties); + massert(16696 , "error converting js type to Utf8Value", *str); + return std::string(*str, str.length()); + } + std::string toSTLString(const v8::TryCatch* try_catch) { stringstream ss; v8::String::Utf8Value exception(try_catch->Exception()); diff --git a/src/mongo/scripting/v8_utils.h b/src/mongo/scripting/v8_utils.h index ba271ffe787..1bdec4ae213 100644 --- a/src/mongo/scripting/v8_utils.h +++ b/src/mongo/scripting/v8_utils.h @@ -34,6 +34,7 @@ namespace mongo { std::string toSTLString(const v8::Handle<v8::Value>& o); std::string toSTLString(const v8::TryCatch* try_catch); + std::string v8ObjectToString(const v8::Handle<v8::Object>& o); class V8Scope; void installFork(V8Scope* scope, |