Bug 104040 - DOMImplementation::createDocument should call appendChild rather than parserAppendChild to add docType and documentElement
Summary: DOMImplementation::createDocument should call appendChild rather than parserA...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: DOM (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Rafael Weinstein
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-12-04 14:00 PST by Rafael Weinstein
Modified: 2012-12-06 11:28 PST (History)
8 users (show)

See Also:


Attachments
Patch (2.80 KB, patch)
2012-12-04 14:03 PST, Rafael Weinstein
rafaelw: commit-queue+
Details | Formatted Diff | Diff
Patch (2.45 KB, patch)
2012-12-04 17:24 PST, Rafael Weinstein
rafaelw: commit-queue+
Details | Formatted Diff | Diff
Patch for landing (2.47 KB, patch)
2012-12-05 09:49 PST, Rafael Weinstein
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Rafael Weinstein 2012-12-04 14:00:31 PST
In particular, using parserAppendChild with doctype., breaks an invariant of that function which is the parent and child should already be owned by the same document.

Note that using appendChild brings webkit closer to DOM4 by not bypassing the standard work of http://dom.spec.whatwg.org/#concept-node-append.
Comment 1 Rafael Weinstein 2012-12-04 14:03:14 PST
Created attachment 177551 [details]
Patch
Comment 2 Rafael Weinstein 2012-12-04 14:03:53 PST
Note that this patch also removes treeScopeAdoption from parserAppendChild, which I think has to be safe if the ASSERT is valid (and I'm assuming it is).
Comment 3 Elliott Sprehn 2012-12-04 16:50:06 PST
(In reply to comment #2)
> Note that this patch also removes treeScopeAdoption from parserAppendChild, which I think has to be safe if the ASSERT is valid (and I'm assuming it is).

Your assertion is about the document, not the treeScope, so they don't really cover the same things. In particular in a shadow document() != treeScope() so doing document() == newNode->document() can pass but treeScope() == newNode->treeScope() might fail.

That said we *also* assert ASSERT(!newChild->parentNode()) which means the only way for newNode->treeScope() to not be newNode->document() would be if newNode was itself a ShadowRoot which never happens (and calling adoptNode wouldn't fix it anyway).
Comment 4 Rafael Weinstein 2012-12-04 17:24:57 PST
Created attachment 177616 [details]
Patch
Comment 5 Rafael Weinstein 2012-12-04 17:32:11 PST
Actually, it looks like this can happen.

If assign markup to innerHTML of a node in the shadow, then the parser will have set the appropriate ownerDocument for the new node, but not the appropriate treeScope.

This seems like an expensive way to pull nodes into the treeScope during innerHTML, but I think changing the parser to create the node in the appropriate treeScope may also be overkill because it adds another pointer compare to every node created during parsing.

I've put the treeScope adoption back. I'd create a test, but I'm not sure how to detect that nodes created from innerHTML in the shadow have the wrong treeScope. Perhaps one of the component folks can do that? =-)
Comment 6 Elliott Sprehn 2012-12-04 17:41:31 PST
(In reply to comment #5)
> Actually, it looks like this can happen.
> 
> If assign markup to innerHTML of a node in the shadow, then the parser will have set the appropriate ownerDocument for the new node, but not the appropriate treeScope.
> 
> This seems like an expensive way to pull nodes into the treeScope during innerHTML, but I think changing the parser to create the node in the appropriate treeScope may also be overkill because it adds another pointer compare to every node created during parsing.
> 
> I've put the treeScope adoption back. I'd create a test, but I'm not sure how to detect that nodes created from innerHTML in the shadow have the wrong treeScope. Perhaps one of the component folks can do that? =-)

That's not how innerHTML works, ShadowRoot::setInnerHTML creates a document fragment and then goes through replaceChildrenWithFragment which does:

    containerNode->removeChildren();
    containerNode->appendChild(fragment, ec);
Comment 7 Rafael Weinstein 2012-12-04 17:47:25 PST
Right. Forgot that part. In any case, Elliot wants to deal with that call in a follow-on patch, so I'll leave the call alone for now.
Comment 8 Rafael Weinstein 2012-12-05 09:49:53 PST
Created attachment 177783 [details]
Patch for landing
Comment 9 WebKit Review Bot 2012-12-05 11:03:01 PST
Comment on attachment 177783 [details]
Patch for landing

Clearing flags on attachment: 177783

Committed r136717: <http://trac.webkit.org/changeset/136717>
Comment 10 WebKit Review Bot 2012-12-05 11:03:07 PST
All reviewed patches have been landed.  Closing bug.
Comment 11 Alexey Proskuryakov 2012-12-05 11:51:32 PST
> Your assertion is about the document, not the treeScope, so they don't really cover the same things. In particular in a shadow document() != treeScope() so doing document() == newNode->document() can pass but treeScope() == newNode->treeScope() might fail.

As the first version of the patch had a bug that was not caught by EWS, it would be very desirable to add a regression test for that.
Comment 12 Eric Seidel (no email) 2012-12-06 11:28:31 PST
Comment on attachment 177783 [details]
Patch for landing

I'm surprised this is not observable.  Do these cause JS execution (for synchronous mutation events?)