diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index bc7ce06dbc..886e0b66b1 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -350,7 +350,7 @@ public: virtual void registerFunction(const QString& name, FunctionSignature fun, int numArguments = -1) = 0; virtual void registerFunction(const QString& parent, const QString& name, FunctionSignature fun, int numArguments = -1) = 0; virtual void registerGetterSetter(const QString& name, FunctionSignature getter, FunctionSignature setter, const QString& parent = QString("")) = 0; - virtual void registerGlobalObject(const QString& name, QObject* object) = 0; + virtual void registerGlobalObject(const QString& name, QObject* object, ScriptEngine::ValueOwnership = ScriptEngine::QtOwnership) = 0; virtual void setDefaultPrototype(int metaTypeId, const ScriptValue& prototype) = 0; virtual void setObjectName(const QString& name) = 0; virtual bool setProperty(const char* name, const QVariant& value) = 0; diff --git a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp index 2b22720b8f..0a2bdf15bb 100644 --- a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp @@ -222,6 +222,11 @@ QString ScriptFunctionContextV8Wrapper::fileName() const { v8::Context::Scope contextScope(_context.Get(isolate)); // V8TODO: does this work for context selected with contextScope? v8::Local name = v8::StackTrace::CurrentScriptNameOrSourceURL(_engine->getIsolate()); + /*auto stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 1); + if (stackTrace.IsEmpty() || stackTrace->GetFrameCount() == 0) { + return ""; + } + auto name = stackTrace->GetFrame(isolate, 0)->GetScriptNameOrSourceURL();*/ v8::String::Utf8Value nameUTF(_engine->getIsolate(), name); return QString(*nameUTF); } diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.cpp b/libraries/script-engine/src/v8/ScriptEngineV8.cpp index c62ae13aaa..84d6c8c99a 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8.cpp @@ -48,6 +48,7 @@ #include "../ScriptProgram.h" #include "../ScriptEngineCast.h" #include "../ScriptValue.h" +#include "../ScriptManagerScriptingInterface.h" #include "ScriptContextV8Wrapper.h" #include "ScriptObjectV8Proxy.h" @@ -335,7 +336,7 @@ void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value } } -void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) { +void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object, ScriptEngine::ValueOwnership) { if (QThread::currentThread() != thread()) { #ifdef THREAD_DEBUGGING qCDebug(scriptengine_v8) << "*** WARNING *** ScriptEngineV8::registerGlobalObject() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; @@ -627,6 +628,9 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, Q_ASSERT(false); } } + // "Script" API is context-dependent, so it needs to be recreated for each new context + registerGlobalObject("Script", new ScriptManagerScriptingInterface(_manager), ScriptEngine::ScriptOwnership); + auto maybeResult = program.constGet()->GetUnboundScript()->BindToCurrentContext()->Run(closureContext); v8::Local v8Result; if (!maybeResult.ToLocal(&v8Result)) { @@ -859,13 +863,13 @@ ScriptContextV8Pointer ScriptEngineV8::pushContext(v8::Local contex v8::HandleScope handleScope(_v8Isolate); Q_ASSERT(!_contexts.isEmpty()); ScriptContextPointer parent = _contexts.last(); - _contexts.append(std::make_shared(this, context, ScriptContextPointer())); + _contexts.append(std::make_shared(this, context, parent)); v8::Context::Scope contextScope(context); - static volatile int debug_context_id = 1; + /*static volatile int debug_context_id = 1; if (!context->Global()->Set(context, v8::String::NewFromUtf8(_v8Isolate, "debug_context_id").ToLocalChecked(), v8::Integer::New(_v8Isolate, debug_context_id)).FromMaybe(false)) { Q_ASSERT(false); } - debug_context_id++; + debug_context_id++;*/ return _contexts.last(); } diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.h b/libraries/script-engine/src/v8/ScriptEngineV8.h index 2dc91aebf4..fce0f40edb 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.h +++ b/libraries/script-engine/src/v8/ScriptEngineV8.h @@ -117,7 +117,7 @@ public: // ScriptEngine implementation ScriptEngine::FunctionSignature getter, ScriptEngine::FunctionSignature setter, const QString& parent = QString("")) override; - Q_INVOKABLE virtual void registerGlobalObject(const QString& name, QObject* object) override; + Q_INVOKABLE virtual void registerGlobalObject(const QString& name, QObject* object, ScriptEngine::ValueOwnership = ScriptEngine::QtOwnership) override; virtual void setDefaultPrototype(int metaTypeId, const ScriptValue& prototype) override; virtual void setObjectName(const QString& name) override; virtual bool setProperty(const char* name, const QVariant& value) override; diff --git a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp index 005ed43a71..9ea1ab0ded 100644 --- a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp +++ b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp @@ -939,7 +939,17 @@ void ScriptMethodV8Proxy::callback(const v8::FunctionCallbackInfo& ar return; } ScriptMethodV8Proxy *proxy = reinterpret_cast(data->GetAlignedPointerFromInternalField(1)); + + // V8TODO: all other V8 callbacks need this too + bool isContextChangeNeeded = (proxy->_engine->getContext() != arguments.GetIsolate()->GetCurrentContext()); + if (isContextChangeNeeded) { + qDebug() << "ScriptMethodV8Proxy::callback : changing context"; + proxy->_engine->pushContext(arguments.GetIsolate()->GetCurrentContext()); + } proxy->call(arguments); + if (isContextChangeNeeded) { + proxy->_engine->popContext(); + } } void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo& arguments) {