//engine_v8.h /* Copyright 2009 10gen Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include "engine.h" #include using namespace v8; namespace mongo { class V8ScriptEngine; class V8Scope; typedef Handle< Value > (*v8Function) ( V8Scope* scope, const v8::Arguments& args ); // Preemption is going to be allowed for the v8 mutex, and some of our v8 // usage is not preemption safe. So we are using an additional mutex that // will not be preempted. The V8Lock should be used in place of v8::Locker // except in certain special cases involving interrupts. namespace v8Locks { // the implementations are quite simple - objects must be destroyed in // reverse of the order created, and should not be shared between threads struct RecursiveLock { RecursiveLock(); ~RecursiveLock(); bool _unlock; }; struct RecursiveUnlock { RecursiveUnlock(); ~RecursiveUnlock(); bool _lock; }; } // namespace v8Locks class V8Lock { v8Locks::RecursiveLock _noPreemptionLock; v8::Locker _preemptionLock; }; struct V8Unlock { v8::Unlocker _preemptionUnlock; v8Locks::RecursiveUnlock _noPreemptionUnlock; }; class V8Scope : public Scope { public: V8Scope( V8ScriptEngine * engine ); ~V8Scope(); virtual void reset(); virtual void init( const BSONObj * data ); virtual void localConnect( const char * dbName ); virtual void externalSetup(); v8::Handle get( const char * field ); // caller must create context and handle scopes virtual double getNumber( const char *field ); virtual int getNumberInt( const char *field ); virtual long long getNumberLongLong( const char *field ); virtual string getString( const char *field ); virtual bool getBoolean( const char *field ); virtual BSONObj getObject( const char *field ); Handle getGlobalObject() { return _global; }; virtual int type( const char *field ); virtual void setNumber( const char *field , double val ); virtual void setString( const char *field , const char * val ); virtual void setBoolean( const char *field , bool val ); virtual void setElement( const char *field , const BSONElement& e ); virtual void setObject( const char *field , const BSONObj& obj , bool readOnly); virtual void setFunction( const char *field , const char * code ); // virtual void setThis( const BSONObj * obj ); virtual void rename( const char * from , const char * to ); virtual ScriptingFunction _createFunction( const char * code ); Local< v8::Function > __createFunction( const char * code ); virtual int invoke( ScriptingFunction func , const BSONObj* args, const BSONObj* recv, int timeoutMs = 0 , bool ignoreReturn = false, bool readOnlyArgs = false, bool readOnlyRecv = false ); virtual bool exec( const StringData& code , const string& name , bool printResult , bool reportError , bool assertOnError, int timeoutMs ); virtual string getError() { return _error; } virtual void injectNative( const char *field, NativeFunction func, void* data = 0 ); void injectNative( const char *field, NativeFunction func, Handle& obj, void* data = 0 ); void injectV8Function( const char *field, v8Function func ); void injectV8Function( const char *field, v8Function func, Handle& obj ); void injectV8Function( const char *field, v8Function func, Handle& t ); Handle createV8Function( v8Function func ); void gc(); Handle< Context > context() const { return _context; } v8::Local mongoToV8( const mongo::BSONObj & m , bool array = 0 , bool readOnly = false ); v8::Handle mongoToLZV8( const mongo::BSONObj & m , bool array = 0 , bool readOnly = false ); mongo::BSONObj v8ToMongo( v8::Handle o , int depth = 0 ); void v8ToMongoElement( BSONObjBuilder & b , v8::Handle name , const string sname , v8::Handle value , int depth = 0, BSONObj* originalParent=0 ); v8::Handle mongoToV8Element( const BSONElement &f, bool readOnly = false ); virtual void append( BSONObjBuilder & builder , const char * fieldName , const char * scopeName ); v8::Function * getNamedCons( const char * name ); v8::Function * getObjectIdCons(); Local< v8::Value > newId( const OID &id ); Persistent wrapBSONObject(Local obj, BSONObj* data); Persistent wrapArrayObject(Local obj, char* data); v8::Handle getV8Str(string str); // inline v8::Handle getV8Str(string str) { return v8::String::New(str.c_str()); } inline v8::Handle getLocalV8Str(string str) { return v8::String::New(str.c_str()); } Handle V8STR_CONN; Handle V8STR_ID; Handle V8STR_LENGTH; Handle V8STR_LEN; Handle V8STR_TYPE; Handle V8STR_ISOBJECTID; Handle V8STR_NATIVE_FUNC; Handle V8STR_NATIVE_DATA; Handle V8STR_V8_FUNC; Handle V8STR_RETURN; Handle V8STR_ARGS; Handle V8STR_T; Handle V8STR_I; Handle V8STR_EMPTY; Handle V8STR_MINKEY; Handle V8STR_MAXKEY; Handle V8STR_NUMBERLONG; Handle V8STR_NUMBERINT; Handle V8STR_DBPTR; Handle V8STR_BINDATA; Handle V8STR_WRAPPER; Handle V8STR_RO; Handle V8STR_MODIFIED; private: void _startCall(); static Handle< Value > nativeCallback( V8Scope* scope, const Arguments &args ); static v8::Handle< v8::Value > v8Callback( const v8::Arguments &args ); static Handle< Value > load( V8Scope* scope, const Arguments &args ); static Handle< Value > Print(V8Scope* scope, const v8::Arguments& args); static Handle< Value > Version(V8Scope* scope, const v8::Arguments& args); static Handle< Value > GCV8(V8Scope* scope, const v8::Arguments& args); V8ScriptEngine * _engine; Persistent _context; Persistent _global; string _error; vector< Persistent > _funcs; v8::Persistent _emptyObj; v8::Persistent _wrapper; enum ConnectState { NOT , LOCAL , EXTERNAL }; ConnectState _connectState; std::map > _strCache; Persistent lzObjectTemplate; Persistent roObjectTemplate; Persistent lzArrayTemplate; Persistent internalFieldObjects; }; class V8ScriptEngine : public ScriptEngine { public: V8ScriptEngine(); virtual ~V8ScriptEngine(); virtual Scope * createScope() { return new V8Scope( this ); } virtual void runTest() {} bool utf8Ok() const { return true; } class V8UnlockForClient : public Unlocker { V8Unlock u_; }; virtual auto_ptr newThreadUnlocker() { return auto_ptr< Unlocker >( new V8UnlockForClient ); } virtual void interrupt( unsigned opSpec ); virtual void interruptAll(); private: friend class V8Scope; }; class ExternalString : public v8::String::ExternalAsciiStringResource { public: ExternalString(std::string str) : _data(str) { } ~ExternalString() { } const char* data () const { return _data.c_str(); } size_t length () const { return _data.length(); } private: // string _str; // const char* _data; std::string _data; // size_t _len; }; extern ScriptEngine * globalScriptEngine; extern map< unsigned, int > __interruptSpecToThreadId; }