aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h16
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp19
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h1
-rw-r--r--src/qml/compiler/qv4isel_p.cpp13
-rw-r--r--src/qml/compiler/qv4isel_p.h1
-rw-r--r--src/qml/jit/qv4isel_masm.cpp17
-rw-r--r--src/qml/jit/qv4isel_masm_p.h1
-rw-r--r--src/qml/jit/qv4regalloc.cpp1
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp22
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp8
-rw-r--r--tests/auto/qml/qqmlengine/data/TypeofQmlProperty.qml6
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp14
13 files changed, 119 insertions, 2 deletions
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 1eebcbbe7f..97aee80e91 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -102,6 +102,8 @@ QT_BEGIN_NAMESPACE
F(CallBuiltinDeleteMember, callBuiltinDeleteMember) \
F(CallBuiltinDeleteSubscript, callBuiltinDeleteSubscript) \
F(CallBuiltinDeleteName, callBuiltinDeleteName) \
+ F(CallBuiltinTypeofScopeObjectProperty, callBuiltinTypeofScopeObjectProperty) \
+ F(CallBuiltinTypeofContextObjectProperty, callBuiltinTypeofContextObjectProperty) \
F(CallBuiltinTypeofMember, callBuiltinTypeofMember) \
F(CallBuiltinTypeofSubscript, callBuiltinTypeofSubscript) \
F(CallBuiltinTypeofName, callBuiltinTypeofName) \
@@ -511,6 +513,18 @@ union Instr
int name;
Param result;
};
+ struct instr_callBuiltinTypeofScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ Param base;
+ Param result;
+ };
+ struct instr_callBuiltinTypeofContextObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ Param base;
+ Param result;
+ };
struct instr_callBuiltinTypeofMember {
MOTH_INSTR_HEADER
int member;
@@ -809,6 +823,8 @@ union Instr
instr_callBuiltinDeleteMember callBuiltinDeleteMember;
instr_callBuiltinDeleteSubscript callBuiltinDeleteSubscript;
instr_callBuiltinDeleteName callBuiltinDeleteName;
+ instr_callBuiltinTypeofScopeObjectProperty callBuiltinTypeofScopeObjectProperty;
+ instr_callBuiltinTypeofContextObjectProperty callBuiltinTypeofContextObjectProperty;
instr_callBuiltinTypeofMember callBuiltinTypeofMember;
instr_callBuiltinTypeofSubscript callBuiltinTypeofSubscript;
instr_callBuiltinTypeofName callBuiltinTypeofName;
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 0dae4d7696..afb36c5f14 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -1177,6 +1177,25 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
addInstruction(call);
}
+void InstructionSelection::callBuiltinTypeofQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::Expr *result)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::CallBuiltinTypeofScopeObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::CallBuiltinTypeofContextObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else {
+ Q_UNREACHABLE();
+ }
+}
+
void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
IR::Expr *result)
{
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 947461f98e..e2385aad6d 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -84,6 +84,7 @@ protected:
virtual void visitRet(IR::Ret *);
virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void callBuiltinTypeofQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::Expr *result);
virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result);
virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result);
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 9d172b1223..184cff43e6 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -282,8 +282,17 @@ void IRDecoder::callBuiltin(IR::Call *call, Expr *result)
return;
case IR::Name::builtin_typeof: {
- if (IR::Member *m = call->args->expr->asMember()) {
- callBuiltinTypeofMember(m->base, *m->name, result);
+ if (IR::Member *member = call->args->expr->asMember()) {
+#ifndef V4_BOOTSTRAP
+ Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
+ if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
+ callBuiltinTypeofQmlContextProperty(member->base,
+ IR::Member::MemberKind(member->kind),
+ member->property->coreIndex, result);
+ return;
+ }
+#endif
+ callBuiltinTypeofMember(member->base, *member->name, result);
return;
} else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
callBuiltinTypeofSubscript(ss->base, ss->index, result);
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 50ee955378..b78d323e7d 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -118,6 +118,7 @@ public: // visitor methods for StmtVisitor:
public: // to implement by subclasses:
virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::Expr *result) = 0;
virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result) = 0;
virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result) = 0;
virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result) = 0;
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 9696f59e7c..dad18c8cf2 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -399,6 +399,23 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
}
}
+void InstructionSelection::callBuiltinTypeofQmlContextProperty(IR::Expr *base,
+ IR::Member::MemberKind kind,
+ int propertyIndex, IR::Expr *result)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ generateFunctionCall(result, Runtime::typeofScopeObjectProperty, Assembler::EngineRegister,
+ Assembler::PointerToValue(base),
+ Assembler::TrustedImm32(propertyIndex));
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ generateFunctionCall(result, Runtime::typeofContextObjectProperty,
+ Assembler::EngineRegister, Assembler::PointerToValue(base),
+ Assembler::TrustedImm32(propertyIndex));
+ } else {
+ Q_UNREACHABLE();
+ }
+}
+
void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
IR::Expr *result)
{
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index 29749f7492..6e9b02b034 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -80,6 +80,7 @@ protected:
virtual QQmlRefPointer<QV4::CompiledData::CompilationUnit> backendCompileStep();
virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void callBuiltinTypeofQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::Expr *result);
virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result);
virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result);
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index e980f181c2..5e836f06f1 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -267,6 +267,7 @@ public:
protected: // IRDecoder
virtual void callBuiltinInvalid(IR::Name *, IR::ExprList *, IR::Expr *) {}
+ virtual void callBuiltinTypeofQmlContextProperty(IR::Expr *, IR::Member::MemberKind, int, IR::Expr *) {}
virtual void callBuiltinTypeofMember(IR::Expr *, const QString &, IR::Expr *) {}
virtual void callBuiltinTypeofSubscript(IR::Expr *, IR::Expr *, IR::Expr *) {}
virtual void callBuiltinTypeofName(const QString &, IR::Expr *) {}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 0d7a1851b8..0e90a3d021 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1146,6 +1146,28 @@ QV4::ReturnedValue Runtime::typeofName(ExecutionEngine *engine, int nameIndex)
return Runtime::typeofValue(engine, prop);
}
+#ifndef V4_BOOTSTRAP
+ReturnedValue Runtime::typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context,
+ int propertyIndex)
+{
+ Scope scope(engine);
+ ScopedValue prop(scope, getQmlScopeObjectProperty(engine, context, propertyIndex));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ return Runtime::typeofValue(engine, prop);
+}
+
+ReturnedValue Runtime::typeofContextObjectProperty(ExecutionEngine *engine, const Value &context,
+ int propertyIndex)
+{
+ Scope scope(engine);
+ ScopedValue prop(scope, getQmlContextObjectProperty(engine, context, propertyIndex));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ return Runtime::typeofValue(engine, prop);
+}
+#endif // V4_BOOTSTRAP
+
QV4::ReturnedValue Runtime::typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex)
{
Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 571abac21e..0d81edca1e 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -127,6 +127,8 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
// typeof
static ReturnedValue typeofValue(ExecutionEngine *engine, const Value &val);
static ReturnedValue typeofName(ExecutionEngine *engine, int nameIndex);
+ static ReturnedValue typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
+ static ReturnedValue typeofContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
static ReturnedValue typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex);
static ReturnedValue typeofElement(ExecutionEngine *engine, const Value &base, const Value &index);
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 68f996c4c7..024a72bde2 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -684,6 +684,14 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::deleteName(engine, instr.name));
MOTH_END_INSTR(CallBuiltinDeleteName)
+ MOTH_BEGIN_INSTR(CallBuiltinTypeofScopeObjectProperty)
+ STOREVALUE(instr.result, Runtime::typeofScopeObjectProperty(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(CallBuiltinTypeofMember)
+
+ MOTH_BEGIN_INSTR(CallBuiltinTypeofContextObjectProperty)
+ STOREVALUE(instr.result, Runtime::typeofContextObjectProperty(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(CallBuiltinTypeofMember)
+
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
STOREVALUE(instr.result, Runtime::typeofMember(engine, VALUE(instr.base), instr.member));
MOTH_END_INSTR(CallBuiltinTypeofMember)
diff --git a/tests/auto/qml/qqmlengine/data/TypeofQmlProperty.qml b/tests/auto/qml/qqmlengine/data/TypeofQmlProperty.qml
new file mode 100644
index 0000000000..2196543dc8
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/TypeofQmlProperty.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.5
+
+Item {
+ property var someProp: 1
+ Component.onCompleted: console.log("typeof someProp:", typeof(someProp));
+}
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index cb911d0115..486a0b4e87 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -75,6 +75,8 @@ private slots:
void urlInterceptor_data();
void urlInterceptor();
+ void qmlContextProperties();
+
public slots:
QObject *createAQObjectForOwnershipTest ()
{
@@ -778,6 +780,18 @@ void tst_qqmlengine::urlInterceptor()
QCOMPARE(o->property("absoluteUrl").toString(), expectedAbsoluteUrl);
}
+void tst_qqmlengine::qmlContextProperties()
+{
+ QQmlEngine e;
+
+ QQmlComponent c(&e, testFileUrl("TypeofQmlProperty.qml"));
+ QObject *o = c.create();
+ if (!o) {
+ qDebug() << c.errorString();
+ }
+ QVERIFY(o);
+}
+
QTEST_MAIN(tst_qqmlengine)
#include "tst_qqmlengine.moc"