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