summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2013-11-20 13:22:43 +0100
committerMilian Wolff <milian.wolff@kdab.com>2013-11-25 14:58:01 +0100
commitb2604fd7932f6bd73f06ca2ebf9e18ad542789d7 (patch)
tree8f27b954e09dbbd1d0de62d3cdc28ad58f2cf6bf
parent09d1bd8126c4eaaa572792ba223b49364805c205 (diff)
downloadqtwebchannel-b2604fd7932f6bd73f06ca2ebf9e18ad542789d7.tar.gz
Test QObject wrapping, when factory-style methods are called.
An HTML client can trigger the creation of new objects, or a published object on the server side might return other objects. These are then wrapped on the fly and can be used like the other objects. Note though that the HTML client can call deleteLater on these objects. Also, it does not yet work to wrap objects on the fly in signal arguments or property values. Change-Id: I92aa8a3e52f42d5325dd0771bbf9e2ae213e88f9 Reviewed-by: Arvid Nilsson <anilsson@blackberry.com> Reviewed-by: Pierre Rossi <pierre.rossi@gmail.com>
-rw-r--r--src/qobject.js6
-rw-r--r--tests/qml/tst_metaobjectpublisher.qml77
-rw-r--r--tests/qml/wrapper.html32
3 files changed, 114 insertions, 1 deletions
diff --git a/src/qobject.js b/src/qobject.js
index cbff4f1..048295c 100644
--- a/src/qobject.js
+++ b/src/qobject.js
@@ -71,6 +71,12 @@ function QObject(name, data, webChannel)
qObject.destroyed.connect(function() {
if (webChannel.objectMap[objectId] === qObject) {
delete webChannel.objectMap[objectId];
+ // reset the now deleted QObject to an empty {} object
+ // just assigning {} though would not have the desired effect, but the
+ // below also ensures all external references will see the empty map
+ for (var prop in qObject) {
+ delete qObject[prop];
+ }
}
});
return qObject;
diff --git a/tests/qml/tst_metaobjectpublisher.qml b/tests/qml/tst_metaobjectpublisher.qml
index 6f1d825..afbf624 100644
--- a/tests/qml/tst_metaobjectpublisher.qml
+++ b/tests/qml/tst_metaobjectpublisher.qml
@@ -57,6 +57,24 @@ WebChannelTest {
property var foo: 1
property var bar: 1
}
+ QtObject {
+ id: myFactory
+ function create(id)
+ {
+ return component.createObject(myFactory, {objectName: id});
+ }
+ }
+
+ Component {
+ id: component
+ QtObject {
+ property var myProperty : 0
+ function myMethod(arg) {
+ mySignal(arg, myProperty);
+ }
+ signal mySignal(var arg1, var arg2)
+ }
+ }
MetaObjectPublisher {
id: publisher
@@ -76,7 +94,8 @@ WebChannelTest {
{
publisher.registerObjects({
"myObj": myObj,
- "myOtherObj": myOtherObj
+ "myOtherObj": myOtherObj,
+ "myFactory": myFactory
});
}
@@ -188,4 +207,60 @@ WebChannelTest {
awaitIdle();
}
+ function test_wrapper()
+ {
+ loadUrl("wrapper.html");
+ awaitInit();
+
+ var msg = awaitMessage();
+ compare(msg.data.type, "Qt.invokeMethod");
+ compare(msg.data.object, "myFactory");
+ compare(msg.data.method, "create");
+
+ awaitIdle();
+
+ msg = awaitMessage();
+ compare(msg.data.type, "Qt.connectToSignal");
+ compare(msg.data.signal, "destroyed");
+ verify(msg.data.object);
+ var objId = msg.data.object;
+ var obj = publisher.unwrapObject(objId);
+ verify(obj);
+ compare(obj.objectName, "testObj");
+
+ msg = awaitMessage();
+ compare(msg.data.type, "Qt.connectToSignal");
+ compare(msg.data.object, objId);
+ compare(msg.data.signal, "mySignal");
+
+ msg = awaitMessage();
+ compare(msg.data.type, "Qt.setProperty");
+ compare(msg.data.object, objId);
+ compare(obj.myProperty, 42);
+
+ msg = awaitMessage();
+ compare(msg.data.type, "Qt.invokeMethod");
+ compare(msg.data.object, objId);
+ compare(msg.data.method, "myMethod");
+ compare(msg.data.args, ["foobar"]);
+
+ msg = awaitMessage();
+ compare(msg.data.label, "signalReceived");
+ compare(msg.data.args, ["foobar", 42]);
+
+ // pass QObject* on the fly and trigger deleteLater from client side
+ webChannel.sendMessage("triggerDelete");
+ awaitIdle();
+
+ msg = awaitMessage();
+ compare(msg.data.type, "Qt.invokeMethod");
+ compare(msg.data.object, objId);
+ compare(msg.data.method, "deleteLater");
+ verify(!publisher.unwrapObject(objId));
+
+ webChannel.sendMessage("report");
+ msg = awaitMessage();
+ compare(msg.data.label, "report");
+ compare(msg.data.obj, {});
+ }
}
diff --git a/tests/qml/wrapper.html b/tests/qml/wrapper.html
new file mode 100644
index 0000000..a6c313b
--- /dev/null
+++ b/tests/qml/wrapper.html
@@ -0,0 +1,32 @@
+<html>
+ <head>
+ <script type="text/javascript" src="qrc:///qwebchannel/webchannel.js"></script>
+ <script type="text/javascript" src="qrc:///qwebchannel/qobject.js"></script>
+ <script type="text/javascript">
+ //BEGIN SETUP
+ var baseUrl = (/[?&]webChannelBaseUrl=([A-Za-z0-9\-:/\.]+)/.exec(location.search)[1]);
+ new QWebChannel(baseUrl, function(channel) {
+ setupQObjectWebChannel(channel, function() {
+ myFactory.create("testObj", function(obj) {
+ window[obj.objectName()] = obj;
+ obj.mySignal.connect(function(arg1, arg2) {
+ channel.exec({label: "signalReceived", args: [arg1, arg2]});
+ });
+ obj.myProperty = 42;
+ obj.myMethod("foobar");
+ });
+ channel.subscribe("triggerDelete", function() {
+ console.log(testObj);
+ testObj.deleteLater();
+ });
+ channel.subscribe("report", function() {
+ channel.exec({label:"report", obj: testObj})
+ });
+ });
+ });
+ //END SETUP
+ </script>
+ </head>
+ <body>
+ </body>
+</html>