Title: [262381] trunk
Revision
262381
Author
commit-qu...@webkit.org
Date
2020-06-01 09:57:58 -0700 (Mon, 01 Jun 2020)

Log Message

Implement ParentNode.prototype.replaceChildren
https://bugs.webkit.org/show_bug.cgi?id=198578

Patch by Tetsuharu Ohzeki <tetsuharu.ohz...@gmail.com> on 2020-06-01
Reviewed by Darin Adler.

LayoutTests/imported/w3c:

* web-platform-tests/dom/idlharness.window-expected.txt:
* web-platform-tests/dom/nodes/ParentNode-replaceChildren-expected.txt:

Source/WebCore:

Ideally, we can use `ContainerNode::replaceAllChildren` to implement
this simply but the current of it does not have a path to support
`DocumentFragment`.

Hence, we call related methods from `ParentNode.prototype.replaceChildren` directly.

* dom/ContainerNode.cpp:
(WebCore::ContainerNode::replaceChildren):
* dom/ContainerNode.h:
* dom/ParentNode.idl:

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (262380 => 262381)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2020-06-01 16:30:53 UTC (rev 262380)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2020-06-01 16:57:58 UTC (rev 262381)
@@ -1,3 +1,13 @@
+2020-06-01  Tetsuharu Ohzeki  <tetsuharu.ohz...@gmail.com>
+
+        Implement ParentNode.prototype.replaceChildren
+        https://bugs.webkit.org/show_bug.cgi?id=198578
+
+        Reviewed by Darin Adler.
+
+        * web-platform-tests/dom/idlharness.window-expected.txt:
+        * web-platform-tests/dom/nodes/ParentNode-replaceChildren-expected.txt:
+
 2020-05-31  Rob Buis  <rb...@igalia.com>
 
         Implement named item condition for images

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/idlharness.window-expected.txt (262380 => 262381)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/idlharness.window-expected.txt	2020-06-01 16:30:53 UTC (rev 262380)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/idlharness.window-expected.txt	2020-06-01 16:57:58 UTC (rev 262381)
@@ -367,7 +367,7 @@
 PASS Document interface: attribute childElementCount 
 PASS Document interface: operation prepend((Node or DOMString)...) 
 PASS Document interface: operation append((Node or DOMString)...) 
-FAIL Document interface: operation replaceChildren((Node or DOMString)...) assert_own_property: interface prototype object missing non-static operation expected property "replaceChildren" missing
+PASS Document interface: operation replaceChildren((Node or DOMString)...) 
 PASS Document interface: operation querySelector(DOMString) 
 PASS Document interface: operation querySelectorAll(DOMString) 
 PASS Document interface: operation createExpression(DOMString, optional XPathNSResolver?) 
@@ -429,8 +429,8 @@
 PASS Document interface: calling prepend((Node or DOMString)...) on new Document() with too few arguments must throw TypeError 
 PASS Document interface: new Document() must inherit property "append((Node or DOMString)...)" with the proper type 
 PASS Document interface: calling append((Node or DOMString)...) on new Document() with too few arguments must throw TypeError 
-FAIL Document interface: new Document() must inherit property "replaceChildren((Node or DOMString)...)" with the proper type assert_inherits: property "replaceChildren" not found in prototype chain
-FAIL Document interface: calling replaceChildren((Node or DOMString)...) on new Document() with too few arguments must throw TypeError assert_inherits: property "replaceChildren" not found in prototype chain
+PASS Document interface: new Document() must inherit property "replaceChildren((Node or DOMString)...)" with the proper type 
+PASS Document interface: calling replaceChildren((Node or DOMString)...) on new Document() with too few arguments must throw TypeError 
 PASS Document interface: new Document() must inherit property "querySelector(DOMString)" with the proper type 
 PASS Document interface: calling querySelector(DOMString) on new Document() with too few arguments must throw TypeError 
 PASS Document interface: new Document() must inherit property "querySelectorAll(DOMString)" with the proper type 
@@ -569,8 +569,8 @@
 PASS Document interface: calling prepend((Node or DOMString)...) on xmlDoc with too few arguments must throw TypeError 
 PASS Document interface: xmlDoc must inherit property "append((Node or DOMString)...)" with the proper type 
 PASS Document interface: calling append((Node or DOMString)...) on xmlDoc with too few arguments must throw TypeError 
