Commit 42306bb0 authored by Romain Courteaud's avatar Romain Courteaud Committed by Gabriel Monnerat

Allow to cancel method call in an iframe gadget

parent 9a7a349a
......@@ -379,12 +379,12 @@
obj[pathItems[pathItems.length - 1]] = (function() {
var cbName = path;
return function(params) {
return trans.invoke(cbName, params);
return trans.invoke(cbName, params, m.id);
};
})();
}
}
var resp = regTbl[method](trans, m.params);
var resp = regTbl[method](trans, m.params, m.id);
if (!trans.delayReturn() && !trans.completed()) trans.complete(resp);
} catch(e) {
// automagic handling of exceptions:
......@@ -580,6 +580,8 @@
s_curTranId++;
postMessage(msg);
// return the transaction id
return s_curTranId - 1;
},
notify: function(m) {
if (!m) throw 'missing arguments to notify function';
......
......@@ -1022,9 +1022,10 @@
function handleChannelDeclareMethod(trans, method_name) {
gadget_instance[method_name] = function triggerChannelDeclareMethod() {
var argument_list = arguments,
channel_call_id,
wait_promise = new RSVP.Promise(
function handleChannelCall(resolve, reject) {
gadget_instance.__chan.call({
channel_call_id = gadget_instance.__chan.call({
method: "methodCall",
params: [
method_name,
......@@ -1032,6 +1033,15 @@
success: resolve,
error: reject
});
},
function cancelChannelCall(msg) {
gadget_instance.__chan.notify({
method: "cancelMethodCall",
params: [
channel_call_id,
msg
]
});
}
);
......@@ -1883,6 +1893,7 @@
function finishAqParentConfiguration(TmpConstructor, root_gadget,
embedded_channel) {
var local_transaction_dict = {};
// Define __aq_parent to inform parent window
root_gadget.__aq_parent =
TmpConstructor.prototype.__aq_parent = function aq_parent(method_name,
......@@ -1905,14 +1916,31 @@
};
// bind calls to renderJS method on the instance
embedded_channel.bind("methodCall", function methodCall(trans, v) {
root_gadget[v[0]].apply(root_gadget, v[1])
.push(trans.complete,
function handleMethodCallError(e) {
embedded_channel.bind("methodCall",
function methodCall(trans, v, transaction_id) {
local_transaction_dict[transaction_id] =
root_gadget[v[0]].apply(root_gadget, v[1])
.push(function handleMethodCallSuccess() {
// drop the promise reference, to allow garbage collection
delete local_transaction_dict[transaction_id];
trans.complete.apply(trans, arguments);
}, function handleMethodCallError(e) {
// drop the promise reference, to allow garbage collection
delete local_transaction_dict[transaction_id];
trans.error(e.toString());
});
trans.delayReturn(true);
});
trans.delayReturn(true);
});
embedded_channel.bind("cancelMethodCall",
function cancelMethodCall(trans, v) {
if (local_transaction_dict.hasOwnProperty(v[0])) {
local_transaction_dict[v[0]].cancel(v[1]);
// drop the promise reference, to allow garbage collection
delete local_transaction_dict[v[0]];
}
});
}
function bootstrap(url) {
......
......@@ -26,6 +26,7 @@
service_started = false,
job_started = false,
event_started = false,
method_cancel_called = false,
state_change_callback_called = false,
state_change_count = 0,
init_state = {bar: 'foo'},
......@@ -110,6 +111,16 @@
'acquireMethodRequestedWithAcquisitionError')
.declareMethod('callErrorAcquire', function (param1, param2) {
return this.plugErrorAcquire(param1, param2);
})
.declareMethod('triggerMethodToCancel', function () {
return new RSVP.Promise(function () {
return;
}, function () {
method_cancel_called = true;
});
})
.declareMethod('wasMethodCancelCalled', function () {
return method_cancel_called;
});
}(window, rJS));
......@@ -5667,7 +5667,7 @@
gadget.__sub_gadget_dict = {};
stop();
expect(23);
expect(25);
gadget.declareGadget(url, {
sandbox: 'iframe',
element: document.getElementById('qunit-fixture'),
......@@ -5846,6 +5846,25 @@
"acquireMethodRequestedWithAcquisitionError",
error
);
})
// cancel call is correctly propagated by declareMethod
.push(function () {
var method_to_cancel = new_gadget.triggerMethodToCancel();
return new RSVP.Queue(RSVP.delay(400))
.push(function () {
return RSVP.all([
method_to_cancel,
method_to_cancel.cancel()
]);
});
})
.push(undefined, function (error) {
ok(error instanceof RSVP.CancellationError, error);
return new_gadget.wasMethodCancelCalled();
})
.push(function (result) {
ok(result, 'Embedded method not cancelled');
});
})
.fail(function (error) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment