aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-05-20 14:09:08 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2021-05-26 14:46:39 +0200
commit0472a7a4326cf9ac1abdcbc0910c3b13f5c4fb5a (patch)
treea6d6ca7ecebcd733d11997f23a7ef2114b078457 /src/qml/compiler
parente2f247fafcd90c02e5db686c791ff4818be9cc50 (diff)
Evaluate type assertions in QML
Type assertions actually check whether the expression matches the type, and return null if it doesn't. [ChangeLog][QtQml] You can use TypeScript-like type assertions using "as" now. In contrast to TypeScript, QML's type assertions are enforced at runtime. If the type doesn't match, null is returned for object types. Also, type assertions can only cast to object types. There is no way to create a value type or primitive type reference. As value types and primitives cannot be polymorphic, this doesn't matter, though. There are other ways of converting those. Task-number: QTBUG-93662 Change-Id: I00fce3d4ea7a8c6b4631c580eaf6c113ac485813 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qv4codegen.cpp12
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
3 files changed, 15 insertions, 3 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index d13ef1bc86..f7c4e2c98f 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1536,6 +1536,7 @@ bool Codegen::visit(BinaryExpression *ast)
// intentional fall-through!
case QSOperator::In:
case QSOperator::InstanceOf:
+ case QSOperator::As:
case QSOperator::Equal:
case QSOperator::NotEqual:
case QSOperator::Ge:
@@ -1568,9 +1569,6 @@ bool Codegen::visit(BinaryExpression *ast)
break;
}
- case QSOperator::As:
- setExprResult(left);
- break;
} // switch
return false;
@@ -1734,6 +1732,14 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
bytecodeGenerator->addInstruction(binop);
break;
}
+ case QSOperator::As: {
+ Instruction::As as;
+ left = left.storeOnStack();
+ right.loadInAccumulator();
+ as.lhs = left.stackSlot();
+ bytecodeGenerator->addInstruction(as);
+ break;
+ }
case QSOperator::In: {
Instruction::CmpIn binop;
left = left.storeOnStack();
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index c791790cba..542e33870e 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -657,6 +657,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << dumpRegister(lhs, nFormals) << ", acc";
MOTH_END_INSTR(Sub)
+ MOTH_BEGIN_INSTR(As)
+ d << dumpRegister(lhs, nFormals) << ", acc";
+ MOTH_END_INSTR(Sub)
+
MOTH_BEGIN_INSTR(CmpIn)
d << dumpRegister(lhs, nFormals) << ", acc";
MOTH_END_INSTR(CmpIn)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 69e4eb26f3..7662f8461f 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -192,6 +192,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs)
#define INSTR_Mod(op) INSTRUCTION(op, Mod, 1, lhs)
#define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs)
+#define INSTR_As(op) INSTRUCTION(op, As, 1, lhs)
#define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result)
#define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count)
#define INSTR_ThrowOnNullOrUndefined(op) INSTRUCTION(op, ThrowOnNullOrUndefined, 0)
@@ -284,6 +285,7 @@ QT_BEGIN_NAMESPACE
F(Div) \
F(Mod) \
F(Sub) \
+ F(As) \
F(CallValue) \
F(CallWithReceiver) \
F(CallProperty) \