From 43cfcb89c2202c186ec2d800af1cfc2fcd543419 Mon Sep 17 00:00:00 2001 From: "cdumez@apple.com" Date: Thu, 4 Aug 2016 22:43:50 +0000 Subject: [PATCH] Move insertAdjacent*() API from HTMLElement to Element https://bugs.webkit.org/show_bug.cgi?id=160567 Reviewed by Sam Weinig. LayoutTests/imported/w3c: Rebaseline several W3C tests now that more checks are passing. * web-platform-tests/dom/interfaces-expected.txt: * web-platform-tests/domparsing/insert_adjacent_html-expected.txt: Source/WebCore: Move insertAdjacent*() API from HTMLElement to Element: - https://w3c.github.io/DOM-Parsing/#extensions-to-the-element-interface - https://dom.spec.whatwg.org/#element Firefox and Chrome both have insertAdjacentHTML() on Element. Chrome has insertAdjacentText() / insertAdjacentElement() on Element as well. Firefox does not have this API at all. Also align insertAdjacentHTML() with the specification so that we now throw a NO_MODIFICATION_ALLOWED_ERR if called with "beforebegin" / "afterend" on a parent-less element. This is as per: - https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml Previously, WebKit would just silently ignore such calls. The new behavior with consistent with both Firefox and Chrome. No new tests, rebaselined existing tests. * dom/Element.cpp: (WebCore::Element::insertAdjacent): (WebCore::Element::insertAdjacentElement): (WebCore::contextElementForInsertion): (WebCore::Element::insertAdjacentHTML): (WebCore::Element::insertAdjacentText): * dom/Element.h: * dom/Element.idl: * html/HTMLElement.cpp: (WebCore::HTMLElement::insertAdjacent): Deleted. (WebCore::HTMLElement::insertAdjacentElement): Deleted. (WebCore::contextElementForInsertion): Deleted. (WebCore::HTMLElement::insertAdjacentHTML): Deleted. (WebCore::HTMLElement::insertAdjacentText): Deleted. * html/HTMLElement.h: * html/HTMLElement.idl: LayoutTests: Rebaseline several tests to reflect behavior change. * fast/dom/HTMLElement/insertAdjacentHTML-errors-expected.txt: * fast/dom/HTMLElement/script-tests/insertAdjacentHTML-errors.js: * fast/dynamic/insertAdjacentElement-expected.txt: git-svn-id: https://svn.webkit.org/repository/webkit/trunk@204150 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- LayoutTests/ChangeLog | 13 ++++ .../insertAdjacentHTML-errors-expected.txt | 4 +- .../script-tests/insertAdjacentHTML-errors.js | 4 +- .../dynamic/insertAdjacentElement-expected.txt | 2 +- LayoutTests/imported/w3c/ChangeLog | 12 ++++ .../web-platform-tests/dom/interfaces-expected.txt | 12 ++-- .../domparsing/insert_adjacent_html-expected.txt | 6 +- Source/WebCore/ChangeLog | 42 +++++++++++++ Source/WebCore/dom/Element.cpp | 70 ++++++++++++++++++++++ Source/WebCore/dom/Element.h | 6 ++ Source/WebCore/dom/Element.idl | 4 ++ Source/WebCore/html/HTMLElement.cpp | 70 ---------------------- Source/WebCore/html/HTMLElement.h | 5 -- Source/WebCore/html/HTMLElement.idl | 5 -- 14 files changed, 161 insertions(+), 94 deletions(-) diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index d56313b..3c2449c 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,16 @@ +2016-08-04 Chris Dumez + + Move insertAdjacent*() API from HTMLElement to Element + https://bugs.webkit.org/show_bug.cgi?id=160567 + + Reviewed by Sam Weinig. + + Rebaseline several tests to reflect behavior change. + + * fast/dom/HTMLElement/insertAdjacentHTML-errors-expected.txt: + * fast/dom/HTMLElement/script-tests/insertAdjacentHTML-errors.js: + * fast/dynamic/insertAdjacentElement-expected.txt: + 2016-08-04 Benjamin Poulain Add some extra test coverage for active touch event handler on subdocuments diff --git a/LayoutTests/fast/dom/HTMLElement/insertAdjacentHTML-errors-expected.txt b/LayoutTests/fast/dom/HTMLElement/insertAdjacentHTML-errors-expected.txt index e65ed35..1725d1d 100644 --- a/LayoutTests/fast/dom/HTMLElement/insertAdjacentHTML-errors-expected.txt +++ b/LayoutTests/fast/dom/HTMLElement/insertAdjacentHTML-errors-expected.txt @@ -3,8 +3,8 @@ Test insertAdjacentHTML exceptions to make sure they match HTML5 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS div.insertAdjacentHTML('beforeBegin', 'text') is undefined. -PASS div.insertAdjacentHTML('afterEnd', 'text') is undefined. +PASS div.insertAdjacentHTML('beforeBegin', 'text') threw exception NoModificationAllowedError (DOM Exception 7): The object can not be modified.. +PASS div.insertAdjacentHTML('afterEnd', 'text') threw exception NoModificationAllowedError (DOM Exception 7): The object can not be modified.. PASS div.insertAdjacentHTML('FOO', 'text') threw exception SyntaxError (DOM Exception 12): The string did not match the expected pattern.. PASS document.documentElement.insertAdjacentHTML('afterEnd', 'text') threw exception NoModificationAllowedError (DOM Exception 7): The object can not be modified.. PASS successfullyParsed is true diff --git a/LayoutTests/fast/dom/HTMLElement/script-tests/insertAdjacentHTML-errors.js b/LayoutTests/fast/dom/HTMLElement/script-tests/insertAdjacentHTML-errors.js index 57eef37..7cde7e2 100644 --- a/LayoutTests/fast/dom/HTMLElement/script-tests/insertAdjacentHTML-errors.js +++ b/LayoutTests/fast/dom/HTMLElement/script-tests/insertAdjacentHTML-errors.js @@ -2,8 +2,8 @@ description('Test insertAdjacentHTML exceptions to make sure they match HTML5'); var div = document.createElement("div"); -shouldBeUndefined("div.insertAdjacentHTML('beforeBegin', 'text')"); -shouldBeUndefined("div.insertAdjacentHTML('afterEnd', 'text')"); +shouldThrow("div.insertAdjacentHTML('beforeBegin', 'text')"); +shouldThrow("div.insertAdjacentHTML('afterEnd', 'text')"); shouldThrow("div.insertAdjacentHTML('FOO', 'text')", '"SyntaxError (DOM Exception 12): The string did not match the expected pattern."'); shouldThrow("document.documentElement.insertAdjacentHTML('afterEnd', 'text')", '"NoModificationAllowedError (DOM Exception 7): The object can not be modified."'); diff --git a/LayoutTests/fast/dynamic/insertAdjacentElement-expected.txt b/LayoutTests/fast/dynamic/insertAdjacentElement-expected.txt index 75b1799..febddb8c 100644 --- a/LayoutTests/fast/dynamic/insertAdjacentElement-expected.txt +++ b/LayoutTests/fast/dynamic/insertAdjacentElement-expected.txt @@ -1,5 +1,5 @@ Caught expected exception: SyntaxError (DOM Exception 12): The string did not match the expected pattern. -Caught expected exception: TypeError: Argument 2 ('element') to HTMLElement.insertAdjacentElement must be an instance of Element +Caught expected exception: TypeError: Argument 2 ('element') to Element.insertAdjacentElement must be an instance of Element 1 (black) 2 (green) 3 (green) 4 (black) PASS diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog index 047cf43..50abcff 100644 --- a/LayoutTests/imported/w3c/ChangeLog +++ b/LayoutTests/imported/w3c/ChangeLog @@ -1,5 +1,17 @@ 2016-08-04 Chris Dumez + Move insertAdjacent*() API from HTMLElement to Element + https://bugs.webkit.org/show_bug.cgi?id=160567 + + Reviewed by Sam Weinig. + + Rebaseline several W3C tests now that more checks are passing. + + * web-platform-tests/dom/interfaces-expected.txt: + * web-platform-tests/domparsing/insert_adjacent_html-expected.txt: + +2016-08-04 Chris Dumez + [[Prototype]] property of an interface object for a callback interface must be the Object.prototype object https://bugs.webkit.org/show_bug.cgi?id=160555 diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/interfaces-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/interfaces-expected.txt index 0800e20..1004a95 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/dom/interfaces-expected.txt +++ b/LayoutTests/imported/w3c/web-platform-tests/dom/interfaces-expected.txt @@ -764,8 +764,8 @@ PASS Element interface: operation webkitMatchesSelector(DOMString) PASS Element interface: operation getElementsByTagName(DOMString) PASS Element interface: operation getElementsByTagNameNS(DOMString,DOMString) PASS Element interface: operation getElementsByClassName(DOMString) -FAIL Element interface: operation insertAdjacentElement(DOMString,Element) assert_own_property: interface prototype object missing non-static operation expected property "insertAdjacentElement" missing -FAIL Element interface: operation insertAdjacentText(DOMString,DOMString) assert_own_property: interface prototype object missing non-static operation expected property "insertAdjacentText" missing +PASS Element interface: operation insertAdjacentElement(DOMString,Element) +PASS Element interface: operation insertAdjacentText(DOMString,DOMString) PASS Element interface: attribute children PASS Element interface: attribute firstElementChild PASS Element interface: attribute lastElementChild @@ -835,10 +835,10 @@ PASS Element interface: element must inherit property "getElementsByTagNameNS" w PASS Element interface: calling getElementsByTagNameNS(DOMString,DOMString) on element with too few arguments must throw TypeError PASS Element interface: element must inherit property "getElementsByClassName" with the proper type (31) PASS Element interface: calling getElementsByClassName(DOMString) on element with too few arguments must throw TypeError -FAIL Element interface: element must inherit property "insertAdjacentElement" with the proper type (32) assert_inherits: property "insertAdjacentElement" not found in prototype chain -FAIL Element interface: calling insertAdjacentElement(DOMString,Element) on element with too few arguments must throw TypeError assert_inherits: property "insertAdjacentElement" not found in prototype chain -FAIL Element interface: element must inherit property "insertAdjacentText" with the proper type (33) assert_inherits: property "insertAdjacentText" not found in prototype chain -FAIL Element interface: calling insertAdjacentText(DOMString,DOMString) on element with too few arguments must throw TypeError assert_inherits: property "insertAdjacentText" not found in prototype chain +PASS Element interface: element must inherit property "insertAdjacentElement" with the proper type (32) +PASS Element interface: calling insertAdjacentElement(DOMString,Element) on element with too few arguments must throw TypeError +PASS Element interface: element must inherit property "insertAdjacentText" with the proper type (33) +PASS Element interface: calling insertAdjacentText(DOMString,DOMString) on element with too few arguments must throw TypeError PASS Element interface: element must inherit property "children" with the proper type (34) PASS Element interface: element must inherit property "firstElementChild" with the proper type (35) PASS Element interface: element must inherit property "lastElementChild" with the proper type (36) diff --git a/LayoutTests/imported/w3c/web-platform-tests/domparsing/insert_adjacent_html-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/domparsing/insert_adjacent_html-expected.txt index 2a204c7..847d747 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/domparsing/insert_adjacent_html-expected.txt +++ b/LayoutTests/imported/w3c/web-platform-tests/domparsing/insert_adjacent_html-expected.txt @@ -8,9 +8,9 @@ PASS Afterbegin content again, with next sibling PASS BeforeEnd content again, with next sibling PASS afterend content again, with next sibling PASS Should throw when inserting with invalid position string -FAIL When the parent node is null, insertAdjacentHTML should throw for beforebegin and afterend (text) assert_throws: function "function () { element.insertAdjacentHTML("afterend", "") }" did not throw -FAIL When the parent node is null, insertAdjacentHTML should throw for beforebegin and afterend (comments) assert_throws: function "function () { element.insertAdjacentHTML("afterend", " + + Move insertAdjacent*() API from HTMLElement to Element + https://bugs.webkit.org/show_bug.cgi?id=160567 + + Reviewed by Sam Weinig. + + Move insertAdjacent*() API from HTMLElement to Element: + - https://w3c.github.io/DOM-Parsing/#extensions-to-the-element-interface + - https://dom.spec.whatwg.org/#element + + Firefox and Chrome both have insertAdjacentHTML() on Element. + Chrome has insertAdjacentText() / insertAdjacentElement() on Element as + well. Firefox does not have this API at all. + + Also align insertAdjacentHTML() with the specification so that we + now throw a NO_MODIFICATION_ALLOWED_ERR if called with "beforebegin" / + "afterend" on a parent-less element. This is as per: + - https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml + + Previously, WebKit would just silently ignore such calls. The new + behavior with consistent with both Firefox and Chrome. + + No new tests, rebaselined existing tests. + + * dom/Element.cpp: + (WebCore::Element::insertAdjacent): + (WebCore::Element::insertAdjacentElement): + (WebCore::contextElementForInsertion): + (WebCore::Element::insertAdjacentHTML): + (WebCore::Element::insertAdjacentText): + * dom/Element.h: + * dom/Element.idl: + * html/HTMLElement.cpp: + (WebCore::HTMLElement::insertAdjacent): Deleted. + (WebCore::HTMLElement::insertAdjacentElement): Deleted. + (WebCore::contextElementForInsertion): Deleted. + (WebCore::HTMLElement::insertAdjacentHTML): Deleted. + (WebCore::HTMLElement::insertAdjacentText): Deleted. + * html/HTMLElement.h: + * html/HTMLElement.idl: + 2016-08-04 Anders Carlsson Another build fix attempt. diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp index f7eb5fb..bd18a3f 100644 --- a/Source/WebCore/dom/Element.cpp +++ b/Source/WebCore/dom/Element.cpp @@ -3481,4 +3481,74 @@ String Element::completeURLsInAttributeValue(const URL& base, const Attribute& a return URL(base, attribute.value()).string(); } + +Node* Element::insertAdjacent(const String& where, Ref&& newChild, ExceptionCode& ec) +{ + // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd", + // a document fragment is created and the elements appended in the correct order. This document + // fragment isn't returned anywhere. + // + // This is impossible for us to implement as the DOM tree does not allow for such structures, + // Opera also appears to disallow such usage. + + if (equalLettersIgnoringASCIICase(where, "beforebegin")) { + ContainerNode* parent = this->parentNode(); + return (parent && parent->insertBefore(newChild, this, ec)) ? newChild.ptr() : nullptr; + } + + if (equalLettersIgnoringASCIICase(where, "afterbegin")) + return insertBefore(newChild, firstChild(), ec) ? newChild.ptr() : nullptr; + + if (equalLettersIgnoringASCIICase(where, "beforeend")) + return appendChild(newChild, ec) ? newChild.ptr() : nullptr; + + if (equalLettersIgnoringASCIICase(where, "afterend")) { + ContainerNode* parent = this->parentNode(); + return (parent && parent->insertBefore(newChild, nextSibling(), ec)) ? newChild.ptr() : nullptr; + } + + ec = SYNTAX_ERR; + return nullptr; +} + +Element* Element::insertAdjacentElement(const String& where, Element& newChild, ExceptionCode& ec) +{ + Node* returnValue = insertAdjacent(where, newChild, ec); + ASSERT_WITH_SECURITY_IMPLICATION(!returnValue || is(*returnValue)); + return downcast(returnValue); +} + +// Step 1 of https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml. +static Element* contextElementForInsertion(const String& where, Element* element, ExceptionCode& ec) +{ + if (equalLettersIgnoringASCIICase(where, "beforebegin") || equalLettersIgnoringASCIICase(where, "afterend")) { + auto* parent = element->parentElement(); + if (!parent) { + ec = NO_MODIFICATION_ALLOWED_ERR; + return nullptr; + } + return parent; + } + if (equalLettersIgnoringASCIICase(where, "afterbegin") || equalLettersIgnoringASCIICase(where, "beforeend")) + return element; + ec = SYNTAX_ERR; + return nullptr; +} + +void Element::insertAdjacentHTML(const String& where, const String& markup, ExceptionCode& ec) +{ + Element* contextElement = contextElementForInsertion(where, this, ec); + if (!contextElement) + return; + RefPtr fragment = createFragmentForInnerOuterHTML(*contextElement, markup, AllowScriptingContent, ec); + if (!fragment) + return; + insertAdjacent(where, fragment.releaseNonNull(), ec); +} + +void Element::insertAdjacentText(const String& where, const String& text, ExceptionCode& ec) +{ + insertAdjacent(where, document().createTextNode(text), ec); +} + } // namespace WebCore diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h index df59cb5..2d82864 100644 --- a/Source/WebCore/dom/Element.h +++ b/Source/WebCore/dom/Element.h @@ -295,6 +295,10 @@ public: void setTabIndex(int); virtual Element* focusDelegate(); + Element* insertAdjacentElement(const String& where, Element& newChild, ExceptionCode&); + void insertAdjacentHTML(const String& where, const String& html, ExceptionCode&); + void insertAdjacentText(const String& where, const String& text, ExceptionCode&); + const RenderStyle* computedStyle(PseudoId = NOPSEUDO) override; bool needsStyleInvalidation() const; @@ -590,6 +594,8 @@ private: void updateIdForDocument(HTMLDocument&, const AtomicString& oldId, const AtomicString& newId, HTMLDocumentNamedItemMapsUpdatingCondition); void updateLabel(TreeScope&, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue); + Node* insertAdjacent(const String& where, Ref&& newChild, ExceptionCode&); + void scrollByUnits(int units, ScrollGranularity); void setPrefix(const AtomicString&, ExceptionCode&) final; diff --git a/Source/WebCore/dom/Element.idl b/Source/WebCore/dom/Element.idl index 9bca396..0545143 100644 --- a/Source/WebCore/dom/Element.idl +++ b/Source/WebCore/dom/Element.idl @@ -143,6 +143,10 @@ [Reflect] attribute DOMString uiactions; #endif + [RaisesException] Element insertAdjacentElement(DOMString where, Element element); + [RaisesException] void insertAdjacentHTML(DOMString where, DOMString html); + [RaisesException] void insertAdjacentText(DOMString where, DOMString text); + [Conditional=POINTER_LOCK] void requestPointerLock(); // CSS Regions API diff --git a/Source/WebCore/html/HTMLElement.cpp b/Source/WebCore/html/HTMLElement.cpp index 2a9de3a..dc23a05 100644 --- a/Source/WebCore/html/HTMLElement.cpp +++ b/Source/WebCore/html/HTMLElement.cpp @@ -630,76 +630,6 @@ void HTMLElement::setOuterText(const String& text, ExceptionCode& ec) mergeWithNextTextNode(downcast(*prev), ec); } -Node* HTMLElement::insertAdjacent(const String& where, Ref&& newChild, ExceptionCode& ec) -{ - // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd", - // a document fragment is created and the elements appended in the correct order. This document - // fragment isn't returned anywhere. - // - // This is impossible for us to implement as the DOM tree does not allow for such structures, - // Opera also appears to disallow such usage. - - if (equalLettersIgnoringASCIICase(where, "beforebegin")) { - ContainerNode* parent = this->parentNode(); - return (parent && parent->insertBefore(newChild, this, ec)) ? newChild.ptr() : nullptr; - } - - if (equalLettersIgnoringASCIICase(where, "afterbegin")) - return insertBefore(newChild, firstChild(), ec) ? newChild.ptr() : nullptr; - - if (equalLettersIgnoringASCIICase(where, "beforeend")) - return appendChild(newChild, ec) ? newChild.ptr() : nullptr; - - if (equalLettersIgnoringASCIICase(where, "afterend")) { - ContainerNode* parent = this->parentNode(); - return (parent && parent->insertBefore(newChild, nextSibling(), ec)) ? newChild.ptr() : nullptr; - } - - ec = SYNTAX_ERR; - return nullptr; -} - -Element* HTMLElement::insertAdjacentElement(const String& where, Element& newChild, ExceptionCode& ec) -{ - Node* returnValue = insertAdjacent(where, newChild, ec); - ASSERT_WITH_SECURITY_IMPLICATION(!returnValue || is(*returnValue)); - return downcast(returnValue); -} - -// Step 3 of http://www.whatwg.org/specs/web-apps/current-work/multipage/apis-in-html-documents.html#insertadjacenthtml() -static Element* contextElementForInsertion(const String& where, Element* element, ExceptionCode& ec) -{ - if (equalLettersIgnoringASCIICase(where, "beforebegin") || equalLettersIgnoringASCIICase(where, "afterend")) { - ContainerNode* parent = element->parentNode(); - if (parent && !is(*parent)) { - ec = NO_MODIFICATION_ALLOWED_ERR; - return nullptr; - } - ASSERT_WITH_SECURITY_IMPLICATION(!parent || is(*parent)); - return downcast(parent); - } - if (equalLettersIgnoringASCIICase(where, "afterbegin") || equalLettersIgnoringASCIICase(where, "beforeend")) - return element; - ec = SYNTAX_ERR; - return nullptr; -} - -void HTMLElement::insertAdjacentHTML(const String& where, const String& markup, ExceptionCode& ec) -{ - Element* contextElement = contextElementForInsertion(where, this, ec); - if (!contextElement) - return; - RefPtr fragment = createFragmentForInnerOuterHTML(*contextElement, markup, AllowScriptingContent, ec); - if (!fragment) - return; - insertAdjacent(where, fragment.releaseNonNull(), ec); -} - -void HTMLElement::insertAdjacentText(const String& where, const String& text, ExceptionCode& ec) -{ - insertAdjacent(where, document().createTextNode(text), ec); -} - void HTMLElement::applyAlignmentAttributeToStyle(const AtomicString& alignment, MutableStyleProperties& style) { // Vertical alignment with respect to the current baseline of the text diff --git a/Source/WebCore/html/HTMLElement.h b/Source/WebCore/html/HTMLElement.h index b4aba88..cfd792a 100644 --- a/Source/WebCore/html/HTMLElement.h +++ b/Source/WebCore/html/HTMLElement.h @@ -49,10 +49,6 @@ public: void setInnerText(const String&, ExceptionCode&); void setOuterText(const String&, ExceptionCode&); - Element* insertAdjacentElement(const String& where, Element& newChild, ExceptionCode&); - void insertAdjacentHTML(const String& where, const String& html, ExceptionCode&); - void insertAdjacentText(const String& where, const String& text, ExceptionCode&); - virtual bool hasCustomFocusLogic() const; bool supportsFocus() const override; @@ -130,7 +126,6 @@ private: virtual HTMLFormElement* virtualForm() const; - Node* insertAdjacent(const String& where, Ref&& newChild, ExceptionCode&); Ref textToFragment(const String&, ExceptionCode&); void dirAttributeChanged(const AtomicString&); diff --git a/Source/WebCore/html/HTMLElement.idl b/Source/WebCore/html/HTMLElement.idl index 6c677640..d2bdf3a 100644 --- a/Source/WebCore/html/HTMLElement.idl +++ b/Source/WebCore/html/HTMLElement.idl @@ -44,11 +44,6 @@ [TreatNullAs=EmptyString, SetterRaisesException] attribute DOMString innerText; [TreatNullAs=EmptyString, SetterRaisesException] attribute DOMString outerText; - [RaisesException] Element insertAdjacentElement(DOMString where, Element element); - - [RaisesException] void insertAdjacentHTML(DOMString where, DOMString html); - [RaisesException] void insertAdjacentText(DOMString where, DOMString text); - [SetterRaisesException] attribute DOMString contentEditable; readonly attribute boolean isContentEditable; -- 1.8.3.1