Skip to content

Comments

selectedcontent element mutation record test is wrong#55849

Open
annevk wants to merge 1 commit intomasterfrom
annevk/selectedcontent-mutations
Open

selectedcontent element mutation record test is wrong#55849
annevk wants to merge 1 commit intomasterfrom
annevk/selectedcontent-mutations

Conversation

@annevk
Copy link
Member

@annevk annevk commented Nov 4, 2025

The replace all primitive uses a single record for additions and removals. With this change my prototype passes the test.

I strongly suspect <option selected><span>span</option> three</option> is also a bug in this test, but I didn't want to change that at the same time.

@josepharhar
Copy link
Contributor

Thanks for looking at this. The reason that there are two separate mutations in chromium is because when the third option, <option selected> is parsed and inserted, it gets cloned into <selectedcontent> two times:

  1. During the option element insertion steps, before the parser has appended children to the option element, because the option is selected. This results in a mutation which just removes all nodes from the selectedcontent element because the option element is empty.
  2. When the option element is done parsing its children because it is selected.

This doesn't match the spec because the option element insertion steps just say to run the selectedness setting algorithm which doesn't clone anything into the selectedcontent element, but I'm not sure if that really is good behavior.

Consider the following:

<select id=select>
  <button>
    <selectedcontent></selectedcontent>
  </button>
  <option>one</option>
</select>
<script>
  const option = document.createElement('option');
  option.setAttribute('selected', '');
  option.textContent = 'two';
  select.appendChild(option);
</script>

I think that the selectedcontent element definitely needs to be updated for the newly selected option in this case, which can only be done through the option element insertion steps, right?

I think this was an oversight when I wrote this part of the spec, unless I'm missing something. I think it would probably be best to update the selectedcontent element in the selectedness setting algorithm, what do you think?

@annevk
Copy link
Member Author

annevk commented Nov 5, 2025

My prototype handles that as part of "finishParsingChildren". I don't really care strongly what we do I suppose, but I do get the feeling we lack a lot of test coverage (what if your example was created imperatively for instance) as there's only a minimal set of tests for this new element. And also that the specification is somewhat incomplete.

(I spotted Chromium setting <selectedelement>'s disabled to false upon removal, but there's nothing that tests for this, even though you might be able to. Although that also depends on whether or not we start guarding everything with "is connected" checks.)

@josepharhar
Copy link
Contributor

Thanks, I am rewriting the test here and will take a closer look at the spec and chromium implementation here.

josepharhar added a commit to josepharhar/html that referenced this pull request Nov 6, 2025
This PR makes sure that the contents of the selectedcontent element stay
up to date when the selected option is changed in the selectedness
setting algorithm.

This issue was found here:
web-platform-tests/wpt#55849 (comment)
@josepharhar
Copy link
Contributor

This PR should fix the selectedness setting issue: whatwg/html#11890

F3n67u added a commit to F3n67u/ladybird that referenced this pull request Dec 11, 2025
Introduce the HTMLSelectedContentElement and integrate it into
<select>, <option> and HTMLParser.

See whatwg/html#10548.

There are two bugs with WPT tests which causes the third subtest
in selectedcontent.html and selectedcontent-mutations.html fail.
See whatwg/html#11882, web-platform-tests/wpt#55849.
AtkinsSJ pushed a commit to LadybirdBrowser/ladybird that referenced this pull request Dec 12, 2025
Introduce the HTMLSelectedContentElement and integrate it into
<select>, <option> and HTMLParser.

See whatwg/html#10548.

There are two bugs with WPT tests which causes the third subtest
in selectedcontent.html and selectedcontent-mutations.html fail.
See whatwg/html#11882, web-platform-tests/wpt#55849.
@annevk
Copy link
Member Author

annevk commented Jan 14, 2026

@josepharhar after spending quite a lot of time debugging the new tests here I'm still seeing different results from you and when I look at the Chromium code I think I understand why. Chromium has very different insertion and removal logic for selectedcontent elements from that what is standardized. I'm not sure Chromium behavior is desirable as it mostly results in different results for authoring error scenarios.

I also find the arrays this test outputs incredibly hard to debug. Claude AI has been helpful, but that really shouldn't be necessary. Not sure I have great suggestions there though, but maybe some guidance as to what is going on would have helped.

I'm going to update this PR with what I think the test should look like. This will require one further change to the standard for the removal case. I've added an early return there for selectedcontent elements that are disabled. Not much use in doing work for them.

The replace all primitive uses a single record for additions and removals.
@josepharhar
Copy link
Contributor

Chromium has very different insertion and removal logic for selectedcontent elements from that what is standardized.

This is expected until this patch finishes getting reviewed and merged: https://chromium-review.googlesource.com/c/chromium/src/+/7127725

I also find the arrays this test outputs incredibly hard to debug. Claude AI has been helpful, but that really shouldn't be necessary. Not sure I have great suggestions there though, but maybe some guidance as to what is going on would have helped.

Agreed, when working on it locally I added console logging to be able to easily rebaseline the test, but such console logs result in lint errors (even when they are commented out if i remember correctly). I could have made a simpler test, but after hearing you say that we are lacking test coverage, I wanted to make sure that I was comprehensively testing many scenarios.

"Type: childList | Target: button | Added: [#text: \"\"] | After: selectedcontent",
"Type: childList | Target: select | Added: [#text: \"\"] | After: button",
"Type: childList | Target: select | Added: [option] | After: #text: \"\"",
"Type: childList | Target: selectedcontent | Removed: [#text: \"outer1\", selectedcontent, #text: \"\"]",
Copy link
Contributor

Choose a reason for hiding this comment

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

"Type: childList | Target: selectedcontent | Removed: [#text: \"one\"]",
"Type: childList | Target: option | Added: [#text: \"two\"]",
"Type: childList | Target: selectedcontent | Added: [#text: \"two\"]",
"Type: childList | Target: selectedcontent | Added: [#text: \"two\"] | Removed: [#text: \"one\"]",
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this change should be necessary after whatwg/html#11890 but if you want to wait for that PR to be merged first then that's ok

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not entirely sure that is the approach we want. Less mutations seems better. WebKit has a single code path for selecting an option HTMLSelectElement::selectOption() which is where I update the selectedcontent element now. That seems to be doing the right thing in all cases and result in fewer mutations here.

Copy link
Contributor

Choose a reason for hiding this comment

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

In the interest of keeping things moving, I think we can merge this.

I think this test will be significantly rebaselined after we make every selectedcontent element stay updated, so I anticipate we may revisit this later.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants