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