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