[FIX] web: prevent destroyed widget from calling start (2)

This completes a commit that was made for the version saas-11.3 (12.0):
https://github.com/odoo/odoo/commit/1440c8be0337c89e3d67d6d93e614c269c8689f1

Indeed, the logic was implemented for the appendTo, prependTo, etc
methods but not for the attachTo...
This could solve unknown problems in stable versions as well but was
judged too risky to merge there. Indeed, if a real problem occurs in a
stable version because of this, the condition can be added to the
related widget individually.

The problem was found in master: during website edition, the public
widgets can be restarted if an element is edited... but sometimes the
public widgets may be restarted in the same JS stack execution. The
willStart method being async, the destroy method was called before
the start method. This does not lead not any known problem with our
current widgets but will create one for a new snippet being implemented.

closes odoo/odoo#39949

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
qsm-odoo
2019-11-07 12:10:59 +00:00
parent 7a18176c86
commit 60d1e26f9a
2 changed files with 15 additions and 9 deletions
+3
View File
@@ -204,6 +204,9 @@ var Widget = core.Class.extend(mixins.PropertiesMixin, ServicesMixin, {
var self = this;
this.setElement(target.$el || target);
return this.willStart().then(function () {
if (self.__parentedDestroyed) {
return;
}
return self.start();
});
},
+12 -9
View File
@@ -452,21 +452,24 @@ QUnit.module('core', {}, function () {
QUnit.test('start is not called when widget is destroyed', function (assert) {
assert.expect(0);
var slowWillStartPromise = testUtils.makeTestPromise();
var $fix = $( "#qunit-fixture");
const $fix = $("#qunit-fixture");
var widget = new (Widget.extend({
willStart: function () {
return slowWillStartPromise;
},
// Note: willStart is always async
const MyWidget = Widget.extend({
start: function () {
throw new Error('Should not call start method');
assert.ok(false, 'Should not call start method');
},
}))();
});
const widget = new MyWidget();
widget.appendTo($fix);
widget.destroy();
slowWillStartPromise.resolve();
const divEl = document.createElement('div');
$fix[0].appendChild(divEl);
const widget2 = new MyWidget();
widget2.attachTo(divEl);
widget2.destroy();
});
QUnit.test("don't destroy twice widget's children", function (assert) {