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