-FAIL Document interface: xmlDoc must inherit property "replaceChildren((Node or DOMString)...)" with the proper type assert_inherits: property "replaceChildren" not found in prototype chain
-FAIL Document interface: calling replaceChildren((Node or DOMString)...) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "replaceChildren" not found in prototype chain
+PASS Document interface: xmlDoc must inherit property "replaceChildren((Node or DOMString)...)" with the proper type 
+PASS Document interface: calling replaceChildren((Node or DOMString)...) on xmlDoc with too few arguments must throw TypeError 
 PASS Document interface: xmlDoc must inherit property "querySelector(DOMString)" with the proper type 
 PASS Document interface: calling querySelector(DOMString) on xmlDoc with too few arguments must throw TypeError 
 PASS Document interface: xmlDoc must inherit property "querySelectorAll(DOMString)" with the proper type 
@@ -770,7 +770,7 @@
 PASS DocumentFragment interface: attribute childElementCount 
 PASS DocumentFragment interface: operation prepend((Node or DOMString)...) 
 PASS DocumentFragment interface: operation append((Node or DOMString)...) 
-FAIL DocumentFragment interface: operation replaceChildren((Node or DOMString)...) assert_own_property: interface prototype object missing non-static operation expected property "replaceChildren" missing
+PASS DocumentFragment interface: operation replaceChildren((Node or DOMString)...) 
 PASS DocumentFragment interface: operation querySelector(DOMString) 
 PASS DocumentFragment interface: operation querySelectorAll(DOMString) 
 PASS DocumentFragment must be primary interface of document.createDocumentFragment() 
@@ -785,8 +785,8 @@
 PASS DocumentFragment interface: calling prepend((Node or DOMString)...) on document.createDocumentFragment() with too few arguments must throw TypeError 
 PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "append((Node or DOMString)...)" with the proper type 
 PASS DocumentFragment interface: calling append((Node or DOMString)...) on document.createDocumentFragment() with too few arguments must throw TypeError 
-FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "replaceChildren((Node or DOMString)...)" with the proper type assert_inherits: property "replaceChildren" not found in prototype chain
-FAIL DocumentFragment interface: calling replaceChildren((Node or DOMString)...) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "replaceChildren" not found in prototype chain
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "replaceChildren((Node or DOMString)...)" with the proper type 
+PASS DocumentFragment interface: calling replaceChildren((Node or DOMString)...) on document.createDocumentFragment() with too few arguments must throw TypeError 
 PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelector(DOMString)" with the proper type 
 PASS DocumentFragment interface: calling querySelector(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
 PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelectorAll(DOMString)" with the proper type 
@@ -913,7 +913,7 @@
 PASS Element interface: attribute childElementCount 
 PASS Element interface: operation prepend((Node or DOMString)...) 
 PASS Element interface: operation append((Node or DOMString)...) 
-FAIL Element interface: operation replaceChildren((Node or DOMString)...) assert_own_property: interface prototype object missing non-static operation expected property "replaceChildren" missing
+PASS Element interface: operation replaceChildren((Node or DOMString)...) 
 PASS Element interface: operation querySelector(DOMString) 
 PASS Element interface: operation querySelectorAll(DOMString) 
 PASS Element interface: attribute previousElementSibling 
@@ -991,8 +991,8 @@
 PASS Element interface: calling prepend((Node or DOMString)...) on element with too few arguments must throw TypeError 
 PASS Element interface: element must inherit property "append((Node or DOMString)...)" with the proper type 
 PASS Element interface: calling append((Node or DOMString)...) on element with too few arguments must throw TypeError 
-FAIL Element interface: element must inherit property "replaceChildren((Node or DOMString)...)" with the proper type assert_inherits: property "replaceChildren" not found in prototype chain
-FAIL Element interface: calling replaceChildren((Node or DOMString)...) on element with too few arguments must throw TypeError assert_inherits: property "replaceChildren" not found in prototype chain
+PASS Element interface: element must inherit property "replaceChildren((Node or DOMString)...)" with the proper type 
+PASS Element interface: calling replaceChildren((Node or DOMString)...) on element with too few arguments must throw TypeError 
 PASS Element interface: element must inherit property "querySelector(DOMString)" with the proper type 
 PASS Element interface: calling querySelector(DOMString) on element with too few arguments must throw TypeError 
 PASS Element interface: element must inherit property "querySelectorAll(DOMString)" with the proper type 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/ParentNode-replaceChildren-expected.txt (262380 => 262381)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/ParentNode-replaceChildren-expected.txt	2020-06-01 16:30:53 UTC (rev 262380)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/ParentNode-replaceChildren-expected.txt	2020-06-01 16:57:58 UTC (rev 262381)
@@ -1,27 +1,27 @@
 
-FAIL If node is a host-including inclusive ancestor of parent, then throw a HierarchyRequestError DOMException. assert_throws_dom: function "() => insert(doc.body, doc.body)" threw object "TypeError: undefined is not an object (evaluating 'parent[methodName].length')" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
-FAIL If node is not a DocumentFragment, DocumentType, Element, Text, ProcessingInstruction, or Comment node, then throw a HierarchyRequestError DOMException. assert_throws_dom: function "() => insert(doc, doc2)" threw object "TypeError: undefined is not an object (evaluating 'parent[methodName].length')" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
-FAIL If node is a Text node and parent is a document, then throw a HierarchyRequestError DOMException. assert_throws_dom: function "() => insert(doc, doc.createTextNode("text"))" threw object "TypeError: undefined is not an object (evaluating 'parent[methodName].length')" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
-FAIL If node is a doctype and parent is not a document, then throw a HierarchyRequestError DOMException. assert_throws_dom: function "() => insert(doc.createElement("a"), doctype)" threw object "TypeError: undefined is not an object (evaluating 'parent[methodName].length')" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
-FAIL If node is a DocumentFragment with multiple elements and parent is a document, then throw a HierarchyRequestError DOMException. assert_throws_dom: function "() => insert(doc, df)" threw object "TypeError: undefined is not an object (evaluating 'parent[methodName].length')" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
-FAIL If node is a DocumentFragment with an element and parent is a document with another element, then throw a HierarchyRequestError DOMException. assert_throws_dom: function "() => insert(doc, df)" threw object "TypeError: undefined is not an object (evaluating 'parent[methodName].length')" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
-FAIL If node is an Element and parent is a document with another element, then throw a HierarchyRequestError DOMException. assert_throws_dom: function "() => insert(doc, el)" threw object "TypeError: undefined is not an object (evaluating 'parent[methodName].length')" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
-FAIL If node is a doctype and parent is a document with another doctype, then throw a HierarchyRequestError DOMException. assert_throws_dom: function "() => insert(doc, doctype)" threw object "TypeError: undefined is not an object (evaluating 'parent[methodName].length')" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
-FAIL If node is a doctype and parent is a document with an element, then throw a HierarchyRequestError DOMException. assert_throws_dom: function "() => insert(doc, doctype)" threw object "TypeError: undefined is not an object (evaluating 'parent[methodName].length')" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
-FAIL Element.replaceChildren() without any argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren()', 'parent.replaceChildren' is undefined)
-FAIL Element.replaceChildren() with null as an argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(null)', 'parent.replaceChildren' is undefined)
-FAIL Element.replaceChildren() with undefined as an argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(undefined)', 'parent.replaceChildren' is undefined)
-FAIL Element.replaceChildren() with only text as an argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren('text')', 'parent.replaceChildren' is undefined)
-FAIL Element.replaceChildren() with only one element as an argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(x)', 'parent.replaceChildren' is undefined)
-FAIL Element.replaceChildren() with null as an argument, on a parent having a child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(null)', 'parent.replaceChildren' is undefined)
-FAIL Element.replaceChildren() with one element and text as argument, on a parent having a child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(x, 'text')', 'parent.replaceChildren' is undefined)
-FAIL Element.replaceChildren() should move nodes in the right order parent.replaceChildren is not a function. (In 'parent.replaceChildren(...previousParent.children)', 'parent.replaceChildren' is undefined)
-FAIL DocumentFragment.replaceChildren() without any argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren()', 'parent.replaceChildren' is undefined)
-FAIL DocumentFragment.replaceChildren() with null as an argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(null)', 'parent.replaceChildren' is undefined)
-FAIL DocumentFragment.replaceChildren() with undefined as an argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(undefined)', 'parent.replaceChildren' is undefined)
-FAIL DocumentFragment.replaceChildren() with only text as an argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren('text')', 'parent.replaceChildren' is undefined)
-FAIL DocumentFragment.replaceChildren() with only one element as an argument, on a parent having no child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(x)', 'parent.replaceChildren' is undefined)
-FAIL DocumentFragment.replaceChildren() with null as an argument, on a parent having a child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(null)', 'parent.replaceChildren' is undefined)
-FAIL DocumentFragment.replaceChildren() with one element and text as argument, on a parent having a child. parent.replaceChildren is not a function. (In 'parent.replaceChildren(x, 'text')', 'parent.replaceChildren' is undefined)
-FAIL DocumentFragment.replaceChildren() should move nodes in the right order parent.replaceChildren is not a function. (In 'parent.replaceChildren(...previousParent.children)', 'parent.replaceChildren' is undefined)
+PASS If node is a host-including inclusive ancestor of parent, then throw a HierarchyRequestError DOMException. 
+PASS If node is not a DocumentFragment, DocumentType, Element, Text, ProcessingInstruction, or Comment node, then throw a HierarchyRequestError DOMException. 
+PASS If node is a Text node and parent is a document, then throw a HierarchyRequestError DOMException. 
+PASS If node is a doctype and parent is not a document, then throw a HierarchyRequestError DOMException. 
+PASS If node is a DocumentFragment with multiple elements and parent is a document, then throw a HierarchyRequestError DOMException. 
+PASS If node is a DocumentFragment with an element and parent is a document with another element, then throw a HierarchyRequestError DOMException. 
+PASS If node is an Element and parent is a document with another element, then throw a HierarchyRequestError DOMException. 
+PASS If node is a doctype and parent is a document with another doctype, then throw a HierarchyRequestError DOMException. 
+PASS If node is a doctype and parent is a document with an element, then throw a HierarchyRequestError DOMException. 
+PASS Element.replaceChildren() without any argument, on a parent having no child. 
+PASS Element.replaceChildren() with null as an argument, on a parent having no child. 
+PASS Element.replaceChildren() with undefined as an argument, on a parent having no child. 
+PASS Element.replaceChildren() with only text as an argument, on a parent having no child. 
+PASS Element.replaceChildren() with only one element as an argument, on a parent having no child. 
+PASS Element.replaceChildren() with null as an argument, on a parent having a child. 
+PASS Element.replaceChildren() with one element and text as argument, on a parent having a child. 
+PASS Element.replaceChildren() should move nodes in the right order 
+PASS DocumentFragment.replaceChildren() without any argument, on a parent having no child. 
+PASS DocumentFragment.replaceChildren() with null as an argument, on a parent having no child. 
+PASS DocumentFragment.replaceChildren() with undefined as an argument, on a parent having no child. 
+PASS DocumentFragment.replaceChildren() with only text as an argument, on a parent having no child. 
+PASS DocumentFragment.replaceChildren() with only one element as an argument, on a parent having no child. 
+PASS DocumentFragment.replaceChildren() with null as an argument, on a parent having a child. 
+PASS DocumentFragment.replaceChildren() with one element and text as argument, on a parent having a child. 
+PASS DocumentFragment.replaceChildren() should move nodes in the right order 
 

Modified: trunk/Source/WebCore/ChangeLog (262380 => 262381)


--- trunk/Source/WebCore/ChangeLog	2020-06-01 16:30:53 UTC (rev 262380)
+++ trunk/Source/WebCore/ChangeLog	2020-06-01 16:57:58 UTC (rev 262381)
@@ -1,3 +1,21 @@
+2020-06-01  Tetsuharu Ohzeki  <tetsuharu.ohz...@gmail.com>
+
+        Implement ParentNode.prototype.replaceChildren
+        https://bugs.webkit.org/show_bug.cgi?id=198578
+
+        Reviewed by Darin Adler.
+
+        Ideally, we can use `ContainerNode::replaceAllChildren` to implement
+        this simply but the current of it does not have a path to support
+        `DocumentFragment`.
+
+        Hence, we call related methods from `ParentNode.prototype.replaceChildren` directly.
+
+        * dom/ContainerNode.cpp:
+        (WebCore::ContainerNode::replaceChildren):
+        * dom/ContainerNode.h:
+        * dom/ParentNode.idl:
+
 2020-05-25  Sergio Villar Senin  <svil...@igalia.com>
 
         [css-flexbox] Tables as flex items should obey the flex container sizing

Modified: trunk/Source/WebCore/dom/ContainerNode.cpp (262380 => 262381)


--- trunk/Source/WebCore/dom/ContainerNode.cpp	2020-06-01 16:30:53 UTC (rev 262380)
+++ trunk/Source/WebCore/dom/ContainerNode.cpp	2020-06-01 16:57:58 UTC (rev 262381)
@@ -952,6 +952,38 @@
     return insertBefore(*node, firstChild());
 }
 
