#pragma once #ifndef V8SCRIPTENV_H #define V8SCRIPTENV_H #include #include #include #include "ScriptBindings.h" #include "V8ScriptObject.h" #include "V8ScriptUtils.h" class IScriptFunction; class V8ScriptEnv : public IScriptEnv { public: V8ScriptEnv(); virtual ~V8ScriptEnv(); int GetType() const override { return 1; } void Initialize() override; void Cleanup(bool shutDown = false) override; IScriptFunction * Compile(const std::string& name, const std::string& source) override; void CallFunctionInScope(std::function function) override; void TerminateExecution() override; // Parse errors from a TryCatch into lastScriptError bool ParseErrors(v8::TryCatch *tryCatch); // -- v8::Isolate * Isolate() const; v8::Local Context() const; v8::Local Global() const; v8::Local GlobalTemplate() const; v8::Local GetConstructor(const std::string& key) const; void SetGlobal(v8::Local global); void SetGlobalTemplate(v8::Local global_tpl); bool SetConstructor(const std::string& key, v8::Local func_tpl); // -- template std::unique_ptr> Wrap(const std::string& constructor_name, T* obj); template T * Unwrap(v8::Local value) const; private: static int s_count; static std::unique_ptr s_platform; bool _initialized; v8::Isolate::CreateParams create_params; v8::Isolate * _isolate; v8::Persistent _context; v8::Persistent _global; v8::Persistent _global_tpl; std::unordered_map> _constructorMap; }; inline v8::Isolate * V8ScriptEnv::Isolate() const { return _isolate; } inline v8::Local V8ScriptEnv::Context() const { return PersistentToLocal(Isolate(), _context); } inline v8::Local V8ScriptEnv::Global() const { return PersistentToLocal(Isolate(), _global); } inline void V8ScriptEnv::SetGlobal(v8::Local global) { _global.Reset(Isolate(), global); } inline v8::Local V8ScriptEnv::GlobalTemplate() const { return PersistentToLocal(Isolate(), _global_tpl); } inline void V8ScriptEnv::SetGlobalTemplate(v8::Local global_tpl) { _global_tpl.Reset(Isolate(), global_tpl); } inline v8::Local V8ScriptEnv::GetConstructor(const std::string& key) const { auto it = _constructorMap.find(key); if (it == _constructorMap.end()) return v8::Local(); return GlobalPersistentToLocal(Isolate(), (*it).second); } template inline std::unique_ptr> V8ScriptEnv::Wrap(const std::string& constructor_name, T *obj) { // Fetch the v8 isolate and context v8::Isolate *isolate = Isolate(); v8::Local context = Context(); assert(!context.IsEmpty()); // Create a stack-allocated scope for v8 calls, and enter context v8::Locker locker(isolate); v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); v8::Context::Scope context_scope(context); // Create an instance for the wrapped object v8::Local ctor_tpl = GetConstructor(constructor_name); v8::Local obj_tpl = ctor_tpl->InstanceTemplate(); v8::Local new_instance = obj_tpl->NewInstance(context).ToLocalChecked(); new_instance->SetAlignedPointerInInternalField(0, obj); return std::make_unique>(obj, isolate, new_instance); } template inline T * V8ScriptEnv::Unwrap(v8::Local value) const { T *obj = 0; if (value->IsObject()) { v8::MaybeLocal handle = value->ToObject(Context()); if (!handle.IsEmpty()) obj = static_cast(handle.ToLocalChecked()->GetAlignedPointerFromInternalField(0)); } return obj; } #endif