FLUID-4722: Need some framework support for clearing listeners that belong to components that have shorter lifecycle than the event firer.

Metadata

Source
FLUID-4722
Type
Improvement
Priority
Major
Status
Closed
Resolution
Fixed
Assignee
Antranig Basman
Reporter
y z
Created
2012-06-14T14:50:43.037-0400
Updated
2014-03-03T12:51:29.081-0500
Versions
  1. 1.4
Fixed Versions
  1. 1.5
Component
  1. Framework

Description

There is a lingering issue where there might be some additional framework support necessary at the time when the component is being cleared away. In particular this issue is very evident when the component that is being cleared attached listener(s) to the event(s) that have longer lifecycle that the component itself. Even though the component will be cleared away, the listener that is nothing but a function object is still present and will be executed on event fire.

Proposed solution would require an addition of another lifecycle function that is only executed on the component clearance - a so called clearFunction. This function is the last point where there's a chance to remove such listeners. Also, we can impose an informal contract where the user would not need to declare such clear function if the listener(s) are specified declaratively and with a namespace. For that to work we would need to implement a "default" clearFunction for "fluid.eventedComponent" grade that will automatically clear all such listeners from the component.

Here's a pasted patch that I used in cspace's infusion :
— a/src/main/webapp/defaults/lib/infusion/CSpaceInfusion.js
+++ b/src/main/webapp/defaults/lib/infusion/CSpaceInfusion.js
-11157,7 +11157,8 var fluid = fluid || fluid_1_5;
fluid.lifecycleFunctions = {
preInitFunction: true,
postInitFunction: true,

  • finalInitFunction: true
    + finalInitFunction: true,
    + clearFunction: false
    };


fluid.rootMergePolicy = fluid.transform(fluid.lifecycleFunctions, function () {
-11275,11 +11276,26 var fluid = fluid || fluid_1_5;
options: 0
}
});
+
+ fluid.clearEventedComponent = function (that) {
+ // Remove all declaratively attached event listeners that have a namespace.
+ fluid.each(that.options.listeners, function (listener, eventName) {
+ var namespace = listener.namespace;
+ if (!namespace) {
+ return;
+ }
+ that.events[eventName].removeListener(namespace);
+ });
+ };

fluid.defaults("fluid.eventedComponent", {
gradeNames: ["fluid.littleComponent"],
mergePolicy: {
listeners: fluid.mergeListenersPolicy
+ },
+ clearFunction: {
+ namespace: "clearEventedComponent",
+ listener: "fluid.clearEventedComponent"
}
});

-11556,6 +11572,9 var fluid = fluid || fluid_1_5;

fluid.clearLifecycleFunctions = function (options) {
fluid.each(fluid.lifecycleFunctions, function (value, key) {
+ if (!value) {
+ return;
+ }
delete options[key];
});
delete options.initFunction;
-14710,6 +14729,7 var fluid_1_5 = fluid_1_5 || {};
that.clearComponent = function(component, name, child, options, noModTree) {
options = options || {visited: {}, flat: true};
child = child || component[name];
+ fluid.fireEvent(child.options.clearFunction, child);
fluid.visitComponentChildren(child, function(gchild, gchildname) {
that.clearComponent(child, gchildname, null, options, noModTree);
}, options);

Environments

Any

Comments

  • Antranig Basman commented 2012-08-16T02:27:21.598-0400

    These events and also framework assistance for auto-removal of listeners added through boiling will be provided as part of the FLUID-4257 work

  • Antranig Basman commented 2012-08-22T14:59:02.215-0400

    Functionality delivered for FLUID-4257 now includes support for automatically deregistering listeners which were attached from components with shorter scopes. We probably need some more test cases to cover a few more special cases. The semantic implemented is that listeners that are registered BY any component - that is - which appear in its configuration - are cleared when the component is cleared - whether the listeners actually bind onto the cleared component or not.