Skip to content

Prevent infinite loop in revealing algorithms #11457

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

josepharhar
Copy link
Contributor

@josepharhar josepharhar commented Jul 15, 2025

The ancestor details revealing algorithm and the hidden until found revealing algorithm may both get stuck in infinite loops because they iterate the flat tree while firing synchronous events. If the page were to listen to these events and change the flat tree in response, then the algorithm could theoretically never end.

Fixes #11436

(See WHATWG Working Mode: Changes for more details.)


/browsing-the-web.html ( diff )
/interaction.html ( diff )
/interactive-elements.html ( diff )

The ancestor details revealing algorithm and the hidden until found
revealing algorithm may both get stuck in infinite loops because they
iterate the flat tree while firing synchronous events. If the page were
to listen to these events and change the flat tree in response, then the
algorithm could theoretically never end.

Fixes whatwg#11436
@nt1m nt1m requested a review from annevk July 15, 2025 20:32
Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Editorially LGTM, although some implementer review from @nt1m and/or @jnjaeschke would be appreciated.

Copy link
Member

@nt1m nt1m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think going through every single ancestor twice is very unefficient. The second loop should only go through relevant elements, rather than all of the ancestors again. I know it may result in some behavior difference in some very specific edge cases, but I'd rather have an efficient algorithm here.

@annevk
Copy link
Member

annevk commented Jul 16, 2025

Yeah, this seems like the right time to combine these algorithms so we only do a single tree walk. That's an observable change in behavior due to the events, but I think it's very much an acceptable one. And if we ever add more cases we care about we don't end up with ever more ancestor walks.

@nt1m
Copy link
Member

nt1m commented Jul 16, 2025

Just to be clear, I was pointing out that the current PR collects all the ancestors into a list for both algorithms, instead of only the relevant ones for each algorithm, which is different from what Anne mentioned in the previous comment.

(But having 1 reveal algorithm instead of 2 separate ones as Anne suggests wouldn't be something I'm opposed to, if the change in order of events/revealing makes sense for web developers)

@annevk
Copy link
Member

annevk commented Jul 16, 2025

@nt1m and I discussed this some more and while in theory you could do a single ancestor walk and collect the nodes to dispatch events on in separate lists depending on the feature, my suspicion is that it would be more useful for web developers if the events are also collapsed into a single reverse-tree-ordered list.

@josepharhar
Copy link
Contributor Author

Thanks, I combined the algorithms and only stored relevant nodes for the second traversal. How does it look?

Copy link
Member

@annevk annevk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After we fire the first event, do we want to check for each node we go through that it's still connected?

And maybe check that the pre-conditions are still valid?

And maybe that if any of that is no longer true, we return early as we're no longer sure what we're dealing with.

@josepharhar
Copy link
Contributor Author

After we fire the first event, do we want to check for each node we go through that it's still connected?

And maybe check that the pre-conditions are still valid?

And maybe that if any of that is no longer true, we return early as we're no longer sure what we're dealing with.

I added checks to make sure that each ancestor to reveal is still connected and still has the open attribute if its a details or still has hidden=until-found otherwise, and stop the algorithm if any of those are not true

Copy link
Member

@annevk annevk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good. Couple of nits.

source Outdated
Comment on lines 79883 to 79884
<li><p>If <var>ancestorToReveal</var> does not have the <code
data-x="attr-details-open">open</code> attribute, then return.</p></li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you mean "If ancestorToReveal has the open attribute", though I don't think you want to early return either way here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would we not want to return early if the circumstances have changed since we started collecting the nodes?

Copy link
Member

@nt1m nt1m Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning early means bailing out of the whole algorithm, including other details & hidden=until-found ancestors (e.g. not just the current details element).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I know. I suggested that above. I don't see a reason to continue if web developers have started mutating the tree to this extent.

<li>
<p>If <var>currentNode</var> has the <code data-x="attr-hidden">hidden</code> attribute in the
<span data-x="attr-hidden-until-found-state">Hidden Until Found</span> state, then:</p>
<p>Otherwise:</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if Otherwise is right here, What if the details element also has the hidden=until-found attribute?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I changed the otherwise and some other conditions to account for this. How does it look?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

hidden=until-found and details revealing algorithms can loop infinitely
5 participants