Bug 148733 - Range.comparePoint shouldn't throw an exception if the range and the node are in the same detached tree
Summary: Range.comparePoint shouldn't throw an exception if the range and the node are...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: DOM (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Ryosuke Niwa
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2015-09-02 18:12 PDT by Ryosuke Niwa
Modified: 2015-09-03 17:48 PDT (History)
5 users (show)

See Also:


Attachments
Test case that pass in Firefox and fail in WebKit (753 bytes, text/html)
2015-09-02 18:12 PDT, Ryosuke Niwa
no flags Details
Fixes the bug (5.63 KB, patch)
2015-09-02 19:27 PDT, Ryosuke Niwa
no flags Details | Formatted Diff | Diff
Fixes the bug (11.89 KB, patch)
2015-09-02 20:04 PDT, Ryosuke Niwa
no flags Details | Formatted Diff | Diff
Fixed a typo (11.90 KB, patch)
2015-09-02 20:05 PDT, Ryosuke Niwa
cdumez: review+
cdumez: commit-queue-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ryosuke Niwa 2015-09-02 18:12:08 PDT
Created attachment 260467 [details]
Test case that pass in Firefox and fail in WebKit

comparePoint currently throws WrongDocumentError if the node passed in the first argument is not in the document.
However, DOM4 spec (http://www.w3.org/TR/dom/#dom-range-comparepoint) allows it as long as the range's boundary point in the same detached tree.

Firefox follows the spec.
Comment 1 Radar WebKit Bug Importer 2015-09-02 18:13:25 PDT
<rdar://problem/22551214>
Comment 2 Ryosuke Niwa 2015-09-02 19:27:00 PDT
Created attachment 260474 [details]
Fixes the bug
Comment 3 Chris Dumez 2015-09-02 19:56:34 PDT
Regressions: Unexpected text-only failures (2)
  http/tests/w3c/dom/ranges/Range-comparePoint.html [ Failure ]
  http/tests/w3c/dom/ranges/Range-set.html [ Failure ]
Comment 4 Chris Dumez 2015-09-02 19:58:19 PDT
Comment on attachment 260474 [details]
Fixes the bug

r- due to w3c tests failures (may need a simple rebaseline)
Comment 5 Ryosuke Niwa 2015-09-02 19:59:21 PDT
(In reply to comment #4)
> Comment on attachment 260474 [details]
> Fixes the bug
> 
> r- due to w3c tests failures (may need a simple rebaseline)

Oh oops, I fixed those tests and forgot to rebase :(
Comment 6 Ryosuke Niwa 2015-09-02 20:04:16 PDT
Created attachment 260478 [details]
Fixes the bug
Comment 7 Ryosuke Niwa 2015-09-02 20:05:22 PDT
Created attachment 260479 [details]
Fixed a typo
Comment 8 Chris Dumez 2015-09-02 20:14:23 PDT
Comment on attachment 260479 [details]
Fixed a typo

View in context: https://bugs.webkit.org/attachment.cgi?id=260479&action=review

> Source/WebCore/dom/Range.cpp:266
> +        if (!refNode->inDocument() && !commonAncestorContainer(refNode, &startContainer()))

This looks odd. Why would we do this check *after* the checkNodeWOffset() call? The spec says:
1. If node’s root is different from the context object’s root, throw a WrongDocumentError exception. (Isn't this the &refNode->document() != &ownerDocument() check above)?
2. If node is a doctype, throw an InvalidNodeTypeError exception. (done in checkNodeWOffset)
3. If offset is greater than node’s length, throw an IndexSizeError exception. (done in checkNodeWOffset)
Comment 9 Ryosuke Niwa 2015-09-02 20:17:01 PDT
Comment on attachment 260479 [details]
Fixed a typo

View in context: https://bugs.webkit.org/attachment.cgi?id=260479&action=review

>> Source/WebCore/dom/Range.cpp:266
>> +        if (!refNode->inDocument() && !commonAncestorContainer(refNode, &startContainer()))
> 
> This looks odd. Why would we do this check *after* the checkNodeWOffset() call? The spec says:
> 1. If node’s root is different from the context object’s root, throw a WrongDocumentError exception. (Isn't this the &refNode->document() != &ownerDocument() check above)?
> 2. If node is a doctype, throw an InvalidNodeTypeError exception. (done in checkNodeWOffset)
> 3. If offset is greater than node’s length, throw an IndexSizeError exception. (done in checkNodeWOffset)

Because checkNodeWOffset is O(1) for text nodes, etc... but commonAncestorContainer is always O(n).
Comment 10 Chris Dumez 2015-09-02 20:21:34 PDT
Comment on attachment 260479 [details]
Fixed a typo

View in context: https://bugs.webkit.org/attachment.cgi?id=260479&action=review

>>> Source/WebCore/dom/Range.cpp:266
>>> +        if (!refNode->inDocument() && !commonAncestorContainer(refNode, &startContainer()))
>> 
>> This looks odd. Why would we do this check *after* the checkNodeWOffset() call? The spec says:
>> 1. If node’s root is different from the context object’s root, throw a WrongDocumentError exception. (Isn't this the &refNode->document() != &ownerDocument() check above)?
>> 2. If node is a doctype, throw an InvalidNodeTypeError exception. (done in checkNodeWOffset)
>> 3. If offset is greater than node’s length, throw an IndexSizeError exception. (done in checkNodeWOffset)
> 
> Because checkNodeWOffset is O(1) for text nodes, etc... but commonAncestorContainer is always O(n).

Doing it in this order means you're going to throw the wrong exception if the offset is wrong AND the nodes don't have the same root (you will throw an index error instead of a wrong document error).
Comment 11 Chris Dumez 2015-09-02 20:23:19 PDT
Comment on attachment 260479 [details]
Fixed a typo

View in context: https://bugs.webkit.org/attachment.cgi?id=260479&action=review

>>>> Source/WebCore/dom/Range.cpp:266
>>>> +        if (!refNode->inDocument() && !commonAncestorContainer(refNode, &startContainer()))
>>> 
>>> This looks odd. Why would we do this check *after* the checkNodeWOffset() call? The spec says:
>>> 1. If node’s root is different from the context object’s root, throw a WrongDocumentError exception. (Isn't this the &refNode->document() != &ownerDocument() check above)?
>>> 2. If node is a doctype, throw an InvalidNodeTypeError exception. (done in checkNodeWOffset)
>>> 3. If offset is greater than node’s length, throw an IndexSizeError exception. (done in checkNodeWOffset)
>> 
>> Because checkNodeWOffset is O(1) for text nodes, etc... but commonAncestorContainer is always O(n).
> 
> Doing it in this order means you're going to throw the wrong exception if the offset is wrong AND the nodes don't have the same root (you will throw an index error instead of a wrong document error).

Wait, I misread. Doesn't this mean you'll throw the WRONG_DOCUMENT_ERR *only* if the offset is also wrong? What if the nodes are detached, don't have the same root and the offset is right?
Comment 12 Ryosuke Niwa 2015-09-02 20:25:44 PDT
(In reply to comment #11)
> Comment on attachment 260479 [details]
> Fixed a typo
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=260479&action=review
> 
> >>>> Source/WebCore/dom/Range.cpp:266
> >>>> +        if (!refNode->inDocument() && !commonAncestorContainer(refNode, &startContainer()))
> >>> 
> >>> This looks odd. Why would we do this check *after* the checkNodeWOffset() call? The spec says:
> >>> 1. If node’s root is different from the context object’s root, throw a WrongDocumentError exception. (Isn't this the &refNode->document() != &ownerDocument() check above)?
> >>> 2. If node is a doctype, throw an InvalidNodeTypeError exception. (done in checkNodeWOffset)
> >>> 3. If offset is greater than node’s length, throw an IndexSizeError exception. (done in checkNodeWOffset)
> >> 
> >> Because checkNodeWOffset is O(1) for text nodes, etc... but commonAncestorContainer is always O(n).
> > 
> > Doing it in this order means you're going to throw the wrong exception if the offset is wrong AND the nodes don't have the same root (you will throw an index error instead of a wrong document error).
> 
> Wait, I misread. Doesn't this mean you'll throw the WRONG_DOCUMENT_ERR
> *only* if the offset is also wrong? What if the nodes are detached, don't
> have the same root and the offset is right?

In that case,compareBoundaryPoints will throw WRONG_DOCUMENT_ERR.  I explained all of this in the change log.
Comment 13 Chris Dumez 2015-09-02 20:39:26 PDT
Comment on attachment 260479 [details]
Fixed a typo

View in context: https://bugs.webkit.org/attachment.cgi?id=260479&action=review

This makes sense now, sorry for not reading the changelog XD r=me.

> Source/WebCore/ChangeLog:11
> +        WRONG_DOCUMENT_ERR is continued to be thrown by compareBoundaryPoints later in the function when the root

s/continued to be/still/ ?

> Source/WebCore/ChangeLog:14
> +        There is one subtly here that we need to throw WRONG_DOCUMENT_ERR instead of INDEX_SIZE_ERR when refNode

"subtlety"

> LayoutTests/fast/dom/Range/range-comparePoint-detached-nodes-expected.txt:3
> +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".

Where is my "TEST COMPLETE"? :)

> LayoutTests/fast/dom/Range/range-comparePoint-detached-nodes.html:25
> +shouldThrow("var range = new Range; range.setStart(detachedDiv, 0); range.comparePoint(detachedP, 0);");

I think we should specify the exception string as second parameter since we really want to make sure a WrongDocumentError is thrown.

> LayoutTests/fast/dom/Range/range-comparePoint-detached-nodes.html:26
> +shouldThrow("var range = new Range; range.setStart(spanInDetachedDiv1, 0); range.comparePoint(spanInDetachedP, 0);");

ditto.

> LayoutTests/fast/dom/Range/range-comparePoint-detached-nodes.html:28
> +</script>

You're missing the js-test-post.js
Comment 14 Ryosuke Niwa 2015-09-03 17:48:29 PDT
Committed r189327: <http://trac.webkit.org/changeset/189327>