fix: [#2389] form-associated element's form attribute wins over an ancestor <form> - #2392
Open
marciomazza wants to merge 1 commit into
Open
fix: [#2389] form-associated element's form attribute wins over an ancestor <form>#2392marciomazza wants to merge 1 commit into
form attribute wins over an ancestor <form>#2392marciomazza wants to merge 1 commit into
Conversation
…orm> Per the WHATWG form-owner algorithm, a present "form" content attribute is authoritative: the owner is the referenced <form>, or null if the id resolves to nothing or to a non-form element. The ancestor <form> is only consulted when the attribute is absent. happy-dom checked the ancestor first. Adds HTMLFormControlElementUtility.getFormOwner() as the single resolver and routes the 7 built-in get form() getters, radio-group scoping, ValidityState and HTMLFormElement.getFormControlItems() through it. PropertySymbol.formNode keeps its meaning (nearest ancestor <form> only) since it propagates down the tree; the attribute is resolved per-element on read, so no cache invalidation is needed when it changes.
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Resolves #2389
Refs #2371
A form control carrying
form="ownerId"is owned by that<form>, even when it sitsinside another
<form>. happy-dom returned the ancestor<form>instead, socontrol.formandform.elementsdisagreed with the browser. Aformattributepointing at a missing id or a non-
<form>element also leaked the wrong node.Root cause: the seven built-in
get form()getters checked the cached ancestorPropertySymbol.formNodefirst and only fell back to theformattribute; theattribute lookup used
getElementByIdwith no tag check.formNodecan't just bemade attribute-aware —
Node.tspropagates it to descendants, and a<fieldset form="B">has children.The fix: a shared
HTMLFormControlElementUtility.getFormOwner()— attribute present →resolve by id within the element's root (connected or not), return it only if it's a
<form>, elsenull; attribute absent → the cached ancestorformNode. It now backsthe seven
get form()getters, radio-group scoping inHTMLInputElement,ValidityState, andHTMLFormElement[getFormControlItems](which powersform.elements/namedItem/reset/ validation /FormData).formNodekeepsmeaning "nearest ancestor
<form>" only.Shares the new helper and the
getFormControlItemschange with #2371 — whichevermerges first, the other drops the duplicate.
Tests
Added 6
HTMLInputElement›get form()tests: attribute beats ancestor form;missing-id and non-
<form>target both givenull; attribute pointing at theancestor itself still resolves; resolves in a disconnected tree; target in a different
tree gives
null; owner re-resolves as the attribute is added / changed / removed.Full
npm testpasses.Verification
Cross-checked in Chrome 152:
input.formfollows the attribute to the owner<form>,ancestor.elementsexcludes it,owner.elementsincludes it once, andform="missing"/
form="<div id>"both givenull.Before submitting the PR, please make sure you do the following:
Tests
input.formfollows theformattribute to the owner<form>;ancestor.elementsexcludes the input,owner.elementsincludes it once;form="missing"andform="<div id>"both yieldnull.npm testlocally to make sure that all tests pass before submitting the PR.Title
feat,fix,choreorBREAKING CHANGE. The issue is optional and can be omitted if the pull request does not relate to an issue.AI
I used Claude Code to write this, over multiple iterations. I guided and reviewed
it myself at every step.