[ https://issues.apache.org/jira/browse/NETBEANS-3196?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Eirik Bakke updated NETBEANS-3196: ---------------------------------- Description: There's a small bug in org.openide.nodes.Node.setChildren(Children). The logic goes something like this: {code:java} protected final void setChildren(final Children ch) { boolean wasInited = hierarchy.isInitialized(); boolean wasLeaf = hierarchy == Children.LEAF; // ... hierarchy = ch; // ... if (wasInited && hierarchy != Children.LEAF) { // init new children if old was inited hierarchy.getNodesCount(); {code} If a Node's children was originally Children.LEAF, and is then changed to a different instance, the resulting behavior now becomes dependent on the result of Children.LEAF.isInitialized(). The latter is a global piece of state which may return false for a long time until _any_ module anywhere in the IDE or in a platform application calls Children.LEAF.getNodesCount(), after which Children.LEAF.isInitialized() will forever after return true. Once Children.LEAF.getNodesCount() has been called, from any module, Node implementations that switch from Children.LEAF to another Children implementation will no longer get lazy loading behavior. The fix is simple; the condition should be "wasInited && !wasLeaf && hierarchy != Children.LEAF)". It might be good to ensure that Children.LEAF is always initialized as well, to prevent accidentally sharing mutable global state. (Actually, I tried calling Children.LEAF.getNodesCount() on LEAF's initial construction, but this caused a failure on startup. So don't bother.) (This bug was found in a NetBeans Platform application that relies heavily on lazy loading of nodes.) was: There's a small bug in org.openide.nodes.Node.setChildren(Children). The logic goes something like this: {code:java} protected final void setChildren(final Children ch) { boolean wasInited = hierarchy.isInitialized(); boolean wasLeaf = hierarchy == Children.LEAF; // ... hierarchy = ch; // ... if (wasInited && hierarchy != Children.LEAF) { // init new children if old was inited hierarchy.getNodesCount(); {code} If a Node's children was originally Children.LEAF, and is then changed to a different instance, the resulting behavior now becomes dependent on the result of Children.LEAF.isInitialized(). The latter is a global piece of state which may return false for a long time until _any_ module anywhere in the IDE or in a platform application calls Children.LEAF.getNodesCount(), after which Children.LEAF.isInitialized() will forever after return true. Once Children.LEAF.getNodesCount() has been called, from any module, Node implementations that switch from Children.LEAF to another Children implementation will no longer get lazy loading behavior. The fix is simple; the condition should be "wasInited && !wasLeaf && hierarchy != Children.LEAF)". It might be good to ensure that Children.LEAF is always initialized as well, to prevent accidentally sharing mutable global state. I will create a patch for this at some point, once I have made sure it doesn't cause any problems. (This bug was found in a NetBeans Platform application that relies heavily on lazy loading of nodes.) > Calling Children.LEAF.getNodesCount() changes lazy loading behavior globally > ---------------------------------------------------------------------------- > > Key: NETBEANS-3196 > URL: https://issues.apache.org/jira/browse/NETBEANS-3196 > Project: NetBeans > Issue Type: Improvement > Components: platform - Nodes > Affects Versions: 11.0 > Reporter: Eirik Bakke > Priority: Minor > Labels: pull-request-available > Time Spent: 10m > Remaining Estimate: 0h > > There's a small bug in org.openide.nodes.Node.setChildren(Children). The > logic goes something like this: > {code:java} > protected final void setChildren(final Children ch) { > boolean wasInited = hierarchy.isInitialized(); > boolean wasLeaf = hierarchy == Children.LEAF; > // ... > hierarchy = ch; > // ... > if (wasInited && hierarchy != Children.LEAF) { > // init new children if old was inited > hierarchy.getNodesCount(); > {code} > If a Node's children was originally Children.LEAF, and is then changed to a > different instance, the resulting behavior now becomes dependent on the > result of Children.LEAF.isInitialized(). The latter is a global piece of > state which may return false for a long time until _any_ module anywhere in > the IDE or in a platform application calls Children.LEAF.getNodesCount(), > after which Children.LEAF.isInitialized() will forever after return true. > Once Children.LEAF.getNodesCount() has been called, from any module, Node > implementations that switch from Children.LEAF to another Children > implementation will no longer get lazy loading behavior. > The fix is simple; the condition should be "wasInited && !wasLeaf && > hierarchy != Children.LEAF)". > It might be good to ensure that Children.LEAF is always initialized as well, > to prevent accidentally sharing mutable global state. (Actually, I tried > calling Children.LEAF.getNodesCount() on LEAF's initial construction, but > this caused a failure on startup. So don't bother.) > (This bug was found in a NetBeans Platform application that relies heavily on > lazy loading of nodes.) -- This message was sent by Atlassian Jira (v8.3.4#803005) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists