summaryrefslogtreecommitdiff
path: root/scripting/v8_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scripting/v8_utils.cpp')
-rw-r--r--scripting/v8_utils.cpp291
1 files changed, 0 insertions, 291 deletions
diff --git a/scripting/v8_utils.cpp b/scripting/v8_utils.cpp
deleted file mode 100644
index 0f575cf31a3..00000000000
--- a/scripting/v8_utils.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-// v8_utils.cpp
-
-/* 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.
- */
-
-#if defined(_WIN32)
-/** this is a hack - v8stdint.h defined uint16_t etc. on _WIN32 only, and that collides with
- our usage of boost */
-#include "boost/cstdint.hpp"
-using namespace boost;
-#define V8STDINT_H_
-#endif
-
-#include "v8_utils.h"
-#include "v8_db.h"
-#include <iostream>
-#include <map>
-#include <sstream>
-#include <vector>
-#include <boost/smart_ptr.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/thread/xtime.hpp>
-#include "engine_v8.h"
-
-using namespace std;
-using namespace v8;
-
-namespace mongo {
-
- std::string toSTLString( const Handle<v8::Value> & o ) {
- v8::String::Utf8Value str(o);
- const char * foo = *str;
- std::string s(foo);
- return s;
- }
-
- std::string toSTLString( const v8::TryCatch * try_catch ) {
-
- stringstream ss;
-
- //while ( try_catch ){ // disabled for v8 bleeding edge
-
- v8::String::Utf8Value exception(try_catch->Exception());
- Handle<v8::Message> message = try_catch->Message();
-
- if (message.IsEmpty()) {
- ss << *exception << endl;
- }
- else {
-
- v8::String::Utf8Value filename(message->GetScriptResourceName());
- int linenum = message->GetLineNumber();
- ss << *filename << ":" << linenum << " " << *exception << endl;
-
- v8::String::Utf8Value sourceline(message->GetSourceLine());
- ss << *sourceline << endl;
-
- int start = message->GetStartColumn();
- for (int i = 0; i < start; i++)
- ss << " ";
-
- int end = message->GetEndColumn();
- for (int i = start; i < end; i++)
- ss << "^";
-
- ss << endl;
- }
-
- //try_catch = try_catch->next_;
- //}
-
- return ss.str();
- }
-
-
- std::ostream& operator<<( std::ostream &s, const Handle<v8::Value> & o ) {
- v8::String::Utf8Value str(o);
- s << *str;
- return s;
- }
-
- std::ostream& operator<<( std::ostream &s, const v8::TryCatch * try_catch ) {
- HandleScope handle_scope;
- v8::String::Utf8Value exception(try_catch->Exception());
- Handle<v8::Message> message = try_catch->Message();
-
- if (message.IsEmpty()) {
- s << *exception << endl;
- }
- else {
-
- v8::String::Utf8Value filename(message->GetScriptResourceName());
- int linenum = message->GetLineNumber();
- cout << *filename << ":" << linenum << " " << *exception << endl;
-
- v8::String::Utf8Value sourceline(message->GetSourceLine());
- cout << *sourceline << endl;
-
- int start = message->GetStartColumn();
- for (int i = 0; i < start; i++)
- cout << " ";
-
- int end = message->GetEndColumn();
- for (int i = start; i < end; i++)
- cout << "^";
-
- cout << endl;
- }
-
- //if ( try_catch->next_ ) // disabled for v8 bleeding edge
- // s << try_catch->next_;
-
- return s;
- }
-
- void ReportException(v8::TryCatch* try_catch) {
- cout << try_catch << endl;
- }
-
- Handle< Context > baseContext_;
-
- class JSThreadConfig {
- public:
- JSThreadConfig( const Arguments &args, bool newScope = false ) : started_(), done_(), newScope_( newScope ) {
- jsassert( args.Length() > 0, "need at least one argument" );
- jsassert( args[ 0 ]->IsFunction(), "first argument must be a function" );
- Local< v8::Function > f = v8::Function::Cast( *args[ 0 ] );
- f_ = Persistent< v8::Function >::New( f );
- for( int i = 1; i < args.Length(); ++i )
- args_.push_back( Persistent< Value >::New( args[ i ] ) );
- }
- ~JSThreadConfig() {
- f_.Dispose();
- for( vector< Persistent< Value > >::iterator i = args_.begin(); i != args_.end(); ++i )
- i->Dispose();
- returnData_.Dispose();
- }
- void start() {
- jsassert( !started_, "Thread already started" );
- JSThread jt( *this );
- thread_.reset( new boost::thread( jt ) );
- started_ = true;
- }
- void join() {
- jsassert( started_ && !done_, "Thread not running" );
- V8Unlock u;
- thread_->join();
- done_ = true;
- }
- Local< Value > returnData() {
- if ( !done_ )
- join();
- return Local< Value >::New( returnData_ );
- }
- private:
- class JSThread {
- public:
- JSThread( JSThreadConfig &config ) : config_( config ) {}
- void operator()() {
- V8Lock l;
- HandleScope handle_scope;
- Handle< Context > context;
- Handle< v8::Function > fun;
- auto_ptr< V8Scope > scope;
- if ( config_.newScope_ ) {
- scope.reset( dynamic_cast< V8Scope * >( globalScriptEngine->newScope() ) );
- context = scope->context();
- // A v8::Function tracks the context in which it was created, so we have to
- // create a new function in the new context.
- Context::Scope baseScope( baseContext_ );
- string fCode = toSTLString( config_.f_->ToString() );
- Context::Scope context_scope( context );
- fun = scope->__createFunction( fCode.c_str() );
- }
- else {
- context = baseContext_;
- Context::Scope context_scope( context );
- fun = config_.f_;
- }
- Context::Scope context_scope( context );
- boost::scoped_array< Local< Value > > argv( new Local< Value >[ config_.args_.size() ] );
- for( unsigned int i = 0; i < config_.args_.size(); ++i )
- argv[ i ] = Local< Value >::New( config_.args_[ i ] );
- TryCatch try_catch;
- Handle< Value > ret = fun->Call( context->Global(), config_.args_.size(), argv.get() );
- if ( ret.IsEmpty() ) {
- string e = toSTLString( &try_catch );
- log() << "js thread raised exception: " << e << endl;
- // v8 probably does something sane if ret is empty, but not going to assume that for now
- ret = v8::Undefined();
- }
- config_.returnData_ = Persistent< Value >::New( ret );
- }
- private:
- JSThreadConfig &config_;
- };
-
- bool started_;
- bool done_;
- bool newScope_;
- Persistent< v8::Function > f_;
- vector< Persistent< Value > > args_;
- auto_ptr< boost::thread > thread_;
- Persistent< Value > returnData_;
- };
-
- Handle< Value > ThreadInit( V8Scope* scope, const Arguments &args ) {
- Handle<v8::Object> it = args.This();
- // NOTE I believe the passed JSThreadConfig will never be freed. If this
- // policy is changed, JSThread may no longer be able to store JSThreadConfig
- // by reference.
- it->SetHiddenValue( v8::String::New( "_JSThreadConfig" ), External::New( new JSThreadConfig( args ) ) );
- return v8::Undefined();
- }
-
- Handle< Value > ScopedThreadInit( V8Scope* scope, const Arguments &args ) {
- Handle<v8::Object> it = args.This();
- // NOTE I believe the passed JSThreadConfig will never be freed. If this
- // policy is changed, JSThread may no longer be able to store JSThreadConfig
- // by reference.
- it->SetHiddenValue( v8::String::New( "_JSThreadConfig" ), External::New( new JSThreadConfig( args, true ) ) );
- return v8::Undefined();
- }
-
- JSThreadConfig *thisConfig( V8Scope* scope, const Arguments &args ) {
- Local< External > c = External::Cast( *(args.This()->GetHiddenValue( v8::String::New( "_JSThreadConfig" ) ) ) );
- JSThreadConfig *config = (JSThreadConfig *)( c->Value() );
- return config;
- }
-
- Handle< Value > ThreadStart( V8Scope* scope, const Arguments &args ) {
- thisConfig( scope, args )->start();
- return v8::Undefined();
- }
-
- Handle< Value > ThreadJoin( V8Scope* scope, const Arguments &args ) {
- thisConfig( scope, args )->join();
- return v8::Undefined();
- }
-
- Handle< Value > ThreadReturnData( V8Scope* scope, const Arguments &args ) {
- HandleScope handle_scope;
- return handle_scope.Close( thisConfig( scope, args )->returnData() );
- }
-
- Handle< Value > ThreadInject( V8Scope* scope, const Arguments &args ) {
- jsassert( args.Length() == 1 , "threadInject takes exactly 1 argument" );
- jsassert( args[0]->IsObject() , "threadInject needs to be passed a prototype" );
-
- Local<v8::Object> o = args[0]->ToObject();
-
- scope->injectV8Function("init", ThreadInit, o);
- scope->injectV8Function("start", ThreadStart, o);
- scope->injectV8Function("join", ThreadJoin, o);
- scope->injectV8Function("returnData", ThreadReturnData, o);
-
- return v8::Undefined();
- }
-
- Handle< Value > ScopedThreadInject( V8Scope* scope, const Arguments &args ) {
- jsassert( args.Length() == 1 , "threadInject takes exactly 1 argument" );
- jsassert( args[0]->IsObject() , "threadInject needs to be passed a prototype" );
-
- Local<v8::Object> o = args[0]->ToObject();
-
- scope->injectV8Function("init", ScopedThreadInit, o);
- // inheritance takes care of other member functions
-
- return v8::Undefined();
- }
-
- void installFork( V8Scope* scope, v8::Handle< v8::Object > &global, v8::Handle< v8::Context > &context ) {
- if ( baseContext_.IsEmpty() ) // if this is the shell, first call will be with shell context, otherwise don't expect to use fork() anyway
- baseContext_ = context;
- scope->injectV8Function("_threadInject", ThreadInject, global);
- scope->injectV8Function("_scopedThreadInject", ScopedThreadInject, global);
- }
-
-}