From 564d58025e46c825ec763193767defd78f5e13a0 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Mon, 10 Oct 2011 12:11:21 +1000 Subject: Ensure that scarce resources work with var properties Now that we have a new property type which stores JavaScript handles, we need to ensure that scarce resources can be used with them. Task-number: QMLNG-18 Task-number: QTBUG-21843 Change-Id: I4a920ae39e7d33cf5e33362e5e0ee21c74cb35e3 Reviewed-by: Martin Jones --- doc/src/declarative/basictypes.qdoc | 13 + doc/src/declarative/javascriptblocks.qdoc | 172 ++------- .../scarceresources/avatarExample.cpp | 124 ++++++ .../scarceresources/avatarExample.h | 73 ++++ .../scarceresources/exampleFive.qml | 54 +++ .../scarceresources/exampleFour.js | 56 +++ .../scarceresources/exampleFour.qml | 56 +++ .../scarceresources/exampleOne.qml | 54 +++ .../scarceresources/exampleThree.js | 58 +++ .../scarceresources/exampleThree.qml | 49 +++ .../scarceresources/exampleTwo.qml | 51 +++ src/declarative/qml/qdeclarativevmemetaobject.cpp | 48 ++- src/declarative/qml/v8/qv8variantresource_p.h | 81 ++++ src/declarative/qml/v8/qv8variantwrapper.cpp | 30 +- src/declarative/qml/v8/v8.pri | 1 + .../data/ScarceResourceSignalComponentVar.qml | 9 + .../data/ScarceResourceSignalComponentVariant.qml | 9 + .../data/ScarceResourceVarComponent.qml | 13 + .../data/scarceResourceCopy.var.qml | 14 + .../data/scarceResourceCopy.variant.qml | 15 + .../data/scarceResourceCopyFromJs.var.qml | 14 + .../data/scarceResourceCopyFromJs.variant.qml | 15 + .../data/scarceResourceCopyImport.var.js | 25 ++ .../data/scarceResourceCopyImport.var.qml | 18 + .../data/scarceResourceCopyImport.variant.js | 25 ++ .../data/scarceResourceCopyImport.variant.qml | 18 + .../data/scarceResourceCopyImportDifferent.var.js | 19 + .../data/scarceResourceCopyImportDifferent.var.qml | 22 ++ .../data/scarceResourceCopyImportFail.var.js | 19 + .../data/scarceResourceCopyImportFail.var.qml | 7 + .../data/scarceResourceCopyImportFail.variant.js | 19 + .../data/scarceResourceCopyImportFail.variant.qml | 8 + .../data/scarceResourceCopyImportNoBinding.var.js | 15 + .../data/scarceResourceCopyImportNoBinding.var.qml | 12 + .../scarceResourceCopyImportNoBinding.variant.js | 15 + .../scarceResourceCopyImportNoBinding.variant.qml | 12 + .../data/scarceResourceCopyNoBinding.var.qml | 14 + .../data/scarceResourceCopyNoBinding.variant.qml | 14 + .../data/scarceResourceDestroyedCopy.var.qml | 13 + .../data/scarceResourceDestroyedCopy.variant.qml | 14 + .../data/scarceResourceFunction.var.qml | 23 ++ .../data/scarceResourceFunction.variant.qml | 23 ++ .../data/scarceResourceFunctionFail.var.qml | 23 ++ .../data/scarceResourceFunctionFail.variant.qml | 23 ++ ...scarceResourceMultipleDifferentNoBinding.var.js | 14 + ...carceResourceMultipleDifferentNoBinding.var.qml | 14 + .../scarceResourceMultipleSameNoBinding.var.js | 15 + .../scarceResourceMultipleSameNoBinding.var.qml | 14 + .../scarceResourceMultipleSameWithBinding.var.qml | 12 + .../data/scarceResourceObjectGc.var.qml | 30 ++ .../data/scarceResourceSignal.var.qml | 29 ++ .../data/scarceResourceSignal.variant.qml | 29 ++ .../data/scarceResourceTest.var.js | 48 +++ .../data/scarceResourceTest.var.qml | 14 + .../data/scarceResourceTest.variant.js | 48 +++ .../data/scarceResourceTest.variant.qml | 14 + .../data/scarceResourceTestMultiple.var.qml | 16 + .../data/scarceResourceTestMultiple.variant.qml | 15 + .../data/scarceResourceTestPreserve.var.qml | 15 + .../data/scarceResourceTestPreserve.variant.qml | 15 + .../ScarceResourceSignalComponent.qml | 9 - .../data/scarceresources/scarceResourceCopy.qml | 15 - .../scarceresources/scarceResourceCopyFromJs.qml | 15 - .../scarceresources/scarceResourceCopyImport.js | 24 -- .../scarceresources/scarceResourceCopyImport.qml | 18 - .../scarceResourceCopyImportFail.js | 18 - .../scarceResourceCopyImportFail.qml | 8 - .../scarceResourceCopyImportNoBinding.js | 14 - .../scarceResourceCopyImportNoBinding.qml | 12 - .../scarceResourceCopyNoBinding.qml | 14 - .../scarceResourceDestroyedCopy.qml | 14 - .../scarceresources/scarceResourceFunction.qml | 23 -- .../scarceresources/scarceResourceFunctionFail.qml | 24 -- .../data/scarceresources/scarceResourceSignal.qml | 29 -- .../data/scarceresources/scarceResourceTest.js | 48 --- .../data/scarceresources/scarceResourceTest.qml | 14 - .../scarceresources/scarceResourceTestMultiple.qml | 16 - .../scarceresources/scarceResourceTestPreserve.qml | 15 - .../tst_qdeclarativeecmascript.cpp | 420 ++++++++++++++++----- 79 files changed, 1921 insertions(+), 561 deletions(-) create mode 100644 doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp create mode 100644 doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.h create mode 100644 doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFive.qml create mode 100644 doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.js create mode 100644 doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.qml create mode 100644 doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleOne.qml create mode 100644 doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.js create mode 100644 doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.qml create mode 100644 doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleTwo.qml create mode 100644 src/declarative/qml/v8/qv8variantresource_p.h create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceSignalComponentVar.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceSignalComponentVariant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceVarComponent.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopy.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopy.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyFromJs.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyFromJs.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.var.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.variant.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportDifferent.var.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportDifferent.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.var.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.variant.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.var.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.variant.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyNoBinding.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyNoBinding.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceDestroyedCopy.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceDestroyedCopy.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunction.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunction.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunctionFail.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunctionFail.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleDifferentNoBinding.var.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleDifferentNoBinding.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameNoBinding.var.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameNoBinding.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameWithBinding.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceObjectGc.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceSignal.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceSignal.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.var.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.variant.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestMultiple.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestMultiple.variant.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestPreserve.var.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestPreserve.variant.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/ScarceResourceSignalComponent.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopy.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyFromJs.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImport.js delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImport.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportFail.js delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportFail.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportNoBinding.js delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportNoBinding.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyNoBinding.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceDestroyedCopy.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunction.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunctionFail.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceSignal.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTest.js delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTest.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTestMultiple.qml delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTestPreserve.qml diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc index 98eea78a07..a908e73ca8 100644 --- a/doc/src/declarative/basictypes.qdoc +++ b/doc/src/declarative/basictypes.qdoc @@ -479,6 +479,19 @@ } \endqml + A \c var type property can also hold an image or pixmap. + A \c var which contains a QPixmap or QImage is known as a + "scarce resource" and the declarative engine will attempt to + automatically release such resources after evaluation of any JavaScript + expression which requires one to be copied has completed. + + Clients may explicitly release such a scarce resource by calling the + "destroy" method on the \c var property from within JavaScript. They + may also explicitly preserve the scarce resource by calling the + "preserve" method on the \c var property from within JavaScript. + For more information regarding the usage of a scarce resource, please + see \l{Scarce Resources in JavaScript}. + \sa {QML Basic Types} */ diff --git a/doc/src/declarative/javascriptblocks.qdoc b/doc/src/declarative/javascriptblocks.qdoc index a9e383c258..34a1986db6 100644 --- a/doc/src/declarative/javascriptblocks.qdoc +++ b/doc/src/declarative/javascriptblocks.qdoc @@ -362,7 +362,7 @@ Item { \section1 Scarce Resources in JavaScript -As described in the documentation for \l{QML Basic Types}, a \c variant type +As described in the documentation for \l{QML Basic Types}, a \c var type property may hold a "scarce resource" (image or pixmap). There are several important semantics of scarce resources which should be noted: @@ -379,30 +379,12 @@ may be necessary for clients to manually preserve or destroy resources for themselves. For the following examples, imagine that we have defined the following class: -\code -class AvatarExample : public QObject -{ - Q_OBJECT - Q_PROPERTY(QPixmap avatar READ avatar WRITE setAvatar NOTIFY avatarChanged) -public: - AvatarExample(QObject *parent = 0) : QObject(parent), m_value(100, 100) { m_value.fill(Qt::blue); } - ~AvatarExample() {} - - QPixmap avatar() const { return m_value; } - void setAvatar(QPixmap v) { m_value = v; emit avatarChanged(); } - -signals: - void avatarChanged(); - -private: - QPixmap m_value; -}; -\endcode + +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.h 0 and that we have registered it with the QML type-system as follows: -\code -qmlRegisterType("Qt.example", 1, 0, "AvatarExample"); -\endcode + +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp 0 The AvatarExample class has a property which is a pixmap. When the property is accessed in JavaScript scope, a copy of the resource will be created and @@ -414,141 +396,59 @@ unless the client explicitly preserves it. \section2 Example One: Automatic Release -In this example, the resource will be automatically +In the following example, the scarce resource will be automatically released +after the binding evaluation is complete. + +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleOne.qml 0 + +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp 1 + +\section2 Example Two: Automatic Release Prevented By Reference + +In this example, the resource will not be automatically released after the binding expression evaluation is -complete. +complete, because there is a property var referencing the +scarce resource. -\qml -// exampleOne.qml -import QtQuick 1.0 -import Qt.example 1.0 - -QtObject { - property AvatarExample a; - a: AvatarExample { id: example } - property variant avatar: example.avatar -} -\endqml +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleTwo.qml 0 -\code -QDeclarativeComponent component(&engine, "exampleOne.qml"); -QObject *object = component.create(); -// The scarce resource will have been released automatically -// after the binding expression was evaluated. -// Since the scarce resource was not released explicitly prior -// to the binding expression being evaluated, we get the -// expected result: -//object->property("scarceResourceCopy").isValid() == true -delete object; -\endcode +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp 2 -\section2 Example Two: Explicit Preservation +\section2 Example Three: Explicit Preservation In this example, the resource must be explicitly preserved in order to prevent the declarative engine from automatically releasing the resource after evaluation of the imported script. -\code -// exampleTwo.js -.import Qt.example 1.0 as QtExample - -var component = Qt.createComponent("exampleOne.qml"); -var exampleOneElement = component.createObject(null); -var avatarExample = exampleOneElement.a; -var retn = avatarExample.avatar; - -// without the following call, the scarce resource held -// by retn would be automatically released by the engine -// after the import statement in exampleTwo.qml, prior -// to the variable assignment. -retn.preserve(); - -function importAvatar() { - return retn; -} -\endcode +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.js 0 -\qml -// exampleTwo.qml -import QtQuick 1.0 -import Qt.example 1.0 -import "exampleTwo.js" as ExampleTwoJs +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.qml 0 -QtObject { - property variant avatar: ExampleTwoJs.importAvatar() -} -\endqml +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp 3 -\code -QDeclarativeComponent component(&engine, "exampleTwo.qml"); -QObject *object = component.create(); -// The resource was preserved explicitly during evaluation of the -// JavaScript expression. Thus, during property assignment, the -// scarce resource was still valid, and so we get the expected result: -//object->property("avatar").isValid() == true -// The scarce resource may not have been cleaned up by the JS GC yet; -// it will continue to consume system resources until the JS GC runs. -delete object; -\endcode - -\section2 Example Three: Explicit Destruction +\section2 Example Four: Explicit Destruction In the following example, we release (via destroy()) an explicitly preserved scarce resource variant. This example shows how a client may free system resources by releasing the scarce resource held in a JavaScript object, if required, during evaluation of a JavaScript expression. -\code -// exampleThree.js -.import Qt.example 1.0 as QtExample +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.js 0 -var component = Qt.createComponent("exampleOne.qml"); -var exampleOneElement = component.createObject(null); -var avatarExample = exampleOneElement.a; -var retn = avatarExample.avatar; -retn.preserve(); +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.qml 0 -function importAvatar() { - return retn; -} +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp 4 -function releaseAvatar() { - retn.destroy(); -} -\endcode +\section2 Example Five: Explicit Destruction And JavaScript References -\qml -// exampleThree.qml -import QtQuick 1.0 -import Qt.example 1.0 -import "exampleThree.js" as ExampleThreeJs - -QtObject { - property variant avatarOne - property variant avatarTwo - - Component.onCompleted: { - avatarOne = ExampleThreeJs.importAvatar(); // valid at this stage - ExampleThreeJs.releaseAvatar(); // explicit release - avatarTwo = ExampleThreeJs.importAvatar(); // invalid at this stage - } -} -\endqml +One thing to be aware of when using "var" type properties is that they +hold references to JavaScript objects. As such, if multiple references +to one scarce resource is held, and the client calls destroy() on one +of those references (to explicitly release the scarce resource), all of +the references will be affected. -\code -QDeclarativeComponent component(&engine, "exampleThree.qml"); -QObject *object = component.create(); -// The scarce resource was explicitly preserved by the client during -// the evaluation of the imported script, and so the scarce resource -// remains valid until the explicit call to releaseAvatar(). As such, -// we get the expected results: -//object->property("avatarOne").isValid() == true -//object->property("avatarTwo").isValid() == false -// Because the scarce resource was released explicitly, it will no longer -// be consuming any system resources (beyond what a normal JS Object would; -// that small overhead will exist until the JS GC runs, as per any other -// JavaScript object). -delete object; -\endcode +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFive.qml 0 + +\snippet doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp 5 */ diff --git a/doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp b/doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp new file mode 100644 index 0000000000..eb521e1e7e --- /dev/null +++ b/doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "avatarExample.h" +#include +#include + +void registerTypes() +{ +//![0] + qmlRegisterType("Qt.example", 1, 0, "AvatarExample"); +//![0] +} + +void expectOne() +{ +//![1] +QDeclarativeComponent component(&engine, "exampleOne.qml"); +QObject *object = component.create(); +// The scarce resource will have been released automatically +// by this point, after the binding expression was evaluated. +delete object; +//![1] +} + +void expectTwo() +{ +//![2] +QDeclarativeComponent component(&engine, "exampleTwo.qml"); +QObject *object = component.create(); +// The scarce resource will not have been released automatically +// after the binding expression was evaluated. +// Since the scarce resource was not released explicitly prior +// to the binding expression being evaluated, we get: +bool expectedResult = (object->property("avatar").isValid() == true); +delete object; +//![2] +} + +void expectThree() +{ +//![3] +QDeclarativeComponent component(&engine, "exampleThree.qml"); +QObject *object = component.create(); +// The resource was preserved explicitly during evaluation of the +// JavaScript expression. Thus, during property assignment, the +// scarce resource was still valid, and so we get: +bool expectedResult = (object->property("avatar").isValid() == true); +// The scarce resource will not be released until all references to +// the resource are released, and the JavaScript garbage collector runs. +delete object; +//![3] +} + +void expectFour() +{ +//![4] +QDeclarativeComponent component(&engine, "exampleFour.qml"); +QObject *object = component.create(); +// The scarce resource was explicitly preserved by the client during +// the importAvatar() function, and so the scarce resource +// remains valid until the explicit call to releaseAvatar(). As such, +// we get the expected results: +bool expectedResultOne = (object->property("avatarOne").isValid() == true); +bool expectedResultTwo = (object->property("avatarTwo").isValid() == false); +// Because the scarce resource referenced by avatarTwo was released explicitly, +// it will no longer be consuming any system resources (beyond what a normal +// JS Object would; that small overhead will exist until the JS GC runs, as per +// any other JavaScript object). +delete object; +//![4] +} + +void expectFive() +{ +//![5] +QDeclarativeComponent component(&engine, "exampleFive.qml"); +QObject *object = component.create(); +// We have the expected results: +bool expectedResultOne = (object->property("avatarOne").isValid() == false); +bool expectedResultTwo = (object->property("avatarTwo").isValid() == false); +// Because although only avatarTwo was explicitly released, +// avatarOne and avatarTwo were referencing the same +// scarce resource. +delete object; +//![5] +} diff --git a/doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.h b/doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.h new file mode 100644 index 0000000000..17cef5e5cd --- /dev/null +++ b/doc/src/snippets/declarative/integrating-javascript/scarceresources/avatarExample.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef AVATAREXAMPLE_P_H +#define AVATAREXAMPLE_P_H + +#include +#include + +//![0] +// avatarExample.h +class AvatarExample : public QObject +{ + Q_OBJECT + Q_PROPERTY(QPixmap avatar READ avatar WRITE setAvatar NOTIFY avatarChanged) +public: + AvatarExample(QObject *parent = 0) + : QObject(parent), m_value(100, 100) + { + m_value.fill(Qt::blue); + } + + ~AvatarExample() {} + + QPixmap avatar() const { return m_value; } + void setAvatar(QPixmap v) { m_value = v; emit avatarChanged(); } + +signals: + void avatarChanged(); + +private: + QPixmap m_value; +}; +//![0] + +#endif diff --git a/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFive.qml b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFive.qml new file mode 100644 index 0000000000..33326b744d --- /dev/null +++ b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFive.qml @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +// exampleFive.qml +import QtQuick 2.0 +import Qt.example 1.0 +import "exampleFour.js" as ExampleFourJs // use factory from example four + +QtObject { + property var avatarOne: ExampleFourJs.importAvatar() + property var avatarTwo: avatarOne + + Component.onCompleted: { + ExampleFourJs.releaseAvatar(avatarTwo); + } +} +//![0] \ No newline at end of file diff --git a/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.js b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.js new file mode 100644 index 0000000000..476e03fdf8 --- /dev/null +++ b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.js @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +// exampleFour.js +.import Qt.example 1.0 as QtExample + +function importAvatar() { + var component = Qt.createComponent("exampleTwo.qml"); + var exampleOneElement = component.createObject(null); + var avatarExample = exampleOneElement.a; + var retn = avatarExample.avatar; + retn.preserve(); + return retn; +} + +function releaseAvatar(avatar) { + avatar.destroy(); +} +//![0] \ No newline at end of file diff --git a/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.qml b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.qml new file mode 100644 index 0000000000..e423771a20 --- /dev/null +++ b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleFour.qml @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +// exampleFour.qml +import QtQuick 2.0 +import Qt.example 1.0 +import "exampleFour.js" as ExampleFourJs + +QtObject { + property var avatarOne + property var avatarTwo + + Component.onCompleted: { + avatarOne = ExampleFourJs.importAvatar(); + avatarTwo = ExampleFourJs.importAvatar(); + ExampleFourJs.releaseAvatar(avatarTwo); + } +} +//![0] \ No newline at end of file diff --git a/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleOne.qml b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleOne.qml new file mode 100644 index 0000000000..c8579b7c6c --- /dev/null +++ b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleOne.qml @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +// exampleOne.qml +import QtQuick 1.0 +import Qt.example 1.0 + +QtObject { + property AvatarExample a; + a: AvatarExample { id: example } + property var avatarWidth: example.avatar,100 + // Here, we use "example.avatar,100" purely for illustration. + // The value of `avatarWidth' will be 100 after evaluation. + // E.g., you could imagine some js function which takes + // an avatar, and returns the width of the avatar. +} +//![0] \ No newline at end of file diff --git a/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.js b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.js new file mode 100644 index 0000000000..4fefb1e3f7 --- /dev/null +++ b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.js @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +// exampleThree.js +.import Qt.example 1.0 as QtExample + +var component = Qt.createComponent("exampleTwo.qml"); +var exampleOneElement = component.createObject(null); +var avatarExample = exampleOneElement.a; +var retn = avatarExample.avatar; + +// without the following call, the scarce resource held +// by retn would be automatically released by the engine +// after the import statement in exampleTwo.qml, prior +// to the variable assignment. +retn.preserve(); + +function importAvatar() { + return retn; +} +//![0] \ No newline at end of file diff --git a/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.qml b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.qml new file mode 100644 index 0000000000..58382902c8 --- /dev/null +++ b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleThree.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +// exampleThree.qml +import QtQuick 1.0 +import Qt.example 1.0 +import "exampleThree.js" as ExampleThreeJs + +QtObject { + property var avatar: ExampleThreeJs.importAvatar() +} +//![0] \ No newline at end of file diff --git a/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleTwo.qml b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleTwo.qml new file mode 100644 index 0000000000..610a75b97f --- /dev/null +++ b/doc/src/snippets/declarative/integrating-javascript/scarceresources/exampleTwo.qml @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +// exampleTwo.qml +import QtQuick 1.0 +import Qt.example 1.0 + +QtObject { + property AvatarExample a; + a: AvatarExample { id: example } + property var avatar: example.avatar + // Now `avatar' contains a reference to the scarce resource. +} +//![0] \ No newline at end of file diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index 229a93b961..0ff6ad581c 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -50,6 +50,8 @@ #include "qdeclarativebinding_p.h" #include "qdeclarativepropertyvalueinterceptor_p.h" +#include + Q_DECLARE_METATYPE(QJSValue); QT_BEGIN_NAMESPACE @@ -819,8 +821,28 @@ QVariant QDeclarativeVMEMetaObject::readPropertyAsVariant(int id) void QDeclarativeVMEMetaObject::writeVarProperty(int id, v8::Handle value) { Q_ASSERT(id >= firstVarPropertyIndex); - ensureVarPropertiesAllocated(); + + // Importantly, if the current value is a scarce resource, we need to ensure that it + // gets automatically released by the engine if no other references to it exist. + v8::Local oldv = varProperties->Get(id - firstVarPropertyIndex); + if (oldv->IsObject()) { + QV8VariantResource *r = v8_resource_cast(v8::Handle::Cast(oldv)); + if (r) { + r->removeVmePropertyReference(); + } + } + + // And, if the new value is a scarce resource, we need to ensure that it does not get + // automatically released by the engine until no other references to it exist. + if (value->IsObject()) { + QV8VariantResource *r = v8_resource_cast(v8::Handle::Cast(value)); + if (r) { + r->addVmePropertyReference(); + } + } + + // Write the value and emit change signal as appropriate. varProperties->Set(id - firstVarPropertyIndex, value); activate(object, methodOffset + id, 0); } @@ -829,8 +851,30 @@ void QDeclarativeVMEMetaObject::writeProperty(int id, const QVariant &value) { if (id >= firstVarPropertyIndex) { ensureVarPropertiesAllocated(); + + // Importantly, if the current value is a scarce resource, we need to ensure that it + // gets automatically released by the engine if no other references to it exist. + v8::Local oldv = varProperties->Get(id - firstVarPropertyIndex); + if (oldv->IsObject()) { + QV8VariantResource *r = v8_resource_cast(v8::Handle::Cast(oldv)); + if (r) { + r->removeVmePropertyReference(); + } + } + + // And, if the new value is a scarce resource, we need to ensure that it does not get + // automatically released by the engine until no other references to it exist. + v8::Handle newv = QDeclarativeEnginePrivate::get(ctxt->engine)->v8engine()->fromVariant(value); + if (newv->IsObject()) { + QV8VariantResource *r = v8_resource_cast(v8::Handle::Cast(newv)); + if (r) { + r->addVmePropertyReference(); + } + } + + // Write the value and emit change signal as appropriate. QVariant currentValue = readPropertyAsVariant(id); - varProperties->Set(id - firstVarPropertyIndex, QDeclarativeEnginePrivate::get(ctxt->engine)->v8engine()->fromVariant(value)); + varProperties->Set(id - firstVarPropertyIndex, newv); if ((currentValue.userType() != value.userType() || currentValue != value)) activate(object, methodOffset + id, 0); } else { diff --git a/src/declarative/qml/v8/qv8variantresource_p.h b/src/declarative/qml/v8/qv8variantresource_p.h new file mode 100644 index 0000000000..d1a5f92696 --- /dev/null +++ b/src/declarative/qml/v8/qv8variantresource_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QV8VARIANTRESOURCE_P_H +#define QV8VARIANTRESOURCE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QV8VariantResource : public QV8ObjectResource, + public QDeclarativeEnginePrivate::ScarceResourceData +{ + V8_RESOURCE_TYPE(VariantType) + +public: + QV8VariantResource(QV8Engine *engine, const QVariant &data); + + void addVmePropertyReference(); + void removeVmePropertyReference(); + + bool m_isScarceResource; + int m_vmePropertyReferenceCount; +}; + +QT_END_NAMESPACE + +#endif // QV8VARIANTRESOURCE_P_H + diff --git a/src/declarative/qml/v8/qv8variantwrapper.cpp b/src/declarative/qml/v8/qv8variantwrapper.cpp index 671e4d33c3..28bcccbaab 100644 --- a/src/declarative/qml/v8/qv8variantwrapper.cpp +++ b/src/declarative/qml/v8/qv8variantwrapper.cpp @@ -40,22 +40,35 @@ ****************************************************************************/ #include "qv8variantwrapper_p.h" +#include "qv8variantresource_p.h" #include "qv8engine_p.h" #include QT_BEGIN_NAMESPACE -class QV8VariantResource : public QV8ObjectResource, - public QDeclarativeEnginePrivate::ScarceResourceData +QV8VariantResource::QV8VariantResource(QV8Engine *engine, const QVariant &data) +: QV8ObjectResource(engine), QDeclarativeEnginePrivate::ScarceResourceData(data), m_isScarceResource(false), m_vmePropertyReferenceCount(0) { - V8_RESOURCE_TYPE(VariantType); -public: - QV8VariantResource(QV8Engine *engine, const QVariant &data); -}; +} -QV8VariantResource::QV8VariantResource(QV8Engine *engine, const QVariant &data) -: QV8ObjectResource(engine), QDeclarativeEnginePrivate::ScarceResourceData(data) +void QV8VariantResource::addVmePropertyReference() +{ + if (m_isScarceResource && ++m_vmePropertyReferenceCount == 1) { + // remove from the ep->scarceResources list + // since it is now no longer eligible to be + // released automatically by the engine. + node.remove(); + } +} + +void QV8VariantResource::removeVmePropertyReference() { + if (m_isScarceResource && --m_vmePropertyReferenceCount == 0) { + // and add to the ep->scarceResources list + // since it is now eligible to be released + // automatically by the engine. + QDeclarativeEnginePrivate::get(engine->engine())->scarceResources.insert(this); + } } QV8VariantWrapper::QV8VariantWrapper() @@ -133,6 +146,7 @@ v8::Local QV8VariantWrapper::newVariant(const QVariant &value) QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_engine->engine()); Q_ASSERT(ep->scarceResourcesRefCount); rv = m_scarceConstructor->NewInstance(); + r->m_isScarceResource = true; ep->scarceResources.insert(r); } else { rv = m_constructor->NewInstance(); diff --git a/src/declarative/qml/v8/v8.pri b/src/declarative/qml/v8/v8.pri index 924602ec39..e3488cd1e5 100644 --- a/src/declarative/qml/v8/v8.pri +++ b/src/declarative/qml/v8/v8.pri @@ -16,6 +16,7 @@ HEADERS += \ $$PWD/qv8typewrapper_p.h \ $$PWD/qv8listwrapper_p.h \ $$PWD/qv8variantwrapper_p.h \ + $$PWD/qv8variantresource_p.h \ $$PWD/qv8valuetypewrapper_p.h \ $$PWD/qv8include_p.h \ $$PWD/qv8worker_p.h \ diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceSignalComponentVar.qml b/tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceSignalComponentVar.qml new file mode 100644 index 0000000000..d56bd41a99 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceSignalComponentVar.qml @@ -0,0 +1,9 @@ +import QtQuick 2.0 + +QtObject { + property var scarceResourceCopy + property int width: 5 + signal testSignal + signal testSignal2 +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceSignalComponentVariant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceSignalComponentVariant.qml new file mode 100644 index 0000000000..e10fcfe36a --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceSignalComponentVariant.qml @@ -0,0 +1,9 @@ +import QtQuick 2.0 + +QtObject { + property variant scarceResourceCopy + property int width: 5 + signal testSignal + signal testSignal2 +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceVarComponent.qml b/tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceVarComponent.qml new file mode 100644 index 0000000000..2cf6b4223b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/ScarceResourceVarComponent.qml @@ -0,0 +1,13 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: first + property var vp: Item { + id: second + property MyScarceResourceObject srp; + srp: MyScarceResourceObject { id: scarceResourceProvider } + property var sr: scarceResourceProvider.scarceResource + property var canary: 5 + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopy.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopy.var.qml new file mode 100644 index 0000000000..805655fc17 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopy.var.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// Here we import a scarce resource directly. +// The instance has a property which is a copy +// of the scarce resource, so it should not be +// detached (but we should automatically release +// the resource from our engine internal list). + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property var scarceResourceCopy: scarceResourceProvider.scarceResource +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopy.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopy.variant.qml new file mode 100644 index 0000000000..ee5b05b28a --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopy.variant.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// Here we import a scarce resource directly. +// The instance has a property which is a copy +// of the scarce resource, so it should not be +// detached (but we should automatically release +// the resource from our engine internal list). + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property variant scarceResourceCopy: scarceResourceProvider.scarceResource +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyFromJs.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyFromJs.var.qml new file mode 100644 index 0000000000..09868e5e7c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyFromJs.var.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceTest.var.js" as ScarceResourceProviderJs + +// Here we import a scarce resource directly, from JS module. +// It is not preserved or released manually, so it should be +// automatically released once evaluation of the binding +// is complete. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property var scarceResourceCopy: ScarceResourceProviderJs.importScarceResource(scarceResourceProvider) +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyFromJs.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyFromJs.variant.qml new file mode 100644 index 0000000000..a1ebeb4073 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyFromJs.variant.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceTest.variant.js" as ScarceResourceProviderJs + +// Here we import a scarce resource directly, from JS module. +// It is not preserved or released manually, so it should be +// automatically released once evaluation of the binding +// is complete. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property variant scarceResourceCopy: ScarceResourceProviderJs.importScarceResource(scarceResourceProvider) +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.var.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.var.js new file mode 100644 index 0000000000..468a6b4f2e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.var.js @@ -0,0 +1,25 @@ +.import Qt.test 1.0 as JsQtTest + +// In this case, the "retn" variable will be evaluated during import. +// Since the "importScarceResource()" function depends on this variable, +// we must explicitly preserve the "retn" variable or the scarce +// resource would automatically be released after import completes +// but before the binding is evaluated. + +var component = Qt.createComponent("scarceResourceCopy.var.qml"); +var scarceResourceElement = component.createObject(null); +var scarceResourceProvider = scarceResourceElement.a; +var retn = scarceResourceProvider.scarceResource; +retn.preserve(); // must preserve manually or it will be released! + +function importScarceResource() { + // if called prior to calling destroyScarceResource(), + // this function should return the preserved scarce resource. + // otherwise, it should return an invalid variant. + return retn; +} + +function destroyScarceResource() { + retn.destroy(); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.var.qml new file mode 100644 index 0000000000..9321481f45 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.var.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceCopyImport.var.js" as ScarceResourceCopyImportJs + +QtObject { + // this binding is evaluated once, prior to the resource being released + property var scarceResourceImportedCopy: ScarceResourceCopyImportJs.importScarceResource() + + property bool arePropertiesEqual + property var scarceResourceAssignedCopyOne; + property var scarceResourceAssignedCopyTwo; + Component.onCompleted: { + scarceResourceAssignedCopyOne = ScarceResourceCopyImportJs.importScarceResource(); + arePropertiesEqual = (scarceResourceAssignedCopyOne == scarceResourceImportedCopy); + ScarceResourceCopyImportJs.destroyScarceResource(); // makes all properties invalid. + scarceResourceAssignedCopyTwo = ScarceResourceCopyImportJs.importScarceResource(); + } +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.variant.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.variant.js new file mode 100644 index 0000000000..9aeb507487 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.variant.js @@ -0,0 +1,25 @@ +.import Qt.test 1.0 as JsQtTest + +// In this case, the "retn" variable will be evaluated during import. +// Since the "importScarceResource()" function depends on this variable, +// we must explicitly preserve the "retn" variable or the scarce +// resource would automatically be released after import completes +// but before the binding is evaluated. + +var component = Qt.createComponent("scarceResourceCopy.variant.qml"); +var scarceResourceElement = component.createObject(null); +var scarceResourceProvider = scarceResourceElement.a; +var retn = scarceResourceProvider.scarceResource; +retn.preserve(); // must preserve manually or it will be released! + +function importScarceResource() { + // if called prior to calling destroyScarceResource(), + // this function should return the preserved scarce resource. + // otherwise, it should return an invalid variant. + return retn; +} + +function destroyScarceResource() { + retn.destroy(); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.variant.qml new file mode 100644 index 0000000000..e8b53979dd --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImport.variant.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceCopyImport.variant.js" as ScarceResourceCopyImportJs + +QtObject { + // this binding is evaluated once, prior to the resource being released + property variant scarceResourceImportedCopy: ScarceResourceCopyImportJs.importScarceResource() + + // this code is evaluated on completion, and so copy one should be valid, copy two invalid. + property variant scarceResourceAssignedCopyOne; + property variant scarceResourceAssignedCopyTwo; + Component.onCompleted: { + scarceResourceAssignedCopyOne = ScarceResourceCopyImportJs.importScarceResource(); + ScarceResourceCopyImportJs.destroyScarceResource(); + scarceResourceAssignedCopyTwo = ScarceResourceCopyImportJs.importScarceResource(); + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportDifferent.var.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportDifferent.var.js new file mode 100644 index 0000000000..000eeddb34 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportDifferent.var.js @@ -0,0 +1,19 @@ +.import Qt.test 1.0 as JsQtTest + +// In this case, we create the returned scarce resource each call, +// so the object will be different every time it is returned. + +var mostRecent + +function importScarceResource() { + var component = Qt.createComponent("scarceResourceCopy.var.qml"); + var scarceResourceElement = component.createObject(null); + var scarceResourceProvider = scarceResourceElement.a; + var retn = scarceResourceProvider.scarceResource; + mostRecent = retn; + return retn; +} + +function destroyScarceResource() { + mostRecent.destroy(); +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportDifferent.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportDifferent.var.qml new file mode 100644 index 0000000000..082d132c24 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportDifferent.var.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceCopyImportDifferent.var.js" as ScarceResourceCopyImportJs + +// in this case, the ScarceResourceCopyImportJs returns a _new_, different +// scarce resource each time. Invalidating one will not invalidate the others. + +QtObject { + // this binding is evaluated once, prior to the resource being released + property var scarceResourceImportedCopy: ScarceResourceCopyImportJs.importScarceResource() + + // the following properties are assigned on component completion. + property bool arePropertiesEqual + property var scarceResourceAssignedCopyOne; + property var scarceResourceAssignedCopyTwo; + Component.onCompleted: { + scarceResourceAssignedCopyOne = ScarceResourceCopyImportJs.importScarceResource(); + arePropertiesEqual = (scarceResourceAssignedCopyOne != scarceResourceImportedCopy); // they're not the same object. + ScarceResourceCopyImportJs.destroyScarceResource(); // makes the MOST RECENT resource invalid (ie, assignedCopyOne). + scarceResourceAssignedCopyTwo = ScarceResourceCopyImportJs.importScarceResource(); + } +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.var.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.var.js new file mode 100644 index 0000000000..ba52b323f0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.var.js @@ -0,0 +1,19 @@ +.import Qt.test 1.0 as JsQtTest + +// In this case, the "retn" variable will be evaluated during import. +// Since the importScarceResource() function depends on this variable, +// because we DO NOT call "retn.preserve()", the scarce resource will +// be released after the import completes but prior to evaluation of +// any binding which calls "importScarceResource()". +// Thus, "importScarceResource()" will return a released (invalid) +// scarce resource. + +var component = Qt.createComponent("scarceResourceCopy.var.qml"); +var scarceResourceElement = component.createObject(null); +var scarceResourceProvider = scarceResourceElement.a; +var retn = scarceResourceProvider.scarceResource; + +function importScarceResource() { + return retn; // should return a released (invalid) scarce resource +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.var.qml new file mode 100644 index 0000000000..a1a3c1d66f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.var.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceCopyImportFail.var.js" as ScarceResourceCopyImportFailJs + +QtObject { + property var scarceResourceCopy: ScarceResourceCopyImportFailJs.importScarceResource() +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.variant.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.variant.js new file mode 100644 index 0000000000..b59b5b1fa9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.variant.js @@ -0,0 +1,19 @@ +.import Qt.test 1.0 as JsQtTest + +// In this case, the "retn" variable will be evaluated during import. +// Since the importScarceResource() function depends on this variable, +// because we DO NOT call "retn.preserve()", the scarce resource will +// be released after the import completes but prior to evaluation of +// any binding which calls "importScarceResource()". +// Thus, "importScarceResource()" will return a released (invalid) +// scarce resource. + +var component = Qt.createComponent("scarceResourceCopy.variant.qml"); +var scarceResourceElement = component.createObject(null); +var scarceResourceProvider = scarceResourceElement.a; +var retn = scarceResourceProvider.scarceResource; + +function importScarceResource() { + return retn; // should return a released (invalid) scarce resource +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.variant.qml new file mode 100644 index 0000000000..8f6dcd6603 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportFail.variant.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceCopyImportFail.variant.js" as ScarceResourceCopyImportFailJs + +QtObject { + property variant scarceResourceCopy: ScarceResourceCopyImportFailJs.importScarceResource() +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.var.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.var.js new file mode 100644 index 0000000000..130199f78a --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.var.js @@ -0,0 +1,15 @@ +.import Qt.test 1.0 as JsQtTest + +// In this case, the "retn" variable will be evaluated during import. +// Since the importScarceResource() function depends on this variable, +// because we DO NOT call "retn.preserve()", the scarce resource will +// be released after the import completes but prior to evaluation of +// any binding which calls "importScarceResource()". +// Thus, "importScarceResource()" will return a released (invalid) +// scarce resource. + +var component = Qt.createComponent("scarceResourceCopyNoBinding.var.qml"); +var scarceResourceElement = component.createObject(null); +var scarceResourceProvider = scarceResourceElement.a; +var retn = scarceResourceProvider.scarceResource; + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.var.qml new file mode 100644 index 0000000000..5284b40cc8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.var.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// the following js import doesn't manually preserve or destroy any resources +import "scarceResourceCopyImportNoBinding.var.js" as ScarceResourceCopyImportNoBindingJs + +QtObject { + // in this case, there is an import but no binding evaluated. + // nonetheless, any resources which are not preserved, should + // be automatically released by the engine. +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.variant.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.variant.js new file mode 100644 index 0000000000..14a36a19ea --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.variant.js @@ -0,0 +1,15 @@ +.import Qt.test 1.0 as JsQtTest + +// In this case, the "retn" variable will be evaluated during import. +// Since the importScarceResource() function depends on this variable, +// because we DO NOT call "retn.preserve()", the scarce resource will +// be released after the import completes but prior to evaluation of +// any binding which calls "importScarceResource()". +// Thus, "importScarceResource()" will return a released (invalid) +// scarce resource. + +var component = Qt.createComponent("scarceResourceCopyNoBinding.variant.qml"); +var scarceResourceElement = component.createObject(null); +var scarceResourceProvider = scarceResourceElement.a; +var retn = scarceResourceProvider.scarceResource; + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.variant.qml new file mode 100644 index 0000000000..826cbe49fc --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyImportNoBinding.variant.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// the following js import doesn't manually preserve or destroy any resources +import "scarceResourceCopyImportNoBinding.variant.js" as ScarceResourceCopyImportNoBindingJs + +QtObject { + // in this case, there is an import but no binding evaluated. + // nonetheless, any resources which are not preserved, should + // be automatically released by the engine. +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyNoBinding.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyNoBinding.var.qml new file mode 100644 index 0000000000..4adef39980 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyNoBinding.var.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +QtObject { + // this component doesn't bind any property to a scarce + // resource from the scarce resource provider, + // so the binding evaluation resource cleanup + // codepath shouldn't be activated; so if the resources + // are released, it will be due to the import evaluation + // resource cleanup codepath being activated correctly. + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyNoBinding.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyNoBinding.variant.qml new file mode 100644 index 0000000000..4adef39980 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceCopyNoBinding.variant.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +QtObject { + // this component doesn't bind any property to a scarce + // resource from the scarce resource provider, + // so the binding evaluation resource cleanup + // codepath shouldn't be activated; so if the resources + // are released, it will be due to the import evaluation + // resource cleanup codepath being activated correctly. + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceDestroyedCopy.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceDestroyedCopy.var.qml new file mode 100644 index 0000000000..500f5d5bd7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceDestroyedCopy.var.qml @@ -0,0 +1,13 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceTest.var.js" as ScarceResourceProviderJs + +// In this case, following the evaluation of the binding, +// the scarceResourceTest value should be an invalid variant, +// since the scarce resource will have been released. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property var scarceResourceCopy: ScarceResourceProviderJs.importReleasedScarceResource(scarceResourceProvider); +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceDestroyedCopy.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceDestroyedCopy.variant.qml new file mode 100644 index 0000000000..7a3b845247 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceDestroyedCopy.variant.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceTest.variant.js" as ScarceResourceProviderJs + +// In this case, following the evaluation of the binding, +// the scarceResourceTest value should be an invalid variant, +// since the scarce resource will have been released. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property variant scarceResourceCopy: ScarceResourceProviderJs.importReleasedScarceResource(scarceResourceProvider); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunction.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunction.var.qml new file mode 100644 index 0000000000..23e4c8d15e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunction.var.qml @@ -0,0 +1,23 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// Here we import a scarce resource directly. +// The copy is only assigned when retrieveScarceResource() +// is called, and so should be detached prior to that. +// The copy should be released when releaseScarceResource() +// is called, and so should be detached after that. + +QtObject { + id: root + property MyScarceResourceObject a: MyScarceResourceObject { id: scarceResourceProvider } + property var scarceResourceCopy; + + function retrieveScarceResource() { + root.scarceResourceCopy = scarceResourceProvider.scarceResource; + } + + function releaseScarceResource() { + root.scarceResourceCopy = null; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunction.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunction.variant.qml new file mode 100644 index 0000000000..fe3707b5d3 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunction.variant.qml @@ -0,0 +1,23 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// Here we import a scarce resource directly. +// The copy is only assigned when retrieveScarceResource() +// is called, and so should be detached prior to that. +// The copy should be released when releaseScarceResource() +// is called, and so should be detached after that. + +QtObject { + id: root + property MyScarceResourceObject a: MyScarceResourceObject { id: scarceResourceProvider } + property variant scarceResourceCopy; + + function retrieveScarceResource() { + root.scarceResourceCopy = scarceResourceProvider.scarceResource; + } + + function releaseScarceResource() { + root.scarceResourceCopy = null; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunctionFail.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunctionFail.var.qml new file mode 100644 index 0000000000..7b4463773c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunctionFail.var.qml @@ -0,0 +1,23 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// In this example, a common syntax error will only be "caught" +// when the function is called via: +// QDeclarativeVMEMetaObject::metaCall->invokeMetaMethod() +// We would like to ensure that a useful error message is printed. + +QtObject { + id: root + property MyScarceResourceObject a: MyScarceResourceObject { id: scarceResourceProvider } + property var scarceResourceCopy; + property string srp_name: a.toString(); + + function retrieveScarceResource() { + root.scarceResourceCopy = scarceResourceProvider.scarceResource(); // common syntax error, should throw exception + } + + function releaseScarceResource() { + root.scarceResourceCopy = null; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunctionFail.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunctionFail.variant.qml new file mode 100644 index 0000000000..45acc53e63 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceFunctionFail.variant.qml @@ -0,0 +1,23 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// In this example, a common syntax error will only be "caught" +// when the function is called via: +// QDeclarativeVMEMetaObject::metaCall->invokeMetaMethod() +// We would like to ensure that a useful error message is printed. + +QtObject { + id: root + property MyScarceResourceObject a: MyScarceResourceObject { id: scarceResourceProvider } + property variant scarceResourceCopy; + property string srp_name: a.toString(); + + function retrieveScarceResource() { + root.scarceResourceCopy = scarceResourceProvider.scarceResource(); // common syntax error, should throw exception + } + + function releaseScarceResource() { + root.scarceResourceCopy = null; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleDifferentNoBinding.var.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleDifferentNoBinding.var.js new file mode 100644 index 0000000000..217f693456 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleDifferentNoBinding.var.js @@ -0,0 +1,14 @@ +.import Qt.test 1.0 as JsQtTest + +function importScarceResource() { + var component = Qt.createComponent("scarceResourceCopy.var.qml"); + var scarceResourceElement = component.createObject(null); + var scarceResourceProvider = scarceResourceElement.a; + var retn = scarceResourceProvider.scarceResource; + retn.preserve(); + return retn; +} + +function releaseScarceResource(resource) { + resource.destroy(); +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleDifferentNoBinding.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleDifferentNoBinding.var.qml new file mode 100644 index 0000000000..205131661f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleDifferentNoBinding.var.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceMultipleDifferentNoBinding.var.js" as ScarceResourcesMultipleDifferentNoBinding + +QtObject { + property var resourceOne + property var resourceTwo + + Component.onCompleted: { + resourceOne = ScarceResourcesMultipleDifferentNoBinding.importScarceResource(); + resourceTwo = ScarceResourcesMultipleDifferentNoBinding.importScarceResource(); + ScarceResourcesMultipleDifferentNoBinding.releaseScarceResource(resourceTwo); + } +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameNoBinding.var.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameNoBinding.var.js new file mode 100644 index 0000000000..5b2494c8e6 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameNoBinding.var.js @@ -0,0 +1,15 @@ +.import Qt.test 1.0 as JsQtTest + +var component = Qt.createComponent("scarceResourceCopy.var.qml"); +var scarceResourceElement = component.createObject(null); +var scarceResourceProvider = scarceResourceElement.a; +var retn = scarceResourceProvider.scarceResource; +retn.preserve(); + +function importScarceResource() { + return retn; +} + +function releaseScarceResource(resource) { + resource.destroy(); +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameNoBinding.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameNoBinding.var.qml new file mode 100644 index 0000000000..e7f6d7868f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameNoBinding.var.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceMultipleSameNoBinding.var.js" as ScarceResourcesMultipleSameNoBinding + +QtObject { + property var resourceOne + property var resourceTwo + + Component.onCompleted: { + resourceOne = ScarceResourcesMultipleSameNoBinding.importScarceResource(); + resourceTwo = ScarceResourcesMultipleSameNoBinding.importScarceResource(); + ScarceResourcesMultipleSameNoBinding.releaseScarceResource(resourceTwo); + } +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameWithBinding.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameWithBinding.var.qml new file mode 100644 index 0000000000..34cb97f39c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceMultipleSameWithBinding.var.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceMultipleDifferentNoBinding.var.js" as ScarceResourcesMultipleDifferentNoBinding + +QtObject { + property var resourceOne: ScarceResourcesMultipleDifferentNoBinding.importScarceResource() + property var resourceTwo: resourceOne + + Component.onCompleted: { + ScarceResourcesMultipleDifferentNoBinding.releaseScarceResource(resourceTwo); + } +} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceObjectGc.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceObjectGc.var.qml new file mode 100644 index 0000000000..7ec98e6619 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceObjectGc.var.qml @@ -0,0 +1,30 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: testScarce + + property var varProperty + + property var canary: 4 + + // constructs an Item which contains a scarce resource. + function constructScarceObject() { + var retn = 1; + var component = Qt.createComponent("ScarceResourceVarComponent.qml"); + if (component.status == Component.Ready) { + retn = component.createObject(null); // has JavaScript ownership + } + return retn; + } + + function assignVarProperty() { + varProperty = constructScarceObject(); + gc(); + } + + function deassignVarProperty() { + varProperty = 2; // causes the original object to be garbage collected. + gc(); // image should be detached; ep->sr should be empty! + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceSignal.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceSignal.var.qml new file mode 100644 index 0000000000..0b30e88fa8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceSignal.var.qml @@ -0,0 +1,29 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +QtObject { + id: root + + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + + property ScarceResourceSignalComponentVar b; + b: ScarceResourceSignalComponentVar { + objectName: "srsc" + + onTestSignal: { + // this signal will be invoked manually in the test. + // the scarce resource should be released automatically after evaluation + // and since we don't keep a copy of it, the pixmap will be detached. + width = (scarceResourceProvider.scarceResource,10) + } + + onTestSignal2: { + // this signal will be invoked manually in the test. + // the scarce resource should be released automatically after evaluation + // but since we assign it to a property, the pixmap won't be detached. + scarceResourceCopy = scarceResourceProvider.scarceResource + } + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceSignal.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceSignal.variant.qml new file mode 100644 index 0000000000..1011c7e240 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceSignal.variant.qml @@ -0,0 +1,29 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +QtObject { + id: root + + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + + property ScarceResourceSignalComponentVariant b; + b: ScarceResourceSignalComponentVariant { + objectName: "srsc" + + onTestSignal: { + // this signal will be invoked manually in the test. + // the scarce resource should be released automatically after evaluation + // and since we don't keep a copy of it, the pixmap will be detached. + width = (scarceResourceProvider.scarceResource,10) + } + + onTestSignal2: { + // this signal will be invoked manually in the test. + // the scarce resource should be released automatically after evaluation + // but since we assign it to a property, the pixmap won't be detached. + scarceResourceCopy = scarceResourceProvider.scarceResource + } + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.var.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.var.js new file mode 100644 index 0000000000..c904eb3564 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.var.js @@ -0,0 +1,48 @@ +.import Qt.test 1.0 as JsQtTest + +function importScarceResource(scarceResourceProvider) { + // the scarce resource should be automatically released + // after the binding is evaluated if preserve is not + // called. + return scarceResourceProvider.scarceResource; +} + +function importPreservedScarceResource(scarceResourceProvider) { + // the scarce resource is manually preserved + // during the evaluation of the binding. + // it should not be released. + var scarceResource = scarceResourceProvider.scarceResource; + scarceResource.preserve(); + return scarceResource; +} + +function importReleasedScarceResource(scarceResourceProvider) { + // release the scarce resource during the + // evaluation of the binding. The returned + // variant will therefore be invalid. + var scarceResource = scarceResourceProvider.scarceResource; + scarceResource.destroy(); + return scarceResource; +} + +function importPreservedScarceResourceFromMultiple(scarceResourceProvider) { + // some scarce resources are manually preserved, + // some of them are manually destroyed, + // and some are automatically managed. + // We return a preserved resource + var sr1 = scarceResourceProvider.scarceResource; // preserved/destroyed. + sr1.preserve(); + var sr2 = scarceResourceProvider.scarceResource; // preserved/destroyed + sr2.preserve(); + var sr3 = scarceResourceProvider.scarceResource; // automatic. + var sr4 = scarceResourceProvider.scarceResource; // automatic and returned. + var sr5 = scarceResourceProvider.scarceResource; // destroyed + sr5.destroy(); + sr2.destroy(); + var sr6 = scarceResourceProvider.scarceResource; // destroyed + var sr7 = scarceResourceProvider.scarceResource; // automatic + sr1.destroy(); + sr6.destroy(); + return sr4; +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.var.qml new file mode 100644 index 0000000000..1d4e67055e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.var.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// Here we import a scarce resource directly, and use it in a binding. +// It is not preserved or released manually, so it should be +// automatically released once evaluation of the binding +// is complete. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property int scarceResourceTest: scarceResourceProvider.scarceResource,100 // return 100, but include the scarceResource in the binding to be evaluated. +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.variant.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.variant.js new file mode 100644 index 0000000000..c904eb3564 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.variant.js @@ -0,0 +1,48 @@ +.import Qt.test 1.0 as JsQtTest + +function importScarceResource(scarceResourceProvider) { + // the scarce resource should be automatically released + // after the binding is evaluated if preserve is not + // called. + return scarceResourceProvider.scarceResource; +} + +function importPreservedScarceResource(scarceResourceProvider) { + // the scarce resource is manually preserved + // during the evaluation of the binding. + // it should not be released. + var scarceResource = scarceResourceProvider.scarceResource; + scarceResource.preserve(); + return scarceResource; +} + +function importReleasedScarceResource(scarceResourceProvider) { + // release the scarce resource during the + // evaluation of the binding. The returned + // variant will therefore be invalid. + var scarceResource = scarceResourceProvider.scarceResource; + scarceResource.destroy(); + return scarceResource; +} + +function importPreservedScarceResourceFromMultiple(scarceResourceProvider) { + // some scarce resources are manually preserved, + // some of them are manually destroyed, + // and some are automatically managed. + // We return a preserved resource + var sr1 = scarceResourceProvider.scarceResource; // preserved/destroyed. + sr1.preserve(); + var sr2 = scarceResourceProvider.scarceResource; // preserved/destroyed + sr2.preserve(); + var sr3 = scarceResourceProvider.scarceResource; // automatic. + var sr4 = scarceResourceProvider.scarceResource; // automatic and returned. + var sr5 = scarceResourceProvider.scarceResource; // destroyed + sr5.destroy(); + sr2.destroy(); + var sr6 = scarceResourceProvider.scarceResource; // destroyed + var sr7 = scarceResourceProvider.scarceResource; // automatic + sr1.destroy(); + sr6.destroy(); + return sr4; +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.variant.qml new file mode 100644 index 0000000000..1d4e67055e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTest.variant.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +// Here we import a scarce resource directly, and use it in a binding. +// It is not preserved or released manually, so it should be +// automatically released once evaluation of the binding +// is complete. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property int scarceResourceTest: scarceResourceProvider.scarceResource,100 // return 100, but include the scarceResource in the binding to be evaluated. +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestMultiple.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestMultiple.var.qml new file mode 100644 index 0000000000..5e6c2d97f9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestMultiple.var.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceTest.var.js" as ScarceResourceProviderJs + +// In this case, multiple scarce resource are explicity preserved +// and then explicitly destroyed, while others are automatically +// managed. Since none are manually preserved without subsequently +// being destroyed, after the evaluation of the binding the +// scarce resource should be detached. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property int scarceResourceTest: ScarceResourceProviderJs.importPreservedScarceResourceFromMultiple(scarceResourceProvider), 100 +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestMultiple.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestMultiple.variant.qml new file mode 100644 index 0000000000..2970bcb26c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestMultiple.variant.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceTest.variant.js" as ScarceResourceProviderJs + +// In this case, multiple scarce resource are explicity preserved +// and then explicitly destroyed, while others are automatically +// managed. Since none are manually preserved without subsequently +// being destroyed, after the evaluation of the binding the +// scarce resource should be detached. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property int scarceResourceTest: ScarceResourceProviderJs.importPreservedScarceResourceFromMultiple(scarceResourceProvider), 100 +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestPreserve.var.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestPreserve.var.qml new file mode 100644 index 0000000000..9e9495c0fa --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestPreserve.var.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceTest.var.js" as ScarceResourceProviderJs + +// In this case, the scarce resource is explicity preserved. +// It should not be automatically released after the evaluation +// of the binding is complete, but instead will be kept in +// memory until the JS garbage collector runs. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property int scarceResourceTest: ScarceResourceProviderJs.importPreservedScarceResource(scarceResourceProvider),100 // return 100, but the resource should be preserved. +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestPreserve.variant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestPreserve.variant.qml new file mode 100644 index 0000000000..022067beca --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceResourceTestPreserve.variant.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import "scarceResourceTest.variant.js" as ScarceResourceProviderJs + +// In this case, the scarce resource is explicity preserved. +// It should not be automatically released after the evaluation +// of the binding is complete, but instead will be kept in +// memory until the JS garbage collector runs. + +QtObject { + property MyScarceResourceObject a; + a: MyScarceResourceObject { id: scarceResourceProvider } + property int scarceResourceTest: ScarceResourceProviderJs.importPreservedScarceResource(scarceResourceProvider),100 // return 100, but the resource should be preserved. +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/ScarceResourceSignalComponent.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/ScarceResourceSignalComponent.qml deleted file mode 100644 index e10fcfe36a..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/ScarceResourceSignalComponent.qml +++ /dev/null @@ -1,9 +0,0 @@ -import QtQuick 2.0 - -QtObject { - property variant scarceResourceCopy - property int width: 5 - signal testSignal - signal testSignal2 -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopy.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopy.qml deleted file mode 100644 index ee5b05b28a..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopy.qml +++ /dev/null @@ -1,15 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 - -// Here we import a scarce resource directly. -// The instance has a property which is a copy -// of the scarce resource, so it should not be -// detached (but we should automatically release -// the resource from our engine internal list). - -QtObject { - property MyScarceResourceObject a; - a: MyScarceResourceObject { id: scarceResourceProvider } - property variant scarceResourceCopy: scarceResourceProvider.scarceResource -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyFromJs.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyFromJs.qml deleted file mode 100644 index 40f6d7bbd6..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyFromJs.qml +++ /dev/null @@ -1,15 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 -import "scarceResourceTest.js" as ScarceResourceProviderJs - -// Here we import a scarce resource directly, from JS module. -// It is not preserved or released manually, so it should be -// automatically released once evaluation of the binding -// is complete. - -QtObject { - property MyScarceResourceObject a; - a: MyScarceResourceObject { id: scarceResourceProvider } - property variant scarceResourceCopy: ScarceResourceProviderJs.importScarceResource(scarceResourceProvider) -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImport.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImport.js deleted file mode 100644 index bacc50dcc9..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImport.js +++ /dev/null @@ -1,24 +0,0 @@ -.import Qt.test 1.0 as JsQtTest - -// In this case, the "retn" variable will be evaluated during import. -// Since the "importScarceResource()" function depends on this variable, -// we must explicitly preserve the "retn" variable or the scarce -// resource would automatically be released after import completes -// but before the binding is evaluated. - -var component = Qt.createComponent("scarceResourceCopy.qml"); -var scarceResourceElement = component.createObject(null); -var scarceResourceProvider = scarceResourceElement.a; -var retn = scarceResourceProvider.scarceResource; -retn.preserve(); // must preserve manually or it will be released! - -function importScarceResource() { - // if called prior to calling destroyScarceResource(), - // this function should return the preserved scarce resource. - // otherwise, it should return an invalid variant. - return retn; -} - -function destroyScarceResource() { - retn.destroy(); -} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImport.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImport.qml deleted file mode 100644 index 08acc1b694..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImport.qml +++ /dev/null @@ -1,18 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 -import "scarceResourceCopyImport.js" as ScarceResourceCopyImportJs - -QtObject { - // this binding is evaluated once, prior to the resource being released - property variant scarceResourceCopy: ScarceResourceCopyImportJs.importScarceResource() - - // this code is evaluated on completion, and so copy one should be valid, copy two invalid. - property variant scarceResourceAssignedCopyOne; - property variant scarceResourceAssignedCopyTwo; - Component.onCompleted: { - scarceResourceAssignedCopyOne = ScarceResourceCopyImportJs.importScarceResource(); - ScarceResourceCopyImportJs.destroyScarceResource(); - scarceResourceAssignedCopyTwo = ScarceResourceCopyImportJs.importScarceResource(); - } -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportFail.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportFail.js deleted file mode 100644 index 6c495863b5..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportFail.js +++ /dev/null @@ -1,18 +0,0 @@ -.import Qt.test 1.0 as JsQtTest - -// In this case, the "retn" variable will be evaluated during import. -// Since the importScarceResource() function depends on this variable, -// because we DO NOT call "retn.preserve()", the scarce resource will -// be released after the import completes but prior to evaluation of -// any binding which calls "importScarceResource()". -// Thus, "importScarceResource()" will return a released (invalid) -// scarce resource. - -var component = Qt.createComponent("scarceResourceCopy.qml"); -var scarceResourceElement = component.createObject(null); -var scarceResourceProvider = scarceResourceElement.a; -var retn = scarceResourceProvider.scarceResource; - -function importScarceResource() { - return retn; // should return a released (invalid) scarce resource -} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportFail.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportFail.qml deleted file mode 100644 index 613d3a8ee8..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportFail.qml +++ /dev/null @@ -1,8 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 -import "scarceResourceCopyImportFail.js" as ScarceResourceCopyImportFailJs - -QtObject { - property variant scarceResourceCopy: ScarceResourceCopyImportFailJs.importScarceResource() -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportNoBinding.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportNoBinding.js deleted file mode 100644 index 4a5b6b4427..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportNoBinding.js +++ /dev/null @@ -1,14 +0,0 @@ -.import Qt.test 1.0 as JsQtTest - -// In this case, the "retn" variable will be evaluated during import. -// Since the importScarceResource() function depends on this variable, -// because we DO NOT call "retn.preserve()", the scarce resource will -// be released after the import completes but prior to evaluation of -// any binding which calls "importScarceResource()". -// Thus, "importScarceResource()" will return a released (invalid) -// scarce resource. - -var component = Qt.createComponent("scarceResourceCopyNoBinding.qml"); -var scarceResourceElement = component.createObject(null); -var scarceResourceProvider = scarceResourceElement.a; -var retn = scarceResourceProvider.scarceResource; diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportNoBinding.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportNoBinding.qml deleted file mode 100644 index 81deec0713..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyImportNoBinding.qml +++ /dev/null @@ -1,12 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 - -// the following js import doesn't manually preserve or destroy any resources -import "scarceResourceCopyImportNoBinding.js" as ScarceResourceCopyImportNoBindingJs - -QtObject { - // in this case, there is an import but no binding evaluated. - // nonetheless, any resources which are not preserved, should - // be automatically released by the engine. -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyNoBinding.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyNoBinding.qml deleted file mode 100644 index 4adef39980..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceCopyNoBinding.qml +++ /dev/null @@ -1,14 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 - -QtObject { - // this component doesn't bind any property to a scarce - // resource from the scarce resource provider, - // so the binding evaluation resource cleanup - // codepath shouldn't be activated; so if the resources - // are released, it will be due to the import evaluation - // resource cleanup codepath being activated correctly. - property MyScarceResourceObject a; - a: MyScarceResourceObject { id: scarceResourceProvider } -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceDestroyedCopy.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceDestroyedCopy.qml deleted file mode 100644 index e47c37aba3..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceDestroyedCopy.qml +++ /dev/null @@ -1,14 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 -import "scarceResourceTest.js" as ScarceResourceProviderJs - -// In this case, following the evaluation of the binding, -// the scarceResourceTest value should be an invalid variant, -// since the scarce resource will have been released. - -QtObject { - property MyScarceResourceObject a; - a: MyScarceResourceObject { id: scarceResourceProvider } - property variant scarceResourceCopy: ScarceResourceProviderJs.importReleasedScarceResource(scarceResourceProvider); -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunction.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunction.qml deleted file mode 100644 index fe3707b5d3..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunction.qml +++ /dev/null @@ -1,23 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 - -// Here we import a scarce resource directly. -// The copy is only assigned when retrieveScarceResource() -// is called, and so should be detached prior to that. -// The copy should be released when releaseScarceResource() -// is called, and so should be detached after that. - -QtObject { - id: root - property MyScarceResourceObject a: MyScarceResourceObject { id: scarceResourceProvider } - property variant scarceResourceCopy; - - function retrieveScarceResource() { - root.scarceResourceCopy = scarceResourceProvider.scarceResource; - } - - function releaseScarceResource() { - root.scarceResourceCopy = null; - } -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunctionFail.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunctionFail.qml deleted file mode 100644 index 38de0ae0aa..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunctionFail.qml +++ /dev/null @@ -1,24 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 - -// In this example, a common syntax error will only be "caught" -// when the function is called via: -// QDeclarativeVMEMetaObject::metaCall->invokeMetaMethod() -// We would like to ensure that a useful error message is printed, -// rather than having QScriptValue::call() function fail silently. - -QtObject { - id: root - property MyScarceResourceObject a: MyScarceResourceObject { id: scarceResourceProvider } - property variant scarceResourceCopy; - property string srp_name: a.toString(); - - function retrieveScarceResource() { - root.scarceResourceCopy = scarceResourceProvider.scarceResource(); // common syntax error, should throw exception - } - - function releaseScarceResource() { - root.scarceResourceCopy = null; - } -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceSignal.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceSignal.qml deleted file mode 100644 index 1d5a39c52d..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceSignal.qml +++ /dev/null @@ -1,29 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 - -QtObject { - id: root - - property MyScarceResourceObject a; - a: MyScarceResourceObject { id: scarceResourceProvider } - - property ScarceResourceSignalComponent b; - b: ScarceResourceSignalComponent { - objectName: "srsc" - - onTestSignal: { - // this signal will be invoked manually in the test. - // the scarce resource should be released automatically after evaluation - // and since we don't keep a copy of it, the pixmap will be detached. - width = (scarceResourceProvider.scarceResource,10) - } - - onTestSignal2: { - // this signal will be invoked manually in the test. - // the scarce resource should be released automatically after evaluation - // but since we assign it to a property, the pixmap won't be detached. - scarceResourceCopy = scarceResourceProvider.scarceResource - } - } -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTest.js b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTest.js deleted file mode 100644 index c904eb3564..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTest.js +++ /dev/null @@ -1,48 +0,0 @@ -.import Qt.test 1.0 as JsQtTest - -function importScarceResource(scarceResourceProvider) { - // the scarce resource should be automatically released - // after the binding is evaluated if preserve is not - // called. - return scarceResourceProvider.scarceResource; -} - -function importPreservedScarceResource(scarceResourceProvider) { - // the scarce resource is manually preserved - // during the evaluation of the binding. - // it should not be released. - var scarceResource = scarceResourceProvider.scarceResource; - scarceResource.preserve(); - return scarceResource; -} - -function importReleasedScarceResource(scarceResourceProvider) { - // release the scarce resource during the - // evaluation of the binding. The returned - // variant will therefore be invalid. - var scarceResource = scarceResourceProvider.scarceResource; - scarceResource.destroy(); - return scarceResource; -} - -function importPreservedScarceResourceFromMultiple(scarceResourceProvider) { - // some scarce resources are manually preserved, - // some of them are manually destroyed, - // and some are automatically managed. - // We return a preserved resource - var sr1 = scarceResourceProvider.scarceResource; // preserved/destroyed. - sr1.preserve(); - var sr2 = scarceResourceProvider.scarceResource; // preserved/destroyed - sr2.preserve(); - var sr3 = scarceResourceProvider.scarceResource; // automatic. - var sr4 = scarceResourceProvider.scarceResource; // automatic and returned. - var sr5 = scarceResourceProvider.scarceResource; // destroyed - sr5.destroy(); - sr2.destroy(); - var sr6 = scarceResourceProvider.scarceResource; // destroyed - var sr7 = scarceResourceProvider.scarceResource; // automatic - sr1.destroy(); - sr6.destroy(); - return sr4; -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTest.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTest.qml deleted file mode 100644 index 1d4e67055e..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTest.qml +++ /dev/null @@ -1,14 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 - -// Here we import a scarce resource directly, and use it in a binding. -// It is not preserved or released manually, so it should be -// automatically released once evaluation of the binding -// is complete. - -QtObject { - property MyScarceResourceObject a; - a: MyScarceResourceObject { id: scarceResourceProvider } - property int scarceResourceTest: scarceResourceProvider.scarceResource,100 // return 100, but include the scarceResource in the binding to be evaluated. -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTestMultiple.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTestMultiple.qml deleted file mode 100644 index 9a6ee30ff1..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTestMultiple.qml +++ /dev/null @@ -1,16 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 -import "scarceResourceTest.js" as ScarceResourceProviderJs - -// In this case, multiple scarce resource are explicity preserved -// and then explicitly destroyed, while others are automatically -// managed. Since none are manually preserved without subsequently -// being destroyed, after the evaluation of the binding the -// scarce resource should be detached. - -QtObject { - property MyScarceResourceObject a; - a: MyScarceResourceObject { id: scarceResourceProvider } - property int scarceResourceTest: ScarceResourceProviderJs.importPreservedScarceResourceFromMultiple(scarceResourceProvider), 100 -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTestPreserve.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTestPreserve.qml deleted file mode 100644 index d7a40312ab..0000000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceTestPreserve.qml +++ /dev/null @@ -1,15 +0,0 @@ -import QtQuick 2.0 -import Qt.test 1.0 -import "scarceResourceTest.js" as ScarceResourceProviderJs - -// In this case, the scarce resource is explicity preserved. -// It should not be automatically released after the evaluation -// of the binding is complete, but instead will be kept in -// memory until the JS garbage collector runs. - -QtObject { - property MyScarceResourceObject a; - a: MyScarceResourceObject { id: scarceResourceProvider } - property int scarceResourceTest: ScarceResourceProviderJs.importPreservedScarceResource(scarceResourceProvider),100 // return 100, but the resource should be preserved. -} - diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 3d50d6ee3d..5e62ec6508 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -152,6 +152,8 @@ private slots: void importScripts_data(); void importScripts(); void scarceResources(); + void scarceResources_data(); + void scarceResources_other(); void propertyChangeSlots(); void propertyVar_data(); void propertyVar(); @@ -1412,15 +1414,15 @@ void tst_qdeclarativeecmascript::functionErrors() delete object; // test that if an exception occurs while invoking js function from cpp, it is reported as expected. - QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml")); + QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceResourceFunctionFail.var.qml")); url = componentTwo.url().toString(); object = componentTwo.create(); QVERIFY(object != 0); QString srpname = object->property("srp_name").toString(); - warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname + - QLatin1String(" is not a function"); + warning = url + QLatin1String(":16: TypeError: Property 'scarceResource' of object ") + srpname + + QLatin1String(" is not a function"); QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed. QMetaObject::invokeMethod(object, "retrieveScarceResource"); delete object; @@ -3197,110 +3199,98 @@ void tst_qdeclarativeecmascript::importScripts() } } -void tst_qdeclarativeecmascript::scarceResources() +void tst_qdeclarativeecmascript::scarceResources_other() { + /* These tests require knowledge of state, since we test values after + performing signal or function invocation. */ + QPixmap origPixmap(100, 100); origPixmap.fill(Qt::blue); - + QString srp_name, expectedWarning; QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine); ScarceResourceObject *eo = 0; + QObject *srsc = 0; QObject *object = 0; - // in the following three cases, the instance created from the component - // has a property which is a copy of the scarce resource; hence, the - // resource should NOT be detached prior to deletion of the object instance, - // unless the resource is destroyed explicitly. - QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml")); - object = component.create(); - QVERIFY(object != 0); - QVERIFY(object->property("scarceResourceCopy").isValid()); - QCOMPARE(object->property("scarceResourceCopy").value(), origPixmap); - QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point. + /* property var semantics */ + + // test that scarce resources are handled properly in signal invocation + QDeclarativeComponent varComponentTen(&engine, TEST_FILE("scarceResourceSignal.var.qml")); + object = varComponentTen.create(); + srsc = object->findChild("srsc"); + QVERIFY(srsc); + QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet. + QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5. + eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); + QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage. + QMetaObject::invokeMethod(srsc, "testSignal"); + QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated + QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10. eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); - QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo. + QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage. + QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap. + QVERIFY(srsc->property("scarceResourceCopy").isValid()); + QCOMPARE(srsc->property("scarceResourceCopy").value(), origPixmap); + eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); + QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now. + QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point. delete object; - QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml")); - object = componentTwo.create(); + // test that scarce resources are handled properly from js functions in qml files + QDeclarativeComponent varComponentEleven(&engine, TEST_FILE("scarceResourceFunction.var.qml")); + object = varComponentEleven.create(); QVERIFY(object != 0); - QVERIFY(object->property("scarceResourceCopy").isValid()); + QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid + eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); + QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage. + QMetaObject::invokeMethod(object, "retrieveScarceResource"); + QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid. QCOMPARE(object->property("scarceResourceCopy").value(), origPixmap); - QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point. eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); - QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo. - delete object; - - QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml")); - object = componentThree.create(); - QVERIFY(object != 0); - QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned. - QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point. + QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage. + QMetaObject::invokeMethod(object, "releaseScarceResource"); + QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); - QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding. - delete object; - - // in the following three cases, no other copy should exist in memory, - // and so it should be detached (unless explicitly preserved). - QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml")); - object = componentFour.create(); - QVERIFY(object != 0); - QVERIFY(object->property("scarceResourceTest").isValid()); - QCOMPARE(object->property("scarceResourceTest").toInt(), 100); + QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage. QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point. - eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); - QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated. delete object; - QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml")); - object = componentFive.create(); + // test that if an exception occurs while invoking js function from cpp, that the resources are released. + QDeclarativeComponent varComponentTwelve(&engine, TEST_FILE("scarceResourceFunctionFail.var.qml")); + object = varComponentTwelve.create(); QVERIFY(object != 0); - QVERIFY(object->property("scarceResourceTest").isValid()); - QCOMPARE(object->property("scarceResourceTest").toInt(), 100); - QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point. + QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); - QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it. - delete object; - - QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml")); - object = componentSix.create(); - QVERIFY(object != 0); - QVERIFY(object->property("scarceResourceTest").isValid()); - QCOMPARE(object->property("scarceResourceTest").toInt(), 100); - QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point. + QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage. + srp_name = object->property("srp_name").toString(); + expectedWarning = varComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. + QMetaObject::invokeMethod(object, "retrieveScarceResource"); + QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred. eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); - QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released. - delete object; - - // test that scarce resources are handled correctly for imports - QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml")); - object = componentSeven.create(); - QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list - QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point. - delete object; - - QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml")); - object = componentEight.create(); - QVERIFY(object != 0); - QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid. + QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage. QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point. delete object; - QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml")); - object = componentNine.create(); + // test that if an Item which has JS ownership but has a scarce resource property is garbage collected, + // that the scarce resource is removed from the engine's list of scarce resources to clean up. + QDeclarativeComponent varComponentThirteen(&engine, TEST_FILE("scarceResourceObjectGc.var.qml")); + object = varComponentThirteen.create(); QVERIFY(object != 0); - QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid. - QCOMPARE(object->property("scarceResourceCopy").value(), origPixmap); - QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid. - QCOMPARE(object->property("scarceResourceAssignedCopyOne").value(), origPixmap); - QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid. - QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list. + QVERIFY(!object->property("varProperty").isValid()); // not assigned yet + QMetaObject::invokeMethod(object, "assignVarProperty"); + QVERIFY(ep->scarceResources.isEmpty()); // the scarce resource is a VME property. + QMetaObject::invokeMethod(object, "deassignVarProperty"); + QVERIFY(ep->scarceResources.isEmpty()); // should still be empty; the resource should have been released on gc. delete object; + /* property variant semantics */ + // test that scarce resources are handled properly in signal invocation - QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml")); - object = componentTen.create(); + QDeclarativeComponent variantComponentTen(&engine, TEST_FILE("scarceResourceSignal.variant.qml")); + object = variantComponentTen.create(); QVERIFY(object != 0); - QObject *srsc = object->findChild("srsc"); + srsc = object->findChild("srsc"); QVERIFY(srsc); QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet. QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5. @@ -3320,8 +3310,8 @@ void tst_qdeclarativeecmascript::scarceResources() delete object; // test that scarce resources are handled properly from js functions in qml files - QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml")); - object = componentEleven.create(); + QDeclarativeComponent variantComponentEleven(&engine, TEST_FILE("scarceResourceFunction.variant.qml")); + object = variantComponentEleven.create(); QVERIFY(object != 0); QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); @@ -3339,14 +3329,14 @@ void tst_qdeclarativeecmascript::scarceResources() delete object; // test that if an exception occurs while invoking js function from cpp, that the resources are released. - QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml")); - object = componentTwelve.create(); + QDeclarativeComponent variantComponentTwelve(&engine, TEST_FILE("scarceResourceFunctionFail.variant.qml")); + object = variantComponentTwelve.create(); QVERIFY(object != 0); QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage. - QString srp_name = object->property("srp_name").toString(); - QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function"); + srp_name = object->property("srp_name").toString(); + expectedWarning = variantComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function"); QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. QMetaObject::invokeMethod(object, "retrieveScarceResource"); QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred. @@ -3356,6 +3346,266 @@ void tst_qdeclarativeecmascript::scarceResources() delete object; } +void tst_qdeclarativeecmascript::scarceResources_data() +{ + QTest::addColumn("qmlFile"); + QTest::addColumn("readDetachStatus"); + QTest::addColumn("expectedDetachStatus"); + QTest::addColumn("propertyNames"); + QTest::addColumn("expectedValidity"); + QTest::addColumn("expectedValues"); + QTest::addColumn("expectedErrors"); + + QPixmap origPixmap(100, 100); + origPixmap.fill(Qt::blue); + + /* property var semantics */ + + // in the following three cases, the instance created from the component + // has a property which is a copy of the scarce resource; hence, the + // resource should NOT be detached prior to deletion of the object instance, + // unless the resource is destroyed explicitly. + QTest::newRow("var: import scarce resource copy directly") + << TEST_FILE("scarceResourceCopy.var.qml") + << true + << false // won't be detached, because assigned to property and not explicitly released + << (QStringList() << QLatin1String("scarceResourceCopy")) + << (QList() << true) + << (QList() << origPixmap) + << QStringList(); + + QTest::newRow("var: import scarce resource copy from JS") + << TEST_FILE("scarceResourceCopyFromJs.var.qml") + << true + << false // won't be detached, because assigned to property and not explicitly released + << (QStringList() << QLatin1String("scarceResourceCopy")) + << (QList() << true) + << (QList() << origPixmap) + << QStringList(); + + QTest::newRow("var: import released scarce resource copy from JS") + << TEST_FILE("scarceResourceDestroyedCopy.var.qml") + << true + << true // explicitly released, so it will be detached + << (QStringList() << QLatin1String("scarceResourceCopy")) + << (QList() << false) + << (QList() << QVariant()) + << QStringList(); + + // in the following three cases, no other copy should exist in memory, + // and so it should be detached (unless explicitly preserved). + QTest::newRow("var: import auto-release SR from JS in binding side-effect") + << TEST_FILE("scarceResourceTest.var.qml") + << true + << true // auto released, so it will be detached + << (QStringList() << QLatin1String("scarceResourceTest")) + << (QList() << true) + << (QList() << QVariant(100)) + << QStringList(); + QTest::newRow("var: import explicit-preserve SR from JS in binding side-effect") + << TEST_FILE("scarceResourceTestPreserve.var.qml") + << true + << false // won't be detached because we explicitly preserve it + << (QStringList() << QLatin1String("scarceResourceTest")) + << (QList() << true) + << (QList() << QVariant(100)) + << QStringList(); + QTest::newRow("var: import explicit-preserve SR from JS in binding side-effect") + << TEST_FILE("scarceResourceTestMultiple.var.qml") + << true + << true // will be detached because all resources were released manually or automatically. + << (QStringList() << QLatin1String("scarceResourceTest")) + << (QList() << true) + << (QList() << QVariant(100)) + << QStringList(); + + // In the following three cases, test that scarce resources are handled + // correctly for imports. + QTest::newRow("var: import with no binding") + << TEST_FILE("scarceResourceCopyImportNoBinding.var.qml") + << false // cannot check detach status. + << false + << QStringList() + << QList() + << QList() + << QStringList(); + QTest::newRow("var: import with binding without explicit preserve") + << TEST_FILE("scarceResourceCopyImportNoBinding.var.qml") + << false + << false + << (QStringList() << QLatin1String("scarceResourceCopy")) + << (QList() << false) // will have been released prior to evaluation of binding. + << (QList() << QVariant()) + << QStringList(); + QTest::newRow("var: import with explicit release after binding evaluation") + << TEST_FILE("scarceResourceCopyImport.var.qml") + << false + << false + << (QStringList() << QLatin1String("scarceResourceImportedCopy") << QLatin1String("scarceResourceAssignedCopyOne") << QLatin1String("scarceResourceAssignedCopyTwo") << QLatin1String("arePropertiesEqual")) + << (QList() << false << false << false << true) // since property var = JS object reference, by releasing the provider's resource, all handles are invalidated. + << (QList() << QVariant() << QVariant() << QVariant() << QVariant(true)) + << QStringList(); + QTest::newRow("var: import with different js objects") + << TEST_FILE("scarceResourceCopyImportDifferent.var.qml") + << false + << false + << (QStringList() << QLatin1String("scarceResourceAssignedCopyOne") << QLatin1String("scarceResourceAssignedCopyTwo") << QLatin1String("arePropertiesEqual")) + << (QList() << false << true << true) // invalidating one shouldn't invalidate the other, because they're not references to the same JS object. + << (QList() << QVariant() << QVariant(origPixmap) << QVariant(false)) + << QStringList(); + QTest::newRow("var: import with different js objects and explicit release") + << TEST_FILE("scarceResourceMultipleDifferentNoBinding.var.qml") + << false + << false + << (QStringList() << QLatin1String("resourceOne") << QLatin1String("resourceTwo")) + << (QList() << true << false) // invalidating one shouldn't invalidate the other, because they're not references to the same JS object. + << (QList() << QVariant(origPixmap) << QVariant()) + << QStringList(); + QTest::newRow("var: import with same js objects and explicit release") + << TEST_FILE("scarceResourceMultipleSameNoBinding.var.qml") + << false + << false + << (QStringList() << QLatin1String("resourceOne") << QLatin1String("resourceTwo")) + << (QList() << false << false) // invalidating one should invalidate the other, because they're references to the same JS object. + << (QList() << QVariant() << QVariant()) + << QStringList(); + QTest::newRow("var: binding with same js objects and explicit release") + << TEST_FILE("scarceResourceMultipleSameWithBinding.var.qml") + << false + << false + << (QStringList() << QLatin1String("resourceOne") << QLatin1String("resourceTwo")) + << (QList() << false << false) // invalidating one should invalidate the other, because they're references to the same JS object. + << (QList() << QVariant() << QVariant()) + << QStringList(); + + + /* property variant semantics */ + + // in the following three cases, the instance created from the component + // has a property which is a copy of the scarce resource; hence, the + // resource should NOT be detached prior to deletion of the object instance, + // unless the resource is destroyed explicitly. + QTest::newRow("variant: import scarce resource copy directly") + << TEST_FILE("scarceResourceCopy.variant.qml") + << true + << false // won't be detached, because assigned to property and not explicitly released + << (QStringList() << QLatin1String("scarceResourceCopy")) + << (QList() << true) + << (QList() << origPixmap) + << QStringList(); + + QTest::newRow("variant: import scarce resource copy from JS") + << TEST_FILE("scarceResourceCopyFromJs.variant.qml") + << true + << false // won't be detached, because assigned to property and not explicitly released + << (QStringList() << QLatin1String("scarceResourceCopy")) + << (QList() << true) + << (QList() << origPixmap) + << QStringList(); + + QTest::newRow("variant: import released scarce resource copy from JS") + << TEST_FILE("scarceResourceDestroyedCopy.variant.qml") + << true + << true // explicitly released, so it will be detached + << (QStringList() << QLatin1String("scarceResourceCopy")) + << (QList() << false) + << (QList() << QVariant()) + << QStringList(); + + // in the following three cases, no other copy should exist in memory, + // and so it should be detached (unless explicitly preserved). + QTest::newRow("variant: import auto-release SR from JS in binding side-effect") + << TEST_FILE("scarceResourceTest.variant.qml") + << true + << true // auto released, so it will be detached + << (QStringList() << QLatin1String("scarceResourceTest")) + << (QList() << true) + << (QList() << QVariant(100)) + << QStringList(); + QTest::newRow("variant: import explicit-preserve SR from JS in binding side-effect") + << TEST_FILE("scarceResourceTestPreserve.variant.qml") + << true + << false // won't be detached because we explicitly preserve it + << (QStringList() << QLatin1String("scarceResourceTest")) + << (QList() << true) + << (QList() << QVariant(100)) + << QStringList(); + QTest::newRow("variant: import multiple scarce resources") + << TEST_FILE("scarceResourceTestMultiple.variant.qml") + << true + << true // will be detached because all resources were released manually or automatically. + << (QStringList() << QLatin1String("scarceResourceTest")) + << (QList() << true) + << (QList() << QVariant(100)) + << QStringList(); + + // In the following three cases, test that scarce resources are handled + // correctly for imports. + QTest::newRow("variant: import with no binding") + << TEST_FILE("scarceResourceCopyImportNoBinding.variant.qml") + << false // cannot check detach status. + << false + << QStringList() + << QList() + << QList() + << QStringList(); + QTest::newRow("variant: import with binding without explicit preserve") + << TEST_FILE("scarceResourceCopyImportNoBinding.variant.qml") + << false + << false + << (QStringList() << QLatin1String("scarceResourceCopy")) + << (QList() << false) // will have been released prior to evaluation of binding. + << (QList() << QVariant()) + << QStringList(); + QTest::newRow("variant: import with explicit release after binding evaluation") + << TEST_FILE("scarceResourceCopyImport.variant.qml") + << false + << false + << (QStringList() << QLatin1String("scarceResourceImportedCopy") << QLatin1String("scarceResourceAssignedCopyOne") << QLatin1String("scarceResourceAssignedCopyTwo")) + << (QList() << true << true << false) // since property variant = variant copy, releasing the provider's resource does not invalidate previously assigned copies. + << (QList() << origPixmap << origPixmap << QVariant()) + << QStringList(); +} + +void tst_qdeclarativeecmascript::scarceResources() +{ + QFETCH(QUrl, qmlFile); + QFETCH(bool, readDetachStatus); + QFETCH(bool, expectedDetachStatus); + QFETCH(QStringList, propertyNames); + QFETCH(QVariantList, expectedValidity); + QFETCH(QVariantList, expectedValues); + QFETCH(QStringList, expectedErrors); + + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine); + ScarceResourceObject *eo = 0; + QObject *object = 0; + + QDeclarativeComponent c(&engine, qmlFile); + object = c.create(); + QVERIFY(object != 0); + for (int i = 0; i < propertyNames.size(); ++i) { + QString prop = propertyNames.at(i); + bool validity = expectedValidity.at(i).toBool(); + QVariant value = expectedValues.at(i); + + QCOMPARE(object->property(prop.toLatin1().constData()).isValid(), validity); + if (value.type() == QVariant::Int) { + QCOMPARE(object->property(prop.toLatin1().constData()).toInt(), value.toInt()); + } else if (value.type() == QVariant::Pixmap) { + QCOMPARE(object->property(prop.toLatin1().constData()).value(), value.value()); + } + } + + if (readDetachStatus) { + eo = qobject_cast(QDeclarativeProperty::read(object, "a").value()); + QCOMPARE(eo->scarceResourceIsDetached(), expectedDetachStatus); + } + + QVERIFY(ep->scarceResources.isEmpty()); + delete object; +} + void tst_qdeclarativeecmascript::propertyChangeSlots() { // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly. -- cgit v1.2.3