summaryrefslogtreecommitdiff
path: root/src/mongo/scripting
diff options
context:
space:
mode:
authorBen Becker <ben.becker@10gen.com>2013-01-18 14:15:28 -0800
committerBen Becker <ben.becker@10gen.com>2013-01-18 14:15:43 -0800
commit41c1110326ae00fc7fb279b3bfeabadc3a82bc5a (patch)
tree646e122504532957a3517ea1b3e82070c629d091 /src/mongo/scripting
parent98d2e5d364e01581a4ba1b2e7df25f79ebd836b2 (diff)
downloadmongo-41c1110326ae00fc7fb279b3bfeabadc3a82bc5a.tar.gz
SERVER-8104: clean up js global object
Diffstat (limited to 'src/mongo/scripting')
-rw-r--r--src/mongo/scripting/bench.cpp17
-rw-r--r--src/mongo/scripting/bench.h5
-rw-r--r--src/mongo/scripting/engine.cpp11
-rw-r--r--src/mongo/scripting/engine.h2
-rw-r--r--src/mongo/scripting/engine_v8.cpp135
-rw-r--r--src/mongo/scripting/engine_v8.h8
-rw-r--r--src/mongo/scripting/utils.cpp4
-rw-r--r--src/mongo/scripting/v8_db.cpp88
-rw-r--r--src/mongo/scripting/v8_db.h9
-rw-r--r--src/mongo/scripting/v8_utils.cpp8
-rw-r--r--src/mongo/scripting/v8_utils.h1
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,