diff options
| author | Géry Debongnie <ged@odoo.com> | 2021-03-15 11:27:05 +0000 |
|---|---|---|
| committer | Géry Debongnie <ged@odoo.com> | 2021-03-15 15:04:16 +0000 |
| commit | b88b634a0363a55411290e54e37806cfec1b2de5 (patch) | |
| tree | 21a551bb817646e638e6ead255c14f0d6d354c1f /addons | |
| parent | 4445207161c84d2854055df63013c1361e5d4697 (diff) | |
[FIX] web_tour: make tour system more resilient
The tour system is based on many assumptions, some of those not being
true all the time. In practice, it works most of the time, but when
some slight changes occurs, we may observe undeterministic behavior.
This was actually the case in a dev branch working on assets: the order
of some files was changed, and it caused crashes in various tours.
This helped us identify two issues in the Tip class:
- the Tip class may be destroyed before it is completely started (so,
the destroy method should not assume that the code in start was called
- the attach_to method should not resolve if the tip was destroyed
meanwhile. This is critical, because some code uses that promise to act
on the widget.
This commit fixes both of these issues.
closes odoo/odoo#67872
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/web_tour/static/src/js/tip.js | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/addons/web_tour/static/src/js/tip.js b/addons/web_tour/static/src/js/tip.js index 98372d33dc2..f1b4a6a0d4a 100644 --- a/addons/web_tour/static/src/js/tip.js +++ b/addons/web_tour/static/src/js/tip.js @@ -57,12 +57,15 @@ var Tip = Widget.extend({ * Attaches the tip to the provided $anchor and $altAnchor. * $altAnchor is an alternative trigger that can consume the step. The tip is * however only displayed on the $anchor. + * + * Note that the returned promise stays pending if the Tip widget was + * destroyed in the meantime. * * @param {jQuery} $anchor the node on which the tip should be placed * @param {jQuery} $altAnchor an alternative node that can consume the step * @return {Promise} */ - attach_to: function ($anchor, $altAnchor) { + attach_to: async function ($anchor, $altAnchor) { this._setupAnchor($anchor, $altAnchor); this.is_anchor_fixed_position = this.$anchor.css("position") === "fixed"; @@ -70,7 +73,10 @@ var Tip = Widget.extend({ // The body never needs to have the o_tooltip_parent class. It is a // safe place to put the tip in the DOM at initialization and be able // to compute its dimensions and reposition it if required. - return this.appendTo(document.body); + await this.appendTo(document.body); + if (this.isDestroyed()) { + return new Promise(() => {}); + } }, start() { this.$tooltip_overlay = this.$(".o_tooltip_overlay"); @@ -132,8 +138,12 @@ var Tip = Widget.extend({ $el.removeClass("o_tooltip_parent"); } }; - _removeParentClass(this.$ideal_location); - _removeParentClass(this.$furtherIdealLocation); + if (this.$el && this.$ideal_location) { + _removeParentClass(this.$ideal_location); + } + if (this.$el && this.$furtherIdealLocation) { + _removeParentClass(this.$furtherIdealLocation); + } return this._super.apply(this, arguments); }, @@ -393,9 +403,15 @@ var Tip = Widget.extend({ return $consumeEventAnchors; }, _unbind_anchor_events: function () { - this.$anchor.off(".anchor"); - this.$consumeEventAnchors.off(".anchor"); - this.$scrolableElement.off('.Tip'); + if (this.$anchor) { + this.$anchor.off(".anchor"); + } + if (this.$consumeEventAnchors) { + this.$consumeEventAnchors.off(".anchor"); + } + if (this.$scrolableElement) { + this.$scrolableElement.off('.Tip'); + } }, _get_spaced_inverted_position: function (position) { if (position === "right") return "left+" + this.info.space; |
