summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Pasette <dan@10gen.com>2013-03-26 16:52:39 -0400
committerDan Pasette <dan@10gen.com>2013-03-26 16:52:39 -0400
commit3c5c12f7d57ba1e44250d3e1734885a5cafaf8e2 (patch)
tree256387a5ffd1be1cfea7dab679bbb2b9d0637830
parentbc7400d46a0e619ad166d219b79970b7aa7e1cff (diff)
downloadmongo-3c5c12f7d57ba1e44250d3e1734885a5cafaf8e2.tar.gz
SERVER-9124: Avoid raw pointers for SM's nativeHelper
-rw-r--r--scripting/engine_spidermonkey.cpp116
1 files changed, 78 insertions, 38 deletions
diff --git a/scripting/engine_spidermonkey.cpp b/scripting/engine_spidermonkey.cpp
index 64fe21cd098..e857b90d138 100644
--- a/scripting/engine_spidermonkey.cpp
+++ b/scripting/engine_spidermonkey.cpp
@@ -47,6 +47,9 @@ namespace mongo {
}
};
+ typedef std::map<long long, NativeFunction> FunctionMap;
+ typedef std::map<long long, void*> ArgumentMap;
+
string trim( string s ) {
while ( s.size() && isspace( s[0] ) )
s = s.substr( 1 );
@@ -997,43 +1000,8 @@ namespace mongo {
return JS_TRUE;
}
- JSBool native_helper( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval ) {
- Convertor c(cx);
-
- NativeFunction func = (NativeFunction)((long long)c.getNumber( obj , "x" ) );
- void* data = (void*)((long long)c.getNumber( obj , "y" ) );
- assert( func );
-
- BSONObj a;
- if ( argc > 0 ) {
- BSONObjBuilder args;
- for ( uintN i=0; i<argc; i++ ) {
- c.append( args , args.numStr( i ) , argv[i] );
- }
-
- a = args.obj();
- }
-
- BSONObj out;
- try {
- out = func( a, data );
- }
- catch ( std::exception& e ) {
- JS_ReportError( cx , e.what() );
- return JS_FALSE;
- }
-
- if ( out.isEmpty() ) {
- *rval = JSVAL_VOID;
- }
- else {
- *rval = c.toval( out.firstElement() );
- }
-
- return JS_TRUE;
- }
-
JSBool native_load( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval );
+ JSBool native_helper( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval );
JSBool native_gc( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval ) {
JS_GC( cx );
@@ -1611,11 +1579,17 @@ namespace mongo {
void injectNative( const char *field, NativeFunction func, void* data ) {
smlock;
string name = field;
- _convertor->setProperty( _global , (name + "_").c_str() , _convertor->toval( (double)(long long)func ) );
+ long long funcId = static_cast<long long>(_functionMap.size());
+ _functionMap.insert(make_pair(funcId, func));
+ jsval v = _convertor->toval(funcId);
+ _convertor->setProperty(_global, (name + "_").c_str(), v);
stringstream code;
if (data) {
- _convertor->setProperty( _global , (name + "_data_").c_str() , _convertor->toval( (double)(long long)data ) );
+ long long argsId = static_cast<long long>(_argumentMap.size());
+ _argumentMap.insert(make_pair(argsId, data));
+ v = _convertor->toval(argsId);
+ _convertor->setProperty(_global, (name + "_data_").c_str(), v);
code << field << "_" << " = { x : " << field << "_ , y: " << field << "_data_ }; ";
} else {
code << field << "_" << " = { x : " << field << "_ }; ";
@@ -1631,6 +1605,10 @@ namespace mongo {
JSContext *SavedContext() const { return _context; }
+ // map from internal function id to function pointer
+ FunctionMap _functionMap;
+ // map from internal function argument id to function pointer
+ ArgumentMap _argumentMap;
private:
void _postCreateHacks() {
@@ -1696,7 +1674,69 @@ namespace mongo {
return JS_TRUE;
}
+ JSBool native_helper( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval ) {
+ try {
+ Convertor c(cx);
+
+ // get function pointer from JS caller's argument property 'x'
+ massert(16735, "nativeHelper argument requires object with 'x' property",
+ c.hasProperty(obj, "x"));
+ FunctionMap::iterator funcIter =
+ currentScope->_functionMap.find(static_cast<long long>(c.getNumber(obj, "x")));
+ massert(16734, "JavaScript function not in map",
+ funcIter != currentScope->_functionMap.end());
+ NativeFunction func = funcIter->second;
+ assert(func);
+
+ // get data pointer from JS caller's argument property 'y'
+ void* data = NULL;
+ if (c.hasProperty(obj, "y")) {
+ ArgumentMap::iterator argIter = currentScope->_argumentMap.find(
+ static_cast<long long>(c.getNumber(obj, "y")));
+ massert(16736, "nativeHelper 'y' parameter must be in the argumentMap",
+ argIter != currentScope->_argumentMap.end());
+ data = argIter->second;
+ }
+
+ BSONObj a;
+ if ( argc > 0 ) {
+ BSONObjBuilder args;
+ for ( uintN i = 0; i < argc; ++i ) {
+ c.append( args , args.numStr( i ) , argv[i] );
+ }
+ a = args.obj();
+ }
+
+ BSONObj out;
+ try {
+ out = func( a, data );
+ }
+ catch ( std::exception& e ) {
+ if ( ! JS_IsExceptionPending( cx ) ) {
+ JS_ReportError( cx, e.what() );
+ }
+ return JS_FALSE;
+ }
+ if ( out.isEmpty() ) {
+ *rval = JSVAL_VOID;
+ }
+ else {
+ *rval = c.toval( out.firstElement() );
+ }
+ }
+ catch ( const AssertionException& e ) {
+ if ( ! JS_IsExceptionPending( cx ) ) {
+ JS_ReportError( cx, e.what() );
+ }
+ return JS_FALSE;
+ }
+ catch ( const std::exception& e ) {
+ log() << "unhandled exception: " << e.what() << ", throwing Fatal Assertion" << endl;
+ verifyFailed( 16281 );
+ }
+ return JS_TRUE;
+ }
void SMEngine::runTest() {
SMScope s;