aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4runtime.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2023-02-16 10:54:34 +0100
committerUlf Hermann <ulf.hermann@qt.io>2023-03-03 12:02:00 +0100
commit05f56d7c78754855c643470ad4e8dfd35c96f927 (patch)
treefe23c5afec83efd75f06046bc0fdb7b7da465999 /src/qml/jsruntime/qv4runtime.cpp
parente625e39845ccecda871659a8ff39ac081f4aee82 (diff)
QML: Allow as-casting to value types
If the "Addressable" option to ValueTypeBehavior is set, you can use the "as" operator to cast a previously unknown type into either undefined or the given type. We can use this in qmlcachegen to generate efficient code for further operations on the same type. In the generated C++ it in fact only works for GetLookup because: a, We generally don't do SetLookup on value types, yet. b, We generally don't call methods on value types, yet. c, We cannot store a union of undefined and a sequence type, yet. However, getting properties of value types is the most important application of the new casts so this is well worth it. As a side effect we can also look up things in potentially undefined results of other operations now. For example list lookups. Task-number: QTBUG-94807 Change-Id: Ifdf34f1f3f67b7a0a8953b9ed0e947b74638a28c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4runtime.cpp')
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp36
1 files changed, 29 insertions, 7 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index aa4d5c875a..c7ee35b810 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -329,7 +329,7 @@ ReturnedValue Runtime::DeleteName::call(ExecutionEngine *engine, Function *funct
}
}
-QV4::ReturnedValue Runtime::Instanceof::call(ExecutionEngine *engine, const Value &lval, const Value &rval)
+static QV4::ReturnedValue doInstanceof(ExecutionEngine *engine, const Value &lval, const Value &rval)
{
// 11.8.6, 5: rval must be an Object
const Object *rhs = rval.as<Object>();
@@ -345,26 +345,48 @@ QV4::ReturnedValue Runtime::Instanceof::call(ExecutionEngine *engine, const Valu
Scope scope(engine);
ScopedValue hasInstance(scope, rhs->get(engine->symbol_hasInstance()));
if (hasInstance->isUndefined())
- return rhs->instanceOf(lval);
+ return Encode(rhs->instanceOf(lval));
+
FunctionObject *fHasInstance = hasInstance->as<FunctionObject>();
if (!fHasInstance)
return engine->throwTypeError();
- ScopedValue result(scope, fHasInstance->call(&rval, &lval, 1));
+ return Encode(fHasInstance->call(&rval, &lval, 1));
+}
+
+QV4::ReturnedValue Runtime::Instanceof::call(ExecutionEngine *engine, const Value &lval, const Value &rval)
+{
+ Scope scope(engine);
+ ScopedValue result(scope, doInstanceof(engine, lval, rval));
return scope.hasException() ? Encode::undefined() : Encode(result->toBoolean());
}
QV4::ReturnedValue Runtime::As::call(ExecutionEngine *engine, const Value &lval, const Value &rval)
{
Scope scope(engine);
- ScopedValue result(scope, Runtime::Instanceof::call(engine, lval, rval));
+ ScopedValue result(scope, doInstanceof(engine, lval, rval));
- if (scope.hasException())
+ if (scope.hasException()) {
+ // "foo instanceof valueType" must not throw an exception.
+ // So this can only be an object type.
engine->catchException();
- else if (result->toBoolean())
+ return Encode::null();
+ }
+
+ if (result->toBoolean())
return lval.asReturnedValue();
+ else if (result->isBoolean())
+ return Encode::null();
- return Encode::null();
+ // Try to convert the value type
+ if (Scoped<QQmlTypeWrapper> typeWrapper(scope, rval); typeWrapper) {
+ const QMetaType metaType = typeWrapper->d()->type().typeId();
+ const QVariant result = engine->toVariant(lval, metaType);
+ if (result.metaType() == metaType)
+ return engine->metaTypeToJS(metaType, result.constData());
+ }
+
+ return Encode::undefined();
}
QV4::ReturnedValue Runtime::In::call(ExecutionEngine *engine, const Value &left, const Value &right)