eirikbakke commented on a change in pull request #652:
URL: https://github.com/apache/netbeans/pull/652#discussion_r479722069



##########
File path: openide.awt/src/org/openide/awt/ContextAction.java
##########
@@ -181,36 +317,90 @@ public Performer(
             ContextActionEnabler<Data> e
         ) {
             Map<Object, Object> map = new HashMap<Object, Object>();
-            map.put("delegate", p);
-            map.put("enabler", e);
+            map.put("delegate", p); // NOI18N
+            map.put("enabler", e);  // NOI18N
             this.delegate = map;
         }
-
-        @SuppressWarnings("unchecked")
-        public void actionPerformed(
-            ActionEvent ev, List<? extends Data> data, Lookup.Provider 
everything
-        ) {
-            Object obj = delegate.get("delegate"); // NOI18N
-            if (obj instanceof ContextActionPerformer) {
-                ContextActionPerformer<Data> perf = 
(ContextActionPerformer<Data>)obj;
-                perf.actionPerformed(ev, data);
-                return;
+        
+        void clear() {
+            stopListeners();
+            Reference r = instDelegate;
+            instDelegate = null;
+            if (r != null) {
+                Object o = r.get();
+                if (o instanceof Performer) {
+                    ((Performer)o).clear();
+                }
             }
-            if (obj instanceof Performer) {
-                Performer<Data> perf = (Performer<Data>)obj;
-                perf.actionPerformed(ev, data, everything);
-                return;
+        }
+        
+        void attach(ContextAction a) {
+            this.owner = new WeakReference<>(a);
+        }
+        
+        /**
+         * Creates a delegate. 
+         * @param everything
+         * @param data
+         * @return 
+         */
+        Object delegate(Lookup.Provider everything, List<?> data) {
+            return delegate0(everything, data, true);
+        }
+        
+        private Object delegate0(Lookup.Provider everything, List<?> data, 
boolean getAction) {
+            Object d = instDelegate != null ? instDelegate.get() : null;

Review comment:
       There seems to be a bug here, which I bumped into this month in my 
NetBeans Platform application. It seems that delegate0 will use a cached copy 
of the instDelegate--but what if the contents of the lookup (the data 
parameter) has changed?
   
   I see there's a clear() method that's supposed to reset instDelegate in 
certain cases, but I'm not sure how it works--and it does not seem to be called 
in all cases where the lookup has changed.
   
   The bug is insidious because instDelegate is a weak reference, so the buggy 
state disappears on garbage collection.
   
   In my platform application, the action in question is declared like this:
   
   ```
   @ActionID(category = "Ultorg", id = "com.ultorg.actionids.FieldsAction")
   @ActionRegistration(displayName = "#CTL_FieldsAction")
   @Messages("CTL_FieldsAction=Fields & Joins...")
   public class FieldsAction implements ActionListener {
     private final ToolboxInvoker invoker;
   
     public FieldsAction(ToolboxInvoker invoker) {
       Preconditions.checkNotNull(invoker);
       this.invoker = invoker;
     }
   
     @Override
     public void actionPerformed(ActionEvent e) {
       invoker.invoke();
     }
   }
   ```
   
   The ToolboxInvoker is exposed in the lookup of a TopComponent subclass. 
Invoking the action from the keyboard will occasionally trigger the wrong 
FieldsAction instance. Once this happens, it will usually happen again and 
again if the keyboard shortcut is pressed again, until a garbage collection 
happens (tested by adding a keyboard shortcut to the Garbage Collect action). 
The cause of the bug seems to be incorrect state kept around in the 
instDelegate variable (confirmed in the debugger).
   
   Is this the same as the bug described in 
https://issues.apache.org/jira/browse/NETBEANS-1985 ?




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to