+// https://dom.spec.whatwg.org/#dom-parentnode-replacechildren
+ExceptionOr<void> ContainerNode::replaceChildren(Vector<NodeOrString>&& vector)
+{
+    // step 1
+    auto result = convertNodesOrStringsIntoNode(WTFMove(vector));
+    if (result.hasException())
+        return result.releaseException();
+
+    RefPtr<Node> node = result.releaseReturnValue();
+    if (!node)
+        return { };
+
+    // step 2
+    auto validityCheckResult = ensurePreInsertionValidity(*node, nullptr);
+    if (validityCheckResult.hasException())
+        return validityCheckResult.releaseException();
+
+    // step 3
+    Ref<ContainerNode> protectedThis(*this);
+    ChildListMutationScope mutation(*this);
+    removeAllChildrenWithScriptAssertion(ChildChangeSource::API, DeferChildrenChanged::Yes);
+
+    auto insertResult = appendChildWithoutPreInsertionValidityCheck(*node);
+    if (insertResult.hasException())
+        return insertResult.releaseException();
+
+    rebuildSVGExtensionsElementsIfNecessary();
+    dispatchSubtreeModifiedEvent();
+
+    return { };
+}
+
 HTMLCollection* ContainerNode::cachedHTMLCollection(CollectionType type)
 {
     return hasRareData() && rareData()->nodeLists() ? rareData()->nodeLists()->cachedCollection<HTMLCollection>(type) : nullptr;

Modified: trunk/Source/WebCore/dom/ContainerNode.h (262380 => 262381)


--- trunk/Source/WebCore/dom/ContainerNode.h	2020-06-01 16:30:53 UTC (rev 262380)
+++ trunk/Source/WebCore/dom/ContainerNode.h	2020-06-01 16:57:58 UTC (rev 262381)
@@ -128,6 +128,8 @@
     ExceptionOr<void> append(Vector<NodeOrString>&&);
     ExceptionOr<void> prepend(Vector<NodeOrString>&&);
 
+    ExceptionOr<void> replaceChildren(Vector<NodeOrString>&&);
+
     ExceptionOr<void> ensurePreInsertionValidity(Node& newChild, Node* refChild);
 
 protected:

Modified: trunk/Source/WebCore/dom/ParentNode.idl (262380 => 262381)


--- trunk/Source/WebCore/dom/ParentNode.idl	2020-06-01 16:30:53 UTC (rev 262380)
+++ trunk/Source/WebCore/dom/ParentNode.idl	2020-06-01 16:57:58 UTC (rev 262381)
@@ -35,6 +35,7 @@
 
     [CEReactions, Unscopable, MayThrowException] void prepend((Node or DOMString)... nodes);
     [CEReactions, Unscopable, MayThrowException] void append((Node or DOMString)... nodes);
+    [CEReactions, Unscopable, MayThrowException] void replaceChildren((Node or DOMString)... nodes);
 
     [MayThrowException] Element? querySelector(DOMString selectors);
     [MayThrowException, NewObject] NodeList querySelectorAll(DOMString selectors);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to