Script engine new function fixes

This commit is contained in:
ksuprynowicz 2022-10-11 23:58:17 +02:00
parent a4c6930a50
commit 58a221541f
6 changed files with 199 additions and 98 deletions

View file

@ -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<ExternalResource::Bucket>());

View file

@ -16,12 +16,17 @@
#include "ScriptEngineV8.h"
#include "ScriptValueV8Wrapper.h"
ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::Local<v8::Context> context) : _engine(engine) {
_context.Reset(_engine->getIsolate(), _engine->getConstContext());
/*ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::Local<v8::Context> 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<v8::Context> context, std::shared_ptr<v8::FunctionCallbackInfo<v8::Value>> functionCallbackInfo) : _context(engine->getIsolate(), engine->getConstContext()), _functionCallbackInfo(functionCallbackInfo), _engine(engine) {
_context.Reset(_engine->getIsolate(), _engine->getConstContext());
ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::FunctionCallbackInfo<v8::Value> *functionCallbackInfo) : _functionCallbackInfo(functionCallbackInfo), _propertyCallbackInfo(nullptr), _engine(engine) {
}
ScriptContextV8Wrapper::ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::PropertyCallbackInfo<v8::Value> *propertyCallbackInfo) : _functionCallbackInfo(nullptr), _propertyCallbackInfo(propertyCallbackInfo), _engine(engine) {
}
ScriptContextV8Wrapper* ScriptContextV8Wrapper::unwrap(ScriptContext* val) {
@ -34,7 +39,7 @@ ScriptContextV8Wrapper* ScriptContextV8Wrapper::unwrap(ScriptContext* val) {
v8::Local<v8::Context> 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<v8::Value> 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<v8::Value> 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<ScriptFunctionContextV8Wrapper>(_context.Get(_engine->getIsolate()));
return std::make_shared<ScriptFunctionContextV8Wrapper>(_engine->getContext());
}
ScriptContextPointer ScriptContextV8Wrapper::parentContext() const {
//V8TODO
Q_ASSERT(false);
//V8ScriptContext* result = _context->parentContext();
//return result ? std::make_shared<ScriptContextV8Wrapper>(_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<v8::Value> 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<v8::Value> 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<v8::Value> result = _propertyCallbackInfo->This();
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result)));
} else {
return _engine->undefinedValue();
}
}
ScriptValue ScriptContextV8Wrapper::throwError(const QString& text) {

View file

@ -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<v8::Context> context);
ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::Local<v8::Context> context, std::shared_ptr<v8::FunctionCallbackInfo<v8::Value>> functionCallbackInfo);
ScriptContextV8Wrapper(ScriptEngineV8* engine);
ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::FunctionCallbackInfo<v8::Value> *functionCallbackInfo);
ScriptContextV8Wrapper(ScriptEngineV8* engine, const v8::PropertyCallbackInfo<v8::Value> *propertyCallbackInfo);
static ScriptContextV8Wrapper* unwrap(ScriptContext* val);
v8::Local<v8::Context> toV8Value() const;
@ -49,8 +50,8 @@ public: // ScriptContext implementation
virtual ScriptValue throwValue(const ScriptValue& value) override;
private: // storage
v8::Persistent<v8::Context> _context;
std::shared_ptr<v8::FunctionCallbackInfo<v8::Value>> _functionCallbackInfo;
const v8::FunctionCallbackInfo<v8::Value> *_functionCallbackInfo;
const v8::PropertyCallbackInfo<v8::Value> *_propertyCallbackInfo;
ScriptEngineV8* _engine;
};

View file

@ -294,7 +294,7 @@ ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8Scri
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
auto lambda = new Lambda(this, operation, data);
auto object = newQObject(lambda, ownership);
//V8TODO?
//V8TODO - I'm not sure if this works
auto call = object.property("call");
call.setPrototype(object); // context->callee().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<QScriptEngine*>(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<v8::Context> context = v8::Context::New(_v8Isolate);
Q_ASSERT(!context.IsEmpty());
_v8Context = v8::UniquePersistent<v8::Context>(_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<v8::Context> context = v8::Context::New(_v8Isolate);
Q_ASSERT(!context.IsEmpty());
v8::Context::Scope contextScope(context);
_v8Context = v8::UniquePersistent<v8::Context>(_v8Isolate, context);
registerSystemTypes();
V8ScriptValue nullScriptValue(_v8Isolate, v8::Null(_v8Isolate));
_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, nullScriptValue));
// V8TODO: dispose of isolate on ScriptEngineV8 destruction
//v8::UniquePersistent<v8::Value> null = v8::UniquePersistent<v8::Value>(_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<v8::Value>(_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<v8::Value> null = v8::UniquePersistent<v8::Value>(_v8Isolate, v8::Null(_v8Isolate));
//_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(null)));
//V8ScriptValue undefined = v8::UniquePersistent<v8::Value>(_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<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& 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<v8::Object>::Cast(info.Data());
Q_ASSERT(object->InternalFieldCount() == 2);
auto function = reinterpret_cast<ScriptEngine::FunctionSignature>
(object->GetAlignedPointerFromInternalField(0));
ScriptEngineV8 *scriptEngine = reinterpret_cast<ScriptEngineV8*>
(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<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& 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<v8::Object>::Cast(info.Data());
Q_ASSERT(object->InternalFieldCount() == 2);
auto function = reinterpret_cast<ScriptEngine::FunctionSignature>
(object->GetAlignedPointerFromInternalField(0));
ScriptEngineV8 *scriptEngine = reinterpret_cast<ScriptEngineV8*>
(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<v8::Object> v8object = v8::Local<v8::Object>::Cast(v8parent.get());
v8::Local<v8::String> 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<v8::String> 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<ScriptContextV8Wrapper>(const_cast<ScriptEngineV8*>(this), localCtx);
if (!_currContext) {
// I'm not sure how to do this without discardin const
_currContext = std::make_shared<ScriptContextV8Wrapper>(const_cast<ScriptEngineV8*>(this), getConstContext());
// I'm not sure how to do this without discarding const
_currContext = std::make_shared<ScriptContextV8Wrapper>(const_cast<ScriptEngineV8*>(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<v8::Object>::Cast(info.Data());
Q_ASSERT(object->InternalFieldCount() == 2);
auto function = reinterpret_cast<ScriptEngine::FunctionSignature>
(object->GetAlignedPointerFromInternalField(0));
ScriptContext *scriptContext = reinterpret_cast<ScriptContext*>
(object->GetAlignedPointerFromInternalField(1));;
ScriptEngineV8 *scriptEngine = reinterpret_cast<ScriptEngineV8*>
(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<void*>(fun));
functionData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(this));
functionData->SetAlignedPointerInInternalField(2, reinterpret_cast<void*>(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();
}

View file

@ -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<v8::Isolate*>(_engine->getIsolate()), nameString));
qDebug(scriptengine) << "Utf8Value 2: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), name.constGet()));
qDebug(scriptengine) << "toQString: " << name.toQString();
//qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), nameString));
//qDebug(scriptengine) << "Utf8Value 2: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), name.constGet()));
//qDebug(scriptengine) << "toQString: " << name.toQString();
methodNames.insert(name, idx);
} else {
int originalMethodId = nameLookup.value();

View file

@ -168,25 +168,26 @@ ScriptValueIteratorPointer ScriptValueV8Wrapper::newIterator() const {
return std::make_shared<ScriptValueIteratorV8Wrapper>(_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<v8::Value> resultLocal;
v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
Q_ASSERT(_value.constGet()->IsObject());
const v8::Local<v8::Object> object = v8::Local<v8::Object>::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<v8::Value> 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<v8::Value> 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<v8::Value> resultLocal;
Q_ASSERT(_value.constGet()->IsObject());
const v8::Local<v8::Object> object = v8::Local<v8::Object>::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<v8::Value> 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<v8::Value> 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<v8::Integer> *integer;
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) {
v8::Local<v8::Integer> integer;
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(&integer)) {
Q_ASSERT(false);
}
return static_cast<int32_t>((*integer)->Value());
return static_cast<int32_t>((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<v8::Integer> *integer;
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) {
v8::Local<v8::Integer> 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<v8::Number> *number;
if (!_value.constGet()->ToNumber(_value.constGetContext()).ToLocal(number)) {
v8::Local<v8::Number> 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<v8::Uint32> *integer;
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) {
v8::Local<v8::Uint32> integer;
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(&integer)) {
Q_ASSERT(false);
}
return static_cast<uint16_t>((*integer)->Value());
return static_cast<uint16_t>(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<v8::Uint32> *integer;
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) {
v8::Local<v8::Uint32> integer;
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(&integer)) {
Q_ASSERT(false);
}
return (*integer)->Value();
return integer->Value();
}
QVariant ScriptValueV8Wrapper::toVariant() const {