Skip to content

Commit

Permalink
DocumentType properties entities and notations are only available in IE
Browse files Browse the repository at this point in the history
Methods append/prepend/replaceChildren added to Element
Element.replaceWith() fixed for the case this was called without any new elements
  • Loading branch information
rbri committed Jan 21, 2023
1 parent 343aa84 commit 4a9fb38
Show file tree
Hide file tree
Showing 7 changed files with 1,391 additions and 40 deletions.
11 changes: 10 additions & 1 deletion src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,16 @@

<body>
<release version="2.70.0" date="xx, 2023" description="Chrome/Edge 109, Firefox 108, Bugfixes">
<action type="fix" dev="rbri" issue="541">"
<action type="fix" dev="rbri">"
DocumentType properties entities and notations are only available in IE.
</action>
<action type="add" dev="rbri" issue="544">"
Methods append/prepend/replaceChildren added to Element.
</action>
<action type="fix" dev="rbri" >"
Element.replaceWith() fixed for the case this was called without any new elements.
</action>
<action type="fix" dev="rbri" issue="541">
Another Xerces detection fix for JDK 17.
</action>
<action type="add" dev="rbri">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1962,7 +1962,7 @@ public static void after(final Context context, final Scriptable thisObj, final
}

/**
* Replaces the node wit a set of Node or DOMString objects.
* Replaces the node with a set of Node or DOMString objects.
* @param context the context
* @param thisObj this object
* @param args the arguments
Expand Down Expand Up @@ -2105,4 +2105,58 @@ public boolean toggleAttribute(final String name, final Object force) {
return false;
}
}

/**
* Inserts a set of Node objects or string objects after the last child of the Element.
* String objects are inserted as equivalent Text nodes.
* @param context the context
* @param thisObj this object
* @param args the arguments
* @param function the function
*/
@JsxFunction({CHROME, EDGE, FF, FF_ESR})
public static void append(final Context context, final Scriptable thisObj, final Object[] args,
final Function function) {
if (!(thisObj instanceof Element)) {
throw ScriptRuntime.typeError("Illegal invocation");
}

Node.append(context, thisObj, args, function);
}

/**
* Inserts a set of Node objects or string objects before the first child of the Element.
* String objects are inserted as equivalent Text nodes.
* @param context the context
* @param thisObj this object
* @param args the arguments
* @param function the function
*/
@JsxFunction({CHROME, EDGE, FF, FF_ESR})
public static void prepend(final Context context, final Scriptable thisObj, final Object[] args,
final Function function) {
if (!(thisObj instanceof Element)) {
throw ScriptRuntime.typeError("Illegal invocation");
}

Node.prepend(context, thisObj, args, function);
}

/**
* Replaces the existing children of a Node with a specified new set of children.
* These can be string or Node objects.
* @param context the context
* @param thisObj this object
* @param args the arguments
* @param function the function
*/
@JsxFunction({CHROME, EDGE, FF, FF_ESR})
public static void replaceChildren(final Context context, final Scriptable thisObj, final Object[] args,
final Function function) {
if (!(thisObj instanceof Element)) {
throw ScriptRuntime.typeError("Illegal invocation");
}

Node.replaceChildren(context, thisObj, args, function);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public String getInternalSubset() {
* Returns entities.
* @return entities
*/
@JsxGetter
@JsxGetter(IE)
public Object getEntities() {
final NamedNodeMap entities = ((DomDocumentType) getDomNodeOrDie()).getEntities();
if (null != entities) {
Expand All @@ -132,7 +132,7 @@ public Object getEntities() {
* Returns notations.
* @return notations
*/
@JsxGetter
@JsxGetter(IE)
public Object getNotations() {
final NamedNodeMap notations = ((DomDocumentType) getDomNodeOrDie()).getNotations();
if (null != notations) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,80 @@ protected static void after(final Context context, final Scriptable thisObj, fin
}
}

/**
* Inserts a set of Node objects or string objects after the last child of the Element.
* String objects are inserted as equivalent Text nodes.
* @param context the context
* @param thisObj this object
* @param args the arguments
* @param function the function
*/
protected static void append(final Context context, final Scriptable thisObj, final Object[] args,
final Function function) {
if (!(thisObj instanceof Element)) {
throw ScriptRuntime.typeError("Illegal invocation");
}

final DomNode thisDomNode = ((Node) thisObj).getDomNodeOrDie();

for (final Object arg : args) {
final Node node = toNodeOrTextNode((Node) thisObj, arg);
final DomNode newNode = node.getDomNodeOrDie();
thisDomNode.appendChild(newNode);
}
}

/**
* Inserts a set of Node objects or string objects before the first child of the Element.
* String objects are inserted as equivalent Text nodes.
* @param context the context
* @param thisObj this object
* @param args the arguments
* @param function the function
*/
protected static void prepend(final Context context, final Scriptable thisObj, final Object[] args,
final Function function) {
if (!(thisObj instanceof Element)) {
throw ScriptRuntime.typeError("Illegal invocation");
}

final DomNode thisDomNode = ((Node) thisObj).getDomNodeOrDie();
final DomNode firstChild = thisDomNode.getFirstChild();
for (final Object arg : args) {
final Node node = toNodeOrTextNode((Node) thisObj, arg);
final DomNode newNode = node.getDomNodeOrDie();
if (firstChild == null) {
thisDomNode.appendChild(newNode);
}
else {
firstChild.insertBefore(newNode);
}
}
}

/**
* Replaces the existing children of a Node with a specified new set of children.
* These can be string or Node objects.
* @param context the context
* @param thisObj this object
* @param args the arguments
* @param function the function
*/
protected static void replaceChildren(final Context context, final Scriptable thisObj, final Object[] args,
final Function function) {
if (!(thisObj instanceof Element)) {
throw ScriptRuntime.typeError("Illegal invocation");
}

final DomNode thisDomNode = ((Node) thisObj).getDomNodeOrDie();
thisDomNode.removeAllChildren();

for (final Object arg : args) {
final Node node = toNodeOrTextNode((Node) thisObj, arg);
thisDomNode.appendChild(node.getDomNodeOrDie());
}
}

private static Node toNodeOrTextNode(final Node thisObj, final Object obj) {
if (obj instanceof Node) {
return (Node) obj;
Expand Down Expand Up @@ -901,6 +975,12 @@ protected static void replaceWith(final Context context, final Scriptable thisOb
final Function function) {
final DomNode thisDomNode = ((Node) thisObj).getDomNodeOrDie();
final DomNode parentNode = thisDomNode.getParentNode();

if (args.length == 0) {
parentNode.removeChild(thisDomNode);
return;
}

final DomNode nextSibling = thisDomNode.getNextSibling();
boolean isFirst = true;
for (final Object arg : args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import com.gargoylesoftware.htmlunit.javascript.host.crypto.Crypto;
import com.gargoylesoftware.htmlunit.javascript.host.crypto.SubtleCrypto;
import com.gargoylesoftware.htmlunit.javascript.host.css.ComputedCSSStyleDeclaration;
import com.gargoylesoftware.htmlunit.javascript.host.dom.CDATASection;
import com.gargoylesoftware.htmlunit.javascript.host.dom.NodeList;
import com.gargoylesoftware.htmlunit.javascript.host.dom.XPathResult;
import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLCollection;
Expand Down Expand Up @@ -583,7 +584,8 @@ public void htmlElement() throws Exception {
+ "scrollLeft,scrollTop,scrollWidth,setAttribute(),setAttributeNode(),setAttributeNodeNS(),"
+ "setAttributeNS(),setPointerCapture(),"
+ "tagName")
@HtmlUnitNYI(CHROME = "after(),attributes,before(),childElementCount,children,classList,className,clientHeight,"
@HtmlUnitNYI(CHROME = "after(),append(),attributes,before(),"
+ "childElementCount,children,classList,className,clientHeight,"
+ "clientLeft,clientTop,clientWidth,closest(),constructor(),"
+ "firstElementChild,getAttribute(),getAttributeNode(),"
+ "getAttributeNodeNS(),getAttributeNS(),getBoundingClientRect(),getClientRects(),"
Expand All @@ -593,12 +595,14 @@ public void htmlElement() throws Exception {
+ "innerHTML,insertAdjacentElement(),insertAdjacentHTML(),insertAdjacentText(),lastElementChild,"
+ "localName,"
+ "matches(),namespaceURI,nextElementSibling,onbeforecopy,onbeforecut,onbeforepaste,"
+ "onsearch,onwebkitfullscreenchange,onwebkitfullscreenerror,outerHTML,prefix,"
+ "onsearch,onwebkitfullscreenchange,onwebkitfullscreenerror,outerHTML,prefix,prepend(),"
+ "previousElementSibling,querySelector(),querySelectorAll(),remove(),removeAttribute(),"
+ "removeAttributeNode(),removeAttributeNS(),replaceWith(),scrollHeight,scrollIntoView(),"
+ "removeAttributeNode(),removeAttributeNS(),replaceChildren(),replaceWith(),"
+ "scrollHeight,scrollIntoView(),"
+ "scrollIntoViewIfNeeded(),scrollLeft,scrollTop,scrollWidth,setAttribute(),setAttributeNode(),"
+ "setAttributeNS(),tagName,toggleAttribute(),webkitMatchesSelector()",
EDGE = "after(),attributes,before(),childElementCount,children,classList,className,clientHeight,"
EDGE = "after(),append(),attributes,before(),"
+ "childElementCount,children,classList,className,clientHeight,"
+ "clientLeft,clientTop,clientWidth,closest(),constructor(),"
+ "firstElementChild,getAttribute(),getAttributeNode(),"
+ "getAttributeNodeNS(),getAttributeNS(),getBoundingClientRect(),getClientRects(),"
Expand All @@ -608,33 +612,39 @@ public void htmlElement() throws Exception {
+ "innerHTML,insertAdjacentElement(),insertAdjacentHTML(),insertAdjacentText(),lastElementChild,"
+ "localName,"
+ "matches(),namespaceURI,nextElementSibling,onbeforecopy,onbeforecut,onbeforepaste,"
+ "onsearch,onwebkitfullscreenchange,onwebkitfullscreenerror,outerHTML,prefix,"
+ "onsearch,onwebkitfullscreenchange,onwebkitfullscreenerror,outerHTML,prefix,prepend(),"
+ "previousElementSibling,querySelector(),querySelectorAll(),remove(),removeAttribute(),"
+ "removeAttributeNode(),removeAttributeNS(),replaceWith(),scrollHeight,scrollIntoView(),"
+ "removeAttributeNode(),removeAttributeNS(),replaceChildren(),replaceWith(),"
+ "scrollHeight,scrollIntoView(),"
+ "scrollIntoViewIfNeeded(),scrollLeft,scrollTop,scrollWidth,setAttribute(),setAttributeNode(),"
+ "setAttributeNS(),tagName,toggleAttribute(),webkitMatchesSelector()",
FF = "after(),attributes,before(),childElementCount,children,classList,className,clientHeight,clientLeft,"
FF = "after(),append(),attributes,before(),"
+ "childElementCount,children,classList,className,clientHeight,clientLeft,"
+ "clientTop,clientWidth,closest(),constructor(),"
+ "firstElementChild,getAttribute(),getAttributeNode(),"
+ "getAttributeNodeNS(),getAttributeNS(),getBoundingClientRect(),getClientRects(),"
+ "getElementsByClassName(),getElementsByTagName(),getElementsByTagNameNS(),hasAttribute(),"
+ "hasAttributeNS(),hasAttributes(),id,innerHTML,insertAdjacentElement(),insertAdjacentHTML(),"
+ "insertAdjacentText(),lastElementChild,localName,matches(),mozMatchesSelector(),namespaceURI,"
+ "nextElementSibling,outerHTML,prefix,previousElementSibling,querySelector(),querySelectorAll(),"
+ "nextElementSibling,outerHTML,prefix,prepend(),previousElementSibling,"
+ "querySelector(),querySelectorAll(),"
+ "releaseCapture(),remove(),removeAttribute(),removeAttributeNode(),"
+ "removeAttributeNS(),replaceWith(),"
+ "removeAttributeNS(),replaceChildren(),replaceWith(),"
+ "scrollHeight,scrollIntoView(),scrollLeft,scrollTop,scrollWidth,setAttribute(),setAttributeNode(),"
+ "setAttributeNS(),setCapture(),tagName,toggleAttribute(),webkitMatchesSelector()",
FF_ESR = "after(),attributes,before(),childElementCount,children,"
FF_ESR = "after(),append(),attributes,before(),"
+ "childElementCount,children,"
+ "classList,className,clientHeight,clientLeft,"
+ "clientTop,clientWidth,closest(),constructor(),"
+ "firstElementChild,getAttribute(),getAttributeNode(),"
+ "getAttributeNodeNS(),getAttributeNS(),getBoundingClientRect(),getClientRects(),"
+ "getElementsByClassName(),getElementsByTagName(),getElementsByTagNameNS(),hasAttribute(),"
+ "hasAttributeNS(),hasAttributes(),id,innerHTML,insertAdjacentElement(),insertAdjacentHTML(),"
+ "insertAdjacentText(),lastElementChild,localName,matches(),mozMatchesSelector(),namespaceURI,"
+ "nextElementSibling,outerHTML,prefix,previousElementSibling,querySelector(),querySelectorAll(),"
+ "releaseCapture(),remove(),removeAttribute(),removeAttributeNode(),removeAttributeNS(),replaceWith(),"
+ "nextElementSibling,outerHTML,prefix,prepend(),previousElementSibling,"
+ "querySelector(),querySelectorAll(),"
+ "releaseCapture(),remove(),removeAttribute(),removeAttributeNode(),"
+ "removeAttributeNS(),replaceChildren(),replaceWith(),"
+ "scrollHeight,scrollIntoView(),scrollLeft,scrollTop,scrollWidth,setAttribute(),setAttributeNode(),"
+ "setAttributeNS(),setCapture(),tagName,toggleAttribute(),webkitMatchesSelector()",
IE = "attributes,childElementCount,clientHeight,clientLeft,clientTop,clientWidth,constructor,"
Expand Down Expand Up @@ -13037,4 +13047,38 @@ public void cryptoSubtle() throws Exception {
public void xPathResult() throws Exception {
testString("var res = document.evaluate('/html/body', document, null, XPathResult.ANY_TYPE, null);", "res");
}

/**
* Test {@link CDATASection}.
*
* @throws Exception if the test fails
*/
@Test
@Alerts(CHROME = "constructor()",
EDGE = "constructor()",
FF = "constructor()",
FF_ESR = "constructor()",
IE = "constructor")
public void cDATASection() throws Exception {
final String setup = " var doc = document.implementation.createDocument('', '', null);\n"
+ "var root = doc.appendChild(doc.createElement('root'));\n"
+ "var cdata = root.appendChild(doc.createCDATASection('abcdef'));\n";

testString(setup, "cdata");
}

/**
* Test {@link CDATASection}.
*
* @throws Exception if the test fails
*/
@Test
@Alerts(CHROME = "after(),before(),constructor(),name,publicId,remove(),replaceWith(),systemId",
EDGE = "after(),before(),constructor(),name,publicId,remove(),replaceWith(),systemId",
FF = "after(),before(),constructor(),name,publicId,remove(),replaceWith(),systemId",
FF_ESR = "after(),before(),constructor(),name,publicId,remove(),replaceWith(),systemId",
IE = "constructor,entities,internalSubset,name,notations,publicId,systemId")
public void documentType() throws Exception {
testString("", "document.firstChild");
}
}

0 comments on commit 4a9fb38

Please sign in to comment.