Skip to content

Adopt an attribute into the document it is set on - #4245

Merged
domenic merged 3 commits into
jsdom:mainfrom
Kjubikstronk:adopt-node-attributes
Aug 23, 2026
Merged

domenic merged 3 commits into
jsdom:mainfrom
Kjubikstronk:adopt-node-attributes

Conversation

@Kjubikstronk

Copy link
Copy Markdown
Contributor

Two places where an attribute kept pointing at the wrong node document.

"Set an attribute" is missing its adopt step, so setNamedItem with an attribute from another document left attr.ownerDocument on the old one. And _adoptNode set the node document of every shadow-including inclusive descendant but not of the attributes in each element's attribute list, which the adopt algorithm also asks for.

Removes two entries from to-run.yaml: attributes-namednodemap-cross-document.window.html and the Node-mutation-adoptNode.html sub-test.

Motivation: still working through the failures recorded in to-run.yaml rather than hitting this in an application.

Setting an attribute node on an element in another document left the attribute
pointing at its old node document, and adopting an element only updated the
element itself, not the attributes in its attribute list.

Co-authored-by: Claude Opus 5 <[email protected]>
Comment thread lib/jsdom/living/attributes.js Outdated
throw DOMException.create(element._globalObject, ["The attribute is in use.", "InUseAttributeError"]);
}

element._ownerDocument._adoptNode(attr);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Append and replace each set the attribute's node document to the element's,
rather than adopting it in "set an attribute".

Co-authored-by: Claude Opus 5 <[email protected]>
@Kjubikstronk

Copy link
Copy Markdown
Contributor Author

You're right, thanks — I had invented an adopt step in "set an attribute" instead of implementing what's actually written. Fixed.

"Append an attribute" step 3 and "replace an attribute" step 4 both say to set the attribute's node document to the element's node document, so it's a plain assignment in those two, not _adoptNode, and not in "set an attribute" at all. _adoptNode also does much more than that step asks for.

The other half of the change does appear in the adopt algorithm, so I've kept it:

Otherwise, if inclusiveDescendant is an element: Set the node document of each attribute in inclusiveDescendant's attribute list to document.

dom/, custom-elements, shadow-dom and the API tests are all green.

@domenic domenic left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you, much better!

@domenic

domenic commented Aug 22, 2026

Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request

@domenic
domenic merged commit 9e09cdc into jsdom:main Aug 23, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants