[IMP] web: protect _rpc calls on destroyed widgets

It might happen that some code in a widget (callbacks given to
other function calls) is executed after the widget's destruction.
For example, trigger an event up with a callback in option, the
event is handled by a parent that performs an rpc, meanwhile, the
child widget is destroyed, then, the rpc returns and the parent
executes the callback.

This shouldn't happen, because it means that the callback is
executed for nothing. Worst, it crashes if the function _rpc is
called inside the callback, because the widget being destroyed,
there is no parent to handle the request, and _rpc thus returns
undefined.

This rev. protects the code from crashing by making _rpc return
a pending deferred instead of undefined.
This commit is contained in:
Aaron Bohy
2017-04-11 19:44:38 +02:00
parent ec9001eb9d
commit b6ce7b136f
2 changed files with 18 additions and 3 deletions
+5 -3
View File
@@ -447,15 +447,17 @@ var ServicesMixin = {
return result;
},
/**
* Build a RPC query
* Builds and executes RPC query. Returns a deferred's promise resolved with
* the RPC result.
*
* @param {string} arg1 either a route or a model
* @param {string} method if a model is given, this argument is a method
* @returns {RPCBuilder}
* @returns {Deferred's Promise}
*/
_rpc: function (params, options) {
var query = rpc.buildQuery(params);
return this.call('ajax', 'rpc', query.route, query.params, options);
var def = this.call('ajax', 'rpc', query.route, query.params, options);
return def ? def.promise() : $.Deferred().promise();
},
loadFieldView: function (dataset, view_id, view_type, options) {
return this.loadViews(dataset.model, dataset.get_context(), [[view_id, view_type]], options).then(function (result) {
@@ -377,6 +377,19 @@ QUnit.module('core', {}, function () {
done();
});
});
QUnit.test("calling _rpc on destroyed widgets", function (assert) {
assert.expect(1);
var widget = new Widget();
widget.destroy();
widget._rpc({route: '/a/route'}).always(function () {
throw Error("Calling _rpc on a destroyed widget should return a " +
"deferred that is never resolved nor rejected");
});
assert.ok(true,
"there should be no crash when calling _rpc on a destroyed widget");
});
});
});