From 58a221541f3de2b7c6e18d71bf70fa8cb6ed4a76 Mon Sep 17 00:00:00 2001 From: ksuprynowicz Date: Tue, 11 Oct 2022 23:58:17 +0200 Subject: [PATCH] Script engine new function fixes --- libraries/script-engine/src/ScriptManager.cpp | 5 +- .../src/v8/ScriptContextV8Wrapper.cpp | 78 ++++++--- .../src/v8/ScriptContextV8Wrapper.h | 9 +- .../script-engine/src/v8/ScriptEngineV8.cpp | 148 +++++++++++++----- .../src/v8/ScriptObjectV8Proxy.cpp | 6 +- .../src/v8/ScriptValueV8Wrapper.cpp | 51 +++--- 6 files changed, 199 insertions(+), 98 deletions(-) diff --git a/libraries/script-engine/src/ScriptManager.cpp b/libraries/script-engine/src/ScriptManager.cpp index c0a335b653..e4273fe5ac 100644 --- a/libraries/script-engine/src/ScriptManager.cpp +++ b/libraries/script-engine/src/ScriptManager.cpp @@ -683,14 +683,15 @@ void ScriptManager::init() { scriptEngine->registerGlobalObject("Script", this); - { + //V8TODO: V8 has no such global object? + /*{ // set up Script.require.resolve and Script.require.cache auto Script = scriptEngine->globalObject().property("Script"); auto require = Script.property("require"); auto resolve = Script.property("_requireResolve"); require.setProperty("resolve", resolve, READONLY_PROP_FLAGS); resetModuleCache(); - } + }*/ scriptEngine->registerEnum("Script.ExternalPaths", QMetaEnum::fromType()); diff --git a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp index d983dacd70..802ca660da 100644 --- a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp @@ -16,12 +16,17 @@ #include "ScriptEngineV8.h" #include "ScriptValueV8Wrapper.h" -ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::Local context) : _engine(engine) { - _context.Reset(_engine->getIsolate(), _engine->getConstContext()); +/*ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::Local context) : _functionCallbackInfo(nullptr), _propertyCallbackInfo(nullptr), _engine(engine) { + _context.Reset(_engine->getIsolate(), context); +}*/ + +ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine) : _functionCallbackInfo(nullptr), _propertyCallbackInfo(nullptr), _engine(engine) { } -ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::Local context, std::shared_ptr> functionCallbackInfo) : _context(engine->getIsolate(), engine->getConstContext()), _functionCallbackInfo(functionCallbackInfo), _engine(engine) { - _context.Reset(_engine->getIsolate(), _engine->getConstContext()); +ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::FunctionCallbackInfo *functionCallbackInfo) : _functionCallbackInfo(functionCallbackInfo), _propertyCallbackInfo(nullptr), _engine(engine) { +} + +ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::PropertyCallbackInfo *propertyCallbackInfo) : _functionCallbackInfo(nullptr), _propertyCallbackInfo(propertyCallbackInfo), _engine(engine) { } ScriptContextV8Wrapper* ScriptContextV8Wrapper::unwrap(ScriptContext* val) { @@ -34,7 +39,7 @@ ScriptContextV8Wrapper* ScriptContextV8Wrapper::unwrap(ScriptContext* val) { v8::Local ScriptContextV8Wrapper::toV8Value() const { v8::EscapableHandleScope handleScope(_engine->getIsolate()); - return handleScope.Escape(_context.Get(_engine->getIsolate())); + return handleScope.Escape(_engine->getContext()); } int ScriptContextV8Wrapper::argumentCount() const { @@ -44,21 +49,35 @@ int ScriptContextV8Wrapper::argumentCount() const { v8::Context::Scope contextScope(_engine->getContext());*/ //Q_ASSERT(_functionCallbackInfo);A // V8TODO - return Q_METAMETHOD_INVOKE_MAX_ARGS; + if (_functionCallbackInfo) { + return _functionCallbackInfo->kArgsLength; + } else if (_propertyCallbackInfo) { + return _propertyCallbackInfo->kArgsLength; + } else { + return Q_METAMETHOD_INVOKE_MAX_ARGS; + } // This was wrong, in function registration it seems to be used as maximum number od arguments instead? // Is it also used for something else? //return _functionCallbackInfo->Length(); } ScriptValue ScriptContextV8Wrapper::argument(int index) const { - auto isolate = _engine->getIsolate(); - Q_ASSERT(isolate->IsCurrent()); - v8::HandleScope handleScope(isolate); - v8::Context::Scope contextScope(_engine->getContext()); - Q_ASSERT(_functionCallbackInfo); - v8::Local result = (*_functionCallbackInfo)[index]; - //V8ScriptValue result = _context->argument(index); - return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result))); + if (_functionCallbackInfo) { + auto isolate = _engine->getIsolate(); + Q_ASSERT(isolate->IsCurrent()); + v8::HandleScope handleScope(isolate); + v8::Context::Scope contextScope(_engine->getContext()); + v8::Local result = (*_functionCallbackInfo)[index]; + if (index < _functionCallbackInfo->kArgsLength) { + return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result))); + } else { + return _engine->undefinedValue(); + } + } else if (_propertyCallbackInfo) { + return _engine->undefinedValue(); + } else { + return _engine->undefinedValue(); + } } QStringList ScriptContextV8Wrapper::backtrace() const { @@ -82,11 +101,12 @@ QStringList ScriptContextV8Wrapper::backtrace() const { } ScriptValue ScriptContextV8Wrapper::callee() const { + Q_ASSERT(false); //V8TODO //Can this be done with CurrentStackTrace? //V8ScriptValue result = _context->callee(); //return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result))); - return ScriptValue(); + return _engine->undefinedValue(); } ScriptEnginePointer ScriptContextV8Wrapper::engine() const { @@ -94,25 +114,35 @@ ScriptEnginePointer ScriptContextV8Wrapper::engine() const { } ScriptFunctionContextPointer ScriptContextV8Wrapper::functionContext() const { - return std::make_shared(_context.Get(_engine->getIsolate())); + return std::make_shared(_engine->getContext()); } ScriptContextPointer ScriptContextV8Wrapper::parentContext() const { //V8TODO + Q_ASSERT(false); //V8ScriptContext* result = _context->parentContext(); //return result ? std::make_shared(_engine, result) : ScriptContextPointer(); return ScriptContextPointer(); } ScriptValue ScriptContextV8Wrapper::thisObject() const { - Q_ASSERT(_functionCallbackInfo); - auto isolate = _engine->getIsolate(); - Q_ASSERT(isolate->IsCurrent()); - v8::HandleScope handleScope(isolate); - v8::Context::Scope contextScope(_engine->getContext()); - v8::Local result = _functionCallbackInfo->This(); - return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result))); - return ScriptValue(); + if (_functionCallbackInfo) { + auto isolate = _engine->getIsolate(); + Q_ASSERT(isolate->IsCurrent()); + v8::HandleScope handleScope(isolate); + v8::Context::Scope contextScope(_engine->getContext()); + v8::Local result = _functionCallbackInfo->This(); + return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result))); + } else if (_propertyCallbackInfo) { + auto isolate = _engine->getIsolate(); + Q_ASSERT(isolate->IsCurrent()); + v8::HandleScope handleScope(isolate); + v8::Context::Scope contextScope(_engine->getContext()); + v8::Local result = _propertyCallbackInfo->This(); + return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result))); + } else { + return _engine->undefinedValue(); + } } ScriptValue ScriptContextV8Wrapper::throwError(const QString& text) { diff --git a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.h b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.h index 3066ec15e1..7cf80495d5 100644 --- a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.h +++ b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.h @@ -31,8 +31,9 @@ class ScriptEngineV8; /// [V8] Implements ScriptContext for V8 and translates calls for V8ScriptContextInfo class ScriptContextV8Wrapper final : public ScriptContext { public: // construction - ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::Local context); - ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::Local context, std::shared_ptr> functionCallbackInfo); + ScriptContextV8Wrapper(ScriptEngineV8* engine); + ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::FunctionCallbackInfo *functionCallbackInfo); + ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::PropertyCallbackInfo *propertyCallbackInfo); static ScriptContextV8Wrapper* unwrap(ScriptContext* val); v8::Local toV8Value() const; @@ -49,8 +50,8 @@ public: // ScriptContext implementation virtual ScriptValue throwValue(const ScriptValue& value) override; private: // storage - v8::Persistent _context; - std::shared_ptr> _functionCallbackInfo; + const v8::FunctionCallbackInfo *_functionCallbackInfo; + const v8::PropertyCallbackInfo *_propertyCallbackInfo; ScriptEngineV8* _engine; }; diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.cpp b/libraries/script-engine/src/v8/ScriptEngineV8.cpp index dcb2f9a26e..514c59d8c3 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8.cpp @@ -294,7 +294,7 @@ ScriptValue ScriptEngineV8::newLambdaFunction(std::functioncallee().prototype() === Lambda QObject call.setData(ScriptValue(new ScriptValueV8Wrapper(this, data))); // context->callee().data() will === data param @@ -334,8 +334,10 @@ V8ScriptValue Lambda::call() { if (!_engine->IS_THREADSAFE_INVOCATION(__FUNCTION__)) { return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate())); } - return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate())); - // V8TODO: something is obviously wrong here, there's no call at all? + // V8TODO: it needs to be done in entirely different way for V8 + Q_ASSERT(false); + //return _operation(_engine->getContext(), _engine); + //return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate())); //return operation(static_cast(engine)->currentContext(), engine); } @@ -379,30 +381,35 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) : v8::V8::Initialize(); } ); _v8InitMutex.unlock(); - v8::Isolate::CreateParams isolateParams; - isolateParams.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); - _v8Isolate = v8::Isolate::New(isolateParams); - _v8Isolate->Enter(); - v8::HandleScope handleScope(_v8Isolate); - v8::Local context = v8::Context::New(_v8Isolate); - Q_ASSERT(!context.IsEmpty()); - _v8Context = v8::UniquePersistent(_v8Isolate, context); + { + v8::Isolate::CreateParams isolateParams; + isolateParams.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); + _v8Isolate = v8::Isolate::New(isolateParams); + _v8Isolate->Enter(); + v8::HandleScope handleScope(_v8Isolate); + v8::Local context = v8::Context::New(_v8Isolate); + Q_ASSERT(!context.IsEmpty()); + v8::Context::Scope contextScope(context); + _v8Context = v8::UniquePersistent(_v8Isolate, context); - registerSystemTypes(); + V8ScriptValue nullScriptValue(_v8Isolate, v8::Null(_v8Isolate)); + _nullValue = ScriptValue(new ScriptValueV8Wrapper(this, nullScriptValue)); - // V8TODO: dispose of isolate on ScriptEngineV8 destruction - //v8::UniquePersistent null = v8::UniquePersistent(_v8Isolate, v8::Null(_v8Isolate)); - //_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(null))); - V8ScriptValue nullScriptValue(_v8Isolate, v8::Null(_v8Isolate)); - _nullValue = ScriptValue(new ScriptValueV8Wrapper(this, nullScriptValue)); + V8ScriptValue undefined(_v8Isolate, v8::Undefined(_v8Isolate)); + _undefinedValue = ScriptValue(new ScriptValueV8Wrapper(this, undefined)); - //V8ScriptValue undefined = v8::UniquePersistent(_v8Isolate,v8::Undefined(_v8Isolate)); - //_undefinedValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(undefined))); - V8ScriptValue undefined(_v8Isolate, v8::Undefined(_v8Isolate)); - _undefinedValue = ScriptValue(new ScriptValueV8Wrapper(this, undefined)); + registerSystemTypes(); - // V8TODO: - //QScriptEngine::setProcessEventsInterval(MSECS_PER_SECOND); + // V8TODO: dispose of isolate on ScriptEngineV8 destruction + //v8::UniquePersistent null = v8::UniquePersistent(_v8Isolate, v8::Null(_v8Isolate)); + //_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(null))); + + //V8ScriptValue undefined = v8::UniquePersistent(_v8Isolate,v8::Undefined(_v8Isolate)); + //_undefinedValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(undefined))); + + // V8TODO: + //QScriptEngine::setProcessEventsInterval(MSECS_PER_SECOND); + } //_currentThread = QThread::currentThread(); @@ -514,6 +521,8 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) } void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) { + //if (QThread::currentThread() != ) { + //} if (QThread::currentThread() != thread()) { #ifdef THREAD_DEBUGGING qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; @@ -556,7 +565,7 @@ void ScriptEngineV8::registerFunction(const QString& parent, const QString& name v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); ScriptValue object = globalObject().property(parent); if (object.isValid()) { - ScriptValue scriptFun = ScriptEngine::newFunction(functionSignature, numArguments); + ScriptValue scriptFun = newFunction(functionSignature, numArguments); object.setProperty(name, scriptFun); } } @@ -580,20 +589,71 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun #endif v8::HandleScope handleScope(_v8Isolate); - v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); + v8::Context::Scope contextScope(getContext()); + + /*auto getterFunction = [](v8::Local property, const v8::PropertyCallbackInfo& info) { + //V8TODO: is using GetCurrentContext ok, or context wrapper needs to be added? + v8::HandleScope handleScope(info.GetIsolate()); + auto context = info.GetIsolate()->GetCurrentContext(); + v8::Context::Scope contextScope(context); + auto object = v8::Local::Cast(info.Data()); + Q_ASSERT(object->InternalFieldCount() == 2); + auto function = reinterpret_cast + (object->GetAlignedPointerFromInternalField(0)); + ScriptEngineV8 *scriptEngine = reinterpret_cast + (object->GetAlignedPointerFromInternalField(1)); + ScriptContextV8Wrapper scriptContext(scriptEngine, &info); + //V8TODO: this scriptContext needs to have FunctionCallbackInfo added + ScriptValue result = function(&scriptContext, scriptEngine); + ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result); + info.GetReturnValue().Set(unwrapped->toV8Value().constGet()); + }; + auto setterFunction = [](v8::Local property, const v8::PropertyCallbackInfo& info) { + //V8TODO: is using GetCurrentContext ok, or context wrapper needs to be added? + v8::HandleScope handleScope(info.GetIsolate()); + auto context = info.GetIsolate()->GetCurrentContext(); + v8::Context::Scope contextScope(context); + auto object = v8::Local::Cast(info.Data()); + Q_ASSERT(object->InternalFieldCount() == 2); + auto function = reinterpret_cast + (object->GetAlignedPointerFromInternalField(0)); + ScriptEngineV8 *scriptEngine = reinterpret_cast + (object->GetAlignedPointerFromInternalField(1)); + ScriptContextV8Wrapper scriptContext(scriptEngine, &info); + //V8TODO: this scriptContext needs to have FunctionCallbackInfo added + ScriptValue result = function(&scriptContext, scriptEngine); + ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result); + };*/ ScriptValue setterFunction = newFunction(setter, 1); ScriptValue getterFunction = newFunction(getter); + V8ScriptValue unwrappedGetter = ScriptValueV8Wrapper::fullUnwrap(this, setterFunction); + V8ScriptValue unwrappedSetter = ScriptValueV8Wrapper::fullUnwrap(this, getterFunction); + v8::PropertyDescriptor propertyDescriptor(unwrappedGetter.get(), unwrappedSetter.get()); + //V8TODO: Getters/setters are probably done in a different way in V8. Maybe object template is needed? if (!parent.isNull() && !parent.isEmpty()) { - ScriptValue object = ScriptEngine::globalObject().property(parent); + ScriptValue object = globalObject().property(parent); if (object.isValid()) { - object.setProperty(name, setterFunction, ScriptValue::PropertySetter); - object.setProperty(name, getterFunction, ScriptValue::PropertyGetter); + V8ScriptValue v8parent = ScriptValueV8Wrapper::fullUnwrap(this, object); + Q_ASSERT(v8parent.get()->IsObject()); + v8::Local v8object = v8::Local::Cast(v8parent.get()); + v8::Local v8propertyName = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); + if(!v8object->DefineProperty(getContext(), v8propertyName, propertyDescriptor).FromMaybe(false)) { + qCDebug(scriptengine) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for parent: \"" << parent << "\""; + } + //object.setProperty(name, setterFunction, ScriptValue::PropertySetter); + //object.setProperty(name, getterFunction, ScriptValue::PropertyGetter); + } else { + qCDebug(scriptengine) << "Parent object \"" << parent << "\" for registerGetterSetter \"" << name << "\" is not valid: "; } } else { - globalObject().setProperty(name, setterFunction, ScriptValue::PropertySetter); - globalObject().setProperty(name, getterFunction, ScriptValue::PropertyGetter); + v8::Local v8propertyName = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); + if(!getContext()->Global()->DefineProperty(getContext(), v8propertyName, propertyDescriptor).FromMaybe(false)) { + qCDebug(scriptengine) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for global object"; + } + //globalObject().setProperty(name, setterFunction, ScriptValue::PropertySetter); + //globalObject().setProperty(name, getterFunction, ScriptValue::PropertyGetter); } } @@ -783,8 +843,9 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f Q_ASSERT(tryCatchRun.HasCaught()); auto runError = tryCatchRun.Message(); ScriptValue errorValue(new ScriptValueV8Wrapper(this, V8ScriptValue(_v8Isolate, runError->Get()))); - raiseException(errorValue); - maybeEmitUncaughtException("evaluate"); + //V8TODO + //raiseException(errorValue); + //maybeEmitUncaughtException("evaluate"); return errorValue; } V8ScriptValue resultValue(_v8Isolate, result); @@ -1016,8 +1077,8 @@ ScriptContext* ScriptEngineV8::currentContext() const { }*/ //_currContext = std::make_shared(const_cast(this), localCtx); if (!_currContext) { - // I'm not sure how to do this without discardin const - _currContext = std::make_shared(const_cast(this), getConstContext()); + // I'm not sure how to do this without discarding const + _currContext = std::make_shared(const_cast(this)); } return _currContext.get(); } @@ -1025,11 +1086,13 @@ ScriptContext* ScriptEngineV8::currentContext() const { bool ScriptEngineV8::hasUncaughtException() const { //V8TODO //return QScriptEngine::hasUncaughtException(); + return false; } bool ScriptEngineV8::isEvaluating() const { //V8TODO //return QScriptEngine::isEvaluating(); + return false; } ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int length) { @@ -1050,13 +1113,14 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int auto context = info.GetIsolate()->GetCurrentContext(); v8::Context::Scope contextScope(context); auto object = v8::Local::Cast(info.Data()); + Q_ASSERT(object->InternalFieldCount() == 2); auto function = reinterpret_cast (object->GetAlignedPointerFromInternalField(0)); - ScriptContext *scriptContext = reinterpret_cast - (object->GetAlignedPointerFromInternalField(1));; ScriptEngineV8 *scriptEngine = reinterpret_cast - (object->GetAlignedPointerFromInternalField(2));; - ScriptValue result = function(scriptContext, scriptEngine); + (object->GetAlignedPointerFromInternalField(1)); + ScriptContextV8Wrapper scriptContext(scriptEngine, &info); + //V8TODO: this scriptContext needs to have FunctionCallbackInfo added + ScriptValue result = function(&scriptContext, scriptEngine); ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result); info.GetReturnValue().Set(unwrapped->toV8Value().constGet()); }; @@ -1066,11 +1130,10 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int v8::HandleScope handleScope(_v8Isolate); v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); auto functionDataTemplate = v8::ObjectTemplate::New(_v8Isolate); - functionDataTemplate->SetInternalFieldCount(3); + functionDataTemplate->SetInternalFieldCount(2); auto functionData = functionDataTemplate->NewInstance(getContext()).ToLocalChecked(); functionData->SetAlignedPointerInInternalField(0, reinterpret_cast(fun)); functionData->SetAlignedPointerInInternalField(1, reinterpret_cast(this)); - functionData->SetAlignedPointerInInternalField(2, reinterpret_cast(currentContext())); //functionData->SetInternalField(3, v8::Null(_v8Isolate)); auto v8Function = v8::Function::New(getContext(), v8FunctionCallback, functionData, length).ToLocalChecked(); //auto functionObjectTemplate = functionTemplate->InstanceTemplate(); @@ -1138,10 +1201,12 @@ int ScriptEngineV8::uncaughtExceptionLineNumber() const { bool ScriptEngineV8::raiseException(const ScriptValue& exception) { //V8TODO - Q_ASSERT(false); + //Q_ASSERT(false); + qCritical() << "Script exception occured: " << exception.toString(); /*ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(exception); V8ScriptValue qException = unwrapped ? unwrapped->toV8Value() : QScriptEngine::newVariant(exception.toVariant()); return raiseException(qException);*/ + return false; } ScriptValue ScriptEngineV8::create(int type, const void* ptr) { @@ -1171,4 +1236,5 @@ QVariant ScriptEngineV8::convert(const ScriptValue& value, int typeId) { } return var; + return QVariant(); } diff --git a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp index bd184b860c..1f8f66fd3b 100644 --- a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp +++ b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp @@ -237,9 +237,9 @@ void ScriptObjectV8Proxy::investigate() { SignalDef& signalDef = _signals.insert(idx, SignalDef(_engine->getIsolate(), name.get())).value(); signalDef.name = name; signalDef.signal = method; - qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast(_engine->getIsolate()), nameString)); - qDebug(scriptengine) << "Utf8Value 2: " << QString(*v8::String::Utf8Value(const_cast(_engine->getIsolate()), name.constGet())); - qDebug(scriptengine) << "toQString: " << name.toQString(); + //qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast(_engine->getIsolate()), nameString)); + //qDebug(scriptengine) << "Utf8Value 2: " << QString(*v8::String::Utf8Value(const_cast(_engine->getIsolate()), name.constGet())); + //qDebug(scriptengine) << "toQString: " << name.toQString(); methodNames.insert(name, idx); } else { int originalMethodId = nameLookup.value(); diff --git a/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp index b4263c53dd..9eae55aa4c 100644 --- a/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp @@ -168,25 +168,26 @@ ScriptValueIteratorPointer ScriptValueV8Wrapper::newIterator() const { return std::make_shared(_engine, _value); } -ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValue::ResolveFlags& mode) const { +ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValue::ResolveFlags &mode) const { auto isolate = _engine->getIsolate(); Q_ASSERT(isolate->IsCurrent()); v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); - if (!_value.constGet()->IsObject()) { + if (_value.constGet()->IsObject()) { //V8TODO: what about flags? v8::Local resultLocal; v8::Local key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked(); - Q_ASSERT(_value.constGet()->IsObject()); const v8::Local object = v8::Local::Cast(_value.constGet()); if (object->Get(_value.constGetContext(), key).ToLocal(&resultLocal)) { V8ScriptValue result(_engine->getIsolate(), resultLocal); return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result))); } } - v8::Local nullValue = v8::Null(_engine->getIsolate()); + qCritical() << "Failed to get property, parent of value: " << name << " is not a V8 object, reported type: " << QString(*v8::String::Utf8Value(isolate, _value.constGet()->TypeOf(isolate))); + return _engine->undefinedValue(); + /*v8::Local nullValue = v8::Null(_engine->getIsolate()); V8ScriptValue nullScriptValue(_engine->getIsolate(), std::move(nullValue)); - return ScriptValue(new ScriptValueV8Wrapper(_engine, nullScriptValue)); + return ScriptValue(new ScriptValueV8Wrapper(_engine, nullScriptValue));*/ //V8ScriptValue result = _value.property(name, (V8ScriptValue::ResolveFlags)(int)mode); //return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result))); } @@ -196,19 +197,20 @@ ScriptValue ScriptValueV8Wrapper::property(quint32 arrayIndex, const ScriptValue Q_ASSERT(isolate->IsCurrent()); v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); - if (!_value.constGet()->IsObject()) { + if (_value.constGet()->IsObject()) { //V8TODO: what about flags? v8::Local resultLocal; - Q_ASSERT(_value.constGet()->IsObject()); const v8::Local object = v8::Local::Cast(_value.constGet()); if (object->Get(_value.constGetContext(), arrayIndex).ToLocal(&resultLocal)) { V8ScriptValue result(_engine->getIsolate(), resultLocal); return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result))); } } - v8::Local nullValue = v8::Null(_engine->getIsolate()); + qCritical() << "Failed to get property, parent of value: " << arrayIndex << " is not a V8 object, reported type: " << QString(*v8::String::Utf8Value(isolate, _value.constGet()->TypeOf(isolate))); + return _engine->undefinedValue(); + /*v8::Local nullValue = v8::Null(_engine->getIsolate()); V8ScriptValue nullScriptValue(_engine->getIsolate(), std::move(nullValue)); - return ScriptValue(new ScriptValueV8Wrapper(_engine, nullScriptValue)); + return ScriptValue(new ScriptValueV8Wrapper(_engine, nullScriptValue));*/ } void ScriptValueV8Wrapper::setData(const ScriptValue& value) { @@ -221,6 +223,7 @@ void ScriptValueV8Wrapper::setData(const ScriptValue& value) { } void ScriptValueV8Wrapper::setProperty(const QString& name, const ScriptValue& value, const ScriptValue::PropertyFlags& flags) { + Q_ASSERT(flags != ScriptValue::PropertyGetter || flags != ScriptValue::PropertySetter); auto isolate = _engine->getIsolate(); Q_ASSERT(isolate->IsCurrent()); v8::HandleScope handleScope(isolate); @@ -304,11 +307,11 @@ qint32 ScriptValueV8Wrapper::toInt32() const { Q_ASSERT(isolate->IsCurrent()); v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); - v8::Local *integer; - if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) { + v8::Local integer; + if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(&integer)) { Q_ASSERT(false); } - return static_cast((*integer)->Value()); + return static_cast((integer)->Value()); } double ScriptValueV8Wrapper::toInteger() const { @@ -316,11 +319,11 @@ double ScriptValueV8Wrapper::toInteger() const { Q_ASSERT(isolate->IsCurrent()); v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); - v8::Local *integer; - if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) { + v8::Local integer; + if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(&integer)) { Q_ASSERT(false); } - return (*integer)->Value(); + return (integer)->Value(); } double ScriptValueV8Wrapper::toNumber() const { @@ -328,11 +331,11 @@ double ScriptValueV8Wrapper::toNumber() const { Q_ASSERT(isolate->IsCurrent()); v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); - v8::Local *number; - if (!_value.constGet()->ToNumber(_value.constGetContext()).ToLocal(number)) { + v8::Local number; + if (!_value.constGet()->ToNumber(_value.constGetContext()).ToLocal(&number)) { Q_ASSERT(false); } - return (*number)->Value(); + return number->Value(); } QString ScriptValueV8Wrapper::toString() const { @@ -350,11 +353,11 @@ quint16 ScriptValueV8Wrapper::toUInt16() const { Q_ASSERT(isolate->IsCurrent()); v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); - v8::Local *integer; - if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) { + v8::Local integer; + if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(&integer)) { Q_ASSERT(false); } - return static_cast((*integer)->Value()); + return static_cast(integer->Value()); } quint32 ScriptValueV8Wrapper::toUInt32() const { @@ -362,11 +365,11 @@ quint32 ScriptValueV8Wrapper::toUInt32() const { Q_ASSERT(isolate->IsCurrent()); v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); - v8::Local *integer; - if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) { + v8::Local integer; + if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(&integer)) { Q_ASSERT(false); } - return (*integer)->Value(); + return integer->Value(); } QVariant ScriptValueV8Wrapper::toVariant() const {