diff options
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext.cpp | 22 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport_p.h | 3 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.js | 7 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.qml | 15 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 8 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt | 2 |
7 files changed, 59 insertions, 16 deletions
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 8f87f24745..4226bf7972 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -90,23 +90,14 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, StringOrSymbol *n, bool QV4::ExecutionEngine *v4 = resource->engine(); QV4::Scope scope(v4); - // In V8 the JS global object would come _before_ the QML global object, - // so simulate that here. - bool hasProp; - QV4::ScopedValue result(scope, v4->globalObject->get(name, &hasProp)); - if (hasProp) { - if (hasProperty) - *hasProperty = hasProp; - return result->asReturnedValue(); - } - if (resource->d()->isNullWrapper) return Object::get(m, name, hasProperty); if (v4->callingQmlContext() != *resource->d()->context) return Object::get(m, name, hasProperty); - result = Object::get(m, name, &hasProp); + bool hasProp = false; + ScopedValue result(scope, Object::get(m, name, &hasProp)); if (hasProp) { if (hasProperty) *hasProperty = hasProp; @@ -224,6 +215,15 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, StringOrSymbol *n, bool context = context->parent; } + // Do a lookup in the global object here to avoid expressionContext->unresolvedNames becoming + // true if we access properties of the global object. + result = v4->globalObject->get(name, &hasProp); + if (hasProp) { + if (hasProperty) + *hasProperty = hasProp; + return result->asReturnedValue(); + } + expressionContext->unresolvedNames = true; return Encode::undefined(); diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index f85fecb5dd..962c92fdb0 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -735,7 +735,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt int *vmajor, int *vminor, QQmlType *type_return, QString *base, bool *typeRecursionDetected, QQmlType::RegistrationType registrationType, - QQmlImport::RecursionRestriction recursionRestriction) const + QQmlImport::RecursionRestriction recursionRestriction, + QList<QQmlError> *errors) const { if (majversion >= 0 && minversion >= 0) { QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion); @@ -818,8 +819,19 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt }; for (uint i = 0; i < sizeof(urlsToTry) / sizeof(urlsToTry[0]); ++i) { const QString url = urlsToTry[i]; - exists = !typeLoader->absoluteFilePath(QQmlFile::urlToLocalFileOrQrc(url)).isEmpty(); + const QString localPath = QQmlFile::urlToLocalFileOrQrc(url); + exists = !typeLoader->absoluteFilePath(localPath).isEmpty(); if (exists) { + // don't let function.qml confuse the use of "new Function(...)" for example. + if (!QQml_isFileCaseCorrect(localPath)) { + exists = false; + if (errors) { + QQmlError caseError; + caseError.setDescription(QLatin1String("File name case mismatch")); + errors->append(caseError); + } + break; + } qmlUrl = url; break; } @@ -906,7 +918,7 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS for (int i=0; i<imports.count(); ++i) { const QQmlImportInstance *import = imports.at(i); if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, base, - &typeRecursionDetected, registrationType, recursionRestriction)) { + &typeRecursionDetected, registrationType, recursionRestriction, errors)) { if (qmlCheckTypes()) { // check for type clashes for (int j = i+1; j<imports.count(); ++j) { diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index 2437979ef8..283bd40660 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -94,7 +94,8 @@ struct QQmlImportInstance int *vmajor, int *vminor, QQmlType* type_return, QString *base = nullptr, bool *typeRecursionDetected = nullptr, QQmlType::RegistrationType = QQmlType::AnyRegistrationType, - QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const; + QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion, + QList<QQmlError> *errors = nullptr) const; }; class QQmlImportNamespace diff --git a/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.js b/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.js new file mode 100644 index 0000000000..500f04bec7 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.js @@ -0,0 +1,7 @@ +.pragma library +var Shadowed = 2; +var global = (function(){return this})() + +// set Shadowed on the global object as well. This should be different from +// the variable above, as the library has it's on context +global.Shadowed = 1; diff --git a/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.qml b/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.qml new file mode 100644 index 0000000000..7cac09d342 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 +import "include_pragma_shadow.js" as Shadowed +import "include_pragma_shadow.js" as Other + +Item { + property bool result + + Component.onCompleted: { + result = false; + var global = (function(){return this})() + if (Shadowed.Shadowed === 2 && Other.Shadowed === 2 && global.Shadowed === 1) + result = true; + } +} + diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 0fa4c03dcb..5959ecc19f 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -6367,6 +6367,14 @@ void tst_qqmlecmascript::include() delete o; } + // Including file with ".pragma library", shadowing a global var + { + QQmlComponent component(&engine, testFileUrl("include_pragma_shadow.qml")); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); + QCOMPARE(o->property("result").toBool(), true); + } + // Remote - error { TestHTTPServer server; diff --git a/tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt b/tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt index 3813680562..4f3f758b7e 100644 --- a/tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt +++ b/tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt @@ -1,2 +1,2 @@ -3:1:Type IncorrectCaseType unavailable +3:1:IncorrectCaseType is not a type -1:-1:File name case mismatch |