tweener: Save handlers on target and remove them on destroy

Saving handlers we had using the wrapper as a property of the object and delete
them when resetting the object state.
Without doing this an handler could be called on a destroyed target when this
happens on the onComplete callback.

https://bugzilla.gnome.org/show_bug.cgi?id=791233
This commit is contained in:
Marco Trevisan (Treviño) 2017-12-05 02:41:50 +01:00 committed by Ray Strode
parent 6622fae6bd
commit c227be4325

View File

@ -69,30 +69,67 @@ function _getTweenState(target) {
return target.__ShellTweenerState;
}
function _ensureHandlers(target) {
if (!target.__ShellTweenerHandlers)
target.__ShellTweenerHandlers = {};
return target.__ShellTweenerHandlers;
}
function _resetTweenState(target) {
let state = target.__ShellTweenerState;
if (state) {
if (state.destroyedId)
if (state.destroyedId) {
state.actor.disconnect(state.destroyedId);
delete state.destroyedId;
}
}
_removeHandler(target, 'onComplete', _tweenCompleted);
target.__ShellTweenerState = {};
}
function _addHandler(target, params, name, handler) {
if (params[name]) {
let oldHandler = params[name];
let oldScope = params[name + 'Scope'];
let oldParams = params[name + 'Params'];
let eventScope = oldScope ? oldScope : target;
let wrapperNeeded = false;
let tweenerHandlers = _ensureHandlers(target);
params[name] = () => {
oldHandler.apply(eventScope, oldParams);
handler(target);
};
} else
params[name] = () => { handler(target); };
if (!(name in tweenerHandlers)) {
tweenerHandlers[name] = [];
wrapperNeeded = true;
}
let handlers = tweenerHandlers[name];
handlers.push(handler);
if (wrapperNeeded) {
if (params[name]) {
let oldHandler = params[name];
let oldScope = params[name + 'Scope'];
let oldParams = params[name + 'Params'];
let eventScope = oldScope ? oldScope : target;
params[name] = () => {
oldHandler.apply(eventScope, oldParams);
handlers.forEach((h) => h(target));
};
} else {
params[name] = () => { handlers.forEach((h) => h(target)); };
}
}
}
function _removeHandler(target, name, handler) {
let tweenerHandlers = _ensureHandlers(target);
if (name in tweenerHandlers) {
let handlers = tweenerHandlers[name];
let handlerIndex = handlers.indexOf(handler);
while (handlerIndex > -1) {
handlers.splice(handlerIndex, 1);
handlerIndex = handlers.indexOf(handler);
}
}
}
function _actorDestroyed(target) {