Fixed script value iterator and connect functionality

This commit is contained in:
ksuprynowicz 2023-01-18 00:01:32 +01:00
parent e786fd4864
commit 1550049b0c
6 changed files with 82 additions and 24 deletions

View file

@ -80,6 +80,7 @@ void AnimVariantMap::animVariantMapFromScriptValue(const ScriptValue& source) {
Q_ASSERT(false);
return;
}
// This was here before, but marking as V8TODO
// POTENTIAL OPTIMIZATION: cache the types we've seen. I.e, keep a dictionary mapping property names to an enumeration of types.
// Whenever we identify a new outbound type in animVariantMapToScriptValue above, or a new inbound type in the code that follows here,
// we would enter it into the dictionary. Then switch on that type here, with the code that follow being executed only if
@ -121,7 +122,8 @@ void AnimVariantMap::animVariantMapFromScriptValue(const ScriptValue& source) {
}
}
qCWarning(animation) << "Ignoring unrecognized data " << value.toString() << " for animation property " << property->name();
Q_ASSERT(false);
// V8TODO this was spamming to much logs but needs to be fixed later
//Q_ASSERT(false);
}
}
}

View file

@ -570,6 +570,7 @@ bool ScriptEngineV8::convertJSObjectToVariant(v8::Local<v8::Object> object, QVar
}
}
dest = QVariant(properties);
return true;
}
QString ScriptEngineV8::valueType(const V8ScriptValue& v8Val) {

View file

@ -477,7 +477,6 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
v8::Local<v8::Value> property;
if(_v8Object.Get(_engine->getIsolate())->GetInternalField(2).As<v8::Object>()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) {
if (!property->IsUndefined()) {
qDebug() << "Using existing method object";
return V8ScriptValue(_engine->getIsolate(), property);
}
}
@ -1021,7 +1020,12 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu
return id;
}
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
auto context = _engine->getContext();
v8::Context::Scope contextScope(context);
//V8ScriptValueList args(isolate, v8::Null(isolate));
v8::Local<v8::Value> args[Q_METAMETHOD_INVOKE_MAX_ARGS];
@ -1073,8 +1077,11 @@ ScriptSignalV8Proxy::ConnectionList::iterator ScriptSignalV8Proxy::findConnectio
return iterOut;
}
/*void ScriptSignalV8Proxy::connect(ScriptValue arg0) {
connect(arg0, ScriptValue(_engine->getIsolate(), v8::Undefined(_engine->getIsolate())));
}*/
void ScriptSignalV8Proxy::connect(V8ScriptValue arg0, V8ScriptValue arg1) {
void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) {
QObject* qobject = _object;
v8::Isolate *isolate = _engine->getIsolate();
if (!qobject) {
@ -1087,11 +1094,22 @@ void ScriptSignalV8Proxy::connect(V8ScriptValue arg0, V8ScriptValue arg1) {
// untangle the arguments
V8ScriptValue callback(isolate, v8::Null(isolate));
V8ScriptValue callbackThis(isolate, v8::Null(isolate));
if (arg1.get()->IsFunction()) {
callbackThis = arg0;
callback = arg1;
if (arg1.isFunction()) {
auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);
if (!unwrappedArg0 || !unwrappedArg1) {
Q_ASSERT(false);
return;
}
callbackThis = unwrappedArg0->toV8Value();
callback = unwrappedArg1->toV8Value();
} else {
callback = arg0;
auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
if (!unwrappedArg0) {
Q_ASSERT(false);
return;
}
callback = unwrappedArg0->toV8Value();
}
if (!callback.get()->IsFunction()) {
isolate->ThrowError("Function expected as argument to 'connect'");
@ -1154,7 +1172,11 @@ void ScriptSignalV8Proxy::connect(V8ScriptValue arg0, V8ScriptValue arg1) {
}
}
void ScriptSignalV8Proxy::disconnect(V8ScriptValue arg0, V8ScriptValue arg1) {
/*void ScriptSignalV8Proxy::disconnect(ScriptValue arg0) {
disconnect(arg0, V8ScriptValue(_engine->getIsolate(), v8::Undefined(_engine->getIsolate())));
}*/
void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) {
QObject* qobject = _object;
v8::Isolate *isolate = _engine->getIsolate();
if (!qobject) {
@ -1166,11 +1188,22 @@ void ScriptSignalV8Proxy::disconnect(V8ScriptValue arg0, V8ScriptValue arg1) {
// untangle the arguments
V8ScriptValue callback(isolate, v8::Null(isolate));
V8ScriptValue callbackThis(isolate, v8::Null(isolate));
if (arg1.get()->IsFunction()) {
callbackThis = arg0;
callback = arg1;
if (arg1.isFunction()) {
auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);
if (!unwrappedArg0 || !unwrappedArg1) {
Q_ASSERT(false);
return;
}
callbackThis = unwrappedArg0->toV8Value();
callback = unwrappedArg1->toV8Value();
} else {
callback = arg0;
auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
if (!unwrappedArg0) {
Q_ASSERT(false);
return;
}
callback = unwrappedArg0->toV8Value();
}
if (!callback.get()->IsFunction()) {
isolate->ThrowError("Function expected as argument to 'disconnect'");

View file

@ -200,8 +200,10 @@ class ScriptSignalV8ProxyBase : public QObject, protected Scriptable {
Q_OBJECT
public: // API
// arg1 was had Null default value, but that needs isolate pointer in V8
Q_INVOKABLE virtual void connect(V8ScriptValue arg0, V8ScriptValue arg1) = 0;
Q_INVOKABLE virtual void disconnect(V8ScriptValue arg0, V8ScriptValue arg1) = 0;
Q_INVOKABLE virtual void connect(ScriptValue arg0, ScriptValue arg1 = ScriptValue()) = 0;
Q_INVOKABLE virtual void disconnect(ScriptValue arg0, ScriptValue arg1 = ScriptValue()) = 0;
//Q_INVOKABLE virtual void connect(ScriptValue arg0) = 0;
//Q_INVOKABLE virtual void disconnect(ScriptValue arg0) = 0;
};
class ScriptSignalV8Proxy final : public ScriptSignalV8ProxyBase, public ReadWriteLockable {
@ -226,9 +228,12 @@ private: // implementation
QString fullName() const;
public: // API
// arg1 was had Null default value, but that needs isolate pointer to cerate Null in V8
virtual void connect(V8ScriptValue arg0, V8ScriptValue arg1) override;
virtual void disconnect(V8ScriptValue arg0, V8ScriptValue arg1) override;
// arg1 was had Null default value, but that needs isolate pointer to create Null in V8
virtual void connect(ScriptValue arg0, ScriptValue arg1 = ScriptValue()) override;
virtual void disconnect(ScriptValue arg0, ScriptValue arg1 = ScriptValue()) override;
//virtual void connect(V8ScriptValue arg0) override;
//virtual void disconnect(V8ScriptValue arg0) override;
private: // storage
ScriptEngineV8* _engine;

View file

@ -15,15 +15,19 @@
V8ScriptValueIterator::V8ScriptValueIterator(ScriptEngineV8* engine, v8::Local<v8::Value> object) : _engine(engine) {
auto isolate = _engine->getIsolate();
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
// V8TODO Is this necessary?
_context.Reset(isolate, _engine->getContext());
auto context = _context.Get(isolate);
v8::Context::Scope contextScope(context);
Q_ASSERT(object->IsObject());
v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(object);
_object.Reset(isolate, v8Object);
_propertyNames.Reset(isolate, v8Object->GetOwnPropertyNames(context).ToLocalChecked());
_length = _propertyNames.Get(isolate)->Length();
_currentIndex = 0;
_currentIndex = -1;
}
bool V8ScriptValueIterator::hasNext() const {
@ -31,29 +35,37 @@ bool V8ScriptValueIterator::hasNext() const {
}
QString V8ScriptValueIterator::name() const {
Q_ASSERT(_currentIndex >= 0);
auto isolate = _engine->getIsolate();
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
auto context = _context.Get(isolate);
v8::Context::Scope contextScope(context);
v8::Local<v8::Value> propertyName;
if (!_propertyNames.Get(isolate)->Get(context, _length).ToLocal(&propertyName)) {
if (!_propertyNames.Get(isolate)->Get(context, _currentIndex).ToLocal(&propertyName)) {
Q_ASSERT(false);
}
return QString(*v8::String::Utf8Value(isolate, propertyName));
}
void V8ScriptValueIterator::next() {
if (_length < _currentIndex - 1) {
_length++;
if (_currentIndex < _length - 1) {
_currentIndex++;
}
}
V8ScriptValue V8ScriptValueIterator::value() {
Q_ASSERT(_currentIndex >= 0);
auto isolate = _engine->getIsolate();
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
auto context = _context.Get(isolate);
v8::Context::Scope contextScope(context);
v8::Local<v8::Value> v8Value;
v8::Local<v8::Value> propertyName;
if (!_propertyNames.Get(isolate)->Get(context, _length).ToLocal(&propertyName)) {
if (!_propertyNames.Get(isolate)->Get(context, _currentIndex).ToLocal(&propertyName)) {
Q_ASSERT(false);
}
if (!_object.Get(isolate)->Get(context, propertyName->ToString(context).ToLocalChecked()).ToLocal(&v8Value)) {

View file

@ -202,7 +202,12 @@ ScriptEnginePointer ScriptValueV8Wrapper::engine() const {
}
ScriptValueIteratorPointer ScriptValueV8Wrapper::newIterator() const {
return std::make_shared<ScriptValueIteratorV8Wrapper>(_engine, _value);
v8::Locker locker(_engine->getIsolate());
v8::Isolate::Scope isolateScope(_engine->getIsolate());
v8::HandleScope handleScope(_engine->getIsolate());
v8::Context::Scope contextScope(_engine->getContext());
ScriptValueIteratorPointer iterator = std::make_shared<ScriptValueIteratorV8Wrapper>(_engine, _value);
return iterator;
}
bool ScriptValueV8Wrapper::hasProperty(const QString& name) const {