summaryrefslogtreecommitdiff
path: root/src/mongo/scripting/v8_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/scripting/v8_utils.cpp')
-rw-r--r--src/mongo/scripting/v8_utils.cpp613
1 files changed, 302 insertions, 311 deletions
diff --git a/src/mongo/scripting/v8_utils.cpp b/src/mongo/scripting/v8_utils.cpp
index 42c33c40f65..e37b1fc1e1c 100644
--- a/src/mongo/scripting/v8_utils.cpp
+++ b/src/mongo/scripting/v8_utils.cpp
@@ -50,366 +50,357 @@ using std::unique_ptr;
namespace mongo {
- std::string toSTLString(const v8::Handle<v8::Value>& o) {
- return StringData(V8String(o)).toString();
- }
+std::string toSTLString(const v8::Handle<v8::Value>& o) {
+ return StringData(V8String(o)).toString();
+}
- /** Get the properties of an object (and its 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());
- }
+/** Get the properties of an object (and its 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::ostream& operator<<(std::ostream& s, const v8::Handle<v8::Value>& o) {
- v8::String::Utf8Value str(o);
- s << *str;
- return s;
- }
+std::ostream& operator<<(std::ostream& s, const v8::Handle<v8::Value>& o) {
+ v8::String::Utf8Value str(o);
+ s << *str;
+ return s;
+}
- std::ostream& operator<<(std::ostream& s, const v8::TryCatch* try_catch) {
- v8::HandleScope handle_scope;
- v8::String::Utf8Value exceptionText(try_catch->Exception());
- v8::Handle<v8::Message> message = try_catch->Message();
+std::ostream& operator<<(std::ostream& s, const v8::TryCatch* try_catch) {
+ v8::HandleScope handle_scope;
+ v8::String::Utf8Value exceptionText(try_catch->Exception());
+ v8::Handle<v8::Message> message = try_catch->Message();
- if (message.IsEmpty()) {
- s << *exceptionText << endl;
- }
- else {
- v8::String::Utf8Value filename(message->GetScriptResourceName());
- int linenum = message->GetLineNumber();
- cout << *filename << ":" << linenum << " " << *exceptionText << endl;
+ if (message.IsEmpty()) {
+ s << *exceptionText << endl;
+ } else {
+ v8::String::Utf8Value filename(message->GetScriptResourceName());
+ int linenum = message->GetLineNumber();
+ cout << *filename << ":" << linenum << " " << *exceptionText << endl;
- v8::String::Utf8Value sourceline(message->GetSourceLine());
- cout << *sourceline << endl;
+ v8::String::Utf8Value sourceline(message->GetSourceLine());
+ cout << *sourceline << endl;
- int start = message->GetStartColumn();
- for (int i = 0; i < start; i++)
- cout << " ";
+ int start = message->GetStartColumn();
+ for (int i = 0; i < start; i++)
+ cout << " ";
- int end = message->GetEndColumn();
- for (int i = start; i < end; i++)
- cout << "^";
+ int end = message->GetEndColumn();
+ for (int i = start; i < end; i++)
+ cout << "^";
- cout << endl;
- }
- return s;
+ cout << endl;
}
+ return s;
+}
- class JSThreadConfig {
- public:
- JSThreadConfig(V8Scope* scope, const v8::Arguments& args) :
- _started(),
- _done(),
- _sharedData(new SharedData()) {
- jsassert(args.Length() > 0, "need at least one argument");
- jsassert(args[0]->IsFunction(), "first argument must be a function");
-
- // arguments need to be copied into the isolate, go through bson
- BSONObjBuilder b;
- for(int i = 0; i < args.Length(); ++i) {
- scope->v8ToMongoElement(b, "arg" + BSONObjBuilder::numStr(i), args[i]);
- }
- _sharedData->_args = b.obj();
+class JSThreadConfig {
+public:
+ JSThreadConfig(V8Scope* scope, const v8::Arguments& args)
+ : _started(), _done(), _sharedData(new SharedData()) {
+ jsassert(args.Length() > 0, "need at least one argument");
+ jsassert(args[0]->IsFunction(), "first argument must be a function");
+
+ // arguments need to be copied into the isolate, go through bson
+ BSONObjBuilder b;
+ for (int i = 0; i < args.Length(); ++i) {
+ scope->v8ToMongoElement(b, "arg" + BSONObjBuilder::numStr(i), args[i]);
}
+ _sharedData->_args = b.obj();
+ }
- ~JSThreadConfig() {
- }
+ ~JSThreadConfig() {}
- void start() {
- jsassert(!_started, "Thread already started");
- JSThread jt(*this);
- _thread.reset(new stdx::thread(jt));
- _started = true;
- }
- void join() {
- jsassert(_started && !_done, "Thread not running");
- _thread->join();
- _done = true;
- }
+ void start() {
+ jsassert(!_started, "Thread already started");
+ JSThread jt(*this);
+ _thread.reset(new stdx::thread(jt));
+ _started = true;
+ }
+ void join() {
+ jsassert(_started && !_done, "Thread not running");
+ _thread->join();
+ _done = true;
+ }
- /**
- * Returns true if the JSThread terminated as a result of an error
- * during its execution, and false otherwise. This operation does
- * not block, nor does it require join() to have been called.
- */
- bool hasFailed() const {
- jsassert(_started, "Thread not started");
- return _sharedData->getErrored();
- }
+ /**
+ * Returns true if the JSThread terminated as a result of an error
+ * during its execution, and false otherwise. This operation does
+ * not block, nor does it require join() to have been called.
+ */
+ bool hasFailed() const {
+ jsassert(_started, "Thread not started");
+ return _sharedData->getErrored();
+ }
+
+ BSONObj returnData() {
+ if (!_done)
+ join();
+ return _sharedData->_returnData;
+ }
- BSONObj returnData() {
- if (!_done)
- join();
- return _sharedData->_returnData;
+private:
+ /*
+ * JSThreadConfig doesn't always outlive its JSThread (for example, if the parent thread
+ * garbage collects the JSThreadConfig before the JSThread has finished running), so any
+ * data shared between them has to go in a shared_ptr.
+ */
+ class SharedData {
+ public:
+ SharedData() : _errored(false) {}
+ BSONObj _args;
+ BSONObj _returnData;
+ void setErrored(bool value) {
+ stdx::lock_guard<stdx::mutex> lck(_erroredMutex);
+ _errored = value;
+ }
+ bool getErrored() {
+ stdx::lock_guard<stdx::mutex> lck(_erroredMutex);
+ return _errored;
}
private:
- /*
- * JSThreadConfig doesn't always outlive its JSThread (for example, if the parent thread
- * garbage collects the JSThreadConfig before the JSThread has finished running), so any
- * data shared between them has to go in a shared_ptr.
- */
- class SharedData {
- public:
- SharedData() : _errored(false) {}
- BSONObj _args;
- BSONObj _returnData;
- void setErrored(bool value) {
- stdx::lock_guard<stdx::mutex> lck(_erroredMutex);
- _errored = value;
- }
- bool getErrored() {
- stdx::lock_guard<stdx::mutex> lck(_erroredMutex);
- return _errored;
- }
- private:
- stdx::mutex _erroredMutex;
- bool _errored;
- };
-
- class JSThread {
- public:
- JSThread(JSThreadConfig& config) : _sharedData(config._sharedData) {}
-
- void operator()() {
- try {
- unique_ptr<V8Scope> scope(
- static_cast<V8Scope*>(globalScriptEngine->newScope()));
- v8::Locker v8lock(scope->getIsolate());
- v8::Isolate::Scope iscope(scope->getIsolate());
- v8::HandleScope handle_scope;
- v8::Context::Scope context_scope(scope->getContext());
-
- BSONObj args = _sharedData->_args;
- v8::Local<v8::Function> f = v8::Function::Cast(
- *(scope->mongoToV8Element(args.firstElement(), true)));
- int argc = args.nFields() - 1;
-
- // TODO SERVER-8016: properly allocate handles on the stack
- v8::Local<v8::Value> argv[24];
- BSONObjIterator it(args);
+ stdx::mutex _erroredMutex;
+ bool _errored;
+ };
+
+ class JSThread {
+ public:
+ JSThread(JSThreadConfig& config) : _sharedData(config._sharedData) {}
+
+ void operator()() {
+ try {
+ unique_ptr<V8Scope> scope(static_cast<V8Scope*>(globalScriptEngine->newScope()));
+ v8::Locker v8lock(scope->getIsolate());
+ v8::Isolate::Scope iscope(scope->getIsolate());
+ v8::HandleScope handle_scope;
+ v8::Context::Scope context_scope(scope->getContext());
+
+ BSONObj args = _sharedData->_args;
+ v8::Local<v8::Function> f =
+ v8::Function::Cast(*(scope->mongoToV8Element(args.firstElement(), true)));
+ int argc = args.nFields() - 1;
+
+ // TODO SERVER-8016: properly allocate handles on the stack
+ v8::Local<v8::Value> argv[24];
+ BSONObjIterator it(args);
+ it.next();
+ for (int i = 0; i < argc && i < 24; ++i) {
+ argv[i] = v8::Local<v8::Value>::New(scope->mongoToV8Element(*it, true));
it.next();
- for(int i = 0; i < argc && i < 24; ++i) {
- argv[i] = v8::Local<v8::Value>::New(
- scope->mongoToV8Element(*it, true));
- it.next();
- }
- v8::TryCatch try_catch;
- v8::Handle<v8::Value> ret =
- f->Call(scope->getContext()->Global(), argc, argv);
- if (ret.IsEmpty() || try_catch.HasCaught()) {
- string e = scope->v8ExceptionToSTLString(&try_catch);
- log() << "js thread raised js exception: " << e << endl;
- ret = v8::Undefined();
- _sharedData->setErrored(true);
- }
- // ret is translated to BSON to switch isolate
- BSONObjBuilder b;
- scope->v8ToMongoElement(b, "ret", ret);
- _sharedData->_returnData = b.obj();
- }
- catch (const DBException& e) {
- // Keeping behavior the same as for js exceptions.
- log() << "js thread threw c++ exception: " << e.toString();
- _sharedData->setErrored(true);
- _sharedData->_returnData = BSON("ret" << BSONUndefined);
- }
- catch (const std::exception& e) {
- log() << "js thread threw c++ exception: " << e.what();
- _sharedData->setErrored(true);
- _sharedData->_returnData = BSON("ret" << BSONUndefined);
}
- catch (...) {
- log() << "js thread threw c++ non-exception";
+ v8::TryCatch try_catch;
+ v8::Handle<v8::Value> ret = f->Call(scope->getContext()->Global(), argc, argv);
+ if (ret.IsEmpty() || try_catch.HasCaught()) {
+ string e = scope->v8ExceptionToSTLString(&try_catch);
+ log() << "js thread raised js exception: " << e << endl;
+ ret = v8::Undefined();
_sharedData->setErrored(true);
- _sharedData->_returnData = BSON("ret" << BSONUndefined);
}
+ // ret is translated to BSON to switch isolate
+ BSONObjBuilder b;
+ scope->v8ToMongoElement(b, "ret", ret);
+ _sharedData->_returnData = b.obj();
+ } catch (const DBException& e) {
+ // Keeping behavior the same as for js exceptions.
+ log() << "js thread threw c++ exception: " << e.toString();
+ _sharedData->setErrored(true);
+ _sharedData->_returnData = BSON("ret" << BSONUndefined);
+ } catch (const std::exception& e) {
+ log() << "js thread threw c++ exception: " << e.what();
+ _sharedData->setErrored(true);
+ _sharedData->_returnData = BSON("ret" << BSONUndefined);
+ } catch (...) {
+ log() << "js thread threw c++ non-exception";
+ _sharedData->setErrored(true);
+ _sharedData->_returnData = BSON("ret" << BSONUndefined);
}
+ }
- private:
- std::shared_ptr<SharedData> _sharedData;
- };
-
- bool _started;
- bool _done;
- unique_ptr<stdx::thread> _thread;
+ private:
std::shared_ptr<SharedData> _sharedData;
};
- class CountDownLatchHolder {
- private:
- struct Latch {
- Latch(int32_t count) : count(count) {}
- stdx::condition_variable cv;
- stdx::mutex mutex;
- int32_t count;
- };
-
- std::shared_ptr<Latch> get(int32_t desc) {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- Map::iterator iter = _latches.find(desc);
- jsassert(iter != _latches.end(), "not a valid CountDownLatch descriptor");
- return iter->second;
- }
+ bool _started;
+ bool _done;
+ unique_ptr<stdx::thread> _thread;
+ std::shared_ptr<SharedData> _sharedData;
+};
+
+class CountDownLatchHolder {
+private:
+ struct Latch {
+ Latch(int32_t count) : count(count) {}
+ stdx::condition_variable cv;
+ stdx::mutex mutex;
+ int32_t count;
+ };
- typedef std::map< int32_t, std::shared_ptr<Latch> > Map;
- Map _latches;
- stdx::mutex _mutex;
- int32_t _counter;
- public:
- CountDownLatchHolder() : _counter(0) {}
- int32_t make(int32_t count) {
- jsassert(count >= 0, "argument must be >= 0");
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- int32_t desc = ++_counter;
- _latches.insert(std::make_pair(desc, std::make_shared<Latch>(count)));
- return desc;
- }
- void await(int32_t desc) {
- std::shared_ptr<Latch> latch = get(desc);
- stdx::unique_lock<stdx::mutex> lock(latch->mutex);
- while (latch->count != 0) {
- latch->cv.wait(lock);
- }
+ std::shared_ptr<Latch> get(int32_t desc) {
+ stdx::lock_guard<stdx::mutex> lock(_mutex);
+ Map::iterator iter = _latches.find(desc);
+ jsassert(iter != _latches.end(), "not a valid CountDownLatch descriptor");
+ return iter->second;
+ }
+
+ typedef std::map<int32_t, std::shared_ptr<Latch>> Map;
+ Map _latches;
+ stdx::mutex _mutex;
+ int32_t _counter;
+
+public:
+ CountDownLatchHolder() : _counter(0) {}
+ int32_t make(int32_t count) {
+ jsassert(count >= 0, "argument must be >= 0");
+ stdx::lock_guard<stdx::mutex> lock(_mutex);
+ int32_t desc = ++_counter;
+ _latches.insert(std::make_pair(desc, std::make_shared<Latch>(count)));
+ return desc;
+ }
+ void await(int32_t desc) {
+ std::shared_ptr<Latch> latch = get(desc);
+ stdx::unique_lock<stdx::mutex> lock(latch->mutex);
+ while (latch->count != 0) {
+ latch->cv.wait(lock);
}
- void countDown(int32_t desc) {
- std::shared_ptr<Latch> latch = get(desc);
- stdx::unique_lock<stdx::mutex> lock(latch->mutex);
- if (latch->count > 0) {
- latch->count--;
- }
- if (latch->count == 0) {
- latch->cv.notify_all();
- }
+ }
+ void countDown(int32_t desc) {
+ std::shared_ptr<Latch> latch = get(desc);
+ stdx::unique_lock<stdx::mutex> lock(latch->mutex);
+ if (latch->count > 0) {
+ latch->count--;
}
- int32_t getCount(int32_t desc) {
- std::shared_ptr<Latch> latch = get(desc);
- stdx::unique_lock<stdx::mutex> lock(latch->mutex);
- return latch->count;
+ if (latch->count == 0) {
+ latch->cv.notify_all();
}
- };
- namespace {
- CountDownLatchHolder globalCountDownLatchHolder;
}
-
- v8::Handle<v8::Value> CountDownLatchNew(V8Scope* scope, const v8::Arguments& args) {
- jsassert(args.Length() == 1, "need exactly one argument");
- jsassert(args[0]->IsInt32(), "argument must be an integer");
- int32_t count = v8::Local<v8::Integer>::Cast(args[0])->Value();
- return v8::Int32::New(globalCountDownLatchHolder.make(count));
+ int32_t getCount(int32_t desc) {
+ std::shared_ptr<Latch> latch = get(desc);
+ stdx::unique_lock<stdx::mutex> lock(latch->mutex);
+ return latch->count;
}
+};
+namespace {
+CountDownLatchHolder globalCountDownLatchHolder;
+}
- v8::Handle<v8::Value> CountDownLatchAwait(V8Scope* scope, const v8::Arguments& args) {
- jsassert(args.Length() == 1, "need exactly one argument");
- jsassert(args[0]->IsInt32(), "argument must be an integer");
- globalCountDownLatchHolder.await(args[0]->ToInt32()->Value());
- return v8::Undefined();
- }
+v8::Handle<v8::Value> CountDownLatchNew(V8Scope* scope, const v8::Arguments& args) {
+ jsassert(args.Length() == 1, "need exactly one argument");
+ jsassert(args[0]->IsInt32(), "argument must be an integer");
+ int32_t count = v8::Local<v8::Integer>::Cast(args[0])->Value();
+ return v8::Int32::New(globalCountDownLatchHolder.make(count));
+}
- v8::Handle<v8::Value> CountDownLatchCountDown(V8Scope* scope, const v8::Arguments& args) {
- jsassert(args.Length() == 1, "need exactly one argument");
- jsassert(args[0]->IsInt32(), "argument must be an integer");
- globalCountDownLatchHolder.countDown(args[0]->ToInt32()->Value());
- return v8::Undefined();
- }
+v8::Handle<v8::Value> CountDownLatchAwait(V8Scope* scope, const v8::Arguments& args) {
+ jsassert(args.Length() == 1, "need exactly one argument");
+ jsassert(args[0]->IsInt32(), "argument must be an integer");
+ globalCountDownLatchHolder.await(args[0]->ToInt32()->Value());
+ return v8::Undefined();
+}
- v8::Handle<v8::Value> CountDownLatchGetCount(V8Scope* scope, const v8::Arguments& args) {
- jsassert(args.Length() == 1, "need exactly one argument");
- jsassert(args[0]->IsInt32(), "argument must be an integer");
- return v8::Int32::New(globalCountDownLatchHolder.getCount(args[0]->ToInt32()->Value()));
- }
+v8::Handle<v8::Value> CountDownLatchCountDown(V8Scope* scope, const v8::Arguments& args) {
+ jsassert(args.Length() == 1, "need exactly one argument");
+ jsassert(args[0]->IsInt32(), "argument must be an integer");
+ globalCountDownLatchHolder.countDown(args[0]->ToInt32()->Value());
+ return v8::Undefined();
+}
- JSThreadConfig *thisConfig(V8Scope* scope, const v8::Arguments& args) {
- v8::Local<v8::External> c = v8::External::Cast(
- *(args.This()->GetHiddenValue(v8::String::New("_JSThreadConfig"))));
- JSThreadConfig *config = static_cast<std::shared_ptr<JSThreadConfig>*>(c->Value())->get();
- return config;
- }
+v8::Handle<v8::Value> CountDownLatchGetCount(V8Scope* scope, const v8::Arguments& args) {
+ jsassert(args.Length() == 1, "need exactly one argument");
+ jsassert(args[0]->IsInt32(), "argument must be an integer");
+ return v8::Int32::New(globalCountDownLatchHolder.getCount(args[0]->ToInt32()->Value()));
+}
- v8::Handle<v8::Value> ThreadInit(V8Scope* scope, const v8::Arguments& args) {
- v8::Persistent<v8::Object> self = v8::Persistent<v8::Object>::New(args.This());
+JSThreadConfig* thisConfig(V8Scope* scope, const v8::Arguments& args) {
+ v8::Local<v8::External> c =
+ v8::External::Cast(*(args.This()->GetHiddenValue(v8::String::New("_JSThreadConfig"))));
+ JSThreadConfig* config = static_cast<std::shared_ptr<JSThreadConfig>*>(c->Value())->get();
+ return config;
+}
- JSThreadConfig* config = new JSThreadConfig(scope, args);
- v8::Local<v8::External> handle = scope->jsThreadConfigTracker.track(self, config);
- args.This()->SetHiddenValue(v8::String::New("_JSThreadConfig"), handle);
+v8::Handle<v8::Value> ThreadInit(V8Scope* scope, const v8::Arguments& args) {
+ v8::Persistent<v8::Object> self = v8::Persistent<v8::Object>::New(args.This());
- invariant(thisConfig(scope, args) == config);
- return v8::Undefined();
- }
+ JSThreadConfig* config = new JSThreadConfig(scope, args);
+ v8::Local<v8::External> handle = scope->jsThreadConfigTracker.track(self, config);
+ args.This()->SetHiddenValue(v8::String::New("_JSThreadConfig"), handle);
- v8::Handle<v8::Value> ScopedThreadInit(V8Scope* scope, const v8::Arguments& args) {
- // NOTE: ScopedThread and Thread behave identically because a new V8 Isolate is always
- // created.
- return ThreadInit(scope, args);
- }
+ invariant(thisConfig(scope, args) == config);
+ return v8::Undefined();
+}
- v8::Handle<v8::Value> ThreadStart(V8Scope* scope, const v8::Arguments& args) {
- thisConfig(scope, args)->start();
- return v8::Undefined();
- }
+v8::Handle<v8::Value> ScopedThreadInit(V8Scope* scope, const v8::Arguments& args) {
+ // NOTE: ScopedThread and Thread behave identically because a new V8 Isolate is always
+ // created.
+ return ThreadInit(scope, args);
+}
- v8::Handle<v8::Value> ThreadJoin(V8Scope* scope, const v8::Arguments& args) {
- thisConfig(scope, args)->join();
- return v8::Undefined();
- }
+v8::Handle<v8::Value> ThreadStart(V8Scope* scope, const v8::Arguments& args) {
+ thisConfig(scope, args)->start();
+ return v8::Undefined();
+}
- // Indicates to the caller that the thread terminated as a result of an error.
- v8::Handle<v8::Value> ThreadHasFailed(V8Scope* scope, const v8::Arguments& args) {
- bool hasFailed = thisConfig(scope, args)->hasFailed();
- return v8::Boolean::New(hasFailed);
- }
+v8::Handle<v8::Value> ThreadJoin(V8Scope* scope, const v8::Arguments& args) {
+ thisConfig(scope, args)->join();
+ return v8::Undefined();
+}
- v8::Handle<v8::Value> ThreadReturnData(V8Scope* scope, const v8::Arguments& args) {
- BSONObj data = thisConfig(scope, args)->returnData();
- return scope->mongoToV8Element(data.firstElement(), true);
- }
+// Indicates to the caller that the thread terminated as a result of an error.
+v8::Handle<v8::Value> ThreadHasFailed(V8Scope* scope, const v8::Arguments& args) {
+ bool hasFailed = thisConfig(scope, args)->hasFailed();
+ return v8::Boolean::New(hasFailed);
+}
- v8::Handle<v8::Value> ThreadInject(V8Scope* scope, const v8::Arguments& args) {
- v8::HandleScope handle_scope;
- jsassert(args.Length() == 1, "threadInject takes exactly 1 argument");
- jsassert(args[0]->IsObject(), "threadInject needs to be passed a prototype");
- v8::Local<v8::Object> o = args[0]->ToObject();
-
- // install method on the Thread object
- scope->injectV8Function("init", ThreadInit, o);
- scope->injectV8Function("start", ThreadStart, o);
- scope->injectV8Function("join", ThreadJoin, o);
- scope->injectV8Function("hasFailed", ThreadHasFailed, o);
- scope->injectV8Function("returnData", ThreadReturnData, o);
- return handle_scope.Close(v8::Handle<v8::Value>());
- }
+v8::Handle<v8::Value> ThreadReturnData(V8Scope* scope, const v8::Arguments& args) {
+ BSONObj data = thisConfig(scope, args)->returnData();
+ return scope->mongoToV8Element(data.firstElement(), true);
+}
+
+v8::Handle<v8::Value> ThreadInject(V8Scope* scope, const v8::Arguments& args) {
+ v8::HandleScope handle_scope;
+ jsassert(args.Length() == 1, "threadInject takes exactly 1 argument");
+ jsassert(args[0]->IsObject(), "threadInject needs to be passed a prototype");
+ v8::Local<v8::Object> o = args[0]->ToObject();
+
+ // install method on the Thread object
+ scope->injectV8Function("init", ThreadInit, o);
+ scope->injectV8Function("start", ThreadStart, o);
+ scope->injectV8Function("join", ThreadJoin, o);
+ scope->injectV8Function("hasFailed", ThreadHasFailed, o);
+ scope->injectV8Function("returnData", ThreadReturnData, o);
+ return handle_scope.Close(v8::Handle<v8::Value>());
+}
- v8::Handle<v8::Value> ScopedThreadInject(V8Scope* scope, const v8::Arguments& args) {
- v8::HandleScope handle_scope;
- jsassert(args.Length() == 1, "threadInject takes exactly 1 argument");
- jsassert(args[0]->IsObject(), "threadInject needs to be passed a prototype");
- v8::Local<v8::Object> o = args[0]->ToObject();
+v8::Handle<v8::Value> ScopedThreadInject(V8Scope* scope, const v8::Arguments& args) {
+ v8::HandleScope handle_scope;
+ jsassert(args.Length() == 1, "threadInject takes exactly 1 argument");
+ jsassert(args[0]->IsObject(), "threadInject needs to be passed a prototype");
+ v8::Local<v8::Object> o = args[0]->ToObject();
- scope->injectV8Function("init", ScopedThreadInit, o);
- // inheritance takes care of other member functions
+ scope->injectV8Function("init", ScopedThreadInit, o);
+ // inheritance takes care of other member functions
- return handle_scope.Close(v8::Handle<v8::Value>());
- }
+ return handle_scope.Close(v8::Handle<v8::Value>());
+}
- void installFork(V8Scope* scope, v8::Handle<v8::Object>& global,
- v8::Handle<v8::Context>& context) {
- scope->injectV8Function("_threadInject", ThreadInject, global);
- scope->injectV8Function("_scopedThreadInject", ScopedThreadInject, global);
-
- scope->setObject("CountDownLatch", BSONObj(), false);
- v8::Handle<v8::Object> cdl = scope->get("CountDownLatch").As<v8::Object>();
- scope->injectV8Function("_new", CountDownLatchNew, cdl);
- scope->injectV8Function("_await", CountDownLatchAwait, cdl);
- scope->injectV8Function("_countDown", CountDownLatchCountDown, cdl);
- scope->injectV8Function("_getCount", CountDownLatchGetCount, cdl);
- }
+void installFork(V8Scope* scope, v8::Handle<v8::Object>& global, v8::Handle<v8::Context>& context) {
+ scope->injectV8Function("_threadInject", ThreadInject, global);
+ scope->injectV8Function("_scopedThreadInject", ScopedThreadInject, global);
- v8::Handle<v8::Value> v8AssertionException(const char* errorMessage) {
- return v8::ThrowException(v8::Exception::Error(v8::String::New(errorMessage)));
- }
- v8::Handle<v8::Value> v8AssertionException(const std::string& errorMessage) {
- return v8AssertionException(errorMessage.c_str());
- }
+ scope->setObject("CountDownLatch", BSONObj(), false);
+ v8::Handle<v8::Object> cdl = scope->get("CountDownLatch").As<v8::Object>();
+ scope->injectV8Function("_new", CountDownLatchNew, cdl);
+ scope->injectV8Function("_await", CountDownLatchAwait, cdl);
+ scope->injectV8Function("_countDown", CountDownLatchCountDown, cdl);
+ scope->injectV8Function("_getCount", CountDownLatchGetCount, cdl);
+}
+
+v8::Handle<v8::Value> v8AssertionException(const char* errorMessage) {
+ return v8::ThrowException(v8::Exception::Error(v8::String::New(errorMessage)));
+}
+v8::Handle<v8::Value> v8AssertionException(const std::string& errorMessage) {
+ return v8AssertionException(errorMessage.c_str());
+}
}