On Thu, 10 Sep 2026 20:29:10 GMT, Marius Hanl <[email protected]> wrote:

>> Another much better try to fix the issue.
>> I recommend to read: https://github.com/openjdk/jfx/pull/2201 first. All 
>> tests from there are included. 
>> I added some new ones that succeed before and after, a first step for more 
>> CSS tests as discussed in: 
>> https://github.com/openjdk/jfx/pull/2218#issuecomment-5094495306
>> 
>> My new idea is now the following constraint, which I think is also a much 
>> better approach:
>> - A `CssStyleHelper` always has a correct `firstStyleableAncestor`. We can 
>> at any time trust and rely on it.
>> - We will also reuse the existing loop for the `isUserSetFont` check to 
>> improve the performance a bit
>> 
>> Implementation:
>> - We now save a flag to exactly know in which CSS state the `Node` is.
>> - We will collect all `Node`s in the scene tree once and then reuse the list 
>> when we need to process a stale `styleHelper` from a parent.
>>   - This will make sure we do no process the parent again and again when we 
>> have some stale `styleHelper`s in the chain 
>> - Not every `Node` has a `styleHelper` - it is only created when needed, so 
>> we can not attach the flag in there.
>> 
>> This fixes the issue while a deep (optionally unstyled) scene graph has no 
>> performance penality.
>> The approach is similar than my previous PR, but more smart. And with the 
>> set constraint mentioned above.
>> 
>> ---
>> 
>> I do think we can improve the `CssStyleHelper` more. But for another day. 
>> Maybe at one point, with more tests and when all requirements are clear, we 
>> can find a way without `CssHelperState` and without creating an empty 
>> `CssStyleHelper` just to hold trigger states (because of that, we need to 
>> check `styleHelper.cacheContainer != null` a lot of times).
>> 
>> 
>> ---------
>> - [x] I confirm that I make this contribution in accordance with the 
>> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
>
> Marius Hanl has updated the pull request incrementally with two additional 
> commits since the last revision:
> 
>  - idea how to fix that issue
>  - failing test

modules/javafx.graphics/src/main/java/javafx/scene/CssStyleHelper.java line 108:

> 106:             if (ancestor.cssHelperStale) {
> 107:                 ancestor.cssHelperResolvedEarly = true;
> 108:                 updateStyleHelper(ancestor, path, index, 
> styleableAncestor, userSetFont);

it looks like we still have quadratic work here: for each stale ancestor, we 
allocate `triggerStates` array at L153 and when the style map changed, 
CacheContainer scans another ancestor at L419

CssStyleHelperTest counts only `getStyleableParent()` but track neither these 
scans nor allocations.

modules/javafx.graphics/src/main/java/javafx/scene/CssStyleHelper.java line 118:

> 116:         }
> 117: 
> 118:         if (recreatedAncestor && !isPathValid(path)) {

another scenario: reparenting an ancestor under a different parent.  in this 
case, the remaining loop rebuilds the ancestor using old path and clears the 
`cssHelperStale` flag in L142.  the recursive call follows the new path, but 
because it sees the state no longer stale it skips the ancestor.

modules/javafx.graphics/src/main/java/javafx/scene/CssStyleHelper.java line 142:

> 140:         }
> 141: 
> 142:         node.cssHelperStale = false;

I think we are hitting the same problem as before: the `cssHelperStale` flag is 
cleared while the old helper is still there.

This is a problem because code that runs after that might execute application 
logic that re-enters the CSS processing and sees the stale helper.

I don't know what the solution might be - either a separate `RESOLVING` state, 
or moving this flag to the helper itself, or discarding the helper, or what?

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/2225#discussion_r4029139494
PR Review Comment: https://git.openjdk.org/jfx/pull/2225#discussion_r4029071750
PR Review Comment: https://git.openjdk.org/jfx/pull/2225#discussion_r4028909401

Reply via email to