Skip to content

Align DOMChildNode parent checks with spec #11905

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

Closed
wants to merge 7 commits into from

Conversation

nielsdos
Copy link
Member

@nielsdos nielsdos commented Aug 7, 2023

This is split off from #11888, where I said I could land the parent check fix to master only to prevent BC breaks.
I think the alignment with spec is a great usability improvement.

@nielsdos nielsdos changed the title Align DOMParentNode parent checks with spec Align DOMChildNode parent checks with spec Aug 7, 2023
Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

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

Minor confusion about some existing code, otherwise LGTM

if (document == NULL) {
php_dom_throw_error(HIERARCHY_REQUEST_ERR, 1);
if (UNEXPECTED(document == NULL)) {
php_dom_throw_error(HIERARCHY_REQUEST_ERR, 1 /* no document, so be strict */);
Copy link
Member

Choose a reason for hiding this comment

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

I'm confused, is it really a hierarchy error if we don't have a document?

Copy link
Member Author

@nielsdos nielsdos Aug 8, 2023

Choose a reason for hiding this comment

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

Couldn't find this condition in spec, it was added in #5990 to fix https://bugs.php.net/bug.php?id=79968.
However, testing it with a custom element (*) in JS seems to work without an exception:

class Foo extends HTMLElement{}
customElements.define("my-foo", Foo)
foo = new Foo;
foo.after(new Foo);
(new XMLSerializer).serializeToString(foo);

(*) custom element, because in JS you can't instantiate an element directly without a document unless you create a custom one.

And you know what's weird? When I remove this check I expected the original bug I linked above to appear again. But nope, no crash 🤔
I guess the actual segfault back then happened not because of the missing document, but because of the context node being NULL. However, in current day's code the context node is NULL-checked.
Also calling dom_get_strict_error with a NULL argument is fine, because dom_get_strict_error will return the default values in that case.

I have pushed a commit to remove that condition and amend the test (again).

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've added an additional test for this with elements.

Copy link
Member Author

@nielsdos nielsdos Aug 8, 2023

Choose a reason for hiding this comment

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

Ah so there was a possible null-pointer crash after all, but I fixed it by reading the document property from the node instead of from the context. The context->document pointer may be NULL, but the node can't be.

Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

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

Good to know that my confusion was a good hint :D

Comment on lines +11 to +13
$element->after("AFTER");
$element->before("BEFORE");
$element->replaceWith("REPLACE");
Copy link
Member

Choose a reason for hiding this comment

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

The reason those are no-ops is that we are not replacing the text node?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good to know that my confusion was a good hint :D

Indeed ^^

Re no-op:
It's a no-op because these nodes don't have a parent. E.g. before and after only are meaningful if you have a parent node. For replaceWith the authors also defined it as a no-op, because the method is defined as replacing within the parent.
So because these are no-ops, nothing changes to the text node. I call these methods to assert they are actually no-ops.

@nielsdos nielsdos closed this in 23ba4cd Aug 9, 2023
ju1ius pushed a commit to ju1ius/php-src that referenced this pull request Aug 15, 2023
jorgsowa pushed a commit to jorgsowa/php-src that referenced this pull request Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants