View Javadoc
1   /*
2    * Copyright (c) 2002-2026 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.dom;
16  
17  import static org.htmlunit.BrowserVersionFeatures.EVENT_TYPE_MUTATIONEVENT;
18  import static org.htmlunit.BrowserVersionFeatures.JS_DOCUMENT_EVALUATE_RECREATES_RESULT;
19  import static org.htmlunit.BrowserVersionFeatures.JS_DOCUMENT_SELECTION_RANGE_COUNT;
20  import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
21  import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
22  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF;
23  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR;
24  
25  import java.io.IOException;
26  import java.io.Serializable;
27  import java.lang.reflect.InvocationTargetException;
28  import java.net.URL;
29  import java.time.ZoneId;
30  import java.time.format.DateTimeFormatter;
31  import java.util.Date;
32  import java.util.HashMap;
33  import java.util.HashSet;
34  import java.util.Locale;
35  import java.util.Map;
36  import java.util.Set;
37  import java.util.UUID;
38  import java.util.function.Predicate;
39  
40  import org.apache.commons.logging.Log;
41  import org.apache.commons.logging.LogFactory;
42  import org.htmlunit.HttpHeader;
43  import org.htmlunit.Page;
44  import org.htmlunit.SgmlPage;
45  import org.htmlunit.StringWebResponse;
46  import org.htmlunit.WebResponse;
47  import org.htmlunit.WebWindow;
48  import org.htmlunit.corejs.javascript.Callable;
49  import org.htmlunit.corejs.javascript.Context;
50  import org.htmlunit.corejs.javascript.Function;
51  import org.htmlunit.corejs.javascript.NativeFunction;
52  import org.htmlunit.corejs.javascript.Scriptable;
53  import org.htmlunit.corejs.javascript.ScriptableObject;
54  import org.htmlunit.corejs.javascript.VarScope;
55  import org.htmlunit.cssparser.parser.CSSException;
56  import org.htmlunit.html.DomComment;
57  import org.htmlunit.html.DomDocumentFragment;
58  import org.htmlunit.html.DomElement;
59  import org.htmlunit.html.DomNode;
60  import org.htmlunit.html.DomText;
61  import org.htmlunit.html.FrameWindow;
62  import org.htmlunit.html.Html;
63  import org.htmlunit.html.HtmlAnchor;
64  import org.htmlunit.html.HtmlArea;
65  import org.htmlunit.html.HtmlAttributeChangeEvent;
66  import org.htmlunit.html.HtmlElement;
67  import org.htmlunit.html.HtmlEmbed;
68  import org.htmlunit.html.HtmlForm;
69  import org.htmlunit.html.HtmlFrameSet;
70  import org.htmlunit.html.HtmlImage;
71  import org.htmlunit.html.HtmlPage;
72  import org.htmlunit.html.HtmlRb;
73  import org.htmlunit.html.HtmlRp;
74  import org.htmlunit.html.HtmlRt;
75  import org.htmlunit.html.HtmlRtc;
76  import org.htmlunit.html.HtmlScript;
77  import org.htmlunit.html.HtmlSvg;
78  import org.htmlunit.html.HtmlUnknownElement;
79  import org.htmlunit.html.UnknownElementFactory;
80  import org.htmlunit.html.impl.SimpleRange;
81  import org.htmlunit.http.Cookie;
82  import org.htmlunit.http.HttpUtils;
83  import org.htmlunit.httpclient.HtmlUnitBrowserCompatCookieSpec;
84  import org.htmlunit.javascript.HtmlUnitScriptable;
85  import org.htmlunit.javascript.JavaScriptEngine;
86  import org.htmlunit.javascript.configuration.JsxClass;
87  import org.htmlunit.javascript.configuration.JsxConstructor;
88  import org.htmlunit.javascript.configuration.JsxFunction;
89  import org.htmlunit.javascript.configuration.JsxGetter;
90  import org.htmlunit.javascript.configuration.JsxSetter;
91  import org.htmlunit.javascript.configuration.JsxStaticFunction;
92  import org.htmlunit.javascript.host.Element;
93  import org.htmlunit.javascript.host.FontFaceSet;
94  import org.htmlunit.javascript.host.Location;
95  import org.htmlunit.javascript.host.NativeFunctionPrefixResolver;
96  import org.htmlunit.javascript.host.Window;
97  import org.htmlunit.javascript.host.animations.AnimationEvent;
98  import org.htmlunit.javascript.host.css.StyleSheetList;
99  import org.htmlunit.javascript.host.dom.AbstractList.EffectOnCache;
100 import org.htmlunit.javascript.host.event.BeforeUnloadEvent;
101 import org.htmlunit.javascript.host.event.CompositionEvent;
102 import org.htmlunit.javascript.host.event.CustomEvent;
103 import org.htmlunit.javascript.host.event.DeviceMotionEvent;
104 import org.htmlunit.javascript.host.event.DeviceOrientationEvent;
105 import org.htmlunit.javascript.host.event.DragEvent;
106 import org.htmlunit.javascript.host.event.Event;
107 import org.htmlunit.javascript.host.event.FocusEvent;
108 import org.htmlunit.javascript.host.event.HashChangeEvent;
109 import org.htmlunit.javascript.host.event.KeyboardEvent;
110 import org.htmlunit.javascript.host.event.MessageEvent;
111 import org.htmlunit.javascript.host.event.MouseEvent;
112 import org.htmlunit.javascript.host.event.MutationEvent;
113 import org.htmlunit.javascript.host.event.PointerEvent;
114 import org.htmlunit.javascript.host.event.PopStateEvent;
115 import org.htmlunit.javascript.host.event.ProgressEvent;
116 import org.htmlunit.javascript.host.event.TextEvent;
117 import org.htmlunit.javascript.host.event.UIEvent;
118 import org.htmlunit.javascript.host.event.WheelEvent;
119 import org.htmlunit.javascript.host.file.Blob;
120 import org.htmlunit.javascript.host.html.HTMLAllCollection;
121 import org.htmlunit.javascript.host.html.HTMLBodyElement;
122 import org.htmlunit.javascript.host.html.HTMLCollection;
123 import org.htmlunit.javascript.host.html.HTMLElement;
124 import org.htmlunit.javascript.host.html.HTMLFrameSetElement;
125 import org.htmlunit.util.StringUtils;
126 import org.htmlunit.util.UrlUtils;
127 import org.htmlunit.xpath.xml.utils.PrefixResolver;
128 import org.w3c.dom.CDATASection;
129 import org.w3c.dom.DOMException;
130 import org.w3c.dom.DocumentType;
131 import org.w3c.dom.ProcessingInstruction;
132 
133 /**
134  * A JavaScript object for {@code Document}.
135  *
136  * @author Mike Bowler
137  * @author David K. Taylor
138  * @author Chen Jun
139  * @author Christian Sell
140  * @author Chris Erskine
141  * @author Marc Guillemot
142  * @author Daniel Gredler
143  * @author Michael Ottati
144  * @author George Murnock
145  * @author Ahmed Ashour
146  * @author Rob Di Marco
147  * @author Ronald Brill
148  * @author Chuck Dumont
149  * @author Frank Danek
150  * @author Madis Pärn
151  * @author Lai Quang Duong
152  * @author Sven Strickroth
153  *
154  * @see <a href="http://msdn.microsoft.com/en-us/library/ms531073.aspx">MSDN documentation</a>
155  * @see <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-7068919">W3C Dom Level 1</a>
156  */
157 @JsxClass
158 public class Document extends Node {
159 
160     private static final Log LOG = LogFactory.getLog(Document.class);
161 
162     /**
163      * See <a href="https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla#Executing_Commands">
164      *     Executing Commands</a>
165      */
166     private static final Set<String> EXECUTE_CMDS_FF = new HashSet<>();
167     private static final Set<String> EXECUTE_CMDS_CHROME = new HashSet<>();
168     /** The formatter to use for the <code>lastModified</code> attribute. */
169     private static final DateTimeFormatter LAST_MODIFIED_DATE_FORMATTER
170                                             = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss");
171 
172     /** Contains all supported DOM level 2 events. */
173     private static final Map<String, Class<? extends Event>> SUPPORTED_DOM2_EVENT_TYPE_MAP;
174     /** Contains all supported DOM level 3 events. DOM level 2 events are not included. */
175     private static final Map<String, Class<? extends Event>> SUPPORTED_DOM3_EVENT_TYPE_MAP;
176     /** Contains all supported vendor specific events. */
177     private static final Map<String, Class<? extends Event>> SUPPORTED_VENDOR_EVENT_TYPE_MAP;
178 
179     /*
180       Initializes the supported event type map.
181       Map<String, Class> which maps strings a caller may use when calling into
182       {@link #createEvent(String)} to the associated event class. To support a new
183       event creation type, the event type and associated class need to be added into this map in
184       the static initializer. The map is unmodifiable. Any class that is a value in this map MUST
185       have a no-arg constructor.
186      */
187     static {
188         SUPPORTED_DOM2_EVENT_TYPE_MAP = Map.of(
189                 "HTMLEvents", Event.class,
190                 "MouseEvents", MouseEvent.class,
191                 "MutationEvents", MutationEvent.class,
192                 "UIEvents", UIEvent.class);
193 
194         SUPPORTED_DOM3_EVENT_TYPE_MAP = Map.ofEntries(
195                 Map.entry("Event", Event.class),
196                 Map.entry("KeyboardEvent", KeyboardEvent.class),
197                 Map.entry("MouseEvent", MouseEvent.class),
198                 Map.entry("MessageEvent", MessageEvent.class),
199                 Map.entry("MutationEvent", MutationEvent.class),
200                 Map.entry("UIEvent", UIEvent.class),
201                 Map.entry("CustomEvent", CustomEvent.class),
202                 Map.entry("CompositionEvent", CompositionEvent.class),
203                 Map.entry("DragEvent", DragEvent.class),
204                 Map.entry("TextEvent", TextEvent.class),
205                 Map.entry("DeviceMotionEvent", DeviceMotionEvent.class),
206                 Map.entry("DeviceOrientationEvent", DeviceOrientationEvent.class));
207 
208         SUPPORTED_VENDOR_EVENT_TYPE_MAP = Map.ofEntries(
209                 Map.entry("BeforeUnloadEvent", BeforeUnloadEvent.class),
210                 Map.entry("Events", Event.class),
211                 Map.entry("HashChangeEvent", HashChangeEvent.class),
212                 Map.entry("KeyEvents", KeyboardEvent.class),
213                 Map.entry("PointerEvent", PointerEvent.class),
214                 Map.entry("PopStateEvent", PopStateEvent.class),
215                 Map.entry("ProgressEvent", ProgressEvent.class),
216                 Map.entry("FocusEvent", FocusEvent.class),
217                 Map.entry("WheelEvent", WheelEvent.class),
218                 Map.entry("AnimationEvent", AnimationEvent.class));
219     }
220 
221     private Window window_;
222     private DOMImplementation implementation_;
223     private String designMode_;
224     private String compatMode_;
225     private int documentMode_ = -1;
226     private String domain_;
227     private String lastModified_;
228     private ScriptableObject currentScript_;
229     private transient FontFaceSet fonts_;
230     private transient StyleSheetList styleSheetList_;
231 
232     private final Map<String, Blob> blobUrl2Blobs_ = new HashMap<>();
233 
234     static {
235         // commands
236         String[] cmds = {
237             "BackColor", "BackgroundImageCache" /* Undocumented */,
238             "Bold",
239             "CreateLink", "Delete",
240             "FontName", "FontSize", "ForeColor", "FormatBlock",
241             "Indent", "InsertHorizontalRule", "InsertImage",
242             "InsertOrderedList", "InsertParagraph", "InsertUnorderedList",
243             "Italic", "JustifyCenter", "JustifyFull", "JustifyLeft", "JustifyNone",
244             "JustifyRight",
245             "Outdent",
246             "Print",
247             "Redo", "RemoveFormat",
248             "SelectAll", "StrikeThrough", "Subscript", "Superscript",
249             "Underline", "Undo", "Unlink", "Unselect"
250         };
251         for (final String cmd : cmds) {
252             if (!"Bold".equals(cmd)) {
253                 EXECUTE_CMDS_CHROME.add(cmd.toLowerCase(Locale.ROOT));
254             }
255         }
256 
257         cmds = new String[] {
258             "backColor", "bold", "contentReadOnly", "copy", "createLink", "cut", "decreaseFontSize", "delete",
259             "fontName", "fontSize", "foreColor", "formatBlock", "heading", "hiliteColor", "increaseFontSize",
260             "indent", "insertHorizontalRule", "insertHTML", "insertImage", "insertOrderedList", "insertUnorderedList",
261             "insertParagraph", "italic",
262             "justifyCenter", "JustifyFull", "justifyLeft", "justifyRight", "outdent", "paste", "redo",
263             "removeFormat", "selectAll", "strikeThrough", "subscript", "superscript", "underline", "undo", "unlink",
264             "useCSS", "styleWithCSS"
265         };
266         for (final String cmd : cmds) {
267             EXECUTE_CMDS_FF.add(cmd.toLowerCase(Locale.ROOT));
268             if (!"bold".equals(cmd)) {
269                 EXECUTE_CMDS_CHROME.add(cmd.toLowerCase(Locale.ROOT));
270             }
271         }
272     }
273 
274     /**
275      * JavaScript constructor.
276      */
277     @Override
278     @JsxConstructor
279     public void jsConstructor() {
280         throw JavaScriptEngine.typeErrorIllegalConstructor();
281     }
282 
283     /**
284      * Parses the given string of HTML without sanitizing it and returns a new HTMLDocument.
285      *
286      * @param cx the current context
287      * @param scope the scope
288      * @param thisObj the scriptable this object
289      * @param args the arguments
290      * @param funObj the function object
291      * @return a newly created {@link org.htmlunit.javascript.host.html.HTMLDocument}
292      *
293      * @see <a href="https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-parsehtmlunsafe">
294      *     HTML spec - parseHTMLUnsafe</a>
295      */
296     @JsxStaticFunction
297     public static Document parseHTMLUnsafe(final Context cx, final VarScope scope,
298             final Scriptable thisObj, final Object[] args, final Function funObj) {
299         if (args.length < 1) {
300             throw JavaScriptEngine
301                     .typeError("Document.parseHTMLUnsafe: At least 1 argument required, but only 0 passed");
302         }
303 
304         final Window win = getWindow(thisObj);
305         if (JavaScriptEngine.isUndefined(args[0])) {
306             return win.getDocument();
307         }
308 
309         final String html = JavaScriptEngine.toString(args[0]);
310 
311         try {
312             final WebWindow webWindow = win.getWebWindow();
313             final WebResponse webResponse = new StringWebResponse(html, webWindow.getEnclosedPage().getUrl());
314             return DOMParser.parseHtmlDocument(win.getDocument(), webResponse, webWindow);
315         }
316         catch (final IOException e) {
317             throw JavaScriptEngine.syntaxError("Parsing failed" + e.getMessage());
318         }
319     }
320 
321     /**
322      * Sets the Window JavaScript object that encloses this document.
323      * @param window the Window JavaScript object that encloses this document
324      */
325     public void setWindow(final Window window) {
326         window_ = window;
327     }
328 
329     /**
330      * Returns the value of the {@code location} property.
331      * @return the value of the {@code location} property
332      */
333     @JsxGetter
334     public Location getLocation() {
335         if (window_ == null) {
336             return null;
337         }
338         return window_.getLocation();
339     }
340 
341     /**
342      * Sets the value of the {@code location} property. The location's default property is "href",
343      * so setting "document.location='http://www.sf.net'" is equivalent to setting
344      * "document.location.href='http://www.sf.net'".
345      * @see <a href="http://msdn.microsoft.com/en-us/library/ms535866.aspx">MSDN documentation</a>
346      * @param location the location to navigate to
347      * @throws IOException when location loading fails
348      */
349     @JsxSetter
350     public void setLocation(final String location) throws IOException {
351         window_.setLocation(location);
352     }
353 
354     /**
355      * Returns the value of the {@code referrer} property.
356      * @return the value of the {@code referrer} property
357      */
358     @JsxGetter
359     public String getReferrer() {
360         String referrer = "";
361         final WebResponse webResponse = getPage().getWebResponse();
362         if (webResponse != null) {
363             referrer = webResponse.getWebRequest().getAdditionalHeaders().get(HttpHeader.REFERER);
364             if (referrer == null) {
365                 referrer = "";
366             }
367         }
368         return referrer;
369     }
370 
371     /**
372      * Gets the JavaScript property {@code documentElement} for the document.
373      * @return the root node for the document
374      */
375     @JsxGetter
376     public Element getDocumentElement() {
377         final Object documentElement = getPage().getDocumentElement();
378         if (documentElement == null) {
379             // for instance with an XML document with parsing error
380             return null;
381         }
382         return (Element) getScriptableFor(documentElement);
383     }
384 
385     /**
386      * Gets the JavaScript property {@code rootElement}.
387      * @return the root node for the document
388      */
389     @JsxGetter
390     public Element getRootElement() {
391         return null;
392     }
393 
394     /**
395      * Gets the JavaScript property {@code doctype} for the document.
396      * @return the DocumentType of the document
397      */
398     @JsxGetter
399     public HtmlUnitScriptable getDoctype() {
400         final Object documentType = getPage().getDoctype();
401         if (documentType == null) {
402             return null;
403         }
404         return getScriptableFor(documentType);
405     }
406 
407     /**
408      * Returns a value which indicates whether or not the document can be edited.
409      * @return a value which indicates whether or not the document can be edited
410      */
411     @JsxGetter
412     public String getDesignMode() {
413         if (designMode_ == null) {
414             designMode_ = "off";
415         }
416         return designMode_;
417     }
418 
419     /**
420      * Sets a value which indicates whether or not the document can be edited.
421      * @param mode a value which indicates whether or not the document can be edited
422      */
423     @JsxSetter
424     public void setDesignMode(final String mode) {
425         if ("on".equalsIgnoreCase(mode)) {
426             designMode_ = "on";
427             final SgmlPage page = getPage();
428             if (page != null && page.isHtmlPage()
429                     && getBrowserVersion().hasFeature(JS_DOCUMENT_SELECTION_RANGE_COUNT)) {
430                 final HtmlPage htmlPage = (HtmlPage) page;
431                 final DomNode child = htmlPage.getBody().getFirstChild();
432                 final DomNode rangeNode = child == null ? htmlPage.getBody() : child;
433                 htmlPage.setSelectionRange(new SimpleRange(rangeNode, 0));
434             }
435         }
436         else if ("off".equalsIgnoreCase(mode)) {
437             designMode_ = "off";
438         }
439     }
440 
441     /**
442      * Returns the page that this document is modeling.
443      * @return the page that this document is modeling
444      */
445     public SgmlPage getPage() {
446         return (SgmlPage) getDomNodeOrDie();
447     }
448 
449     /**
450      * Gets the window in which this document is contained.
451      * @return the window
452      */
453     @JsxGetter
454     public Object getDefaultView() {
455         return getWindow();
456     }
457 
458     /**
459      * Creates a new document fragment.
460      * @return a newly created document fragment
461      */
462     @JsxFunction
463     public HtmlUnitScriptable createDocumentFragment() {
464         final DomDocumentFragment fragment = getDomNodeOrDie().getPage().createDocumentFragment();
465         final DocumentFragment node = new DocumentFragment();
466         node.setParentScope(getParentScope());
467         node.setPrototype(getPrototype(node.getClass()));
468         node.setDomNode(fragment);
469         return getScriptableFor(fragment);
470     }
471 
472     /**
473      * Creates a new HTML attribute with the specified name.
474      *
475      * @param attributeName the name of the attribute to create
476      * @return an attribute with the specified name
477      */
478     @JsxFunction
479     public Attr createAttribute(final String attributeName) {
480         return getPage().createAttribute(attributeName).getScriptableObject();
481     }
482 
483     /**
484      * Imports a node from another document to this document.
485      * The source node is not altered or removed from the original document;
486      * this method creates a new copy of the source node.
487      *
488      * @param importedNode the node to import
489      * @param deep Whether to recursively import the subtree under the specified node; or not
490      * @return the imported node that belongs to this Document
491      */
492     @JsxFunction
493     public HtmlUnitScriptable importNode(final Node importedNode, final boolean deep) {
494         DomNode domNode = importedNode.getDomNodeOrDie();
495         domNode = domNode.cloneNode(deep);
496         domNode.processImportNode(this);
497         for (final DomNode childNode : domNode.getDescendants()) {
498             childNode.processImportNode(this);
499         }
500         return domNode.getScriptableObject();
501     }
502 
503     /**
504      * Adopts a node from an external document.
505      * The node and its subtree are removed from the document it's in (if any),
506      * and its ownerDocument is changed to the current document.
507      * The node can then be inserted into the current document.
508      *
509      * @param externalNode the node from another document to be adopted
510      * @return the adopted node that can be used in the current document
511      */
512     @JsxFunction
513     public HtmlUnitScriptable adoptNode(final Node externalNode) {
514         externalNode.remove();
515         return importNode(externalNode, true);
516     }
517 
518     /**
519      * Returns the implementation object of the current document.
520      * @return implementation-specific object
521      */
522     @JsxGetter
523     public DOMImplementation getImplementation() {
524         if (implementation_ == null) {
525             implementation_ = new DOMImplementation();
526             implementation_.setParentScope(getParentScope());
527             implementation_.setPrototype(getPrototype(implementation_.getClass()));
528         }
529         return implementation_;
530     }
531 
532     /**
533      * Adapts any DOM node to resolve namespaces so that an XPath expression can be easily
534      * evaluated relative to the context of the node where it appeared within the document.
535      * @param nodeResolver the node to be used as a context for namespace resolution
536      * @return an XPathNSResolver which resolves namespaces with respect to the definitions
537      *         in scope for a specified node
538      */
539     @JsxFunction
540     public NativeXPathNSResolver createNSResolver(final Node nodeResolver) {
541         final NativeXPathNSResolver resolver = new NativeXPathNSResolver();
542         resolver.setElement(nodeResolver);
543         resolver.setParentScope(getParentScope());
544         resolver.setPrototype(getPrototype(resolver.getClass()));
545         return resolver;
546     }
547 
548     /**
549      * Create a new DOM text node with the given data.
550      *
551      * @param newData the string value for the text node
552      * @return the new text node or NOT_FOUND if there is an error
553      */
554     @JsxFunction
555     public HtmlUnitScriptable createTextNode(final String newData) {
556         final DomNode domNode = new DomText(getDomNodeOrDie().getPage(), newData);
557         return makeScriptableFor(domNode);
558     }
559 
560     /**
561      * Creates a new Comment.
562      * @param comment the comment text
563      * @return the new Comment
564      */
565     @JsxFunction
566     public HtmlUnitScriptable createComment(final String comment) {
567         final DomNode domNode = new DomComment(getDomNodeOrDie().getPage(), comment);
568         return getScriptableFor(domNode);
569     }
570 
571     /**
572      * Evaluates an XPath expression string and returns a result of the specified type if possible.
573      * @param expression the XPath expression string to be parsed and evaluated
574      * @param contextNode the context node for the evaluation of this XPath expression
575      * @param resolver the resolver permits translation of all prefixes, including the XML namespace prefix,
576      *        within the XPath expression into appropriate namespace URIs.
577      * @param type If a specific type is specified, then the result will be returned as the corresponding type
578      * @param result the result object which may be reused and returned by this method
579      * @return the result of the evaluation of the XPath expression
580      */
581     @JsxFunction
582     public XPathResult evaluate(final String expression, final Node contextNode,
583             final Object resolver, final int type, final Object result) {
584         XPathResult xPathResult = null;
585         if (result instanceof XPathResult pathResult) {
586             xPathResult = pathResult;
587 
588             if (getBrowserVersion().hasFeature(JS_DOCUMENT_EVALUATE_RECREATES_RESULT)) {
589                 xPathResult = new XPathResult();
590                 xPathResult.setParentScope(getParentScope());
591                 xPathResult.setPrototype(getPrototype(xPathResult.getClass()));
592             }
593         }
594         else if (result == null
595                 || JavaScriptEngine.isUndefined(result)
596                 || result instanceof ScriptableObject) {
597             xPathResult = new XPathResult();
598             xPathResult.setParentScope(getParentScope());
599             xPathResult.setPrototype(getPrototype(xPathResult.getClass()));
600         }
601         else {
602             throw JavaScriptEngine.typeError("Argument 5 of Document.evaluate has to be an XPathResult or null.");
603         }
604 
605         try {
606             PrefixResolver prefixResolver = null;
607             if (resolver instanceof NativeFunction function) {
608                 prefixResolver = new NativeFunctionPrefixResolver(
609                                             function, contextNode.getParentScope());
610             }
611             else if (resolver instanceof PrefixResolver prefixResolver1) {
612                 prefixResolver = prefixResolver1;
613             }
614             xPathResult.init(contextNode.getDomNodeOrDie().getByXPath(expression, prefixResolver), type);
615             return xPathResult;
616         }
617         catch (final Exception e) {
618             throw JavaScriptEngine.asJavaScriptException(
619                     getWindow(),
620                     "Failed to execute 'evaluate': " + e.getMessage(),
621                     org.htmlunit.javascript.host.dom.DOMException.SYNTAX_ERR);
622         }
623     }
624 
625     /**
626      * Creates a new element with the given tag name.
627      *
628      * @param tagName the tag name
629      * @return the new HTML element, or NOT_FOUND if the tag is not supported
630      */
631     @JsxFunction
632     public HtmlUnitScriptable createElement(final Object tagName) {
633         if (tagName == null || JavaScriptEngine.isUndefined(tagName)) {
634             final org.w3c.dom.Node element = getPage().createElement("unknown");
635             ((HtmlUnknownElement) element).markAsCreatedByJavascript();
636             return getScriptableFor(element);
637         }
638 
639         // https://dom.spec.whatwg.org/#dom-document-createelement
640         // NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D]
641         //                       | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF]
642         //                       | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
643         // NameChar      ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
644         // Name          ::= NameStartChar (NameChar)*
645 
646         // but I have no idea what the browsers are doing
647         // the following code is a wild guess that might be good enough for the moment
648 
649         // April 2026
650         // looks like the browsers using a more simple approach now
651         // see
652         //   org.htmlunit.javascript.host.dom.DocumentTest.documentCreateElementValidTagNames()
653         //   org.htmlunit.javascript.host.dom.DocumentTest.documentCreateElementValidTagNames1000()
654         //   org.htmlunit.javascript.host.dom.DocumentTest.documentCreateElementValidTagNames2000()
655         //   org.htmlunit.javascript.host.dom.DocumentTest.documentCreateElementValidTagNames3000()
656         //   org.htmlunit.javascript.host.dom.DocumentTest.documentCreateElementValidTagNames4000()
657 
658         final String tagNameString = JavaScriptEngine.toString(tagName);
659         if (tagNameString.length() > 0) {
660             final int firstChar = tagNameString.charAt(0);
661             if (firstChar < 128
662                     && !Character.isLetter(firstChar)
663                     && firstChar != ':' && firstChar != '_') {
664                 if (LOG.isInfoEnabled()) {
665                     LOG.info("createElement: Provided string '" + tagNameString + "' contains an invalid character");
666                 }
667                 throw JavaScriptEngine.asJavaScriptException(
668                         getWindow(),
669                         "createElement: Provided string '" + tagNameString + "' contains an invalid character",
670                         org.htmlunit.javascript.host.dom.DOMException.INVALID_CHARACTER_ERR);
671             }
672 
673             final int length = tagNameString.length();
674             for (int i = 1; i < length; i++) {
675                 final int c = tagNameString.charAt(i);
676                 if (c < 128) {
677                     if (c == 0
678                             || c == 9
679                             || c == 10
680                             || c == 12
681                             || c == 13
682                             || c == ' '
683                             || c == '/'
684                             || c == '>') {
685                         if (LOG.isInfoEnabled()) {
686                             LOG.info("createElement: Provided string '"
687                                         + tagNameString + "' contains an invalid character");
688                         }
689                         throw JavaScriptEngine.asJavaScriptException(
690                                 getWindow(),
691                                 "createElement: Provided string '" + tagNameString
692                                     + "' contains an invalid character",
693                                 org.htmlunit.javascript.host.dom.DOMException.INVALID_CHARACTER_ERR);
694                     }
695                 }
696             }
697         }
698 
699         org.w3c.dom.Node element = getPage().createElement(tagNameString);
700 
701         if (element instanceof HtmlImage image) {
702             image.markAsCreatedByJavascript();
703         }
704         else if (element instanceof HtmlRb rb) {
705             rb.markAsCreatedByJavascript();
706         }
707         else if (element instanceof HtmlRp rp) {
708             rp.markAsCreatedByJavascript();
709         }
710         else if (element instanceof HtmlRt rt) {
711             rt.markAsCreatedByJavascript();
712         }
713         else if (element instanceof HtmlRtc rtc) {
714             rtc.markAsCreatedByJavascript();
715         }
716         else if (element instanceof HtmlUnknownElement unknownElement) {
717             unknownElement.markAsCreatedByJavascript();
718         }
719         else if (element instanceof HtmlSvg) {
720             element = UnknownElementFactory.INSTANCE.createElementNS(getPage(), "", "svg", null);
721             ((HtmlUnknownElement) element).markAsCreatedByJavascript();
722         }
723         final HtmlUnitScriptable jsElement = getScriptableFor(element);
724 
725         if (jsElement == NOT_FOUND) {
726             if (LOG.isDebugEnabled()) {
727                 LOG.debug("createElement(" + tagName
728                     + ") cannot return a result as there isn't a JavaScript object for the element "
729                     + element.getClass().getName());
730             }
731         }
732         return jsElement;
733     }
734 
735     /**
736      * Creates a new HTML element with the given tag name, and name.
737      *
738      * @param namespaceURI the URI that identifies an XML namespace
739      * @param qualifiedName the qualified name of the element type to instantiate
740      * @return the new HTML element, or NOT_FOUND if the tag is not supported
741      */
742     @JsxFunction
743     public HtmlUnitScriptable createElementNS(final String namespaceURI, final String qualifiedName) {
744         if ("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul".equals(namespaceURI)) {
745             throw JavaScriptEngine.typeError("XUL not available");
746         }
747 
748         final org.w3c.dom.Element element;
749         if (Html.XHTML_NAMESPACE.equals(namespaceURI)
750                 || Html.SVG_NAMESPACE.equals(namespaceURI)) {
751             element = getPage().createElementNS(namespaceURI, qualifiedName);
752         }
753         else {
754             element = new DomElement(namespaceURI, qualifiedName, getPage(), null);
755         }
756         return getScriptableFor(element);
757     }
758 
759     /**
760      * Returns all the descendant elements with the specified tag name.
761      * @param tagName the name to search for
762      * @return all the descendant elements with the specified tag name
763      */
764     @JsxFunction
765     public HTMLCollection getElementsByTagName(final String tagName) {
766         final HTMLCollection collection = new HTMLCollection(getDomNodeOrDie(), false);
767 
768         if (StringUtils.equalsChar('*', tagName)) {
769             collection.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> true);
770         }
771         else {
772             collection.setIsMatchingPredicate(
773                     (Predicate<DomNode> & Serializable)
774                     node -> tagName.equalsIgnoreCase(node.getNodeName()));
775         }
776 
777         return collection;
778     }
779 
780     /**
781      * Returns a list of elements with the given tag name belonging to the given namespace.
782      * @param namespaceURI the namespace URI of elements to look for
783      * @param localName is either the local name of elements to look for or the special value "*",
784      *                  which matches all elements.
785      * @return a live NodeList of found elements in the order they appear in the tree
786      */
787     @JsxFunction
788     public HTMLCollection getElementsByTagNameNS(final Object namespaceURI, final String localName) {
789         final HTMLCollection elements = new HTMLCollection(getDomNodeOrDie(), false);
790         elements.setIsMatchingPredicate(
791                 (Predicate<DomNode> & Serializable)
792                 node -> localName.equals(node.getLocalName()));
793         return elements;
794     }
795 
796     /**
797      * Returns the value of the {@code activeElement} property.
798      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533065.aspx">MSDN documentation</a>
799      * @return the value of the {@code activeElement} property
800      */
801     @JsxGetter
802     public Object getActiveElement() {
803         return null;
804     }
805 
806     /**
807      * Returns the character encoding of the current document.
808      * @return the character encoding of the current document
809      */
810     @JsxGetter
811     public String getCharacterSet() {
812         if (!(getPage() instanceof HtmlPage)) {
813             // TODO: implement XmlPage.getCharset
814             return "";
815         }
816         return getPage().getCharset().name();
817     }
818 
819     /**
820      * Retrieves the character set used to encode the document.
821      * @return the character set used to encode the document
822      */
823     @JsxGetter
824     public String getCharset() {
825         if (!(getPage() instanceof HtmlPage)) {
826             // TODO: implement XmlPage.getCharset
827             return "";
828         }
829         return getPage().getCharset().name();
830     }
831 
832     /**
833      * Returns the value of the JavaScript property {@code anchors}.
834      * @see <a href="http://msdn.microsoft.com/en-us/library/ms537435.aspx">MSDN documentation</a>
835      * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_doc_ref4.html#1024543">
836      *     Gecko DOM reference</a>
837      * @return the value of this property
838      */
839     @JsxGetter
840     public HTMLCollection getAnchors() {
841         final HTMLCollection anchors = new HTMLCollection(getDomNodeOrDie(), true);
842 
843         anchors.setIsMatchingPredicate(
844                 (Predicate<DomNode> & Serializable)
845                 node -> {
846                     if (!(node instanceof HtmlAnchor anchor)) {
847                         return false;
848                     }
849                     return anchor.hasAttribute(DomElement.NAME_ATTRIBUTE);
850                 });
851 
852         anchors.setEffectOnCacheFunction(
853                 (java.util.function.Function<HtmlAttributeChangeEvent, EffectOnCache> & Serializable)
854                     event -> {
855                         if (DomElement.NAME_ATTRIBUTE.equals(event.getName())
856                                 || DomElement.ID_ATTRIBUTE.equals(event.getName())) {
857                             return EffectOnCache.RESET;
858                         }
859                         return EffectOnCache.NONE;
860                     });
861 
862         return anchors;
863     }
864 
865     /**
866      * Returns the value of the JavaScript property {@code applets}.
867      * @see <a href="http://msdn.microsoft.com/en-us/library/ms537436.aspx">
868      *     MSDN documentation</a>
869      * @see <a href="https://developer.mozilla.org/En/DOM:document.applets">
870      *     Gecko DOM reference</a>
871      * @return the value of this property
872      */
873     @JsxGetter
874     public HTMLCollection getApplets() {
875         return new HTMLCollection(getDomNodeOrDie(), false);
876     }
877 
878     /**
879      * Returns this document's {@code body} element.
880      * @return this document's {@code body} element
881      */
882     @JsxGetter
883     public HTMLElement getBody() {
884         final Page page = getPage();
885         if (page instanceof HtmlPage htmlPage) {
886             final HtmlElement body = htmlPage.getBody();
887             if (body != null) {
888                 return body.getScriptableObject();
889             }
890 
891             // strange but this returns the frameset element
892             final DomElement doc = htmlPage.getDocumentElement();
893             if (doc != null) {
894                 for (final DomNode node : doc.getChildren()) {
895                     if (node instanceof HtmlFrameSet) {
896                         return node.getScriptableObject();
897                     }
898                 }
899             }
900         }
901         return null;
902     }
903 
904     /**
905      * Sets the {@code body} element of the document.
906      * @param htmlElement the new html element
907      */
908     @JsxSetter
909     public void setBody(final HTMLElement htmlElement) {
910         if (htmlElement instanceof HTMLBodyElement || htmlElement instanceof HTMLFrameSetElement) {
911             final Page page = getPage();
912             if (page instanceof HtmlPage htmlPage) {
913                 final HtmlElement body = htmlPage.getBody();
914                 if (body != null) {
915                     body.replace(htmlElement.getDomNodeOrDie());
916                 }
917             }
918             return;
919         }
920         throw JavaScriptEngine.asJavaScriptException(
921                 getWindow(),
922                 "Failed to set the 'body' property on 'Document': "
923                         + "The new body element is of type '" +  htmlElement.getTagName() + "'. "
924                         + "It must be either a 'BODY' or 'FRAMESET' element.",
925                 org.htmlunit.javascript.host.dom.DOMException.HIERARCHY_REQUEST_ERR);
926     }
927 
928     /**
929      * JavaScript function {@code close}.
930      * <p>See <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/section-dynamic.html">
931      * http://www.whatwg.org/specs/web-apps/current-work/multipage/section-dynamic.html</a> for
932      * a good description of the semantics of open(), write(), writeln() and close().</p>
933      *
934      * @throws IOException if an IO problem occurs
935      */
936     @JsxFunction({CHROME, EDGE})
937     public void close() throws IOException {
938         // nothing to do
939     }
940 
941     /**
942      * Returns the {@code compatMode} property.
943      * @return the {@code compatMode} property
944      */
945     @JsxGetter
946     public String getCompatMode() {
947         // initialize the modes
948         getDocumentMode();
949         return compatMode_;
950     }
951 
952     /**
953      * Returns the {@code documentMode} property.
954      * @return the {@code documentMode} property
955      */
956     public int getDocumentMode() {
957         if (documentMode_ != -1) {
958             return documentMode_;
959         }
960 
961         compatMode_ = "CSS1Compat";
962 
963         if (isQuirksDocType()) {
964             compatMode_ = "BackCompat";
965         }
966 
967         final float version = getBrowserVersion().getBrowserVersionNumeric();
968         documentMode_ = (int) Math.floor(version);
969         return documentMode_;
970     }
971 
972     private boolean isQuirksDocType() {
973         final DocumentType docType = getPage().getDoctype();
974         if (docType != null) {
975             final String systemId = docType.getSystemId();
976             if (systemId != null) {
977                 if ("http://www.w3.org/TR/html4/strict.dtd".equals(systemId)) {
978                     return false;
979                 }
980 
981                 if ("http://www.w3.org/TR/html4/loose.dtd".equals(systemId)) {
982                     final String publicId = docType.getPublicId();
983                     if ("-//W3C//DTD HTML 4.01 Transitional//EN".equals(publicId)) {
984                         return false;
985                     }
986                 }
987 
988                 if ("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd".equals(systemId)
989                     || "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd".equals(systemId)) {
990                     return false;
991                 }
992             }
993             else if (docType.getPublicId() == null) {
994                 return docType.getName() == null;
995             }
996         }
997         return true;
998     }
999 
1000     /**
1001      * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
1002      *
1003      * Called from the HTMLParser if an 'X-UA-Compatible' meta tag found.
1004      * @param documentMode the mode forced by the meta tag
1005      */
1006     public void forceDocumentMode(final int documentMode) {
1007         documentMode_ = documentMode;
1008         compatMode_ = documentMode == 5 ? "BackCompat" : "CSS1Compat";
1009     }
1010 
1011     /**
1012      * Returns the first element within the document that matches the specified group of selectors.
1013      * @param selectors the selectors
1014      * @return null if no matches are found; otherwise, it returns the first matching element
1015      */
1016     @JsxFunction
1017     public Node querySelector(final String selectors) {
1018         try {
1019             final DomNode node = getDomNodeOrDie().querySelector(selectors);
1020             if (node != null) {
1021                 return node.getScriptableObject();
1022             }
1023             return null;
1024         }
1025         catch (final CSSException e) {
1026             throw JavaScriptEngine.asJavaScriptException(
1027                     getWindow(),
1028                     "An invalid or illegal selector was specified (selector: '"
1029                             + selectors + "' error: " + e.getMessage() + ").",
1030                     org.htmlunit.javascript.host.dom.DOMException.SYNTAX_ERR);
1031         }
1032     }
1033 
1034     /**
1035      * Retrieves all element nodes from descendants of the starting element node that match any selector
1036      * within the supplied selector strings.
1037      * The NodeList object returned by the querySelectorAll() method must be static, not live.
1038      * @param selectors the selectors
1039      * @return the static node list
1040      */
1041     @JsxFunction
1042     public NodeList querySelectorAll(final String selectors) {
1043         try {
1044             return NodeList.staticNodeList(getParentScope(), getDomNodeOrDie().querySelectorAll(selectors));
1045         }
1046         catch (final CSSException e) {
1047             throw JavaScriptEngine.asJavaScriptException(
1048                     getWindow(),
1049                     "An invalid or illegal selector was specified (selector: '"
1050                             + selectors + "' error: " + e.getMessage() + ").",
1051                     org.htmlunit.javascript.host.dom.DOMException.SYNTAX_ERR);
1052         }
1053     }
1054 
1055     /**
1056      * Indicates if the command is supported.
1057      * @see <a href="http://msdn2.microsoft.com/en-us/library/ms536681.aspx">MSDN documentation</a>
1058      * @param cmd the command identifier
1059      * @return {@code true} if the command is supported
1060      */
1061     @JsxFunction
1062     public boolean queryCommandSupported(final String cmd) {
1063         return hasCommand(cmd, true);
1064     }
1065 
1066     private boolean hasCommand(final String cmd, final boolean includeBold) {
1067         if (null == cmd) {
1068             return false;
1069         }
1070 
1071         final String cmdLC = cmd.toLowerCase(Locale.ROOT);
1072         if (getBrowserVersion().isChrome() || getBrowserVersion().isEdge()) {
1073             return EXECUTE_CMDS_CHROME.contains(cmdLC) || (includeBold && "bold".equalsIgnoreCase(cmd));
1074         }
1075         return EXECUTE_CMDS_FF.contains(cmdLC);
1076     }
1077 
1078     /**
1079      * Indicates if the command can be successfully executed using <code>execCommand</code>, given
1080      * the current state of the document.
1081      * @param cmd the command identifier
1082      * @return {@code true} if the command can be successfully executed
1083      */
1084     @JsxFunction
1085     public boolean queryCommandEnabled(final String cmd) {
1086         return hasCommand(cmd, true);
1087     }
1088 
1089     /**
1090      * Executes a command.
1091      * @see <a href="http://msdn2.microsoft.com/en-us/library/ms536419.aspx">MSDN documentation</a>
1092      * @param cmd the command identifier
1093      * @param userInterface display a user interface if the command supports one
1094      * @param value the string, number, or other value to assign (possible values depend on the command)
1095      * @return {@code true} if the command was successful, {@code false} otherwise
1096      */
1097     @JsxFunction
1098     public boolean execCommand(final String cmd, final boolean userInterface, final Object value) {
1099         if (!hasCommand(cmd, false)) {
1100             return false;
1101         }
1102         if (LOG.isWarnEnabled()) {
1103             LOG.warn("Nothing done for execCommand(" + cmd + ", ...) (feature not implemented)");
1104         }
1105         return true;
1106     }
1107 
1108     /**
1109      * Returns the value of the {@code URL} property.
1110      * @return the value of the {@code URL} property
1111      */
1112     @JsxGetter(propertyName = "URL")
1113     public String getURL_js() {
1114         return getPage().getUrl().toExternalForm();
1115     }
1116 
1117     /**
1118      * Returns the value of the {@code documentURI} property.
1119      * @return the value of the {@code documentURI} property
1120      */
1121     @JsxGetter
1122     public String getDocumentURI() {
1123         return getURL_js();
1124     }
1125 
1126     /**
1127      * Returns the {@code cookie} property.
1128      * @return the {@code cookie} property
1129      */
1130     @JsxGetter
1131     public String getCookie() {
1132         final SgmlPage sgmlPage = getPage();
1133 
1134         final StringBuilder builder = new StringBuilder();
1135         final Set<Cookie> cookies = sgmlPage.getWebClient().getCookies(sgmlPage.getUrl());
1136         for (final Cookie cookie : cookies) {
1137             if (cookie.isHttpOnly()) {
1138                 continue;
1139             }
1140             if (builder.length() != 0) {
1141                 builder.append("; ");
1142             }
1143             if (!HtmlUnitBrowserCompatCookieSpec.EMPTY_COOKIE_NAME.equals(cookie.getName())) {
1144                 builder.append(cookie.getName()).append('=');
1145             }
1146             builder.append(cookie.getValue());
1147         }
1148 
1149         return builder.toString();
1150     }
1151 
1152     /**
1153      * Adds a cookie, as long as cookies are enabled.
1154      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533693.aspx">MSDN documentation</a>
1155      * @param newCookie in the format "name=value[;expires=date][;domain=domainname][;path=path][;secure]"
1156      */
1157     @JsxSetter
1158     public void setCookie(final String newCookie) {
1159         if (StringUtils.isBlank(newCookie)) {
1160             return;
1161         }
1162 
1163         final SgmlPage sgmlPage = getPage();
1164         sgmlPage.getWebClient().addCookie(newCookie, sgmlPage.getUrl(), this);
1165     }
1166 
1167     /**
1168      * Implementation of the {@link org.w3c.dom.events.DocumentEvent} interface's
1169      * {@link org.w3c.dom.events.DocumentEvent#createEvent(String)} method. The method creates an
1170      * uninitialized event of the specified type.
1171      *
1172      * @see <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-DocumentEvent">DocumentEvent</a>
1173      * @param eventType the event type to create
1174      * @return an event object for the specified type
1175      * @throws DOMException if the event type is not supported (will have a type of
1176      *         DOMException.NOT_SUPPORTED_ERR)
1177      */
1178     @JsxFunction
1179     public Event createEvent(final String eventType) throws DOMException {
1180         Class<? extends Event> clazz = SUPPORTED_DOM2_EVENT_TYPE_MAP.get(eventType);
1181         if (clazz == null) {
1182             clazz = SUPPORTED_DOM3_EVENT_TYPE_MAP.get(eventType);
1183         }
1184 
1185         if (MutationEvent.class == clazz
1186                 && !getBrowserVersion().hasFeature(EVENT_TYPE_MUTATIONEVENT)) {
1187             clazz = null;
1188         }
1189         else if (clazz == null
1190                 && ("Events".equals(eventType)
1191                     || "HashChangeEvent".equals(eventType)
1192                     || "BeforeUnloadEvent".equals(eventType)
1193                     || "FocusEvent".equals(eventType))) {
1194             clazz = SUPPORTED_VENDOR_EVENT_TYPE_MAP.get(eventType);
1195         }
1196 
1197         if (clazz == null) {
1198             throw JavaScriptEngine.asJavaScriptException(
1199                     this,
1200                     "Event Type '" + eventType + "' is not supported.",
1201                     org.htmlunit.javascript.host.dom.DOMException.NOT_SUPPORTED_ERR);
1202         }
1203 
1204         try {
1205             final Event event = clazz.getDeclaredConstructor().newInstance();
1206             event.setParentScope(getParentScope());
1207             event.setPrototype(getPrototype(clazz));
1208             event.eventCreated();
1209             return event;
1210         }
1211         catch (final InstantiationException | IllegalAccessException
1212                 | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
1213             throw JavaScriptEngine.reportRuntimeError("Failed to instantiate event: class ='" + clazz.getName()
1214                             + "' for event type of '" + eventType + "': " + e.getMessage());
1215         }
1216     }
1217 
1218     /**
1219      * Returns a new NodeIterator object.
1220      *
1221      * @param root The root node at which to begin the NodeIterator's traversal.
1222      * @param whatToShow an optional long representing a bitmask created by combining
1223      *        the constant properties of {@link NodeFilter}
1224      * @param filter an object implementing the {@link NodeFilter} interface
1225      * @return a new NodeIterator object
1226      */
1227     @JsxFunction
1228     public NodeIterator createNodeIterator(final Node root, final int whatToShow, final Scriptable filter) {
1229         final org.w3c.dom.traversal.NodeFilter filterWrapper = createFilterWrapper(filter, false);
1230         final NodeIterator iterator = new NodeIterator(root, whatToShow, filterWrapper);
1231         iterator.setParentScope(getParentScope());
1232         iterator.setPrototype(getPrototype(iterator.getClass()));
1233         return iterator;
1234     }
1235 
1236     private static org.w3c.dom.traversal.NodeFilter createFilterWrapper(final Scriptable filter,
1237             final boolean filterFunctionOnly) {
1238         org.w3c.dom.traversal.NodeFilter filterWrapper = null;
1239         if (filter != null) {
1240             filterWrapper = n -> {
1241                 final Object[] args = {((DomNode) n).getScriptableObject()};
1242                 final Object response;
1243                 if (filter instanceof Callable callable) {
1244                     response = callable.call(Context.getCurrentContext(), filter.getParentScope(), filter, args);
1245                 }
1246                 else {
1247                     if (filterFunctionOnly) {
1248                         throw JavaScriptEngine.reportRuntimeError("only a function is allowed as filter");
1249                     }
1250                     response = ScriptableObject.callMethod(filter, "acceptNode", args);
1251                 }
1252                 return (short) JavaScriptEngine.toNumber(response);
1253             };
1254         }
1255         return filterWrapper;
1256     }
1257 
1258     /**
1259      * Creates and returns a new TreeWalker. The following JavaScript parameters are passed into this method:
1260      * <ul>
1261      *   <li>JavaScript param 1: The root node of the TreeWalker. Must not be {@code null}.</li>
1262      *   <li>JavaScript param 2: Flag specifying which types of nodes appear in the logical view of the TreeWalker.
1263      *       See {@link NodeFilter} for the set of possible Show_ values.</li>
1264      *   <li>JavaScript param 3: The {@link NodeFilter} to be used with this TreeWalker, or {@code null}
1265      *       to indicate no filter.</li>
1266      *   <li>JavaScript param 4: If {@code false}, the contents of EntityReference nodes are not present
1267      *       in the logical view.</li>
1268      * </ul>
1269      *
1270      * @see <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html">DOM-Level-2-Traversal-Range</a>
1271      * @param root the node which will serve as the root for the TreeWalker
1272      * @param whatToShow specifies which node types may appear in the logical view of the tree presented
1273      * @param filter the NodeFilter to be used with this TreeWalker, or null to indicate no filter
1274      * @param expandEntityReferences If false,
1275      *        the contents of EntityReference nodes are not presented in the logical view
1276      * @throws DOMException on attempt to create a TreeWalker with a root that is {@code null}
1277      * @return a new TreeWalker
1278      */
1279     @JsxFunction
1280     public TreeWalker createTreeWalker(final Node root, final double whatToShow, final Scriptable filter,
1281             final boolean expandEntityReferences) throws DOMException {
1282 
1283         // seems that Rhino doesn't like long as parameter type
1284         // this strange conversation preserves NodeFilter.SHOW_ALL
1285         final int whatToShowI = (int) Double.valueOf(whatToShow).longValue();
1286 
1287         final org.w3c.dom.traversal.NodeFilter filterWrapper = createFilterWrapper(filter, false);
1288         final TreeWalker t = new TreeWalker(root, whatToShowI, filterWrapper, false);
1289         t.setParentScope(getParentScope());
1290         t.setPrototype(staticGetPrototype(getWindow(this), TreeWalker.class));
1291         return t;
1292     }
1293 
1294     @SuppressWarnings("unchecked")
1295     private static Scriptable staticGetPrototype(final Window window,
1296             final Class<? extends HtmlUnitScriptable> javaScriptClass) {
1297         final Scriptable prototype = window.getPrototype(javaScriptClass);
1298         if (prototype == null && javaScriptClass != HtmlUnitScriptable.class) {
1299             return staticGetPrototype(window, (Class<? extends HtmlUnitScriptable>) javaScriptClass.getSuperclass());
1300         }
1301         return prototype;
1302     }
1303 
1304     /**
1305      * Creates and returns a new range.
1306      * @return a new range
1307      * @see <a href="http://www.xulplanet.com/references/objref/HTMLDocument.html#method_createRange">XUL Planet</a>
1308      */
1309     @JsxFunction
1310     public Range createRange() {
1311         final Range range = new Range(this);
1312         range.setParentScope(getParentScope());
1313         range.setPrototype(getPrototype(Range.class));
1314         return range;
1315     }
1316 
1317     /**
1318      * Returns the domain name of the server that served the document, or {@code null} if the server
1319      * cannot be identified by a domain name.
1320      * @return the domain name of the server that served the document
1321      * @see <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-2250147">
1322      *     W3C documentation</a>
1323      */
1324     @JsxGetter
1325     public String getDomain() {
1326         if (domain_ == null && getPage().getWebResponse() != null) {
1327             URL url = getPage().getUrl();
1328             if (url == UrlUtils.URL_ABOUT_BLANK) {
1329                 final WebWindow w = getWindow().getWebWindow();
1330                 if (w instanceof FrameWindow window) {
1331                     url = window.getEnclosingPage().getUrl();
1332                 }
1333                 else {
1334                     return null;
1335                 }
1336             }
1337             domain_ = url.getHost().toLowerCase(Locale.ROOT);
1338         }
1339 
1340         return domain_;
1341     }
1342 
1343     /**
1344      * Sets the domain of this document.
1345      *
1346      * <p>Domains can only be set to suffixes of the existing domain
1347      * with the except of setting the domain to itself.</p>
1348      * <p>
1349      * The domain will be set according to the following rules:
1350      * <ol>
1351      * <li>If the newDomain.equalsIgnoreCase(currentDomain) the method returns with no error.</li>
1352      * <li>If the browser version is netscape, the newDomain is downshifted.</li>
1353      * <li>The change will take place if and only if the suffixes of the
1354      *       current domain and the new domain match AND there are at least
1355      *       two domain qualifiers e.g. the following transformations are legal
1356      *       d1.d2.d3.gargoylesoftware.com may be transformed to itself or:
1357      *          d2.d3.gargoylesoftware.com
1358      *             d3.gargoylesoftware.com
1359      *                gargoylesoftware.com
1360      * <p>
1361      *        transformation to:        com
1362      *        will fail
1363      * </li>
1364      * </ol>
1365      * <p>
1366      * TODO This code could be modified to understand country domain suffixes.
1367      * The domain www.bbc.co.uk should be trimmable only down to bbc.co.uk
1368      * trimming to co.uk should not be possible.
1369      * @param newDomain the new domain to set
1370      */
1371     @JsxSetter
1372     public void setDomain(String newDomain) {
1373         newDomain = newDomain.toLowerCase(Locale.ROOT);
1374 
1375         final String currentDomain = getDomain();
1376         if (currentDomain.equalsIgnoreCase(newDomain)) {
1377             return;
1378         }
1379 
1380         if (newDomain.indexOf('.') == -1) {
1381             throw JavaScriptEngine.reportRuntimeError("Illegal domain value, cannot set domain from: \""
1382                     + currentDomain + "\" to: \"" + newDomain + "\" (new domain has to contain a dot).");
1383         }
1384 
1385         if (currentDomain.indexOf('.') > -1
1386                 && !currentDomain.toLowerCase(Locale.ROOT).endsWith("." + newDomain.toLowerCase(Locale.ROOT))) {
1387             throw JavaScriptEngine.reportRuntimeError("Illegal domain value, cannot set domain from: \""
1388                     + currentDomain + "\" to: \"" + newDomain + "\"");
1389         }
1390 
1391         domain_ = newDomain;
1392     }
1393 
1394     /**
1395      * Sets the {@code onclick} event handler for this element.
1396      * @param handler the {@code onclick} event handler for this element
1397      */
1398     @JsxSetter
1399     public void setOnclick(final Object handler) {
1400         setEventHandler(MouseEvent.TYPE_CLICK, handler);
1401     }
1402 
1403     /**
1404      * Returns the {@code onclick} event handler for this element.
1405      * @return the {@code onclick} event handler for this element
1406      */
1407     @JsxGetter
1408     public Function getOnclick() {
1409         return getEventHandler(MouseEvent.TYPE_CLICK);
1410     }
1411 
1412     /**
1413      * Sets the {@code ondblclick} event handler for this element.
1414      * @param handler the {@code ondblclick} event handler for this element
1415      */
1416     @JsxSetter
1417     public void setOndblclick(final Object handler) {
1418         setEventHandler(MouseEvent.TYPE_DBL_CLICK, handler);
1419     }
1420 
1421     /**
1422      * Returns the {@code ondblclick} event handler for this element.
1423      * @return the {@code ondblclick} event handler for this element
1424      */
1425     @JsxGetter
1426     public Function getOndblclick() {
1427         return getEventHandler(MouseEvent.TYPE_DBL_CLICK);
1428     }
1429 
1430     /**
1431      * Sets the {@code onblur} event handler for this element.
1432      * @param handler the {@code onblur} event handler for this element
1433      */
1434     @JsxSetter
1435     public void setOnblur(final Object handler) {
1436         setEventHandler(Event.TYPE_BLUR, handler);
1437     }
1438 
1439     /**
1440      * Returns the {@code onblur} event handler for this element.
1441      * @return the {@code onblur} event handler for this element
1442      */
1443     @JsxGetter
1444     public Function getOnblur() {
1445         return getEventHandler(Event.TYPE_BLUR);
1446     }
1447 
1448     /**
1449      * Sets the {@code onfocus} event handler for this element.
1450      * @param handler the {@code onfocus} event handler for this element
1451      */
1452     @JsxSetter
1453     public void setOnfocus(final Object handler) {
1454         setEventHandler(Event.TYPE_FOCUS, handler);
1455     }
1456 
1457     /**
1458      * Returns the {@code onfocus} event handler for this element.
1459      * @return the {@code onfocus} event handler for this element
1460      */
1461     @JsxGetter
1462     public Function getOnfocus() {
1463         return getEventHandler(Event.TYPE_FOCUS);
1464     }
1465 
1466     /**
1467      * Sets the {@code onkeydown} event handler for this element.
1468      * @param handler the {@code onkeydown} event handler for this element
1469      */
1470     @JsxSetter
1471     public void setOnkeydown(final Object handler) {
1472         setEventHandler(Event.TYPE_KEY_DOWN, handler);
1473     }
1474 
1475     /**
1476      * Returns the {@code onkeydown} event handler for this element.
1477      * @return the {@code onkeydown} event handler for this element
1478      */
1479     @JsxGetter
1480     public Function getOnkeydown() {
1481         return getEventHandler(Event.TYPE_KEY_DOWN);
1482     }
1483 
1484     /**
1485      * Sets the {@code onkeypress} event handler for this element.
1486      * @param handler the {@code onkeypress} event handler for this element
1487      */
1488     @JsxSetter
1489     public void setOnkeypress(final Object handler) {
1490         setEventHandler(Event.TYPE_KEY_PRESS, handler);
1491     }
1492 
1493     /**
1494      * Returns the {@code onkeypress} event handler for this element.
1495      * @return the {@code onkeypress} event handler for this element
1496      */
1497     @JsxGetter
1498     public Function getOnkeypress() {
1499         return getEventHandler(Event.TYPE_KEY_PRESS);
1500     }
1501 
1502     /**
1503      * Sets the {@code onkeyup} event handler for this element.
1504      * @param handler the {@code onkeyup} event handler for this element
1505      */
1506     @JsxSetter
1507     public void setOnkeyup(final Object handler) {
1508         setEventHandler(Event.TYPE_KEY_UP, handler);
1509     }
1510 
1511     /**
1512      * Returns the {@code onkeyup} event handler for this element.
1513      * @return the {@code onkeyup} event handler for this element
1514      */
1515     @JsxGetter
1516     public Function getOnkeyup() {
1517         return getEventHandler(Event.TYPE_KEY_UP);
1518     }
1519 
1520     /**
1521      * Sets the {@code onmousedown} event handler for this element.
1522      * @param handler the {@code onmousedown} event handler for this element
1523      */
1524     @JsxSetter
1525     public void setOnmousedown(final Object handler) {
1526         setEventHandler(MouseEvent.TYPE_MOUSE_DOWN, handler);
1527     }
1528 
1529     /**
1530      * Returns the {@code onmousedown} event handler for this element.
1531      * @return the {@code onmousedown} event handler for this element
1532      */
1533     @JsxGetter
1534     public Function getOnmousedown() {
1535         return getEventHandler(MouseEvent.TYPE_MOUSE_DOWN);
1536     }
1537 
1538     /**
1539      * Sets the {@code onmousemove} event handler for this element.
1540      * @param handler the {@code onmousemove} event handler for this element
1541      */
1542     @JsxSetter
1543     public void setOnmousemove(final Object handler) {
1544         setEventHandler(MouseEvent.TYPE_MOUSE_MOVE, handler);
1545     }
1546 
1547     /**
1548      * Returns the {@code onmousemove} event handler for this element.
1549      * @return the {@code onmousemove} event handler for this element
1550      */
1551     @JsxGetter
1552     public Function getOnmousemove() {
1553         return getEventHandler(MouseEvent.TYPE_MOUSE_MOVE);
1554     }
1555 
1556     /**
1557      * Sets the {@code onmouseout} event handler for this element.
1558      * @param handler the {@code onmouseout} event handler for this element
1559      */
1560     @JsxSetter
1561     public void setOnmouseout(final Object handler) {
1562         setEventHandler(MouseEvent.TYPE_MOUSE_OUT, handler);
1563     }
1564 
1565     /**
1566      * Returns the {@code onmouseout} event handler for this element.
1567      * @return the {@code onmouseout} event handler for this element
1568      */
1569     @JsxGetter
1570     public Function getOnmouseout() {
1571         return getEventHandler(MouseEvent.TYPE_MOUSE_OUT);
1572     }
1573 
1574     /**
1575      * Sets the {@code onmouseover} event handler for this element.
1576      * @param handler the {@code onmouseover} event handler for this element
1577      */
1578     @JsxSetter
1579     public void setOnmouseover(final Object handler) {
1580         setEventHandler(MouseEvent.TYPE_MOUSE_OVER, handler);
1581     }
1582 
1583     /**
1584      * Returns the {@code onmouseover} event handler for this element.
1585      * @return the {@code onmouseover} event handler for this element
1586      */
1587     @JsxGetter
1588     public Function getOnmouseover() {
1589         return getEventHandler(MouseEvent.TYPE_MOUSE_OVER);
1590     }
1591 
1592     /**
1593      * Sets the {@code onmouseup} event handler for this element.
1594      * @param handler the {@code onmouseup} event handler for this element
1595      */
1596     @JsxSetter
1597     public void setOnmouseup(final Object handler) {
1598         setEventHandler(MouseEvent.TYPE_MOUSE_UP, handler);
1599     }
1600 
1601     /**
1602      * Returns the {@code onmouseup} event handler for this element.
1603      * @return the {@code onmouseup} event handler for this element
1604      */
1605     @JsxGetter
1606     public Function getOnmouseup() {
1607         return getEventHandler(MouseEvent.TYPE_MOUSE_UP);
1608     }
1609 
1610     /**
1611      * Sets the {@code oncontextmenu} event handler for this element.
1612      * @param handler the {@code oncontextmenu} event handler for this element
1613      */
1614     @JsxSetter
1615     public void setOncontextmenu(final Object handler) {
1616         setEventHandler(MouseEvent.TYPE_CONTEXT_MENU, handler);
1617     }
1618 
1619     /**
1620      * Returns the {@code oncontextmenu} event handler for this element.
1621      * @return the {@code oncontextmenu} event handler for this element
1622      */
1623     @JsxGetter
1624     public Function getOncontextmenu() {
1625         return getEventHandler(MouseEvent.TYPE_CONTEXT_MENU);
1626     }
1627 
1628     /**
1629      * Sets the {@code onresize} event handler for this element.
1630      * @param handler the {@code onresize} event handler for this element
1631      */
1632     @JsxSetter
1633     public void setOnresize(final Object handler) {
1634         setEventHandler(Event.TYPE_RESIZE, handler);
1635     }
1636 
1637     /**
1638      * Returns the {@code onresize} event handler for this element.
1639      * @return the {@code onresize} event handler for this element
1640      */
1641     @JsxGetter
1642     public Function getOnresize() {
1643         return getEventHandler(Event.TYPE_RESIZE);
1644     }
1645 
1646     /**
1647      * Sets the {@code onerror} event handler for this element.
1648      * @param handler the {@code onerror} event handler for this element
1649      */
1650     @JsxSetter
1651     public void setOnerror(final Object handler) {
1652         setEventHandler(Event.TYPE_ERROR, handler);
1653     }
1654 
1655     /**
1656      * Returns the {@code onerror} event handler for this element.
1657      * @return the {@code onerror} event handler for this element
1658      */
1659     @JsxGetter
1660     public Function getOnerror() {
1661         return getEventHandler(Event.TYPE_ERROR);
1662     }
1663 
1664     /**
1665      * Returns the {@code oninput} event handler for this element.
1666      * @return the {@code oninput} event handler for this element
1667      */
1668     @JsxGetter
1669     public Function getOninput() {
1670         return getEventHandler(Event.TYPE_INPUT);
1671     }
1672 
1673     /**
1674      * Sets the {@code oninput} event handler for this element.
1675      * @param oninput the {@code oninput} event handler for this element
1676      */
1677     @JsxSetter
1678     public void setOninput(final Object oninput) {
1679         setEventHandler(Event.TYPE_INPUT, oninput);
1680     }
1681 
1682     /**
1683      * Returns the {@code hidden} property.
1684      * @return the {@code hidden} property
1685      */
1686     @JsxGetter
1687     public boolean isHidden() {
1688         return false;
1689     }
1690 
1691     /**
1692      * {@inheritDoc}
1693      */
1694     @Override
1695     @JsxGetter
1696     public int getChildElementCount() {
1697         int counter = 0;
1698         if (getPage().getDocumentElement() != null) {
1699             counter++;
1700         }
1701         return counter;
1702     }
1703 
1704     /**
1705      * Returns the element for the specified x coordinate and the specified y coordinate.
1706      * The current implementation always returns null element.
1707      *
1708      * @param x the x offset, in pixels
1709      * @param y the y offset, in pixels
1710      * @return the element for the specified x coordinate and the specified y coordinate
1711      */
1712     @JsxFunction
1713     public HtmlUnitScriptable elementFromPoint(final int x, final int y) {
1714         return null;
1715     }
1716 
1717     /**
1718      * Returns the value of the {@code forms} property.
1719      * @return the value of the {@code forms} property
1720      */
1721     @JsxGetter
1722     public HTMLCollection getForms() {
1723         final HTMLCollection forms = new HTMLCollection(getDomNodeOrDie(), false);
1724 
1725         forms.setIsMatchingPredicate(
1726                 (Predicate<DomNode> & Serializable)
1727                 node -> node instanceof HtmlForm && node.getPrefix() == null);
1728         return forms;
1729     }
1730 
1731     /**
1732      * Returns the value of the {@code embeds} property.
1733      * @return the value of the {@code embeds} property
1734      */
1735     @JsxGetter
1736     public HTMLCollection getEmbeds() {
1737         final HTMLCollection embeds = new HTMLCollection(getDomNodeOrDie(), false);
1738 
1739         embeds.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> node instanceof HtmlEmbed);
1740         return embeds;
1741     }
1742 
1743     /**
1744      * Returns the value of the {@code embeds} property.
1745      * @return the value of the {@code embeds} property
1746      */
1747     @JsxGetter
1748     public HTMLCollection getImages() {
1749         final HTMLCollection images = new HTMLCollection(getDomNodeOrDie(), false);
1750 
1751         images.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> node instanceof HtmlImage);
1752         return images;
1753     }
1754 
1755     /**
1756      * Returns the value of the {@code scripts} property.
1757      * @return the value of the {@code scripts} property
1758      */
1759     @JsxGetter
1760     public HTMLCollection getScripts() {
1761         final HTMLCollection scripts = new HTMLCollection(getDomNodeOrDie(), false);
1762 
1763         scripts.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> node instanceof HtmlScript);
1764         return scripts;
1765     }
1766 
1767     /**
1768      * Retrieves a collection of stylesheet objects representing the style sheets that correspond
1769      * to each instance of a Link or
1770      * {@link org.htmlunit.javascript.host.css.CSSStyleDeclaration} object in the document.
1771      *
1772      * @return styleSheet collection
1773      */
1774     @JsxGetter
1775     public StyleSheetList getStyleSheets() {
1776         if (styleSheetList_ == null) {
1777             styleSheetList_ = new StyleSheetList(this);
1778         }
1779         return styleSheetList_;
1780     }
1781 
1782     /**
1783      * Returns the value of the {@code plugins} property.
1784      * @return the value of the {@code plugins} property
1785      */
1786     @JsxGetter
1787     public HTMLCollection getPlugins() {
1788         return getEmbeds();
1789     }
1790 
1791     /**
1792      * Returns the value of the JavaScript property {@code links}. Refer also to the
1793      * <a href="http://msdn.microsoft.com/en-us/library/ms537465.aspx">MSDN documentation</a>.
1794      * @return the value of this property
1795      */
1796     @JsxGetter
1797     public HTMLCollection getLinks() {
1798         final HTMLCollection links = new HTMLCollection(getDomNodeOrDie(), true);
1799 
1800         links.setEffectOnCacheFunction(
1801                 (java.util.function.Function<HtmlAttributeChangeEvent, EffectOnCache> & Serializable)
1802                 event -> {
1803                     final HtmlElement node = event.getHtmlElement();
1804                     if ((node instanceof HtmlAnchor || node instanceof HtmlArea) && "href".equals(event.getName())) {
1805                         return EffectOnCache.RESET;
1806                     }
1807                     return EffectOnCache.NONE;
1808                 });
1809 
1810         links.setIsMatchingPredicate(
1811                 (Predicate<DomNode> & Serializable)
1812                 node ->
1813                     (node instanceof HtmlAnchor || node instanceof HtmlArea)
1814                     && ((HtmlElement) node).hasAttribute("href"));
1815 
1816         return links;
1817     }
1818 
1819     /**
1820      * Returns all the descendant elements with the specified class name.
1821      * @param className the name to search for
1822      * @return all the descendant elements with the specified class name
1823      * @see <a href="https://developer.mozilla.org/en/DOM/document.getElementsByClassName">Mozilla doc</a>
1824      */
1825     @JsxFunction
1826     public HTMLCollection getElementsByClassName(final String className) {
1827         return null;
1828     }
1829 
1830     /**
1831      * Returns all HTML elements that have a {@code name} attribute with the specified value.
1832      * <p>
1833      * Refer to <a href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-71555259">
1834      * The DOM spec</a> for details.
1835      *
1836      * @param elementName - value of the {@code name} attribute to look for
1837      * @return all HTML elements that have a {@code name} attribute with the specified value
1838      */
1839     @JsxFunction
1840     public NodeList getElementsByName(final String elementName) {
1841         return null;
1842     }
1843 
1844     /**
1845      * Returns {@code false} if the active element in the document has no focus;
1846      * {@code true} if the active element in the document has focus.
1847      * @return whether the active element in the document has focus or not
1848      */
1849     @JsxFunction
1850     public boolean hasFocus() {
1851         return false;
1852     }
1853 
1854     /**
1855      * Returns this document's title.
1856      * @return this document's title
1857      */
1858     @JsxGetter
1859     public String getTitle() {
1860         return "";
1861     }
1862 
1863     /**
1864      * Sets this document's title.
1865      * @param title the new title
1866      */
1867     @JsxSetter
1868     public void setTitle(final String title) {
1869         // nothing to do
1870     }
1871 
1872     /**
1873      * {@inheritDoc}
1874      */
1875     @Override
1876     @JsxGetter
1877     public HTMLCollection getChildren() {
1878         return super.getChildren();
1879     }
1880 
1881     /**
1882      * Returns the {@code contentType} property.
1883      * @return the {@code contentType} property
1884      */
1885     @JsxGetter
1886     public String getContentType() {
1887         return getPage().getContentType();
1888     }
1889 
1890     /**
1891      * Returns the current selection.
1892      * @return the current selection
1893      */
1894     @JsxFunction
1895     public Selection getSelection() {
1896         return null;
1897     }
1898 
1899     /**
1900      * Returns this document's {@code head} element.
1901      * @return this document's {@code head} element
1902      */
1903     @JsxGetter
1904     public Object getHead() {
1905         return null;
1906     }
1907 
1908     /**
1909      * Returns a string representing the encoding under which the document was parsed.
1910      * @return a string representing the encoding under which the document was parsed
1911      */
1912     @JsxGetter
1913     public String getInputEncoding() {
1914         return getPage().getCharset().name();
1915     }
1916 
1917     /**
1918      * Returns the last modification date of the document.
1919      * @see <a href="https://developer.mozilla.org/en/DOM/document.lastModified">Mozilla documentation</a>
1920      * @return the date as string
1921      */
1922     @JsxGetter
1923     public String getLastModified() {
1924         if (lastModified_ == null) {
1925             final WebResponse webResponse = getPage().getWebResponse();
1926             final Date lastModified;
1927             if (webResponse != null) {
1928                 String stringDate = webResponse.getResponseHeaderValue("Last-Modified");
1929                 if (stringDate == null) {
1930                     stringDate = webResponse.getResponseHeaderValue("Date");
1931                 }
1932                 lastModified = parseDateOrNow(stringDate);
1933             }
1934             else {
1935                 lastModified = new Date();
1936             }
1937 
1938             final ZoneId zoneid = Context.getCurrentContext().getTimeZone().toZoneId();
1939             lastModified_ = LAST_MODIFIED_DATE_FORMATTER.format(lastModified.toInstant().atZone(zoneid));
1940         }
1941         return lastModified_;
1942     }
1943 
1944     private static Date parseDateOrNow(final String stringDate) {
1945         final Date date = HttpUtils.parseDate(stringDate);
1946         if (date == null) {
1947             return new Date();
1948         }
1949         return date;
1950     }
1951 
1952     /**
1953      * Mock for the moment.
1954      */
1955     @JsxFunction({FF, FF_ESR})
1956     public void releaseCapture() {
1957         // nothing to do
1958     }
1959 
1960     /**
1961      * Returns the ready state of the document.
1962      * @return the ready state of the document
1963      *
1964      * @see DomNode#READY_STATE_UNINITIALIZED
1965      * @see DomNode#READY_STATE_LOADING
1966      * @see DomNode#READY_STATE_LOADED
1967      * @see DomNode#READY_STATE_INTERACTIVE
1968      * @see DomNode#READY_STATE_COMPLETE
1969      */
1970     @JsxGetter
1971     public String getReadyState() {
1972         return getDomNodeOrDie().getReadyState();
1973     }
1974 
1975     /**
1976      * Does nothing special anymore.
1977      *
1978      * @param type the type of events to capture
1979      * @see Window#captureEvents(String)
1980      */
1981     @JsxFunction
1982     public void captureEvents(final String type) {
1983         // Empty.
1984     }
1985 
1986     /**
1987      * Does nothing special anymore.
1988      *
1989      * @param type the type of events to capture
1990      * @see Window#releaseEvents(String)
1991      */
1992     @JsxFunction
1993     public void releaseEvents(final String type) {
1994         // Empty.
1995     }
1996 
1997     /**
1998      * Returns the value of the {@code alinkColor} property.
1999      * @return the value of the {@code alinkColor} property
2000      */
2001     @JsxGetter
2002     public String getAlinkColor() {
2003         final HTMLElement body = getBody();
2004         if (body instanceof HTMLBodyElement element) {
2005             return element.getALink();
2006         }
2007         return null;
2008     }
2009 
2010     /**
2011      * Sets the value of the {@code alinkColor} property.
2012      * @param color the value of the {@code alinkColor} property
2013      */
2014     @JsxSetter
2015     public void setAlinkColor(final String color) {
2016         final HTMLElement body = getBody();
2017         if (body instanceof HTMLBodyElement element) {
2018             element.setALink(color);
2019         }
2020     }
2021 
2022     /**
2023      * Returns the value of the {@code bgColor} property.
2024      * @return the value of the {@code bgColor} property
2025      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533505.aspx">MSDN Documentation</a>
2026      */
2027     @JsxGetter
2028     public String getBgColor() {
2029         final HTMLElement body = getBody();
2030         if (body instanceof HTMLBodyElement element) {
2031             return element.getBgColor();
2032         }
2033         return null;
2034     }
2035 
2036     /**
2037      * Sets the value of the {@code bgColor} property.
2038      * @param color the value of the {@code bgColor} property
2039      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533505.aspx">MSDN Documentation</a>
2040      */
2041     @JsxSetter
2042     public void setBgColor(final String color) {
2043         final HTMLElement body = getBody();
2044         if (body instanceof HTMLBodyElement element) {
2045             element.setBgColor(color);
2046         }
2047     }
2048 
2049     /**
2050      * Returns the value of the {@code fgColor} property.
2051      * @return the value of the {@code fgColor} property
2052      */
2053     @JsxGetter
2054     public String getFgColor() {
2055         final HTMLElement body = getBody();
2056         if (body instanceof HTMLBodyElement element) {
2057             return element.getText();
2058         }
2059         return null;
2060     }
2061 
2062     /**
2063      * Sets the value of the {@code fgColor} property.
2064      * @param color the value of the {@code fgColor} property
2065      */
2066     @JsxSetter
2067     public void setFgColor(final String color) {
2068         final HTMLElement body = getBody();
2069         if (body instanceof HTMLBodyElement element) {
2070             element.setText(color);
2071         }
2072     }
2073 
2074     /**
2075      * Returns the value of the {@code linkColor} property.
2076      * @return the value of the {@code linkColor} property
2077      */
2078     @JsxGetter
2079     public String getLinkColor() {
2080         final HTMLElement body = getBody();
2081         if (body instanceof HTMLBodyElement element) {
2082             return element.getLink();
2083         }
2084         return null;
2085     }
2086 
2087     /**
2088      * Sets the value of the {@code linkColor} property.
2089      * @param color the value of the {@code linkColor} property
2090      */
2091     @JsxSetter
2092     public void setLinkColor(final String color) {
2093         final HTMLElement body = getBody();
2094         if (body instanceof HTMLBodyElement element) {
2095             element.setLink(color);
2096         }
2097     }
2098 
2099     /**
2100      * Returns the value of the {@code vlinkColor} property.
2101      * @return the value of the {@code vlinkColor} property
2102      */
2103     @JsxGetter
2104     public String getVlinkColor() {
2105         final HTMLElement body = getBody();
2106         if (body instanceof HTMLBodyElement element) {
2107             return element.getVLink();
2108         }
2109         return null;
2110     }
2111 
2112     /**
2113      * Sets the value of the {@code vlinkColor} property.
2114      * @param color the value of the {@code vlinkColor} property
2115      */
2116     @JsxSetter
2117     public void setVlinkColor(final String color) {
2118         final HTMLElement body = getBody();
2119         if (body instanceof HTMLBodyElement element) {
2120             element.setVLink(color);
2121         }
2122     }
2123 
2124     /**
2125      * {@inheritDoc}
2126      */
2127     @Override
2128     @JsxGetter
2129     public Element getLastElementChild() {
2130         return super.getLastElementChild();
2131     }
2132 
2133     /**
2134      * {@inheritDoc}
2135      */
2136     @Override
2137     @JsxGetter
2138     public Element getFirstElementChild() {
2139         return super.getFirstElementChild();
2140     }
2141 
2142     /**
2143      * Returns the {@code xmlEncoding} property.
2144      * @return the {@code xmlEncoding} property
2145      */
2146     @JsxGetter({CHROME, EDGE})
2147     public String getXmlEncoding() {
2148         return getPage().getXmlEncoding();
2149     }
2150 
2151     /**
2152      * Returns the {@code xmlStandalone} property.
2153      * @return the {@code xmlStandalone} property
2154      */
2155     @JsxGetter({CHROME, EDGE})
2156     public boolean isXmlStandalone() {
2157         return getPage().getXmlStandalone();
2158     }
2159 
2160     /**
2161      * Returns the {@code xmlVersion} property.
2162      * @return the {@code xmlVersion} property
2163      */
2164     @JsxGetter({CHROME, EDGE})
2165     public String getXmlVersion() {
2166         return getPage().getXmlVersion();
2167     }
2168 
2169     /**
2170      * Returns the {@code onabort} event handler for this element.
2171      * @return the {@code onabort} event handler for this element
2172      */
2173     @JsxGetter
2174     public Function getOnabort() {
2175         return getEventHandler(Event.TYPE_ABORT);
2176     }
2177 
2178     /**
2179      * Sets the {@code onabort} event handler for this element.
2180      * @param onabort the {@code onabort} event handler for this element
2181      */
2182     @JsxSetter
2183     public void setOnabort(final Object onabort) {
2184         setEventHandler(Event.TYPE_ABORT, onabort);
2185     }
2186 
2187     /**
2188      * Returns the {@code onauxclick} event handler for this element.
2189      * @return the {@code onauxclick} event handler for this element
2190      */
2191     @JsxGetter({CHROME, EDGE})
2192     public Function getOnauxclick() {
2193         return getEventHandler(Event.TYPE_AUXCLICK);
2194     }
2195 
2196     /**
2197      * Sets the {@code onauxclick} event handler for this element.
2198      * @param onauxclick the {@code onauxclick} event handler for this element
2199      */
2200     @JsxSetter({CHROME, EDGE})
2201     public void setOnauxclick(final Object onauxclick) {
2202         setEventHandler(Event.TYPE_AUXCLICK, onauxclick);
2203     }
2204 
2205     /**
2206      * Returns the {@code onbeforecopy} event handler for this element.
2207      * @return the {@code onbeforecopy} event handler for this element
2208      */
2209     @JsxGetter({CHROME, EDGE})
2210     public Function getOnbeforecopy() {
2211         return getEventHandler(Event.TYPE_BEFORECOPY);
2212     }
2213 
2214     /**
2215      * Sets the {@code onbeforecopy} event handler for this element.
2216      * @param onbeforecopy the {@code onbeforecopy} event handler for this element
2217      */
2218     @JsxSetter({CHROME, EDGE})
2219     public void setOnbeforecopy(final Object onbeforecopy) {
2220         setEventHandler(Event.TYPE_BEFORECOPY, onbeforecopy);
2221     }
2222 
2223     /**
2224      * Returns the {@code onbeforecut} event handler for this element.
2225      * @return the {@code onbeforecut} event handler for this element
2226      */
2227     @JsxGetter({CHROME, EDGE})
2228     public Function getOnbeforecut() {
2229         return getEventHandler(Event.TYPE_BEFORECUT);
2230     }
2231 
2232     /**
2233      * Sets the {@code onbeforecut} event handler for this element.
2234      * @param onbeforecut the {@code onbeforecut} event handler for this element
2235      */
2236     @JsxSetter({CHROME, EDGE})
2237     public void setOnbeforecut(final Object onbeforecut) {
2238         setEventHandler(Event.TYPE_BEFORECUT, onbeforecut);
2239     }
2240 
2241     /**
2242      * Returns the {@code onbeforepaste} event handler for this element.
2243      * @return the {@code onbeforepaste} event handler for this element
2244      */
2245     @JsxGetter({CHROME, EDGE})
2246     public Function getOnbeforepaste() {
2247         return getEventHandler(Event.TYPE_BEFOREPASTE);
2248     }
2249 
2250     /**
2251      * Sets the {@code onbeforepaste} event handler for this element.
2252      * @param onbeforepaste the {@code onbeforepaste} event handler for this element
2253      */
2254     @JsxSetter({CHROME, EDGE})
2255     public void setOnbeforepaste(final Object onbeforepaste) {
2256         setEventHandler(Event.TYPE_BEFOREPASTE, onbeforepaste);
2257     }
2258 
2259     /**
2260      * Returns the {@code oncancel} event handler for this element.
2261      * @return the {@code oncancel} event handler for this element
2262      */
2263     @JsxGetter({CHROME, EDGE})
2264     public Function getOncancel() {
2265         return getEventHandler(Event.TYPE_CANCEL);
2266     }
2267 
2268     /**
2269      * Sets the {@code oncancel} event handler for this element.
2270      * @param oncancel the {@code oncancel} event handler for this element
2271      */
2272     @JsxSetter({CHROME, EDGE})
2273     public void setOncancel(final Object oncancel) {
2274         setEventHandler(Event.TYPE_CANCEL, oncancel);
2275     }
2276 
2277     /**
2278      * Returns the {@code oncanplay} event handler for this element.
2279      * @return the {@code oncanplay} event handler for this element
2280      */
2281     @JsxGetter
2282     public Function getOncanplay() {
2283         return getEventHandler(Event.TYPE_CANPLAY);
2284     }
2285 
2286     /**
2287      * Sets the {@code oncanplay} event handler for this element.
2288      * @param oncanplay the {@code oncanplay} event handler for this element
2289      */
2290     @JsxSetter
2291     public void setOncanplay(final Object oncanplay) {
2292         setEventHandler(Event.TYPE_CANPLAY, oncanplay);
2293     }
2294 
2295     /**
2296      * Returns the {@code oncanplaythrough} event handler for this element.
2297      * @return the {@code oncanplaythrough} event handler for this element
2298      */
2299     @JsxGetter
2300     public Function getOncanplaythrough() {
2301         return getEventHandler(Event.TYPE_CANPLAYTHROUGH);
2302     }
2303 
2304     /**
2305      * Sets the {@code oncanplaythrough} event handler for this element.
2306      * @param oncanplaythrough the {@code oncanplaythrough} event handler for this element
2307      */
2308     @JsxSetter
2309     public void setOncanplaythrough(final Object oncanplaythrough) {
2310         setEventHandler(Event.TYPE_CANPLAYTHROUGH, oncanplaythrough);
2311     }
2312 
2313     /**
2314      * Returns the {@code onchange} event handler for this element.
2315      * @return the {@code onchange} event handler for this element
2316      */
2317     @JsxGetter
2318     public Function getOnchange() {
2319         return getEventHandler(Event.TYPE_CHANGE);
2320     }
2321 
2322     /**
2323      * Sets the {@code onchange} event handler for this element.
2324      * @param onchange the {@code onchange} event handler for this element
2325      */
2326     @JsxSetter
2327     public void setOnchange(final Object onchange) {
2328         setEventHandler(Event.TYPE_CHANGE, onchange);
2329     }
2330 
2331     /**
2332      * Returns the {@code onclose} event handler for this element.
2333      * @return the {@code onclose} event handler for this element
2334      */
2335     @JsxGetter({CHROME, EDGE})
2336     public Function getOnclose() {
2337         return getEventHandler(Event.TYPE_CLOSE);
2338     }
2339 
2340     /**
2341      * Sets the {@code onclose} event handler for this element.
2342      * @param onclose the {@code onclose} event handler for this element
2343      */
2344     @JsxSetter({CHROME, EDGE})
2345     public void setOnclose(final Object onclose) {
2346         setEventHandler(Event.TYPE_CLOSE, onclose);
2347     }
2348 
2349     /**
2350      * Returns the {@code oncopy} event handler for this element.
2351      * @return the {@code oncopy} event handler for this element
2352      */
2353     @JsxGetter
2354     public Function getOncopy() {
2355         return getEventHandler(Event.TYPE_COPY);
2356     }
2357 
2358     /**
2359      * Sets the {@code oncopy} event handler for this element.
2360      * @param oncopy the {@code oncopy} event handler for this element
2361      */
2362     @JsxSetter
2363     public void setOncopy(final Object oncopy) {
2364         setEventHandler(Event.TYPE_COPY, oncopy);
2365     }
2366 
2367     /**
2368      * Returns the {@code oncuechange} event handler for this element.
2369      * @return the {@code oncuechange} event handler for this element
2370      */
2371     @JsxGetter({CHROME, EDGE})
2372     public Function getOncuechange() {
2373         return getEventHandler(Event.TYPE_CUECHANGE);
2374     }
2375 
2376     /**
2377      * Sets the {@code oncuechange} event handler for this element.
2378      * @param oncuechange the {@code oncuechange} event handler for this element
2379      */
2380     @JsxSetter({CHROME, EDGE})
2381     public void setOncuechange(final Object oncuechange) {
2382         setEventHandler(Event.TYPE_CUECHANGE, oncuechange);
2383     }
2384 
2385     /**
2386      * Returns the {@code oncut} event handler for this element.
2387      * @return the {@code oncut} event handler for this element
2388      */
2389     @JsxGetter
2390     public Function getOncut() {
2391         return getEventHandler(Event.TYPE_CUT);
2392     }
2393 
2394     /**
2395      * Sets the {@code oncut} event handler for this element.
2396      * @param oncut the {@code oncut} event handler for this element
2397      */
2398     @JsxSetter
2399     public void setOncut(final Object oncut) {
2400         setEventHandler(Event.TYPE_CUT, oncut);
2401     }
2402 
2403     /**
2404      * Returns the {@code ondrag} event handler for this element.
2405      * @return the {@code ondrag} event handler for this element
2406      */
2407     @JsxGetter
2408     public Function getOndrag() {
2409         return getEventHandler(Event.TYPE_DRAG);
2410     }
2411 
2412     /**
2413      * Sets the {@code ondrag} event handler for this element.
2414      * @param ondrag the {@code ondrag} event handler for this element
2415      */
2416     @JsxSetter
2417     public void setOndrag(final Object ondrag) {
2418         setEventHandler(Event.TYPE_DRAG, ondrag);
2419     }
2420 
2421     /**
2422      * Returns the {@code ondragend} event handler for this element.
2423      * @return the {@code ondragend} event handler for this element
2424      */
2425     @JsxGetter
2426     public Function getOndragend() {
2427         return getEventHandler(Event.TYPE_DRAGEND);
2428     }
2429 
2430     /**
2431      * Sets the {@code ondragend} event handler for this element.
2432      * @param ondragend the {@code ondragend} event handler for this element
2433      */
2434     @JsxSetter
2435     public void setOndragend(final Object ondragend) {
2436         setEventHandler(Event.TYPE_DRAGEND, ondragend);
2437     }
2438 
2439     /**
2440      * Returns the {@code ondragenter} event handler for this element.
2441      * @return the {@code ondragenter} event handler for this element
2442      */
2443     @JsxGetter
2444     public Function getOndragenter() {
2445         return getEventHandler(Event.TYPE_DRAGENTER);
2446     }
2447 
2448     /**
2449      * Sets the {@code ondragenter} event handler for this element.
2450      * @param ondragenter the {@code ondragenter} event handler for this element
2451      */
2452     @JsxSetter
2453     public void setOndragenter(final Object ondragenter) {
2454         setEventHandler(Event.TYPE_DRAGENTER, ondragenter);
2455     }
2456 
2457     /**
2458      * Returns the {@code ondragleave} event handler for this element.
2459      * @return the {@code ondragleave} event handler for this element
2460      */
2461     @JsxGetter
2462     public Function getOndragleave() {
2463         return getEventHandler(Event.TYPE_DRAGLEAVE);
2464     }
2465 
2466     /**
2467      * Sets the {@code ondragleave} event handler for this element.
2468      * @param ondragleave the {@code ondragleave} event handler for this element
2469      */
2470     @JsxSetter
2471     public void setOndragleave(final Object ondragleave) {
2472         setEventHandler(Event.TYPE_DRAGLEAVE, ondragleave);
2473     }
2474 
2475     /**
2476      * Returns the {@code ondragover} event handler for this element.
2477      * @return the {@code ondragover} event handler for this element
2478      */
2479     @JsxGetter
2480     public Function getOndragover() {
2481         return getEventHandler(Event.TYPE_DRAGOVER);
2482     }
2483 
2484     /**
2485      * Sets the {@code ondragover} event handler for this element.
2486      * @param ondragover the {@code ondragover} event handler for this element
2487      */
2488     @JsxSetter
2489     public void setOndragover(final Object ondragover) {
2490         setEventHandler(Event.TYPE_DRAGOVER, ondragover);
2491     }
2492 
2493     /**
2494      * Returns the {@code ondragstart} event handler for this element.
2495      * @return the {@code ondragstart} event handler for this element
2496      */
2497     @JsxGetter
2498     public Function getOndragstart() {
2499         return getEventHandler(Event.TYPE_DRAGSTART);
2500     }
2501 
2502     /**
2503      * Sets the {@code ondragstart} event handler for this element.
2504      * @param ondragstart the {@code ondragstart} event handler for this element
2505      */
2506     @JsxSetter
2507     public void setOndragstart(final Object ondragstart) {
2508         setEventHandler(Event.TYPE_DRAGSTART, ondragstart);
2509     }
2510 
2511     /**
2512      * Returns the {@code ondrop} event handler for this element.
2513      * @return the {@code ondrop} event handler for this element
2514      */
2515     @JsxGetter
2516     public Function getOndrop() {
2517         return getEventHandler(Event.TYPE_DROP);
2518     }
2519 
2520     /**
2521      * Sets the {@code ondrop} event handler for this element.
2522      * @param ondrop the {@code ondrop} event handler for this element
2523      */
2524     @JsxSetter
2525     public void setOndrop(final Object ondrop) {
2526         setEventHandler(Event.TYPE_DROP, ondrop);
2527     }
2528 
2529     /**
2530      * Returns the {@code ondurationchange} event handler for this element.
2531      * @return the {@code ondurationchange} event handler for this element
2532      */
2533     @JsxGetter
2534     public Function getOndurationchange() {
2535         return getEventHandler(Event.TYPE_DURATIONCHANGE);
2536     }
2537 
2538     /**
2539      * Sets the {@code ondurationchange} event handler for this element.
2540      * @param ondurationchange the {@code ondurationchange} event handler for this element
2541      */
2542     @JsxSetter
2543     public void setOndurationchange(final Object ondurationchange) {
2544         setEventHandler(Event.TYPE_DURATIONCHANGE, ondurationchange);
2545     }
2546 
2547     /**
2548      * Returns the {@code onemptied} event handler for this element.
2549      * @return the {@code onemptied} event handler for this element
2550      */
2551     @JsxGetter
2552     public Function getOnemptied() {
2553         return getEventHandler(Event.TYPE_EMPTIED);
2554     }
2555 
2556     /**
2557      * Sets the {@code onemptied} event handler for this element.
2558      * @param onemptied the {@code onemptied} event handler for this element
2559      */
2560     @JsxSetter
2561     public void setOnemptied(final Object onemptied) {
2562         setEventHandler(Event.TYPE_EMPTIED, onemptied);
2563     }
2564 
2565     /**
2566      * Returns the {@code onended} event handler for this element.
2567      * @return the {@code onended} event handler for this element
2568      */
2569     @JsxGetter
2570     public Function getOnended() {
2571         return getEventHandler(Event.TYPE_ENDED);
2572     }
2573 
2574     /**
2575      * Sets the {@code onended} event handler for this element.
2576      * @param onended the {@code onended} event handler for this element
2577      */
2578     @JsxSetter
2579     public void setOnended(final Object onended) {
2580         setEventHandler(Event.TYPE_ENDED, onended);
2581     }
2582 
2583     /**
2584      * Returns the {@code ongotpointercapture} event handler for this element.
2585      * @return the {@code ongotpointercapture} event handler for this element
2586      */
2587     @JsxGetter({CHROME, EDGE})
2588     public Function getOngotpointercapture() {
2589         return getEventHandler(Event.TYPE_GOTPOINTERCAPTURE);
2590     }
2591 
2592     /**
2593      * Sets the {@code ongotpointercapture} event handler for this element.
2594      * @param ongotpointercapture the {@code ongotpointercapture} event handler for this element
2595      */
2596     @JsxSetter({CHROME, EDGE})
2597     public void setOngotpointercapture(final Object ongotpointercapture) {
2598         setEventHandler(Event.TYPE_GOTPOINTERCAPTURE, ongotpointercapture);
2599     }
2600 
2601     /**
2602      * Returns the {@code oninvalid} event handler for this element.
2603      * @return the {@code oninvalid} event handler for this element
2604      */
2605     @JsxGetter
2606     public Function getOninvalid() {
2607         return getEventHandler(Event.TYPE_INVALID);
2608     }
2609 
2610     /**
2611      * Sets the {@code oninvalid} event handler for this element.
2612      * @param oninvalid the {@code oninvalid} event handler for this element
2613      */
2614     @JsxSetter
2615     public void setOninvalid(final Object oninvalid) {
2616         setEventHandler(Event.TYPE_INVALID, oninvalid);
2617     }
2618 
2619     /**
2620      * Returns the {@code onload} event handler for this element.
2621      * @return the {@code onload} event handler for this element
2622      */
2623     @JsxGetter
2624     public Function getOnload() {
2625         return getEventHandler(Event.TYPE_LOAD);
2626     }
2627 
2628     /**
2629      * Sets the {@code onload} event handler for this element.
2630      * @param onload the {@code onload} event handler for this element
2631      */
2632     @JsxSetter
2633     public void setOnload(final Object onload) {
2634         setEventHandler(Event.TYPE_LOAD, onload);
2635     }
2636 
2637     /**
2638      * Returns the {@code onloadeddata} event handler for this element.
2639      * @return the {@code onloadeddata} event handler for this element
2640      */
2641     @JsxGetter
2642     public Function getOnloadeddata() {
2643         return getEventHandler(Event.TYPE_LOADEDDATA);
2644     }
2645 
2646     /**
2647      * Sets the {@code onloadeddata} event handler for this element.
2648      * @param onloadeddata the {@code onloadeddata} event handler for this element
2649      */
2650     @JsxSetter
2651     public void setOnloadeddata(final Object onloadeddata) {
2652         setEventHandler(Event.TYPE_LOADEDDATA, onloadeddata);
2653     }
2654 
2655     /**
2656      * Returns the {@code onloadedmetadata} event handler for this element.
2657      * @return the {@code onloadedmetadata} event handler for this element
2658      */
2659     @JsxGetter
2660     public Function getOnloadedmetadata() {
2661         return getEventHandler(Event.TYPE_LOADEDMETADATA);
2662     }
2663 
2664     /**
2665      * Sets the {@code onloadedmetadata} event handler for this element.
2666      * @param onloadedmetadata the {@code onloadedmetadata} event handler for this element
2667      */
2668     @JsxSetter
2669     public void setOnloadedmetadata(final Object onloadedmetadata) {
2670         setEventHandler(Event.TYPE_LOADEDMETADATA, onloadedmetadata);
2671     }
2672 
2673     /**
2674      * Returns the {@code onloadstart} event handler for this element.
2675      * @return the {@code onloadstart} event handler for this element
2676      */
2677     @JsxGetter
2678     public Function getOnloadstart() {
2679         return getEventHandler(Event.TYPE_LOAD_START);
2680     }
2681 
2682     /**
2683      * Sets the {@code onloadstart} event handler for this element.
2684      * @param onloadstart the {@code onloadstart} event handler for this element
2685      */
2686     @JsxSetter
2687     public void setOnloadstart(final Object onloadstart) {
2688         setEventHandler(Event.TYPE_LOAD_START, onloadstart);
2689     }
2690 
2691     /**
2692      * Returns the {@code onlostpointercapture} event handler for this element.
2693      * @return the {@code onlostpointercapture} event handler for this element
2694      */
2695     @JsxGetter({CHROME, EDGE})
2696     public Function getOnlostpointercapture() {
2697         return getEventHandler(Event.TYPE_LOSTPOINTERCAPTURE);
2698     }
2699 
2700     /**
2701      * Sets the {@code onlostpointercapture} event handler for this element.
2702      * @param onlostpointercapture the {@code onlostpointercapture} event handler for this element
2703      */
2704     @JsxSetter({CHROME, EDGE})
2705     public void setOnlostpointercapture(final Object onlostpointercapture) {
2706         setEventHandler(Event.TYPE_LOSTPOINTERCAPTURE, onlostpointercapture);
2707     }
2708 
2709     /**
2710      * Returns the {@code onmouseenter} event handler for this element.
2711      * @return the {@code onmouseenter} event handler for this element
2712      */
2713     @JsxGetter
2714     public Function getOnmouseenter() {
2715         return getEventHandler(Event.TYPE_MOUDEENTER);
2716     }
2717 
2718     /**
2719      * Sets the {@code onmouseenter} event handler for this element.
2720      * @param onmouseenter the {@code onmouseenter} event handler for this element
2721      */
2722     @JsxSetter
2723     public void setOnmouseenter(final Object onmouseenter) {
2724         setEventHandler(Event.TYPE_MOUDEENTER, onmouseenter);
2725     }
2726 
2727     /**
2728      * Returns the {@code onmouseleave} event handler for this element.
2729      * @return the {@code onmouseleave} event handler for this element
2730      */
2731     @JsxGetter
2732     public Function getOnmouseleave() {
2733         return getEventHandler(Event.TYPE_MOUSELEAVE);
2734     }
2735 
2736     /**
2737      * Sets the {@code onmouseleave} event handler for this element.
2738      * @param onmouseleave the {@code onmouseleave} event handler for this element
2739      */
2740     @JsxSetter
2741     public void setOnmouseleave(final Object onmouseleave) {
2742         setEventHandler(Event.TYPE_MOUSELEAVE, onmouseleave);
2743     }
2744 
2745     /**
2746      * Returns the {@code onmousewheel} event handler for this element.
2747      * @return the {@code onmousewheel} event handler for this element
2748      */
2749     @JsxGetter({CHROME, EDGE})
2750     public Function getOnmousewheel() {
2751         return getEventHandler(Event.TYPE_MOUSEWHEEL);
2752     }
2753 
2754     /**
2755      * Sets the {@code onmousewheel} event handler for this element.
2756      * @param onmousewheel the {@code onmousewheel} event handler for this element
2757      */
2758     @JsxSetter({CHROME, EDGE})
2759     public void setOnmousewheel(final Object onmousewheel) {
2760         setEventHandler(Event.TYPE_MOUSEWHEEL, onmousewheel);
2761     }
2762 
2763     /**
2764      * Returns the {@code onpaste} event handler for this element.
2765      * @return the {@code onpaste} event handler for this element
2766      */
2767     @JsxGetter
2768     public Function getOnpaste() {
2769         return getEventHandler(Event.TYPE_PASTE);
2770     }
2771 
2772     /**
2773      * Sets the {@code onpaste} event handler for this element.
2774      * @param onpaste the {@code onpaste} event handler for this element
2775      */
2776     @JsxSetter
2777     public void setOnpaste(final Object onpaste) {
2778         setEventHandler(Event.TYPE_PASTE, onpaste);
2779     }
2780 
2781     /**
2782      * Returns the {@code onpause} event handler for this element.
2783      * @return the {@code onpause} event handler for this element
2784      */
2785     @JsxGetter
2786     public Function getOnpause() {
2787         return getEventHandler(Event.TYPE_PAUSE);
2788     }
2789 
2790     /**
2791      * Sets the {@code onpause} event handler for this element.
2792      * @param onpause the {@code onpause} event handler for this element
2793      */
2794     @JsxSetter
2795     public void setOnpause(final Object onpause) {
2796         setEventHandler(Event.TYPE_PAUSE, onpause);
2797     }
2798 
2799     /**
2800      * Returns the {@code onplay} event handler for this element.
2801      * @return the {@code onplay} event handler for this element
2802      */
2803     @JsxGetter
2804     public Function getOnplay() {
2805         return getEventHandler(Event.TYPE_PLAY);
2806     }
2807 
2808     /**
2809      * Sets the {@code onplay} event handler for this element.
2810      * @param onplay the {@code onplay} event handler for this element
2811      */
2812     @JsxSetter
2813     public void setOnplay(final Object onplay) {
2814         setEventHandler(Event.TYPE_PLAY, onplay);
2815     }
2816 
2817     /**
2818      * Returns the {@code onplaying} event handler for this element.
2819      * @return the {@code onplaying} event handler for this element
2820      */
2821     @JsxGetter
2822     public Function getOnplaying() {
2823         return getEventHandler(Event.TYPE_PLAYING);
2824     }
2825 
2826     /**
2827      * Sets the {@code onplaying} event handler for this element.
2828      * @param onplaying the {@code onplaying} event handler for this element
2829      */
2830     @JsxSetter
2831     public void setOnplaying(final Object onplaying) {
2832         setEventHandler(Event.TYPE_PLAYING, onplaying);
2833     }
2834 
2835     /**
2836      * Returns the {@code onpointercancel} event handler for this element.
2837      * @return the {@code onpointercancel} event handler for this element
2838      */
2839     @JsxGetter({CHROME, EDGE})
2840     public Function getOnpointercancel() {
2841         return getEventHandler(Event.TYPE_POINTERCANCEL);
2842     }
2843 
2844     /**
2845      * Sets the {@code onpointercancel} event handler for this element.
2846      * @param onpointercancel the {@code onpointercancel} event handler for this element
2847      */
2848     @JsxSetter({CHROME, EDGE})
2849     public void setOnpointercancel(final Object onpointercancel) {
2850         setEventHandler(Event.TYPE_POINTERCANCEL, onpointercancel);
2851     }
2852 
2853     /**
2854      * Returns the {@code onpointerdown} event handler for this element.
2855      * @return the {@code onpointerdown} event handler for this element
2856      */
2857     @JsxGetter({CHROME, EDGE})
2858     public Function getOnpointerdown() {
2859         return getEventHandler(Event.TYPE_POINTERDOWN);
2860     }
2861 
2862     /**
2863      * Sets the {@code onpointerdown} event handler for this element.
2864      * @param onpointerdown the {@code onpointerdown} event handler for this element
2865      */
2866     @JsxSetter({CHROME, EDGE})
2867     public void setOnpointerdown(final Object onpointerdown) {
2868         setEventHandler(Event.TYPE_POINTERDOWN, onpointerdown);
2869     }
2870 
2871     /**
2872      * Returns the {@code onpointerenter} event handler for this element.
2873      * @return the {@code onpointerenter} event handler for this element
2874      */
2875     @JsxGetter({CHROME, EDGE})
2876     public Function getOnpointerenter() {
2877         return getEventHandler(Event.TYPE_POINTERENTER);
2878     }
2879 
2880     /**
2881      * Sets the {@code onpointerenter} event handler for this element.
2882      * @param onpointerenter the {@code onpointerenter} event handler for this element
2883      */
2884     @JsxSetter({CHROME, EDGE})
2885     public void setOnpointerenter(final Object onpointerenter) {
2886         setEventHandler(Event.TYPE_POINTERENTER, onpointerenter);
2887     }
2888 
2889     /**
2890      * Returns the {@code onpointerleave} event handler for this element.
2891      * @return the {@code onpointerleave} event handler for this element
2892      */
2893     @JsxGetter({CHROME, EDGE})
2894     public Function getOnpointerleave() {
2895         return getEventHandler(Event.TYPE_POINTERLEAVE);
2896     }
2897 
2898     /**
2899      * Sets the {@code onpointerleave} event handler for this element.
2900      * @param onpointerleave the {@code onpointerleave} event handler for this element
2901      */
2902     @JsxSetter({CHROME, EDGE})
2903     public void setOnpointerleave(final Object onpointerleave) {
2904         setEventHandler(Event.TYPE_POINTERLEAVE, onpointerleave);
2905     }
2906 
2907     /**
2908      * Returns the {@code onpointerlockchange} event handler for this element.
2909      * @return the {@code onpointerlockchange} event handler for this element
2910      */
2911     @JsxGetter({CHROME, EDGE})
2912     public Function getOnpointerlockchange() {
2913         return getEventHandler(Event.TYPE_POINTERLOCKCHANGE);
2914     }
2915 
2916     /**
2917      * Sets the {@code onpointerlockchange} event handler for this element.
2918      * @param onpointerlockchange the {@code onpointerlockchange} event handler for this element
2919      */
2920     @JsxSetter({CHROME, EDGE})
2921     public void setOnpointerlockchange(final Object onpointerlockchange) {
2922         setEventHandler(Event.TYPE_POINTERLOCKCHANGE, onpointerlockchange);
2923     }
2924 
2925     /**
2926      * Returns the {@code onpointerlockerror} event handler for this element.
2927      * @return the {@code onpointerlockerror} event handler for this element
2928      */
2929     @JsxGetter({CHROME, EDGE})
2930     public Function getOnpointerlockerror() {
2931         return getEventHandler(Event.TYPE_POINTERLOCKERROR);
2932     }
2933 
2934     /**
2935      * Sets the {@code onpointerlockerror} event handler for this element.
2936      * @param onpointerlockerror the {@code onpointerlockerror} event handler for this element
2937      */
2938     @JsxSetter({CHROME, EDGE})
2939     public void setOnpointerlockerror(final Object onpointerlockerror) {
2940         setEventHandler(Event.TYPE_POINTERLOCKERROR, onpointerlockerror);
2941     }
2942 
2943     /**
2944      * Returns the {@code onpointermove} event handler for this element.
2945      * @return the {@code onpointermove} event handler for this element
2946      */
2947     @JsxGetter({CHROME, EDGE})
2948     public Function getOnpointermove() {
2949         return getEventHandler(Event.TYPE_POINTERMOVE);
2950     }
2951 
2952     /**
2953      * Sets the {@code onpointermove} event handler for this element.
2954      * @param onpointermove the {@code onpointermove} event handler for this element
2955      */
2956     @JsxSetter({CHROME, EDGE})
2957     public void setOnpointermove(final Object onpointermove) {
2958         setEventHandler(Event.TYPE_POINTERMOVE, onpointermove);
2959     }
2960 
2961     /**
2962      * Returns the {@code onpointerout} event handler for this element.
2963      * @return the {@code onpointerout} event handler for this element
2964      */
2965     @JsxGetter({CHROME, EDGE})
2966     public Function getOnpointerout() {
2967         return getEventHandler(Event.TYPE_POINTEROUT);
2968     }
2969 
2970     /**
2971      * Sets the {@code onpointerout} event handler for this element.
2972      * @param onpointerout the {@code onpointerout} event handler for this element
2973      */
2974     @JsxSetter({CHROME, EDGE})
2975     public void setOnpointerout(final Object onpointerout) {
2976         setEventHandler(Event.TYPE_POINTEROUT, onpointerout);
2977     }
2978 
2979     /**
2980      * Returns the {@code onpointerover} event handler for this element.
2981      * @return the {@code onpointerover} event handler for this element
2982      */
2983     @JsxGetter({CHROME, EDGE})
2984     public Function getOnpointerover() {
2985         return getEventHandler(Event.TYPE_POINTEROVER);
2986     }
2987 
2988     /**
2989      * Sets the {@code onpointerover} event handler for this element.
2990      * @param onpointerover the {@code onpointerover} event handler for this element
2991      */
2992     @JsxSetter({CHROME, EDGE})
2993     public void setOnpointerover(final Object onpointerover) {
2994         setEventHandler(Event.TYPE_POINTEROVER, onpointerover);
2995     }
2996 
2997     /**
2998      * Returns the {@code onpointerup} event handler for this element.
2999      * @return the {@code onpointerup} event handler for this element
3000      */
3001     @JsxGetter({CHROME, EDGE})
3002     public Function getOnpointerup() {
3003         return getEventHandler(Event.TYPE_POINTERUP);
3004     }
3005 
3006     /**
3007      * Sets the {@code onpointerup} event handler for this element.
3008      * @param onpointerup the {@code onpointerup} event handler for this element
3009      */
3010     @JsxSetter({CHROME, EDGE})
3011     public void setOnpointerup(final Object onpointerup) {
3012         setEventHandler(Event.TYPE_POINTERUP, onpointerup);
3013     }
3014 
3015     /**
3016      * Returns the {@code onprogress} event handler for this element.
3017      * @return the {@code onprogress} event handler for this element
3018      */
3019     @JsxGetter
3020     public Function getOnprogress() {
3021         return getEventHandler(Event.TYPE_PROGRESS);
3022     }
3023 
3024     /**
3025      * Sets the {@code onprogress} event handler for this element.
3026      * @param onprogress the {@code onprogress} event handler for this element
3027      */
3028     @JsxSetter
3029     public void setOnprogress(final Object onprogress) {
3030         setEventHandler(Event.TYPE_PROGRESS, onprogress);
3031     }
3032 
3033     /**
3034      * Returns the {@code onratechange} event handler for this element.
3035      * @return the {@code onratechange} event handler for this element
3036      */
3037     @JsxGetter
3038     public Function getOnratechange() {
3039         return getEventHandler(Event.TYPE_RATECHANGE);
3040     }
3041 
3042     /**
3043      * Sets the {@code onratechange} event handler for this element.
3044      * @param onratechange the {@code onratechange} event handler for this element
3045      */
3046     @JsxSetter
3047     public void setOnratechange(final Object onratechange) {
3048         setEventHandler(Event.TYPE_RATECHANGE, onratechange);
3049     }
3050 
3051     /**
3052      * Returns the {@code onreadystatechange} event handler for this element.
3053      * @return the {@code onreadystatechange} event handler for this element
3054      */
3055     @JsxGetter
3056     public Function getOnreadystatechange() {
3057         return getEventHandler(Event.TYPE_READY_STATE_CHANGE);
3058     }
3059 
3060     /**
3061      * Sets the {@code onreadystatechange} event handler for this element.
3062      * @param onreadystatechange the {@code onreadystatechange} event handler for this element
3063      */
3064     @JsxSetter
3065     public void setOnreadystatechange(final Object onreadystatechange) {
3066         setEventHandler(Event.TYPE_READY_STATE_CHANGE, onreadystatechange);
3067     }
3068 
3069     /**
3070      * Returns the {@code onreset} event handler for this element.
3071      * @return the {@code onreset} event handler for this element
3072      */
3073     @JsxGetter
3074     public Function getOnreset() {
3075         return getEventHandler(Event.TYPE_RESET);
3076     }
3077 
3078     /**
3079      * Sets the {@code onreset} event handler for this element.
3080      * @param onreset the {@code onreset} event handler for this element
3081      */
3082     @JsxSetter
3083     public void setOnreset(final Object onreset) {
3084         setEventHandler(Event.TYPE_RESET, onreset);
3085     }
3086 
3087     /**
3088      * Returns the {@code onscroll} event handler for this element.
3089      * @return the {@code onscroll} event handler for this element
3090      */
3091     @JsxGetter
3092     public Function getOnscroll() {
3093         return getEventHandler(Event.TYPE_SCROLL);
3094     }
3095 
3096     /**
3097      * Sets the {@code onscroll} event handler for this element.
3098      * @param onscroll the {@code onscroll} event handler for this element
3099      */
3100     @JsxSetter
3101     public void setOnscroll(final Object onscroll) {
3102         setEventHandler(Event.TYPE_SCROLL, onscroll);
3103     }
3104 
3105     /**
3106      * Returns the {@code onsearch} event handler for this element.
3107      * @return the {@code onsearch} event handler for this element
3108      */
3109     @JsxGetter({CHROME, EDGE})
3110     public Function getOnsearch() {
3111         return getEventHandler(Event.TYPE_SEARCH);
3112     }
3113 
3114     /**
3115      * Sets the {@code onsearch} event handler for this element.
3116      * @param onsearch the {@code onsearch} event handler for this element
3117      */
3118     @JsxSetter({CHROME, EDGE})
3119     public void setOnsearch(final Object onsearch) {
3120         setEventHandler(Event.TYPE_SEARCH, onsearch);
3121     }
3122 
3123     /**
3124      * Returns the {@code onseeked} event handler for this element.
3125      * @return the {@code onseeked} event handler for this element
3126      */
3127     @JsxGetter
3128     public Function getOnseeked() {
3129         return getEventHandler(Event.TYPE_SEEKED);
3130     }
3131 
3132     /**
3133      * Sets the {@code onseeked} event handler for this element.
3134      * @param onseeked the {@code onseeked} event handler for this element
3135      */
3136     @JsxSetter
3137     public void setOnseeked(final Object onseeked) {
3138         setEventHandler(Event.TYPE_SEEKED, onseeked);
3139     }
3140 
3141     /**
3142      * Returns the {@code onseeking} event handler for this element.
3143      * @return the {@code onseeking} event handler for this element
3144      */
3145     @JsxGetter
3146     public Function getOnseeking() {
3147         return getEventHandler(Event.TYPE_SEEKING);
3148     }
3149 
3150     /**
3151      * Sets the {@code onseeking} event handler for this element.
3152      * @param onseeking the {@code onseeking} event handler for this element
3153      */
3154     @JsxSetter
3155     public void setOnseeking(final Object onseeking) {
3156         setEventHandler(Event.TYPE_SEEKING, onseeking);
3157     }
3158 
3159     /**
3160      * Returns the {@code onselect} event handler for this element.
3161      * @return the {@code onselect} event handler for this element
3162      */
3163     @JsxGetter
3164     public Function getOnselect() {
3165         return getEventHandler(Event.TYPE_SELECT);
3166     }
3167 
3168     /**
3169      * Sets the {@code onselect} event handler for this element.
3170      * @param onselect the {@code onselect} event handler for this element
3171      */
3172     @JsxSetter
3173     public void setOnselect(final Object onselect) {
3174         setEventHandler(Event.TYPE_SELECT, onselect);
3175     }
3176 
3177     /**
3178      * Returns the {@code onselectionchange} event handler for this element.
3179      * @return the {@code onselectionchange} event handler for this element
3180      */
3181     @JsxGetter({CHROME, EDGE})
3182     public Function getOnselectionchange() {
3183         return getEventHandler(Event.TYPE_SELECTIONCHANGE);
3184     }
3185 
3186     /**
3187      * Sets the {@code onselectionchange} event handler for this element.
3188      * @param onselectionchange the {@code onselectionchange} event handler for this element
3189      */
3190     @JsxSetter({CHROME, EDGE})
3191     public void setOnselectionchange(final Object onselectionchange) {
3192         setEventHandler(Event.TYPE_SELECTIONCHANGE, onselectionchange);
3193     }
3194 
3195     /**
3196      * Returns the {@code onselectstart} event handler for this element.
3197      * @return the {@code onselectstart} event handler for this element
3198      */
3199     @JsxGetter
3200     public Function getOnselectstart() {
3201         return getEventHandler(Event.TYPE_SELECTSTART);
3202     }
3203 
3204     /**
3205      * Sets the {@code onselectstart} event handler for this element.
3206      * @param onselectstart the {@code onselectstart} event handler for this element
3207      */
3208     @JsxSetter
3209     public void setOnselectstart(final Object onselectstart) {
3210         setEventHandler(Event.TYPE_SELECTSTART, onselectstart);
3211     }
3212 
3213     /**
3214      * Returns the {@code onstalled} event handler for this element.
3215      * @return the {@code onstalled} event handler for this element
3216      */
3217     @JsxGetter
3218     public Function getOnstalled() {
3219         return getEventHandler(Event.TYPE_STALLED);
3220     }
3221 
3222     /**
3223      * Sets the {@code onstalled} event handler for this element.
3224      * @param onstalled the {@code onstalled} event handler for this element
3225      */
3226     @JsxSetter
3227     public void setOnstalled(final Object onstalled) {
3228         setEventHandler(Event.TYPE_STALLED, onstalled);
3229     }
3230 
3231     /**
3232      * Returns the {@code onsubmit} event handler for this element.
3233      * @return the {@code onsubmit} event handler for this element
3234      */
3235     @JsxGetter
3236     public Function getOnsubmit() {
3237         return getEventHandler(Event.TYPE_SUBMIT);
3238     }
3239 
3240     /**
3241      * Sets the {@code onsubmit} event handler for this element.
3242      * @param onsubmit the {@code onsubmit} event handler for this element
3243      */
3244     @JsxSetter
3245     public void setOnsubmit(final Object onsubmit) {
3246         setEventHandler(Event.TYPE_SUBMIT, onsubmit);
3247     }
3248 
3249     /**
3250      * Returns the {@code onsuspend} event handler for this element.
3251      * @return the {@code onsuspend} event handler for this element
3252      */
3253     @JsxGetter
3254     public Function getOnsuspend() {
3255         return getEventHandler(Event.TYPE_SUSPEND);
3256     }
3257 
3258     /**
3259      * Sets the {@code onsuspend} event handler for this element.
3260      * @param onsuspend the {@code onsuspend} event handler for this element
3261      */
3262     @JsxSetter
3263     public void setOnsuspend(final Object onsuspend) {
3264         setEventHandler(Event.TYPE_SUSPEND, onsuspend);
3265     }
3266 
3267     /**
3268      * Returns the {@code ontimeupdate} event handler for this element.
3269      * @return the {@code ontimeupdate} event handler for this element
3270      */
3271     @JsxGetter
3272     public Function getOntimeupdate() {
3273         return getEventHandler(Event.TYPE_TIMEUPDATE);
3274     }
3275 
3276     /**
3277      * Sets the {@code ontimeupdate} event handler for this element.
3278      * @param ontimeupdate the {@code ontimeupdate} event handler for this element
3279      */
3280     @JsxSetter
3281     public void setOntimeupdate(final Object ontimeupdate) {
3282         setEventHandler(Event.TYPE_TIMEUPDATE, ontimeupdate);
3283     }
3284 
3285     /**
3286      * Returns the {@code ontoggle} event handler for this element.
3287      * @return the {@code ontoggle} event handler for this element
3288      */
3289     @JsxGetter({CHROME, EDGE})
3290     public Function getOntoggle() {
3291         return getEventHandler(Event.TYPE_TOGGLE);
3292     }
3293 
3294     /**
3295      * Sets the {@code ontoggle} event handler for this element.
3296      * @param ontoggle the {@code ontoggle} event handler for this element
3297      */
3298     @JsxSetter({CHROME, EDGE})
3299     public void setOntoggle(final Object ontoggle) {
3300         setEventHandler(Event.TYPE_TOGGLE, ontoggle);
3301     }
3302 
3303     /**
3304      * Returns the {@code onvolumechange} event handler for this element.
3305      * @return the {@code onvolumechange} event handler for this element
3306      */
3307     @JsxGetter
3308     public Function getOnvolumechange() {
3309         return getEventHandler(Event.TYPE_VOLUMECHANGE);
3310     }
3311 
3312     /**
3313      * Sets the {@code onvolumechange} event handler for this element.
3314      * @param onvolumechange the {@code onvolumechange} event handler for this element
3315      */
3316     @JsxSetter
3317     public void setOnvolumechange(final Object onvolumechange) {
3318         setEventHandler(Event.TYPE_VOLUMECHANGE, onvolumechange);
3319     }
3320 
3321     /**
3322      * Returns the {@code onwaiting} event handler for this element.
3323      * @return the {@code onwaiting} event handler for this element
3324      */
3325     @JsxGetter
3326     public Function getOnwaiting() {
3327         return getEventHandler(Event.TYPE_WAITING);
3328     }
3329 
3330     /**
3331      * Sets the {@code onwaiting} event handler for this element.
3332      * @param onwaiting the {@code onwaiting} event handler for this element
3333      */
3334     @JsxSetter
3335     public void setOnwaiting(final Object onwaiting) {
3336         setEventHandler(Event.TYPE_WAITING, onwaiting);
3337     }
3338 
3339     /**
3340      * Returns the {@code onwebkitfullscreenchange} event handler for this element.
3341      * @return the {@code onwebkitfullscreenchange} event handler for this element
3342      */
3343     @JsxGetter({CHROME, EDGE})
3344     public Function getOnwebkitfullscreenchange() {
3345         return getEventHandler(Event.TYPE_WEBKITFULLSCREENCHANGE);
3346     }
3347 
3348     /**
3349      * Sets the {@code onwebkitfullscreenchange} event handler for this element.
3350      * @param onwebkitfullscreenchange the {@code onwebkitfullscreenchange} event handler for this element
3351      */
3352     @JsxSetter({CHROME, EDGE})
3353     public void setOnwebkitfullscreenchange(final Object onwebkitfullscreenchange) {
3354         setEventHandler(Event.TYPE_WEBKITFULLSCREENCHANGE, onwebkitfullscreenchange);
3355     }
3356 
3357     /**
3358      * Returns the {@code onwebkitfullscreenerror} event handler for this element.
3359      * @return the {@code onwebkitfullscreenerror} event handler for this element
3360      */
3361     @JsxGetter({CHROME, EDGE})
3362     public Function getOnwebkitfullscreenerror() {
3363         return getEventHandler(Event.TYPE_WEBKITFULLSCREENERROR);
3364     }
3365 
3366     /**
3367      * Sets the {@code onwebkitfullscreenerror} event handler for this element.
3368      * @param onwebkitfullscreenerror the {@code onwebkitfullscreenerror} event handler for this element
3369      */
3370     @JsxSetter
3371     public void setOnwebkitfullscreenerror(final Object onwebkitfullscreenerror) {
3372         setEventHandler(Event.TYPE_WEBKITFULLSCREENERROR, onwebkitfullscreenerror);
3373     }
3374 
3375     /**
3376      * Returns the {@code onwheel} event handler for this element.
3377      * @return the {@code onwheel} event handler for this element
3378      */
3379     @JsxGetter
3380     public Function getOnwheel() {
3381         return getEventHandler(Event.TYPE_WHEEL);
3382     }
3383 
3384     /**
3385      * Sets the {@code onwheel} event handler for this element.
3386      * @param onwheel the {@code onwheel} event handler for this element
3387      */
3388     @JsxSetter
3389     public void setOnwheel(final Object onwheel) {
3390         setEventHandler(Event.TYPE_WHEEL, onwheel);
3391     }
3392 
3393     /**
3394      * Returns the {@code onafterscriptexecute} event handler for this element.
3395      * @return the {@code onafterscriptexecute} event handler for this element
3396      */
3397     @JsxGetter({FF, FF_ESR})
3398     public Function getOnafterscriptexecute() {
3399         return getEventHandler(Event.TYPE_AFTERSCRIPTEXECUTE);
3400     }
3401 
3402     /**
3403      * Sets the {@code onafterscriptexecute} event handler for this element.
3404      * @param onafterscriptexecute the {@code onafterscriptexecute} event handler for this element
3405      */
3406     @JsxSetter({FF, FF_ESR})
3407     public void setOnafterscriptexecute(final Object onafterscriptexecute) {
3408         setEventHandler(Event.TYPE_AFTERSCRIPTEXECUTE, onafterscriptexecute);
3409     }
3410 
3411     /**
3412      * Returns the {@code onbeforescriptexecute} event handler for this element.
3413      * @return the {@code onbeforescriptexecute} event handler for this element
3414      */
3415     @JsxGetter({FF, FF_ESR})
3416     public Function getOnbeforescriptexecute() {
3417         return getEventHandler(Event.TYPE_BEFORESCRIPTEXECUTE);
3418     }
3419 
3420     /**
3421      * Sets the {@code onbeforescriptexecute} event handler for this element.
3422      * @param onbeforescriptexecute the {@code onbeforescriptexecute} event handler for this element
3423      */
3424     @JsxSetter({FF, FF_ESR})
3425     public void setOnbeforescriptexecute(final Object onbeforescriptexecute) {
3426         setEventHandler(Event.TYPE_BEFORESCRIPTEXECUTE, onbeforescriptexecute);
3427     }
3428 
3429     /**
3430      * Returns the {@code onmozfullscreenchange} event handler for this element.
3431      * @return the {@code onmozfullscreenchange} event handler for this element
3432      */
3433     @JsxGetter({FF, FF_ESR})
3434     public Function getOnmozfullscreenchange() {
3435         return getEventHandler(Event.TYPE_MOZFULLSCREENCHANGE);
3436     }
3437 
3438     /**
3439      * Sets the {@code onmozfullscreenchange} event handler for this element.
3440      * @param onmozfullscreenchange the {@code onmozfullscreenchange} event handler for this element
3441      */
3442     @JsxSetter({FF, FF_ESR})
3443     public void setOnmozfullscreenchange(final Object onmozfullscreenchange) {
3444         setEventHandler(Event.TYPE_MOZFULLSCREENCHANGE, onmozfullscreenchange);
3445     }
3446 
3447     /**
3448      * Returns the {@code onmozfullscreenerror} event handler for this element.
3449      * @return the {@code onmozfullscreenerror} event handler for this element
3450      */
3451     @JsxGetter({FF, FF_ESR})
3452     public Function getOnmozfullscreenerror() {
3453         return getEventHandler(Event.TYPE_MOZFULLSCREENERROR);
3454     }
3455 
3456     /**
3457      * Sets the {@code onmozfullscreenerror} event handler for this element.
3458      * @param onmozfullscreenerror the {@code onmozfullscreenerror} event handler for this element
3459      */
3460     @JsxSetter({FF, FF_ESR})
3461     public void setOnmozfullscreenerror(final Object onmozfullscreenerror) {
3462         setEventHandler(Event.TYPE_MOZFULLSCREENERROR, onmozfullscreenerror);
3463     }
3464 
3465     /**
3466      * @return the {@code currentScript}
3467      */
3468     @JsxGetter
3469     public ScriptableObject getCurrentScript() {
3470         return currentScript_;
3471     }
3472 
3473     /**
3474      * @param script the {@code currentScript}
3475      */
3476     public void setCurrentScript(final ScriptableObject script) {
3477         currentScript_ = script;
3478     }
3479 
3480     /**
3481      * @return the {@code FontFaceSet}
3482      */
3483     @JsxGetter
3484     public ScriptableObject getFonts() {
3485         if (fonts_ == null) {
3486             final FontFaceSet fonts = new FontFaceSet();
3487             fonts.setParentScope(getParentScope());
3488             fonts.setPrototype(getPrototype(fonts.getClass()));
3489             fonts_ = fonts;
3490         }
3491         return fonts_;
3492     }
3493 
3494     /**
3495      * Returns the value of the {@code all} property.
3496      * @return the value of the {@code all} property
3497      */
3498     @JsxGetter
3499     public HTMLAllCollection getAll() {
3500         final HTMLAllCollection all = new HTMLAllCollection(getDomNodeOrDie());
3501         all.setAvoidObjectDetection(true);
3502         all.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> true);
3503         return all;
3504     }
3505 
3506     /**
3507      * Returns the element with the specified ID, as long as it is an HTML element; {@code null} otherwise.
3508      * @param id the ID to search for
3509      * @return the element with the specified ID, as long as it is an HTML element; {@code null} otherwise
3510      */
3511     @JsxFunction
3512     public HtmlUnitScriptable getElementById(final String id) {
3513         final DomNode domNode = getDomNodeOrDie();
3514         for (final DomElement descendant : domNode.getDomElementDescendants()) {
3515             if (id.equals(descendant.getId())) {
3516                 return descendant.getScriptableObject();
3517             }
3518         }
3519         return null;
3520     }
3521 
3522     /**
3523      * Creates a new ProcessingInstruction.
3524      * @param target the target
3525      * @param data the data
3526      * @return the new ProcessingInstruction
3527      */
3528     @JsxFunction
3529     public HtmlUnitScriptable createProcessingInstruction(final String target, final String data) {
3530         final ProcessingInstruction node = getPage().createProcessingInstruction(target, data);
3531         return getScriptableFor(node);
3532     }
3533 
3534     /**
3535      * Creates a new createCDATASection.
3536      * @param data the data
3537      * @return the new CDATASection
3538      */
3539     @JsxFunction
3540     public HtmlUnitScriptable createCDATASection(final String data) {
3541         final CDATASection node = getPage().createCDATASection(data);
3542         return getScriptableFor(node);
3543     }
3544 
3545     /**
3546      * Does... nothing.
3547      * @see <a href="https://developer.mozilla.org/en/DOM/document.clear">Mozilla doc</a>
3548      */
3549     @JsxFunction
3550     public void clear() {
3551         // nothing
3552     }
3553 
3554     /**
3555      * {@inheritDoc}
3556      */
3557     @JsxFunction
3558     @Override
3559     public boolean contains(final Object element) {
3560         return getDocumentElement().contains(element);
3561     }
3562 
3563     /**
3564      * Generate and return the URL for the given blob.
3565      * @param blob the Blob containing the data
3566      * @return the URL {@link org.htmlunit.javascript.host.URL#createObjectURL(Object)}
3567      */
3568     public String generateBlobUrl(final Blob blob) {
3569         final URL url = getPage().getUrl();
3570 
3571         String origin = "null";
3572         if (!UrlUtils.URL_ABOUT_BLANK.equals(url)) {
3573             origin = url.getProtocol() + "://" + url.getAuthority();
3574         }
3575 
3576         final String blobUrl = "blob:" + origin + "/" + UUID.randomUUID();
3577         blobUrl2Blobs_.put(blobUrl, blob);
3578         return blobUrl;
3579     }
3580 
3581     /**
3582      * @param url the url to resolve
3583      * @return the Blob for the given URL or {@code null} if not found.
3584      */
3585     public Blob resolveBlobUrl(final String url) {
3586         return blobUrl2Blobs_.get(url);
3587     }
3588 
3589     /**
3590      * Revokes the URL for the given blob.
3591      * @param url the url to revoke {@link org.htmlunit.javascript.host.URL#revokeObjectURL(Scriptable)}
3592      */
3593     public void revokeBlobUrl(final String url) {
3594         blobUrl2Blobs_.remove(url);
3595     }
3596 }