View Javadoc
1   /*
2    * Copyright (c) 2002-2026 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host;
16  
17  import static org.htmlunit.BrowserVersionFeatures.EVENT_SCROLL_UIEVENT;
18  import static org.htmlunit.BrowserVersionFeatures.JS_WINDOW_SELECTION_NULL_IF_INVISIBLE;
19  import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
20  import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
21  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF;
22  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR;
23  
24  import java.io.IOException;
25  import java.io.ObjectInputStream;
26  import java.io.Serializable;
27  import java.lang.reflect.Method;
28  import java.net.MalformedURLException;
29  import java.net.URL;
30  import java.util.ArrayList;
31  import java.util.EnumMap;
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.function.Predicate;
36  import java.util.function.Supplier;
37  
38  import org.apache.commons.logging.Log;
39  import org.apache.commons.logging.LogFactory;
40  import org.htmlunit.AlertHandler;
41  import org.htmlunit.BrowserVersion;
42  import org.htmlunit.ConfirmHandler;
43  import org.htmlunit.ElementNotFoundException;
44  import org.htmlunit.Page;
45  import org.htmlunit.PrintHandler;
46  import org.htmlunit.PromptHandler;
47  import org.htmlunit.ScriptException;
48  import org.htmlunit.ScriptResult;
49  import org.htmlunit.SgmlPage;
50  import org.htmlunit.StatusHandler;
51  import org.htmlunit.StorageHolder.Type;
52  import org.htmlunit.TopLevelWindow;
53  import org.htmlunit.WebAssert;
54  import org.htmlunit.WebClient;
55  import org.htmlunit.WebConsole;
56  import org.htmlunit.WebWindow;
57  import org.htmlunit.WebWindowNotFoundException;
58  import org.htmlunit.corejs.javascript.AccessorSlot;
59  import org.htmlunit.corejs.javascript.Context;
60  import org.htmlunit.corejs.javascript.EcmaError;
61  import org.htmlunit.corejs.javascript.Function;
62  import org.htmlunit.corejs.javascript.JavaScriptException;
63  import org.htmlunit.corejs.javascript.NativeConsole.Level;
64  import org.htmlunit.corejs.javascript.NativeObject;
65  import org.htmlunit.corejs.javascript.Scriptable;
66  import org.htmlunit.corejs.javascript.ScriptableObject;
67  import org.htmlunit.corejs.javascript.Slot;
68  import org.htmlunit.corejs.javascript.TopLevel;
69  import org.htmlunit.corejs.javascript.VarScope;
70  import org.htmlunit.css.ComputedCssStyleDeclaration;
71  import org.htmlunit.html.BaseFrameElement;
72  import org.htmlunit.html.DomElement;
73  import org.htmlunit.html.DomNode;
74  import org.htmlunit.html.FrameWindow;
75  import org.htmlunit.html.HtmlAnchor;
76  import org.htmlunit.html.HtmlAttributeChangeEvent;
77  import org.htmlunit.html.HtmlButton;
78  import org.htmlunit.html.HtmlElement;
79  import org.htmlunit.html.HtmlEmbed;
80  import org.htmlunit.html.HtmlForm;
81  import org.htmlunit.html.HtmlImage;
82  import org.htmlunit.html.HtmlInput;
83  import org.htmlunit.html.HtmlMap;
84  import org.htmlunit.html.HtmlObject;
85  import org.htmlunit.html.HtmlPage;
86  import org.htmlunit.html.HtmlSelect;
87  import org.htmlunit.html.HtmlTextArea;
88  import org.htmlunit.javascript.AbstractJavaScriptEngine;
89  import org.htmlunit.javascript.HtmlUnitContextFactory;
90  import org.htmlunit.javascript.HtmlUnitScriptable;
91  import org.htmlunit.javascript.JavaScriptEngine;
92  import org.htmlunit.javascript.PostponedAction;
93  import org.htmlunit.javascript.configuration.JsxClass;
94  import org.htmlunit.javascript.configuration.JsxConstant;
95  import org.htmlunit.javascript.configuration.JsxConstructor;
96  import org.htmlunit.javascript.configuration.JsxFunction;
97  import org.htmlunit.javascript.configuration.JsxGetter;
98  import org.htmlunit.javascript.configuration.JsxSetter;
99  import org.htmlunit.javascript.host.crypto.Crypto;
100 import org.htmlunit.javascript.host.css.ComputedCSSStyleDeclaration;
101 import org.htmlunit.javascript.host.css.MediaQueryList;
102 import org.htmlunit.javascript.host.css.StyleMedia;
103 import org.htmlunit.javascript.host.dom.AbstractList.EffectOnCache;
104 import org.htmlunit.javascript.host.dom.DOMException;
105 import org.htmlunit.javascript.host.dom.Document;
106 import org.htmlunit.javascript.host.dom.Node;
107 import org.htmlunit.javascript.host.dom.Selection;
108 import org.htmlunit.javascript.host.event.Event;
109 import org.htmlunit.javascript.host.event.EventTarget;
110 import org.htmlunit.javascript.host.event.MessageEvent;
111 import org.htmlunit.javascript.host.event.MouseEvent;
112 import org.htmlunit.javascript.host.event.UIEvent;
113 import org.htmlunit.javascript.host.html.DocumentProxy;
114 import org.htmlunit.javascript.host.html.HTMLCollection;
115 import org.htmlunit.javascript.host.html.HTMLDocument;
116 import org.htmlunit.javascript.host.html.HTMLElement;
117 import org.htmlunit.javascript.host.performance.Performance;
118 import org.htmlunit.javascript.host.speech.SpeechSynthesis;
119 import org.htmlunit.javascript.host.xml.XMLDocument;
120 import org.htmlunit.util.StringUtils;
121 import org.htmlunit.util.UrlUtils;
122 import org.htmlunit.xml.XmlPage;
123 
124 /**
125  * JavaScript host object for {@code Window}.
126  *
127  * @author Mike Bowler
128  * @author Chen Jun
129  * @author David K. Taylor
130  * @author Christian Sell
131  * @author Darrell DeBoer
132  * @author Marc Guillemot
133  * @author Dierk Koenig
134  * @author Daniel Gredler
135  * @author David D. Kilzer
136  * @author Chris Erskine
137  * @author Ahmed Ashour
138  * @author Ronald Brill
139  * @author Frank Danek
140  * @author Carsten Steul
141  * @author Colin Alworth
142  * @author Atsushi Nakagawa
143  * @author Sven Strickroth
144  * @author Lai Quang Duong
145  *
146  * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window">MDN Documentation</a>
147  */
148 @JsxClass
149 @SuppressWarnings("PMD.TooManyFields")
150 public class Window extends EventTarget implements WindowOrWorkerGlobalScope, AutoCloseable {
151 
152     private static final Log LOG = LogFactory.getLog(Window.class);
153 
154     /** To be documented. */
155     @JsxConstant({CHROME, EDGE})
156     public static final int TEMPORARY = 0;
157 
158     /** To be documented. */
159     @JsxConstant({CHROME, EDGE})
160     public static final int PERSISTENT = 1;
161 
162     private static final Method GETTER_LENGTH;
163     private static final Method SETTER_LENGTH;
164     private static final Method GETTER_SELF;
165     private static final Method SETTER_SELF;
166     private static final Method GETTER_PARENT;
167     private static final Method SETTER_PARENT;
168     private static final Method GETTER_FRAMES;
169     private static final Method SETTER_FRAMES;
170 
171     static {
172         try {
173             GETTER_LENGTH = Window.class.getDeclaredMethod("jsGetLength");
174             SETTER_LENGTH = Window.class.getDeclaredMethod("jsSetLength", Scriptable.class);
175 
176             GETTER_SELF = Window.class.getDeclaredMethod("jsGetSelf");
177             SETTER_SELF = Window.class.getDeclaredMethod("jsSetSelf", Scriptable.class);
178 
179             GETTER_PARENT = Window.class.getDeclaredMethod("jsGetParent");
180             SETTER_PARENT = Window.class.getDeclaredMethod("jsSetParent", Scriptable.class);
181 
182             GETTER_FRAMES = Window.class.getDeclaredMethod("jsGetFrames");
183             SETTER_FRAMES = Window.class.getDeclaredMethod("jsSetFrames", Scriptable.class);
184         }
185         catch (NoSuchMethodException | SecurityException e) {
186             throw new RuntimeException(e);
187         }
188     }
189 
190     private Scriptable lengthShadow_;
191     private Scriptable selfShadow_;
192     private Scriptable parentShadow_;
193     private Scriptable framesShadow_;
194 
195     private Document document_;
196     private DocumentProxy documentProxy_;
197     private Navigator navigator_;
198     private Object clientInformation_;
199     private WebWindow webWindow_;
200     private WindowProxy windowProxy_;
201     private Screen screen_;
202     private History history_;
203     private Location location_;
204     private Selection selection_;
205     private Event currentEvent_;
206     private String status_ = "";
207     private Map<Class<? extends Scriptable>, Scriptable> prototypes_ = new HashMap<>();
208     private Object controllers_;
209     private Object opener_;
210     private Crypto crypto_;
211     private Scriptable performance_;
212 
213     private final EnumMap<Type, Storage> storages_ = new EnumMap<>(Type.class);
214 
215     private transient List<AnimationFrame> animationFrames_ = new ArrayList<>();
216 
217     private record AnimationFrame(long id_, Function callback_) {
218     }
219 
220     /**
221      * Creates an instance.
222      *
223      * @param cx the current context
224      * @param scope the scope
225      * @param args the arguments
226      * @param ctorObj the function object
227      * @param inNewExpr Is new or not
228      * @return the java object to allow JavaScript to access
229      */
230     @JsxConstructor
231     public static Scriptable jsConstructor(final Context cx, final VarScope scope,
232             final Object[] args, final Function ctorObj, final boolean inNewExpr) {
233         throw JavaScriptEngine.typeError("Illegal constructor");
234     }
235 
236     /**
237      * Restores the transient fields during deserialization.
238      * @param stream the stream to read the object from
239      * @throws IOException if an IO error occurs
240      * @throws ClassNotFoundException if a class is not found
241      */
242     private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
243         stream.defaultReadObject();
244         animationFrames_ = new ArrayList<>();
245     }
246 
247     /**
248      * Returns the prototype object corresponding to the specified HtmlUnit class inside the window scope.
249      * @param jsClass the class whose prototype is to be returned
250      * @return the prototype object corresponding to the specified class inside the specified scope
251      */
252     @Override
253     public Scriptable getPrototype(final Class<? extends HtmlUnitScriptable> jsClass) {
254         return prototypes_.get(jsClass);
255     }
256 
257     /**
258      * Sets the prototypes for HtmlUnit host classes.
259      * @param map a Map of ({@link Class}, {@link Scriptable})
260      */
261     public void setPrototypes(final Map<Class<? extends Scriptable>, Scriptable> map) {
262         prototypes_ = map;
263     }
264 
265     /**
266      * The JavaScript function {@code alert()}.
267      * @param message the message
268      */
269     @JsxFunction
270     public void alert(final Object message) {
271         // use Object as parameter and perform String conversion by ourself
272         // this allows to place breakpoint here and "see" the message object and its properties
273         final String stringMessage = JavaScriptEngine.toString(message);
274         final AlertHandler handler = getWebWindow().getWebClient().getAlertHandler();
275         if (handler == null) {
276             if (LOG.isWarnEnabled()) {
277                 LOG.warn("window.alert(\"" + stringMessage + "\") no alert handler installed");
278             }
279         }
280         else {
281             handler.handleAlert(document_.getPage(), stringMessage);
282         }
283     }
284 
285     /**
286      * Creates a base-64 encoded ASCII string from a string of binary data.
287      * @param stringToEncode string to encode
288      * @return the encoded string
289      */
290     @JsxFunction
291     @Override
292     public String btoa(final String stringToEncode) {
293         return WindowOrWorkerGlobalScopeMixin.btoa(stringToEncode, this);
294     }
295 
296     /**
297      * Decodes a string of data which has been encoded using base-64 encoding.
298      * @param encodedData the encoded string
299      * @return the decoded value
300      */
301     @JsxFunction
302     @Override
303     public String atob(final String encodedData) {
304         return WindowOrWorkerGlobalScopeMixin.atob(encodedData, this);
305     }
306 
307     /**
308      * The JavaScript function {@code confirm}.
309      * @param message the message
310      * @return true if ok was pressed, false if cancel was pressed
311      */
312     @JsxFunction
313     public boolean confirm(final String message) {
314         final ConfirmHandler handler = getWebWindow().getWebClient().getConfirmHandler();
315         if (handler == null) {
316             if (LOG.isWarnEnabled()) {
317                 LOG.warn("window.confirm(\""
318                         + message + "\") no confirm handler installed, simulating the OK button");
319             }
320             return true;
321         }
322         return handler.handleConfirm(document_.getPage(), message);
323     }
324 
325     /**
326      * The JavaScript function {@code prompt}.
327      * @param message the message
328      * @param defaultValue the default value displayed in the text input field
329      * @return the value typed in or {@code null} if the user pressed {@code cancel}
330      */
331     @JsxFunction
332     public String prompt(final String message, Object defaultValue) {
333         final PromptHandler handler = getWebWindow().getWebClient().getPromptHandler();
334         if (handler == null) {
335             if (LOG.isWarnEnabled()) {
336                 LOG.warn("window.prompt(\"" + message + "\") no prompt handler installed");
337             }
338             return null;
339         }
340         if (JavaScriptEngine.isUndefined(defaultValue)) {
341             defaultValue = null;
342         }
343         else {
344             defaultValue = JavaScriptEngine.toString(defaultValue);
345         }
346         return handler.handlePrompt(document_.getPage(), message, (String) defaultValue);
347     }
348 
349     /**
350      * Returns the JavaScript property {@code document}.
351      * @return the document
352      */
353     @JsxGetter(propertyName = "document")
354     public DocumentProxy getDocument_js() {
355         return documentProxy_;
356     }
357 
358     /**
359      * Returns the window's current document.
360      * @return the window's current document
361      */
362     public Document getDocument() {
363         return document_;
364     }
365 
366     /**
367      * Returns the current event.
368      * @return the current event, or {@code null} if no event is currently available
369      */
370     @JsxGetter
371     public Object getEvent() {
372         if (currentEvent_ == null) {
373             return JavaScriptEngine.UNDEFINED;
374         }
375         return currentEvent_;
376     }
377 
378     /**
379      * Returns the current event (used internally regardless of the emulation mode).
380      * @return the current event, or {@code null} if no event is currently available
381      */
382     public Event getCurrentEvent() {
383         return currentEvent_;
384     }
385 
386     /**
387      * Sets the current event.
388      * @param event the current event
389      */
390     public void setCurrentEvent(final Event event) {
391         currentEvent_ = event;
392     }
393 
394     /**
395      * Opens a new window.
396      *
397      * @param url when a new document is opened, <i>url</i> is a String that specifies a MIME type for the document.
398      *        When a new window is opened, <i>url</i> is a String that specifies the URL to render in the new window
399      * @param name the name
400      * @param features the features
401      * @param replace whether to replace in the history list or no
402      * @return the newly opened window, or {@code null} if popup windows have been disabled
403      * @see org.htmlunit.WebClientOptions#isPopupBlockerEnabled()
404      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/open">MDN documentation</a>
405      */
406     @JsxFunction
407     public WindowProxy open(final Object url, final Object name, final Object features,
408             final Object replace) {
409         String urlString = null;
410         if (!JavaScriptEngine.isUndefined(url)) {
411             urlString = JavaScriptEngine.toString(url);
412         }
413         String windowName = "";
414         if (!JavaScriptEngine.isUndefined(name)) {
415             windowName = JavaScriptEngine.toString(name);
416         }
417         String featuresString = null;
418         if (!JavaScriptEngine.isUndefined(features)) {
419             featuresString = JavaScriptEngine.toString(features);
420         }
421         final WebClient webClient = getWebWindow().getWebClient();
422 
423         if (webClient.getOptions().isPopupBlockerEnabled()) {
424             LOG.debug("Ignoring window.open() invocation because popups are blocked.");
425             return null;
426         }
427 
428         boolean replaceCurrentEntryInBrowsingHistory = false;
429         if (!JavaScriptEngine.isUndefined(replace)) {
430             replaceCurrentEntryInBrowsingHistory = JavaScriptEngine.toBoolean(replace);
431         }
432         if ((featuresString != null || replaceCurrentEntryInBrowsingHistory) && LOG.isDebugEnabled()) {
433             LOG.debug(
434                    "window.open: features and replaceCurrentEntryInBrowsingHistory "
435                     + "not implemented: url=[" + urlString
436                     + "] windowName=[" + windowName
437                     + "] features=[" + featuresString
438                     + "] replaceCurrentEntry=[" + replaceCurrentEntryInBrowsingHistory
439                     + "]");
440         }
441 
442         // if specified name is the name of an existing window, then hold it
443         if (StringUtils.isEmptyOrNull(urlString) && !StringUtils.isEmptyString(windowName)) {
444             try {
445                 final WebWindow webWindow = webClient.getWebWindowByName(windowName);
446                 return getProxy(webWindow);
447             }
448             catch (final WebWindowNotFoundException ignored) {
449                 // nothing
450             }
451         }
452         final URL newUrl = makeUrlForOpenWindow(urlString);
453         final WebWindow newWebWindow = webClient.openWindow(newUrl, windowName, webWindow_);
454         return getProxy(newWebWindow);
455     }
456 
457     private URL makeUrlForOpenWindow(final String urlString) {
458         if (urlString.isEmpty()) {
459             return UrlUtils.URL_ABOUT_BLANK;
460         }
461 
462         try {
463             final Page page = getWebWindow().getEnclosedPage();
464             if (page != null && page.isHtmlPage()) {
465                 return ((HtmlPage) page).getFullyQualifiedUrl(urlString);
466             }
467             return new URL(urlString);
468         }
469         catch (final MalformedURLException e) {
470             if (LOG.isWarnEnabled()) {
471                 LOG.error("Unable to create URL for openWindow: relativeUrl=[" + urlString + "]", e);
472             }
473             return null;
474         }
475     }
476 
477     /**
478      * Sets a chunk of JavaScript to be invoked at some specified time later.
479      * The invocation occurs only if the window is opened after the delay
480      * and does not contain an other page than the one that originated the setTimeout.
481      *
482      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">
483      *     MDN web docs</a>
484      *
485      * @param context the JavaScript context
486      * @param scope the scope
487      * @param thisObj the scriptable
488      * @param args the arguments passed into the method
489      * @param function the function
490      * @return the id of the created timer
491      */
492     @JsxFunction
493     public static Object setTimeout(final Context context, final VarScope scope,
494             final Scriptable thisObj, final Object[] args, final Function function) {
495         return WindowOrWorkerGlobalScopeMixin.setTimeout(context, thisObj, args, function);
496     }
497 
498     /**
499      * Queues a microtask to be executed.
500      *
501      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask">
502      *     MDN web docs</a>
503      * @param context the JavaScript context
504      * @param scope the scope
505      * @param thisObj the scriptable
506      * @param args the arguments passed into the method
507      * @param function the function
508      * @return undefined
509      */
510     @JsxFunction
511     public static Object queueMicrotask(final Context context, final VarScope scope,
512             final Scriptable thisObj, final Object[] args, final Function function) {
513         return WindowOrWorkerGlobalScopeMixin.queueMicrotask(thisObj, args);
514     }
515 
516     /**
517      * Sets a chunk of JavaScript to be invoked each time a specified number of milliseconds has elapsed.
518      *
519      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">
520      *     MDN web docs</a>
521      * @param context the JavaScript context
522      * @param scope the scope
523      * @param thisObj the scriptable
524      * @param args the arguments passed into the method
525      * @param function the function
526      * @return the id of the created interval
527      */
528     @JsxFunction
529     public static Object setInterval(final Context context, final VarScope scope,
530             final Scriptable thisObj, final Object[] args, final Function function) {
531         return WindowOrWorkerGlobalScopeMixin.setInterval(context, thisObj, args, function);
532     }
533 
534     /**
535      * Cancels a one-time timeout that was previously established by a call to
536      * {@link #setTimeout(Context, VarScope, Scriptable, Object[], Function)}.
537      *
538      * <p>If {@code timeoutId} is {@code 0} or negative, this method does nothing,
539      * since valid job IDs are always positive integers. This matches browser behavior
540      * where {@code clearTimeout(0)} is a safe no-op, commonly used when {@code 0}
541      * is employed as a sentinel value to indicate "no active timeout".</p>
542      *
543      * <p>If the given ID does not correspond to any active timeout (e.g. it has
544      * already fired or been cancelled), this method returns silently without
545      * throwing an error, consistent with the HTML Living Standard.</p>
546      *
547      * @param timeoutId the ID of the timeout to cancel, as returned by
548      *        {@link #setTimeout(Context, VarScope, Scriptable, Object[], Function)};
549      *        values of {@code 0} or less are ignored
550      * @see #setTimeout(Context, VarScope, Scriptable, Object[], Function)
551      * @see #clearInterval(int)
552      * @see <a href="https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-cleartimeout">
553      *      HTML Living Standard – clearTimeout</a>
554      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout">
555      *      MDN Web Docs – clearTimeout</a>
556      */
557     @JsxFunction
558     public void clearTimeout(final int timeoutId) {
559         if (timeoutId > 0) {
560             if (LOG.isDebugEnabled()) {
561                 LOG.debug("clearTimeout(" + timeoutId + ")");
562             }
563             getWebWindow().getJobManager().removeJob(timeoutId);
564         }
565     }
566 
567     /**
568      * Cancels a repeating interval that was previously established by a call to
569      * {@link #setInterval(Context, VarScope, Scriptable, Object[], Function)}.
570      *
571      * <p>If {@code intervalID} is {@code 0} or negative, this method does nothing,
572      * since valid job IDs are always positive integers. This matches browser behavior
573      * where {@code clearInterval(0)} is a safe no-op, commonly used when {@code 0}
574      * is employed as a sentinel value to indicate "no active interval".</p>
575      *
576      * <p>If the given ID does not correspond to any active interval (e.g. it has
577      * already fired or been cancelled), this method returns silently without
578      * throwing an error, consistent with the HTML Living Standard.</p>
579      *
580      * @param intervalID the ID of the interval to cancel, as returned by
581      *        {@link #setInterval(Context, VarScope, Scriptable, Object[], Function)};
582      *        values of {@code 0} or less are ignored
583      * @see #setInterval(Context, VarScope, Scriptable, Object[], Function)
584      * @see #clearTimeout(int)
585      * @see <a href="https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-clearinterval">
586      *      HTML Living Standard – clearInterval</a>
587      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/clearInterval">
588      *      MDN Web Docs – clearInterval</a>
589      */
590     @JsxFunction
591     public void clearInterval(final int intervalID) {
592         if (intervalID > 0) {
593             if (LOG.isDebugEnabled()) {
594                 LOG.debug("clearInterval(" + intervalID + ")");
595             }
596             getWebWindow().getJobManager().removeJob(intervalID);
597         }
598     }
599 
600     /**
601      * Returns the JavaScript property {@code navigator}.
602      * @return the navigator
603      */
604     @JsxGetter
605     public Navigator getNavigator() {
606         return navigator_;
607     }
608 
609     /**
610      * Returns the JavaScript property {@code clientInformation}.
611      * @return the client information
612      */
613     @JsxGetter
614     public Object getClientInformation() {
615         if (clientInformation_ != null) {
616             return clientInformation_;
617         }
618         return navigator_;
619     }
620 
621     /**
622      * Sets the {@code clientInformation} property.
623      *
624      * @param clientInformation the new value
625      */
626     @JsxSetter
627     public void setClientInformation(final Object clientInformation) {
628         clientInformation_ = clientInformation;
629     }
630 
631     /**
632      * Returns the window property. This is a synonym for {@code self}.
633      * @return the window property (a reference to <code>this</code>)
634      */
635     @JsxGetter(propertyName = "window")
636     public Window getWindow_js() {
637         return this;
638     }
639 
640     /**
641      * Returns the {@code localStorage} property.
642      * @return the {@code localStorage} property
643      */
644     @JsxGetter
645     public Storage getLocalStorage() {
646         return getStorage(Type.LOCAL_STORAGE);
647     }
648 
649     /**
650      * Returns the {@code sessionStorage} property.
651      * @return the {@code sessionStorage} property
652      */
653     @JsxGetter
654     public Storage getSessionStorage() {
655         return getStorage(Type.SESSION_STORAGE);
656     }
657 
658     /**
659      * Gets the storage of the specified type.
660      * @param storageType the type
661      * @return the storage
662      */
663     public Storage getStorage(final Type storageType) {
664         return storages_.computeIfAbsent(storageType,
665             k -> {
666                 final WebWindow webWindow = getWebWindow();
667                 final Map<String, String> store = webWindow.getWebClient().getStorageHolder().
668                         getStore(storageType, webWindow.getEnclosedPage());
669                 return new Storage(this, store);
670             }
671         );
672     }
673 
674     /**
675      * Returns the {@code location} property.
676      * @return the {@code location} property
677      */
678     @JsxGetter
679     public Location getLocation() {
680         return location_;
681     }
682 
683     /**
684      * Sets the {@code location} property. This will cause a reload of the window.
685      * @param newLocation the URL of the new content
686      * @throws IOException when location loading fails
687      */
688     @JsxSetter
689     public void setLocation(final String newLocation) throws IOException {
690         location_.setHref(newLocation);
691     }
692 
693     /**
694      * Logs messages to the browser's standard output (stdout). If the browser was started
695      * from a terminal, output sent to dump() will appear in the terminal.
696      * Output from dump() is not sent to the browser's developer tools console.
697      * To log to the developer tools console, use console.log().
698      * <p>
699      * HtmlUnit always uses the WebConsole.
700      * </p>
701      * @param message the message to log
702      */
703     @JsxFunction({FF, FF_ESR})
704     public void dump(final String message) {
705         final WebConsole console = getWebWindow().getWebClient().getWebConsole();
706         console.print(Context.getCurrentContext(), getParentScope(), Level.INFO, new String[] {message}, null);
707     }
708 
709     /**
710      * Invokes all the animation callbacks registered for this window by
711      * calling {@link #requestAnimationFrame(Object)} once.
712      * @return the number of pending animation callbacks
713      */
714     public int animateAnimationsFrames() {
715         final List<AnimationFrame> animationFrames = new ArrayList<>(animationFrames_);
716         animationFrames_.clear();
717 
718         final double now = System.nanoTime() / 1_000_000d;
719         final Object[] args = {now};
720 
721         final WebWindow ww = getWindow().getWebWindow();
722         final JavaScriptEngine jsEngine = (JavaScriptEngine) ww.getWebClient().getJavaScriptEngine();
723 
724         for (final AnimationFrame animationFrame : animationFrames) {
725             jsEngine.callFunction((HtmlPage) ww.getEnclosedPage(),
726                         animationFrame.callback_, getParentScope(), this, args);
727         }
728         return animationFrames_.size();
729     }
730 
731     /**
732      * Add callback to the list of animationFrames.
733      * @param callback the function to call when it's time to update the animation
734      * @return an identification id
735      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame">MDN Doc</a>
736      */
737     @JsxFunction
738     public int requestAnimationFrame(final Object callback) {
739         if (callback instanceof Function function) {
740             final int id = animationFrames_.size();
741             final AnimationFrame animationFrame = new AnimationFrame(id, function);
742             animationFrames_.add(animationFrame);
743             return id;
744         }
745         return -1;
746     }
747 
748     /**
749      * Remove the callback from the list of animationFrames.
750      * @param requestId the ID value returned by the call to window.requestAnimationFrame()
751      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame">MDN Doc</a>
752      */
753     @JsxFunction
754     public void cancelAnimationFrame(final Object requestId) {
755         final int id = (int) JavaScriptEngine.toNumber(requestId);
756 
757         animationFrames_.removeIf(animationFrame -> animationFrame.id_ == id);
758     }
759 
760     /**
761      * Returns the {@code screen} property.
762      * @return the {@code screen} property
763      */
764     @JsxGetter
765     public Screen getScreen() {
766         return screen_;
767     }
768 
769     /**
770      * Returns the {@code history} property.
771      * @return the {@code history} property
772      */
773     @JsxGetter
774     public History getHistory() {
775         return history_;
776     }
777 
778     /**
779      * Returns the {@code external} property.
780      * @return the {@code external} property
781      */
782     @JsxGetter
783     public External getExternal() {
784         final External external = new External();
785         external.setParentScope(getParentScope());
786         external.setPrototype(getPrototype(external.getClass()));
787         return external;
788     }
789 
790     /**
791      * Initializes this window.
792      * @param scope the scope
793      * @param webWindow the web window corresponding to this window
794      * @param pageToEnclose the page that will become the enclosing page
795      */
796     public void initialize(final TopLevel scope, final WebWindow webWindow, final Page pageToEnclose) {
797         webWindow_ = webWindow;
798         webWindow_.setScriptableObject(this);
799 
800         defineProperty(scope, "length", null, GETTER_LENGTH, SETTER_LENGTH, ScriptableObject.READONLY);
801         defineProperty(scope, "self", null, GETTER_SELF, SETTER_SELF, ScriptableObject.READONLY);
802         defineProperty(scope, "parent", null, GETTER_PARENT, SETTER_PARENT, ScriptableObject.READONLY);
803         defineProperty(scope, "frames", null, GETTER_FRAMES, SETTER_FRAMES, ScriptableObject.READONLY);
804 
805         windowProxy_ = new WindowProxy(webWindow_);
806 
807         if (pageToEnclose instanceof XmlPage) {
808             document_ = new XMLDocument();
809         }
810         else {
811             document_ = new HTMLDocument();
812         }
813         document_.setParentScope(scope);
814         document_.setPrototype(getPrototype(document_.getClass()));
815         document_.setWindow(this);
816 
817         if (pageToEnclose instanceof SgmlPage page) {
818             document_.setDomNode(page);
819 
820             if (page.isHtmlPage()) {
821                 final HtmlPage htmlPage = (HtmlPage) page;
822 
823                 htmlPage.addAutoCloseable(this);
824             }
825         }
826 
827         documentProxy_ = new DocumentProxy(webWindow_);
828 
829         navigator_ = new Navigator();
830         navigator_.setParentScope(scope);
831         navigator_.setPrototype(getPrototype(navigator_.getClass()));
832 
833         screen_ = new Screen(getWebWindow().getScreen());
834         screen_.setParentScope(scope);
835         screen_.setPrototype(getPrototype(screen_.getClass()));
836 
837         history_ = new History();
838         history_.setParentScope(scope);
839         history_.setPrototype(getPrototype(history_.getClass()));
840 
841         location_ = new Location();
842         location_.setParentScope(scope);
843         location_.setPrototype(getPrototype(location_.getClass()));
844         location_.initialize(scope, this, pageToEnclose);
845 
846         // like a JS new Object()
847         controllers_ = JavaScriptEngine.newObject(scope);
848 
849         if (webWindow_ instanceof TopLevelWindow window) {
850             final WebWindow opener = window.getOpener();
851             if (opener != null) {
852                 opener_ = opener.getScriptableObject();
853             }
854         }
855     }
856 
857     /**
858      * Initialize the object.
859      * @param enclosedPage the page containing the JavaScript
860      */
861     public void initialize(final Page enclosedPage) {
862         if (enclosedPage != null && enclosedPage.isHtmlPage()) {
863             final HtmlPage htmlPage = (HtmlPage) enclosedPage;
864 
865             // Windows don't have corresponding DomNodes so set the domNode
866             // variable to be the page. If this isn't set then HtmlUnitScriptable.get()
867             // won't work properly
868             setDomNode(htmlPage);
869             clearEventListenersContainer();
870 
871             WebAssert.notNull("document_", document_);
872             document_.setDomNode(htmlPage);
873         }
874     }
875 
876     /**
877      * Initializes the object. Only called for Windows with no contents.
878      */
879     public void initialize() {
880         // Empty.
881     }
882 
883     /**
884      * Returns the value of the {@code top} property.
885      * @return the value of {@code top}
886      */
887     @JsxGetter
888     public Object getTop() {
889         final WebWindow top = getWebWindow().getTopWindow();
890         return top.getScriptableObject();
891     }
892 
893     /**
894      * Returns the value of the {@code opener} property.
895      * @return the value of the {@code opener}, or {@code null} for a top level window
896      */
897     @JsxGetter
898     public Object getOpener() {
899         Object opener = opener_;
900         if (opener instanceof Window window) {
901             opener = window.windowProxy_;
902         }
903         return opener;
904     }
905 
906     /**
907      * Sets the {@code opener} property.
908      * @param newValue the new value
909      */
910     @JsxSetter
911     public void setOpener(final Object newValue) {
912         opener_ = newValue;
913     }
914 
915     /**
916      * Returns the (i)frame in which the window is contained.
917      * @return {@code null} for a top level window
918      */
919     @JsxGetter
920     public HtmlUnitScriptable getFrameElement() {
921         final WebWindow window = getWebWindow();
922         if (window instanceof FrameWindow frameWindow) {
923             return frameWindow.getFrameElement().getScriptableObject();
924         }
925         return null;
926     }
927 
928     /**
929      * Returns the number of frames contained by this window.
930      * @return the number of frames contained by this window
931      */
932     @JsxGetter
933     public Object getLength() {
934         return JavaScriptEngine.UNDEFINED;
935     }
936 
937     /**
938      * Gets the {@code length} property. Setting this shadows the
939      * defined value (see https://webidl.spec.whatwg.org/#Replaceable)
940      * @return the shadow value if set otherwise the number of frames
941      */
942     public Object jsGetLength() {
943         if (lengthShadow_ != null) {
944             return lengthShadow_;
945         }
946 
947         final HTMLCollection frames = getFrames();
948         if (frames != null) {
949             return frames.getLength();
950         }
951         return 0;
952     }
953 
954     /**
955      * Sets the {@code length} property. Setting this shadows the
956      * defined value (see https://webidl.spec.whatwg.org/#Replaceable)
957      * @param lengthShadow the value to overwrite the defined property value
958      */
959     public void jsSetLength(final Scriptable lengthShadow) {
960         lengthShadow_ = lengthShadow;
961     }
962 
963     /**
964      * Returns the {@code self} property.
965      * @return this
966      */
967     @JsxGetter
968     public Object getSelf() {
969         return JavaScriptEngine.UNDEFINED;
970     }
971 
972     /**
973      * Gets the {@code self} property. Setting this shadows the
974      * defined value (see https://webidl.spec.whatwg.org/#Replaceable)
975      * @return the shadow value if set otherwise the number of frames
976      */
977     public Object jsGetSelf() {
978         if (selfShadow_ != null) {
979             return selfShadow_;
980         }
981 
982         return this;
983     }
984 
985     /**
986      * Sets the {@code self} property. Setting this shadows the
987      * defined value (see https://webidl.spec.whatwg.org/#Replaceable)
988      * @param selfShadow the value to overwrite the defined property value
989      */
990     public void jsSetSelf(final Scriptable selfShadow) {
991         selfShadow_ = selfShadow;
992     }
993 
994     /**
995      * Returns the value of the {@code parent} property.
996      * @return the value of the {@code parent} property
997      */
998     @JsxGetter
999     public Object getParent() {
1000         return JavaScriptEngine.UNDEFINED;
1001     }
1002 
1003     /**
1004      * Gets the {@code parent} property. Setting this shadows the
1005      * defined value (see https://webidl.spec.whatwg.org/#Replaceable)
1006      * @return the shadow value if set otherwise the number of frames
1007      */
1008     public Object jsGetParent() {
1009         if (parentShadow_ != null) {
1010             return parentShadow_;
1011         }
1012 
1013         final WebWindow parent = getWebWindow().getParentWindow();
1014         return parent.getScriptableObject();
1015     }
1016 
1017     /**
1018      * Sets the {@code parent} property. Setting this shadows the
1019      * defined value (see https://webidl.spec.whatwg.org/#Replaceable)
1020      * @param parentShadow the value to overwrite the defined property value
1021      */
1022     public void jsSetParent(final Scriptable parentShadow) {
1023         parentShadow_ = parentShadow;
1024     }
1025 
1026     /**
1027      * Returns the value of the {@code frames} property.
1028      * @return the value of the {@code frames} property
1029      */
1030     @JsxGetter(propertyName = "frames")
1031     public Object getFrames_js() {
1032         return JavaScriptEngine.UNDEFINED;
1033     }
1034 
1035     /**
1036      * Gets the {@code frames} property. Setting this shadows the
1037      * defined value (see https://webidl.spec.whatwg.org/#Replaceable)
1038      * @return the shadow value if set otherwise the number of frames
1039      */
1040     public Object jsGetFrames() {
1041         if (framesShadow_ != null) {
1042             return framesShadow_;
1043         }
1044 
1045         return this;
1046     }
1047 
1048     /**
1049      * Sets the {@code frames} property. Setting this shadows the
1050      * defined value (see https://webidl.spec.whatwg.org/#Replaceable)
1051      * @param framesShadow the value to overwrite the defined property value
1052      */
1053     public void jsSetFrames(final Scriptable framesShadow) {
1054         framesShadow_ = framesShadow;
1055     }
1056 
1057     /**
1058      * Returns the live collection of frames contained by this window.
1059      * @return the live collection of frames contained by this window
1060      */
1061     private HTMLCollection getFrames() {
1062         final Page page = getWebWindow().getEnclosedPage();
1063         if (page instanceof HtmlPage htmlPage) {
1064             return new HTMLCollectionFrames(htmlPage);
1065         }
1066         return null;
1067     }
1068 
1069     /**
1070      * Returns the WebWindow associated with this Window.
1071      * @return the WebWindow
1072      */
1073     public WebWindow getWebWindow() {
1074         return webWindow_;
1075     }
1076 
1077     /**
1078      * Sets the focus to this element.
1079      */
1080     @JsxFunction
1081     public void focus() {
1082         final WebWindow window = getWebWindow();
1083         window.getWebClient().setCurrentWindow(window);
1084     }
1085 
1086     /**
1087      * Removes focus from this element.
1088      */
1089     @JsxFunction
1090     public void blur() {
1091         LOG.debug("window.blur() not implemented");
1092     }
1093 
1094     /**
1095      * Closes this window.
1096      */
1097     @JsxFunction(functionName = "close")
1098     public void close_js() {
1099         final WebWindow webWindow = getWebWindow();
1100         if (webWindow instanceof TopLevelWindow window) {
1101             window.close();
1102         }
1103         else {
1104             webWindow.getWebClient().deregisterWebWindow(webWindow);
1105         }
1106     }
1107 
1108     /**
1109      * Indicates if this window is closed.
1110      * @return {@code true} if this window is closed
1111      */
1112     @JsxGetter
1113     public boolean isClosed() {
1114         final WebWindow webWindow = getWebWindow();
1115         return !webWindow.getWebClient().containsWebWindow(webWindow);
1116     }
1117 
1118     /**
1119      * Does nothing.
1120      * @param x the horizontal position
1121      * @param y the vertical position
1122      */
1123     @JsxFunction
1124     public void moveTo(final int x, final int y) {
1125         LOG.debug("window.moveTo() not implemented");
1126     }
1127 
1128     /**
1129      * Does nothing.
1130      * @param x the horizontal position
1131      * @param y the vertical position
1132      */
1133     @JsxFunction
1134     public void moveBy(final int x, final int y) {
1135         LOG.debug("window.moveBy() not implemented");
1136     }
1137 
1138     /**
1139      * Does nothing.
1140      * @param width the width offset
1141      * @param height the height offset
1142      */
1143     @JsxFunction
1144     public void resizeBy(final int width, final int height) {
1145         LOG.debug("window.resizeBy() not implemented");
1146     }
1147 
1148     /**
1149      * Does nothing.
1150      * @param width the width of the Window in pixel after resize
1151      * @param height the height of the Window in pixel after resize
1152      */
1153     @JsxFunction
1154     public void resizeTo(final int width, final int height) {
1155         LOG.debug("window.resizeTo() not implemented");
1156     }
1157 
1158     /**
1159      * Scrolls to the specified location on the page.
1160      * @param x the horizontal position to scroll to
1161      * @param y the vertical position to scroll to
1162      */
1163     @JsxFunction
1164     public void scroll(final Scriptable x, final Scriptable y) {
1165         scrollTo(x, y);
1166     }
1167 
1168     /**
1169      * Scrolls the window content the specified distance.
1170      * @param x the horizontal distance to scroll by
1171      * @param y the vertical distance to scroll by
1172      */
1173     @JsxFunction
1174     public void scrollBy(final Scriptable x, final Scriptable y) {
1175         final HTMLElement body = document_.getBody();
1176         if (body != null) {
1177             int xOff = 0;
1178             int yOff = 0;
1179             if (y != null) {
1180                 xOff = JavaScriptEngine.toInt32(x);
1181                 yOff = JavaScriptEngine.toInt32(y);
1182             }
1183             else {
1184                 if (!(x instanceof NativeObject)) {
1185                     throw JavaScriptEngine.typeError("eee");
1186                 }
1187                 if (x.has("left", x)) {
1188                     xOff = JavaScriptEngine.toInt32(x.get("left", x));
1189                 }
1190                 if (x.has("top", x)) {
1191                     yOff = JavaScriptEngine.toInt32(x.get("top", x));
1192                 }
1193             }
1194 
1195             body.setScrollLeft(body.getScrollLeft() + xOff);
1196             body.setScrollTop(body.getScrollTop() + yOff);
1197 
1198             fireScrollEvent(body);
1199         }
1200 
1201         fireScrollEvent(document_);
1202     }
1203 
1204     private void fireScrollEvent(final Node node) {
1205         final Event event;
1206         if (getBrowserVersion().hasFeature(EVENT_SCROLL_UIEVENT)) {
1207             event = new UIEvent(node, Event.TYPE_SCROLL);
1208         }
1209         else {
1210             event = new Event(node, Event.TYPE_SCROLL);
1211             event.setCancelable(false);
1212         }
1213         node.fireEvent(event);
1214     }
1215 
1216     /**
1217      * Scrolls the window content down by the specified number of lines.
1218      * @param lines the number of lines to scroll down
1219      */
1220     @JsxFunction({FF, FF_ESR})
1221     public void scrollByLines(final int lines) {
1222         final HTMLElement body = document_.getBody();
1223         if (body != null) {
1224             body.setScrollTop(body.getScrollTop() + (19 * lines));
1225 
1226             fireScrollEvent(body);
1227         }
1228 
1229         fireScrollEvent(document_);
1230     }
1231 
1232     /**
1233      * Scrolls the window content down by the specified number of pages.
1234      * @param pages the number of pages to scroll down
1235      */
1236     @JsxFunction({FF, FF_ESR})
1237     public void scrollByPages(final int pages) {
1238         final HTMLElement body = document_.getBody();
1239         if (body != null) {
1240             body.setScrollTop(body.getScrollTop() + (getInnerHeight() * pages));
1241 
1242             fireScrollEvent(body);
1243         }
1244 
1245         fireScrollEvent(document_);
1246     }
1247 
1248     /**
1249      * Scrolls to the specified location on the page.
1250      * @param x the horizontal position to scroll to
1251      * @param y the vertical position to scroll to
1252      */
1253     @JsxFunction
1254     public void scrollTo(final Scriptable x, final Scriptable y) {
1255         final HTMLElement body = document_.getBody();
1256         if (body != null) {
1257             int xOff;
1258             int yOff;
1259             if (y != null) {
1260                 xOff = JavaScriptEngine.toInt32(x);
1261                 yOff = JavaScriptEngine.toInt32(y);
1262             }
1263             else {
1264                 if (!(x instanceof NativeObject)) {
1265                     throw JavaScriptEngine.typeError("eee");
1266                 }
1267 
1268                 xOff = body.getScrollLeft();
1269                 yOff = body.getScrollTop();
1270 
1271                 if (x.has("left", x)) {
1272                     xOff = JavaScriptEngine.toInt32(x.get("left", x));
1273                 }
1274                 if (x.has("top", x)) {
1275                     yOff = JavaScriptEngine.toInt32(x.get("top", x));
1276                 }
1277             }
1278             body.setScrollLeft(xOff);
1279             body.setScrollTop(yOff);
1280 
1281             fireScrollEvent(body);
1282         }
1283 
1284         fireScrollEvent(document_);
1285     }
1286 
1287     /**
1288      * Returns the {@code onload} property. Note that this is not necessarily a function if something else has been set.
1289      * @return the {@code onload} property
1290      */
1291     @JsxGetter
1292     public Function getOnload() {
1293         return getEventHandler(Event.TYPE_LOAD);
1294     }
1295 
1296     /**
1297      * Sets the value of the {@code onload} event handler.
1298      * @param onload the new handler
1299      */
1300     @JsxSetter
1301     public void setOnload(final Object onload) {
1302         setHandlerForJavaScript(Event.TYPE_LOAD, onload);
1303     }
1304 
1305     /**
1306      * Sets the value of the {@code onblur} event handler.
1307      * @param onblur the new handler
1308      */
1309     @JsxSetter
1310     public void setOnblur(final Object onblur) {
1311         setHandlerForJavaScript(Event.TYPE_BLUR, onblur);
1312     }
1313 
1314     /**
1315      * Returns the {@code onblur} property (not necessary a function if something else has been set).
1316      * @return the {@code onblur} property
1317      */
1318     @JsxGetter
1319     public Function getOnblur() {
1320         return getEventHandler(Event.TYPE_BLUR);
1321     }
1322 
1323     /**
1324      * Returns the {@code onclick} property (not necessary a function if something else has been set).
1325      * @return the {@code onclick} property
1326      */
1327     @JsxGetter
1328     public Function getOnclick() {
1329         return getEventHandler(MouseEvent.TYPE_CLICK);
1330     }
1331 
1332     /**
1333      * Sets the value of the {@code onclick} event handler.
1334      * @param onclick the new handler
1335      */
1336     @JsxSetter
1337     public void setOnclick(final Object onclick) {
1338         setHandlerForJavaScript(MouseEvent.TYPE_CLICK, onclick);
1339     }
1340 
1341     /**
1342      * Returns the {@code ondblclick} property (not necessary a function if something else has been set).
1343      * @return the {@code ondblclick} property
1344      */
1345     @JsxGetter
1346     public Function getOndblclick() {
1347         return getEventHandler(MouseEvent.TYPE_DBL_CLICK);
1348     }
1349 
1350     /**
1351      * Sets the value of the {@code ondblclick} event handler.
1352      * @param ondblclick the new handler
1353      */
1354     @JsxSetter
1355     public void setOndblclick(final Object ondblclick) {
1356         setHandlerForJavaScript(MouseEvent.TYPE_DBL_CLICK, ondblclick);
1357     }
1358 
1359     /**
1360      * Returns the {@code onhashchange} property (not necessary a function if something else has been set).
1361      * @return the {@code onhashchange} property
1362      */
1363     @JsxGetter
1364     public Function getOnhashchange() {
1365         return getEventHandler(Event.TYPE_HASH_CHANGE);
1366     }
1367 
1368     /**
1369      * Sets the value of the {@code onhashchange} event handler.
1370      * @param onhashchange the new handler
1371      */
1372     @JsxSetter
1373     public void setOnhashchange(final Object onhashchange) {
1374         setHandlerForJavaScript(Event.TYPE_HASH_CHANGE, onhashchange);
1375     }
1376 
1377     /**
1378      * Returns the value of the window's {@code name} property.
1379      * @return the value of the window's {@code name} property
1380      */
1381     @JsxGetter
1382     public String getName() {
1383         return getWebWindow().getName();
1384     }
1385 
1386      /**
1387       * Sets the value of the window's {@code name} property.
1388       * @param name the value of the window's {@code name} property
1389       */
1390     @JsxSetter
1391     public void setName(final String name) {
1392         getWebWindow().setName(name);
1393     }
1394 
1395     /**
1396      * Returns the value of the window's {@code onbeforeunload} property.
1397      * @return the value of the window's {@code onbeforeunload} property
1398      */
1399     @JsxGetter
1400     public Function getOnbeforeunload() {
1401         return getEventHandler(Event.TYPE_BEFORE_UNLOAD);
1402     }
1403 
1404     /**
1405      * Sets the value of the window's {@code onbeforeunload} property.
1406      * @param onbeforeunload the value of the window's {@code onbeforeunload} property
1407      */
1408     @JsxSetter
1409     public void setOnbeforeunload(final Object onbeforeunload) {
1410         setHandlerForJavaScript(Event.TYPE_BEFORE_UNLOAD, onbeforeunload);
1411     }
1412 
1413     /**
1414      * Returns the value of the window's {@code onerror} property.
1415      * @return the value of the window's {@code onerror} property
1416      */
1417     @JsxGetter
1418     public Function getOnerror() {
1419         return getEventHandler(Event.TYPE_ERROR);
1420     }
1421 
1422     /**
1423      * Sets the value of the window's {@code onerror} property.
1424      * @param onerror the value of the window's {@code onerror} property
1425      */
1426     @JsxSetter
1427     public void setOnerror(final Object onerror) {
1428         setHandlerForJavaScript(Event.TYPE_ERROR, onerror);
1429     }
1430 
1431     /**
1432      * Returns the value of the window's {@code onmessage} property.
1433      * @return the value of the window's {@code onmessage} property
1434      */
1435     @JsxGetter
1436     public Function getOnmessage() {
1437         return getEventHandler(Event.TYPE_MESSAGE);
1438     }
1439 
1440     /**
1441      * Sets the value of the window's {@code onmessage} property.
1442      * @param onmessage the value of the window's {@code onmessage} property
1443      */
1444     @JsxSetter
1445     public void setOnmessage(final Object onmessage) {
1446         setHandlerForJavaScript(Event.TYPE_MESSAGE, onmessage);
1447     }
1448 
1449     /**
1450      * Triggers the {@code onerror} handler, if one has been set.
1451      * @param e the error that needs to be reported
1452      */
1453     public void triggerOnError(final ScriptException e) {
1454         final Function f = getOnerror();
1455         if (f != null) {
1456             String msg = e.getMessage();
1457             final String url = e.getPage().getUrl().toExternalForm();
1458 
1459             final int line = e.getFailingLineNumber();
1460             final int column = e.getFailingColumnNumber();
1461 
1462             final TopLevel scope = getTopLevelScope(getParentScope());
1463 
1464             Object jsError = e.getMessage();
1465             if (e.getCause() instanceof JavaScriptException) {
1466                 msg = "uncaught exception: " + e.getCause().getMessage();
1467                 jsError = ((JavaScriptException) e.getCause()).getValue();
1468             }
1469             else if (e.getCause() instanceof EcmaError ecmaError) {
1470                 msg = "uncaught " + e.getCause().getMessage();
1471 
1472                 final Scriptable err = JavaScriptEngine.newObject(scope, "Error", JavaScriptEngine.EMPTY_ARGS);
1473                 ScriptableObject.putProperty(err, "message", ecmaError.getMessage());
1474                 ScriptableObject.putProperty(err, "fileName", ecmaError.sourceName());
1475                 ScriptableObject.putProperty(err, "lineNumber", Integer.valueOf(ecmaError.lineNumber()));
1476                 jsError = err;
1477             }
1478 
1479             final Object[] args = {msg, url, Integer.valueOf(line), Integer.valueOf(column), jsError};
1480             f.call(Context.getCurrentContext(), scope, this, args);
1481         }
1482     }
1483 
1484     private void setHandlerForJavaScript(final String eventName, final Object handler) {
1485         getEventListenersContainer().setEventHandler(eventName, handler);
1486     }
1487 
1488     /**
1489      * {@inheritDoc}
1490      */
1491     @Override
1492     protected Object getWithPreemption(final String name) {
1493         final DomNode domNode = getDomNodeOrNull();
1494         if (domNode == null) {
1495             return NOT_FOUND;
1496         }
1497 
1498         // May be attempting to retrieve a frame by name.
1499         final HtmlPage page = (HtmlPage) domNode.getPage();
1500         Object result = getFrameWindowByName(page, name);
1501 
1502         if (result == NOT_FOUND) {
1503             result = getElementsByName(page, name);
1504 
1505             if (result == NOT_FOUND) {
1506                 // May be attempting to retrieve element by ID (try map-backed operation again instead of XPath).
1507                 try {
1508                     final HtmlElement htmlElement = page.getHtmlElementById(name);
1509                     result = getScriptableFor(htmlElement);
1510                 }
1511                 catch (final ElementNotFoundException e) {
1512                     result = NOT_FOUND;
1513                 }
1514             }
1515         }
1516 
1517         if (result instanceof Window window) {
1518             final WebWindow webWindow = window.getWebWindow();
1519             result = getProxy(webWindow);
1520         }
1521 
1522         return result;
1523     }
1524 
1525     /**
1526      * {@inheritDoc}
1527      */
1528     @Override
1529     public Object get(final int index, final Scriptable start) {
1530         if (index < 0 || getWebWindow() == null) {
1531             return JavaScriptEngine.UNDEFINED;
1532         }
1533 
1534         final HTMLCollection frames = getFrames();
1535         if (frames == null || index >= frames.getLength()) {
1536             return JavaScriptEngine.UNDEFINED;
1537         }
1538         return frames.item(Integer.valueOf(index));
1539     }
1540 
1541     private static Object getFrameWindowByName(final HtmlPage page, final String name) {
1542         try {
1543             return page.getFrameByName(name).getScriptableObject();
1544         }
1545         catch (final ElementNotFoundException e) {
1546             return NOT_FOUND;
1547         }
1548     }
1549 
1550     private Object getElementsByName(final HtmlPage page, final String name) {
1551 
1552         // May be attempting to retrieve element(s) by name. IMPORTANT: We're using map-backed operations
1553         // like getHtmlElementsByName() and getHtmlElementById() as much as possible, so as to avoid XPath
1554         // overhead. We only use an XPath-based operation when we have to (where there is more than one
1555         // matching element). This optimization appears to improve performance in certain situations by ~15%
1556         // vs using XPath-based operations throughout.
1557         final List<DomElement> elements = page.getElementsByName(name);
1558 
1559         final Filter filter = new Filter(false);
1560 
1561         elements.removeIf(domElement -> !filter.matches(domElement));
1562 
1563         if (elements.isEmpty()) {
1564             return NOT_FOUND;
1565         }
1566 
1567         if (elements.size() == 1) {
1568             return getScriptableFor(elements.get(0));
1569         }
1570 
1571         // Null must be changed to '' for proper collection initialization.
1572         final String expElementName = "null".equals(name) ? "" : name;
1573 
1574         final HTMLCollection coll = new HTMLCollection(page, true);
1575         coll.setElementsSupplier(
1576                 (Supplier<List<DomNode>> & Serializable)
1577                 () -> {
1578                     final List<DomElement> expElements = page.getElementsByName(expElementName);
1579                     final List<DomNode> result = new ArrayList<>(expElements.size());
1580 
1581                     for (final DomElement domElement : expElements) {
1582                         if (filter.matches(domElement)) {
1583                             result.add(domElement);
1584                         }
1585                     }
1586                     return result;
1587                 });
1588 
1589         coll.setEffectOnCacheFunction(
1590                 (java.util.function.Function<HtmlAttributeChangeEvent, EffectOnCache> & Serializable)
1591                 event -> {
1592                     if ("name".equals(event.getName())) {
1593                         return EffectOnCache.RESET;
1594                     }
1595                     return EffectOnCache.NONE;
1596                 });
1597 
1598         return coll;
1599     }
1600 
1601     /**
1602      * Returns the proxy for the specified window.
1603      * @param w the window whose proxy is to be returned
1604      * @return the proxy for the specified window
1605      */
1606     public static WindowProxy getProxy(final WebWindow w) {
1607         return ((Window) w.getScriptableObject()).windowProxy_;
1608     }
1609 
1610     /**
1611      * Returns the text from the status line.
1612      * @return the status line text
1613      */
1614     @JsxGetter
1615     public String getStatus() {
1616         return status_;
1617     }
1618 
1619     /**
1620      * Sets the text from the status line.
1621      * @param message the status line text
1622      */
1623     @JsxSetter
1624     public void setStatus(final String message) {
1625         status_ = message;
1626 
1627         final StatusHandler statusHandler = webWindow_.getWebClient().getStatusHandler();
1628         if (statusHandler != null) {
1629             statusHandler.statusMessageChanged(webWindow_.getEnclosedPage(), message);
1630         }
1631     }
1632 
1633     /**
1634      * Returns the {@code innerWidth}.
1635      * @return the {@code innerWidth}
1636      * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_window_ref28.html">Mozilla doc</a>
1637      */
1638     @JsxGetter
1639     public int getInnerWidth() {
1640         return getWebWindow().getInnerWidth();
1641     }
1642 
1643     /**
1644      * Sets the {@code innerWidth}.
1645      * @param width the {@code innerWidth}
1646      */
1647     @JsxSetter
1648     public void setInnerWidth(final int width) {
1649         getWebWindow().setInnerWidth(width);
1650     }
1651 
1652     /**
1653      * Returns the {@code outerWidth}.
1654      * @return the {@code outerWidth}
1655      * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_window_ref79.html">Mozilla doc</a>
1656      */
1657     @JsxGetter
1658     public int getOuterWidth() {
1659         return getWebWindow().getOuterWidth();
1660     }
1661 
1662     /**
1663      * Sets the {@code outerWidth}.
1664      * @param width the {@code outerWidth}
1665      */
1666     @JsxSetter
1667     public void setOuterWidth(final int width) {
1668         getWebWindow().setOuterWidth(width);
1669     }
1670 
1671     /**
1672      * Returns the {@code innerHeight}.
1673      * @return the {@code innerHeight}
1674      * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_window_ref27.html">Mozilla doc</a>
1675      */
1676     @JsxGetter
1677     public int getInnerHeight() {
1678         return getWebWindow().getInnerHeight();
1679     }
1680 
1681     /**
1682      * Sets the {@code innerHeight}.
1683      * @param height the {@code innerHeight}
1684      */
1685     @JsxSetter
1686     public void setInnerHeight(final int height) {
1687         getWebWindow().setInnerHeight(height);
1688     }
1689 
1690     /**
1691      * Returns the {@code outerHeight}.
1692      * @return the {@code outerHeight}
1693      * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_window_ref78.html">Mozilla doc</a>
1694      */
1695     @JsxGetter
1696     public int getOuterHeight() {
1697         return getWebWindow().getOuterHeight();
1698     }
1699 
1700     /**
1701      * Sets the {@code outerHeight}.
1702      * @param height the {@code outerHeight}
1703      */
1704     @JsxSetter
1705     public void setOuterHeight(final int height) {
1706         getWebWindow().setOuterHeight(height);
1707     }
1708 
1709     /**
1710      * Prints the current page. The current implementation uses the {@link PrintHandler}
1711      * defined for the {@link WebClient} to process the window.
1712      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/print">MDN documentation</a>
1713      */
1714     @JsxFunction
1715     public void print() {
1716         final PrintHandler handler = getWebWindow().getWebClient().getPrintHandler();
1717         if (handler == null) {
1718             LOG.info("No PrintHandler installed - window.print() ignored");
1719             return;
1720         }
1721 
1722         final SgmlPage sgmlPage = getDocument().getPage();
1723         if (!(sgmlPage instanceof HtmlPage page)) {
1724             LOG.debug("Page is not an HtmlPage - window.print() ignored");
1725             return;
1726         }
1727 
1728         Event event = new Event(this, Event.TYPE_BEFOREPRINT);
1729         fireEvent(event);
1730 
1731         page.setPrinting(true);
1732         try {
1733             handler.handlePrint(page);
1734         }
1735         finally {
1736             page.setPrinting(false);
1737         }
1738         event = new Event(this, Event.TYPE_AFTERPRINT);
1739         fireEvent(event);
1740     }
1741 
1742     /**
1743      * Does nothing special anymore.
1744      * @param type the type of events to capture
1745      * @see HTMLDocument#captureEvents(String)
1746      */
1747     @JsxFunction
1748     public void captureEvents(final String type) {
1749         // Empty.
1750     }
1751 
1752     /**
1753      * Does nothing special anymore.
1754      * @param type the type of events to capture
1755      * @see HTMLDocument#releaseEvents(String)
1756      */
1757     @JsxFunction
1758     public void releaseEvents(final String type) {
1759         // Empty.
1760     }
1761 
1762     /**
1763      * Returns computed style of the element. Computed style represents the final computed values
1764      * of all CSS properties for the element. This method's return value is of the same type as
1765      * that of <code>element.style</code>, but the value returned by this method is read-only.
1766      *
1767      * @param element the element
1768      * @param pseudoElement a string specifying the pseudo-element to match (may be {@code null});
1769      *        e.g. ':before'
1770      * @return the computed style
1771      */
1772     @JsxFunction
1773     public ComputedCSSStyleDeclaration getComputedStyle(final Object element, final String pseudoElement) {
1774         if (!(element instanceof Element e)) {
1775             throw JavaScriptEngine.typeError("parameter 1 is not of type 'Element'");
1776         }
1777 
1778         final ComputedCssStyleDeclaration style = getWebWindow().getComputedStyle(e.getDomNodeOrDie(), pseudoElement);
1779         return new ComputedCSSStyleDeclaration(e, style);
1780     }
1781 
1782     /**
1783      * Returns the current selection.
1784      * @return the current selection
1785      */
1786     @JsxFunction
1787     public Selection getSelection() {
1788         final WebWindow webWindow = getWebWindow();
1789         // return null if the window is in a frame that is not displayed
1790         if (webWindow instanceof FrameWindow frameWindow) {
1791             if (getBrowserVersion().hasFeature(JS_WINDOW_SELECTION_NULL_IF_INVISIBLE)
1792                     && !frameWindow.getFrameElement().isDisplayed()) {
1793                 return null;
1794             }
1795         }
1796         return getSelectionImpl();
1797     }
1798 
1799     /**
1800      * Returns the current selection.
1801      * @return the current selection
1802      */
1803     public Selection getSelectionImpl() {
1804         if (selection_ == null) {
1805             selection_ = new Selection();
1806             selection_.setParentScope(getParentScope());
1807             selection_.setPrototype(getPrototype(selection_.getClass()));
1808         }
1809         return selection_;
1810     }
1811 
1812     /**
1813      * Gets the {@code controllers}. The result doesn't currently matter but it is important to return an
1814      * object as some JavaScript libraries check it.
1815      * @see <a href="https://developer.mozilla.org/En/DOM/Window.controllers">Mozilla documentation</a>
1816      * @return some object
1817      */
1818     @JsxGetter({FF, FF_ESR})
1819     public Object getControllers() {
1820         return controllers_;
1821     }
1822 
1823     /**
1824      * Sets the {@code controllers}.
1825      * @param value the new value
1826      */
1827     @JsxSetter({FF, FF_ESR})
1828     public void setControllers(final Object value) {
1829         controllers_ = value;
1830     }
1831 
1832     /**
1833      * Returns the value of {@code mozInnerScreenX} property.
1834      * @return the value of {@code mozInnerScreenX} property
1835      */
1836     @JsxGetter({FF, FF_ESR})
1837     public int getMozInnerScreenX() {
1838         return 12;
1839     }
1840 
1841     /**
1842      * Returns the value of {@code mozInnerScreenY} property.
1843      * @return the value of {@code mozInnerScreenY} property
1844      */
1845     @JsxGetter({FF, FF_ESR})
1846     public int getMozInnerScreenY() {
1847         return 90;
1848     }
1849 
1850     private static final class Filter {
1851         private final boolean includeFormFields_;
1852 
1853         Filter(final boolean includeFormFields) {
1854             includeFormFields_ = includeFormFields;
1855         }
1856 
1857         boolean matches(final Object object) {
1858             if (object instanceof HtmlEmbed
1859                 || object instanceof HtmlForm
1860                 || object instanceof HtmlImage
1861                 || object instanceof HtmlObject) {
1862                 return true;
1863             }
1864 
1865             return includeFormFields_
1866                     && (object instanceof HtmlAnchor
1867                         || object instanceof HtmlButton
1868                         || object instanceof HtmlInput
1869                         || object instanceof HtmlMap
1870                         || object instanceof HtmlSelect
1871                         || object instanceof HtmlTextArea);
1872         }
1873     }
1874 
1875     /**
1876      * Should implement the stop() function on the window object.
1877      * (currently empty implementation)
1878      * @see <a href="https://developer.mozilla.org/en/DOM/window.stop">window.stop</a>
1879      */
1880     @JsxFunction
1881     public void stop() {
1882         //empty
1883     }
1884 
1885     /**
1886      * Returns the value of {@code pageXOffset} property.
1887      * @return the value of {@code pageXOffset} property
1888      */
1889     @JsxGetter
1890     public int getPageXOffset() {
1891         return 0;
1892     }
1893 
1894     /**
1895      * Returns the value of {@code pageYOffset} property.
1896      * @return the value of {@code pageYOffset} property
1897      */
1898     @JsxGetter
1899     public int getPageYOffset() {
1900         return 0;
1901     }
1902 
1903     /**
1904      * Returns the value of {@code scrollX} property.
1905      * @return the value of {@code scrollX} property
1906      */
1907     @JsxGetter
1908     public int getScrollX() {
1909         return 0;
1910     }
1911 
1912     /**
1913      * Returns the value of {@code scrollY} property.
1914      * @return the value of {@code scrollY} property
1915      */
1916     @JsxGetter
1917     public int getScrollY() {
1918         return 0;
1919     }
1920 
1921     /**
1922      * Returns the {@code netscape} property.
1923      *
1924      * @return the value of {@code netscape} property
1925      */
1926     @JsxGetter({FF, FF_ESR})
1927     public Netscape getNetscape() {
1928         return new Netscape(getParentScope());
1929     }
1930 
1931     /**
1932      * {@inheritDoc}
1933      * Used to allow re-declaration of constants (eg: "var undefined;").
1934      */
1935     @Override
1936     public boolean isConst(final String name) {
1937         if ("undefined".equals(name) || "Infinity".equals(name) || "NaN".equals(name)) {
1938             return false;
1939         }
1940 
1941         return super.isConst(name);
1942     }
1943 
1944     /**
1945      * {@inheritDoc}
1946      */
1947     @Override
1948     public boolean dispatchEvent(final Event event) {
1949         event.setTarget(this);
1950         final ScriptResult result = fireEvent(event);
1951         return !event.isAborted(result);
1952     }
1953 
1954     /**
1955      * Getter for the {@code onchange} event handler.
1956      * @return the handler
1957      */
1958     @JsxGetter
1959     public Function getOnchange() {
1960         return getEventHandler(Event.TYPE_CHANGE);
1961     }
1962 
1963     /**
1964      * Setter for the {@code onchange} event handler.
1965      * @param onchange the handler
1966      */
1967     @JsxSetter
1968     public void setOnchange(final Object onchange) {
1969         setHandlerForJavaScript(Event.TYPE_CHANGE, onchange);
1970     }
1971 
1972     /**
1973      * Getter for the {@code onsubmit} event handler.
1974      * @return the handler
1975      */
1976     @JsxGetter
1977     public Function getOnsubmit() {
1978         return getEventHandler(Event.TYPE_SUBMIT);
1979     }
1980 
1981     /**
1982      * Setter for the {@code onsubmit} event handler.
1983      * @param onsubmit the handler
1984      */
1985     @JsxSetter
1986     public void setOnsubmit(final Object onsubmit) {
1987         setHandlerForJavaScript(Event.TYPE_SUBMIT, onsubmit);
1988     }
1989 
1990     /**
1991      * Posts a message.
1992      * @param context the current context
1993      * @param scope the scope
1994      * @param thisObj this object
1995      * @param args the script(s) to import
1996      * @param funObj the JS function called
1997      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage">MDN documentation</a>
1998      */
1999     @JsxFunction
2000     public static void postMessage(final Context context, final VarScope scope,
2001             final Scriptable thisObj, final Object[] args, final Function funObj) {
2002 
2003         // support the structured clone algorithm
2004         if (args.length < 1) {
2005             throw JavaScriptEngine.typeError("message not provided");
2006         }
2007         final Object message = args[0];
2008 
2009         String targetOrigin = "*";
2010         Object transfer = JavaScriptEngine.UNDEFINED;
2011 
2012         if (args.length > 1) {
2013             if (JavaScriptEngine.isArray(args[1])) {
2014                 transfer = args[1];
2015             }
2016             else {
2017                 targetOrigin = JavaScriptEngine.toString(args[1]);
2018             }
2019         }
2020 
2021         if (args.length > 2) {
2022             if (JavaScriptEngine.isArray(args[2])) {
2023                 transfer = args[2];
2024             }
2025         }
2026 
2027         final TopLevel topLevel = ScriptableObject.getTopLevelScope(scope);
2028         final Window sender = (Window) topLevel.getGlobalThis();
2029         final Window receiver = (Window) thisObj;
2030         final URL receiverURL = receiver.getWebWindow().getEnclosedPage().getUrl();
2031 
2032         final WebWindow webWindow = sender.getWebWindow();
2033         final Page page = webWindow.getEnclosedPage();
2034         final URL senderURL = page.getUrl();
2035 
2036         if (!StringUtils.equalsChar('*', targetOrigin)) {
2037             final URL targetURL;
2038             if (StringUtils.equalsChar('/', targetOrigin)) {
2039                 targetURL = senderURL;
2040             }
2041             else {
2042                 try {
2043                     targetURL = new URL(targetOrigin);
2044                 }
2045                 catch (final Exception e) {
2046                     throw JavaScriptEngine.asJavaScriptException(
2047                             sender,
2048                             "Failed to execute 'postMessage' on 'Window': Invalid target origin '"
2049                                     + targetOrigin + "' was specified (reason: " + e.getMessage() + ".",
2050                             DOMException.SYNTAX_ERR);
2051                 }
2052             }
2053 
2054             if (getPort(targetURL) != getPort(receiverURL)) {
2055                 return;
2056             }
2057             if (!targetURL.getHost().equals(receiverURL.getHost())) {
2058                 return;
2059             }
2060             if (!targetURL.getProtocol().equals(receiverURL.getProtocol())) {
2061                 return;
2062             }
2063         }
2064 
2065         final String origin;
2066         try {
2067             final URL originUrl = UrlUtils.getUrlWithoutPathRefQuery(senderURL);
2068             origin = UrlUtils.removeRedundantPort(originUrl).toExternalForm();
2069         }
2070         catch (final MalformedURLException e) {
2071             throw JavaScriptEngine.throwAsScriptRuntimeEx(e);
2072         }
2073 
2074         final MessageEvent event = new MessageEvent();
2075         event.initMessageEvent(Event.TYPE_MESSAGE, false, false, message, origin, "", sender, transfer);
2076         event.setParentScope(scope);
2077         event.setPrototype(receiver.getPrototype(event.getClass()));
2078 
2079         final AbstractJavaScriptEngine<?> jsEngine = webWindow.getWebClient().getJavaScriptEngine();
2080         final PostponedAction action = new PostponedAction(page, "Window.postMessage") {
2081             @Override
2082             public void execute() {
2083                 final HtmlUnitContextFactory cf = jsEngine.getContextFactory();
2084                 cf.call(cx -> receiver.dispatchEvent(event));
2085             }
2086         };
2087         jsEngine.addPostponedAction(action);
2088     }
2089 
2090     /**
2091      * Returns the port of the specified URL.
2092      * @param url the URL
2093      * @return the port
2094      */
2095     public static int getPort(final URL url) {
2096         int port = url.getPort();
2097         if (port == -1) {
2098             if ("http".equals(url.getProtocol())) {
2099                 port = 80;
2100             }
2101             else {
2102                 port = 443;
2103             }
2104         }
2105         return port;
2106     }
2107 
2108     /**
2109      * The performance attribute is defined as replacable
2110      * (https://w3c.github.io/hr-time/#the-performance-attribute) but not implemented
2111      * as that.
2112      * @return the value of the {@code performance} property
2113      */
2114     @JsxGetter
2115     public Scriptable getPerformance() {
2116         if (performance_ == null) {
2117             final Performance performance = new Performance();
2118             performance.setParentScope(getParentScope());
2119             performance.setPrototype(getPrototype(performance.getClass()));
2120             performance_ = performance;
2121         }
2122         return performance_;
2123     }
2124 
2125     /**
2126      * The performance attribute is defined as replacable
2127      * (https://w3c.github.io/hr-time/#the-performance-attribute) but not implemented
2128      * as that.
2129      * <p>
2130      * Sets the {@code performance} property.
2131      * </p>
2132      * @param performance the value to overwrite the defined property value
2133      */
2134     @JsxSetter
2135     public void setPerformance(final Scriptable performance) {
2136         performance_ = performance;
2137     }
2138 
2139     /**
2140      * Returns the {@code devicePixelRatio} property.
2141      * @return the {@code devicePixelRatio} property
2142      */
2143     @JsxGetter
2144     public int getDevicePixelRatio() {
2145         return 1;
2146     }
2147 
2148     /**
2149      * Returns the {@code styleMedia} property.
2150      * @return the {@code styleMedia} property
2151      */
2152     @JsxGetter({CHROME, EDGE})
2153     public StyleMedia getStyleMedia() {
2154         final StyleMedia styleMedia = new StyleMedia();
2155         styleMedia.setParentScope(getParentScope());
2156         styleMedia.setPrototype(getPrototype(styleMedia.getClass()));
2157         return styleMedia;
2158     }
2159 
2160     /**
2161      * Returns a new MediaQueryList object representing the parsed results of the specified media query string.
2162      *
2163      * @param mediaQueryString the media query
2164      * @return a new MediaQueryList object
2165      */
2166     @JsxFunction
2167     public MediaQueryList matchMedia(final String mediaQueryString) {
2168         final MediaQueryList mediaQueryList = new MediaQueryList(mediaQueryString);
2169         mediaQueryList.setParentScope(getParentScope());
2170         mediaQueryList.setPrototype(getPrototype(mediaQueryList.getClass()));
2171         return mediaQueryList;
2172     }
2173 
2174     /**
2175      * Stub only at the moment.
2176      * @param search the text string for which to search
2177      * @param caseSensitive if true, specifies a case-sensitive search
2178      * @param backwards if true, specifies a backward search
2179      * @param wrapAround if true, specifies a wrap around search
2180      * @param wholeWord if true, specifies a whole word search
2181      * @param searchInFrames if true, specifies a search in frames
2182      * @param showDialog if true, specifies a show Dialog.
2183      * @return false
2184      */
2185     @JsxFunction
2186     public boolean find(final String search, final boolean caseSensitive,
2187             final boolean backwards, final boolean wrapAround,
2188             final boolean wholeWord, final boolean searchInFrames, final boolean showDialog) {
2189         return false;
2190     }
2191 
2192     /**
2193      * Returns the {@code speechSynthesis} property.
2194      * @return the {@code speechSynthesis} property
2195      */
2196     @JsxGetter({CHROME, EDGE})
2197     public SpeechSynthesis getSpeechSynthesis() {
2198         final SpeechSynthesis speechSynthesis = new SpeechSynthesis();
2199         speechSynthesis.setParentScope(getParentScope());
2200         speechSynthesis.setPrototype(getPrototype(speechSynthesis.getClass()));
2201         return speechSynthesis;
2202     }
2203 
2204     /**
2205      * Returns the {@code offscreenBuffering} property.
2206      * @return the {@code offscreenBuffering} property
2207      */
2208     @JsxGetter({CHROME, EDGE})
2209     public boolean isOffscreenBuffering() {
2210         return true;
2211     }
2212 
2213     /**
2214      * Returns the {@code crypto} property.
2215      * @return the {@code crypto} property
2216      */
2217     @JsxGetter
2218     public Crypto getCrypto() {
2219         if (crypto_ == null) {
2220             crypto_ = new Crypto(this);
2221         }
2222         return crypto_;
2223     }
2224 
2225     /**
2226      * {@inheritDoc}
2227      */
2228     @Override
2229     public void close() {
2230         // nothing to do
2231     }
2232 
2233     /**
2234      * Returns the {@code onfocus} event handler.
2235      * @return the {@code onfocus} event handler
2236      */
2237     @JsxGetter
2238     public Function getOnfocus() {
2239         return getEventHandler(Event.TYPE_FOCUS);
2240     }
2241 
2242     /**
2243      * Sets the {@code onfocus} event handler.
2244      * @param onfocus the {@code onfocus} event handler
2245      */
2246     @JsxSetter
2247     public void setOnfocus(final Object onfocus) {
2248         setHandlerForJavaScript(Event.TYPE_FOCUS, onfocus);
2249     }
2250 
2251     /**
2252      * Returns the {@code ondragend} event handler.
2253      * @return the {@code ondragend} event handler
2254      */
2255     @JsxGetter
2256     public Function getOndragend() {
2257         return getEventHandler(Event.TYPE_DRAGEND);
2258     }
2259 
2260     /**
2261      * Sets the {@code ondragend} event handler.
2262      * @param ondragend the {@code ondragend} event handler
2263      */
2264     @JsxSetter
2265     public void setOndragend(final Object ondragend) {
2266         setHandlerForJavaScript(Event.TYPE_DRAGEND, ondragend);
2267     }
2268 
2269     /**
2270      * Returns the {@code oninvalid} event handler.
2271      * @return the {@code oninvalid} event handler
2272      */
2273     @JsxGetter
2274     public Function getOninvalid() {
2275         return getEventHandler(Event.TYPE_INVALID);
2276     }
2277 
2278     /**
2279      * Sets the {@code oninvalid} event handler.
2280      * @param oninvalid the {@code oninvalid} event handler
2281      */
2282     @JsxSetter
2283     public void setOninvalid(final Object oninvalid) {
2284         setHandlerForJavaScript(Event.TYPE_INVALID, oninvalid);
2285     }
2286 
2287     /**
2288      * Returns the {@code onpointerout} event handler.
2289      * @return the {@code onpointerout} event handler
2290      */
2291     @JsxGetter({CHROME, EDGE})
2292     public Function getOnpointerout() {
2293         return getEventHandler(Event.TYPE_POINTEROUT);
2294     }
2295 
2296     /**
2297      * Sets the {@code onpointerout} event handler.
2298      * @param onpointerout the {@code onpointerout} event handler
2299      */
2300     @JsxSetter({CHROME, EDGE})
2301     public void setOnpointerout(final Object onpointerout) {
2302         setHandlerForJavaScript(Event.TYPE_POINTEROUT, onpointerout);
2303     }
2304 
2305     /**
2306      * Returns the {@code onratechange} event handler.
2307      * @return the {@code onratechange} event handler
2308      */
2309     @JsxGetter
2310     public Function getOnratechange() {
2311         return getEventHandler(Event.TYPE_RATECHANGE);
2312     }
2313 
2314     /**
2315      * Sets the {@code onratechange} event handler.
2316      * @param onratechange the {@code onratechange} event handler
2317      */
2318     @JsxSetter
2319     public void setOnratechange(final Object onratechange) {
2320         setHandlerForJavaScript(Event.TYPE_RATECHANGE, onratechange);
2321     }
2322 
2323     /**
2324      * Returns the {@code onanimationiteration} event handler.
2325      * @return the {@code onanimationiteration} event handler
2326      */
2327     @JsxGetter
2328     public Function getOnanimationiteration() {
2329         return getEventHandler(Event.TYPE_ANIMATIONITERATION);
2330     }
2331 
2332     /**
2333      * Sets the {@code onanimationiteration} event handler.
2334      * @param onanimationiteration the {@code onanimationiteration} event handler
2335      */
2336     @JsxSetter
2337     public void setOnanimationiteration(final Object onanimationiteration) {
2338         setHandlerForJavaScript(Event.TYPE_ANIMATIONITERATION, onanimationiteration);
2339     }
2340 
2341     /**
2342      * Returns the {@code oncanplaythrough} event handler.
2343      * @return the {@code oncanplaythrough} event handler
2344      */
2345     @JsxGetter
2346     public Function getOncanplaythrough() {
2347         return getEventHandler(Event.TYPE_CANPLAYTHROUGH);
2348     }
2349 
2350     /**
2351      * Sets the {@code oncanplaythrough} event handler.
2352      * @param oncanplaythrough the {@code oncanplaythrough} event handler
2353      */
2354     @JsxSetter
2355     public void setOncanplaythrough(final Object oncanplaythrough) {
2356         setHandlerForJavaScript(Event.TYPE_CANPLAYTHROUGH, oncanplaythrough);
2357     }
2358 
2359     /**
2360      * Returns the {@code oncancel} event handler.
2361      * @return the {@code oncancel} event handler
2362      */
2363     @JsxGetter({CHROME, EDGE})
2364     public Function getOncancel() {
2365         return getEventHandler(Event.TYPE_CANCEL);
2366     }
2367 
2368     /**
2369      * Sets the {@code oncancel} event handler.
2370      * @param oncancel the {@code oncancel} event handler
2371      */
2372     @JsxSetter({CHROME, EDGE})
2373     public void setOncancel(final Object oncancel) {
2374         setHandlerForJavaScript(Event.TYPE_CANCEL, oncancel);
2375     }
2376 
2377     /**
2378      * Returns the {@code onpointerenter} event handler.
2379      * @return the {@code onpointerenter} event handler
2380      */
2381     @JsxGetter({CHROME, EDGE})
2382     public Function getOnpointerenter() {
2383         return getEventHandler(Event.TYPE_POINTERENTER);
2384     }
2385 
2386     /**
2387      * Sets the {@code onpointerenter} event handler.
2388      * @param onpointerenter the {@code onpointerenter} event handler
2389      */
2390     @JsxSetter({CHROME, EDGE})
2391     public void setOnpointerenter(final Object onpointerenter) {
2392         setHandlerForJavaScript(Event.TYPE_POINTERENTER, onpointerenter);
2393     }
2394 
2395     /**
2396      * Returns the {@code onselect} event handler.
2397      * @return the {@code onselect} event handler
2398      */
2399     @JsxGetter
2400     public Function getOnselect() {
2401         return getEventHandler(Event.TYPE_SELECT);
2402     }
2403 
2404     /**
2405      * Sets the {@code onselect} event handler.
2406      * @param onselect the {@code onselect} event handler
2407      */
2408     @JsxSetter
2409     public void setOnselect(final Object onselect) {
2410         setHandlerForJavaScript(Event.TYPE_SELECT, onselect);
2411     }
2412 
2413     /**
2414      * Returns the {@code onauxclick} event handler.
2415      * @return the {@code onauxclick} event handler
2416      */
2417     @JsxGetter({CHROME, EDGE})
2418     public Function getOnauxclick() {
2419         return getEventHandler(Event.TYPE_AUXCLICK);
2420     }
2421 
2422     /**
2423      * Sets the {@code onauxclick} event handler.
2424      * @param onauxclick the {@code onauxclick} event handler
2425      */
2426     @JsxSetter({CHROME, EDGE})
2427     public void setOnauxclick(final Object onauxclick) {
2428         setHandlerForJavaScript(Event.TYPE_AUXCLICK, onauxclick);
2429     }
2430 
2431     /**
2432      * Returns the {@code onscroll} event handler.
2433      * @return the {@code onscroll} event handler
2434      */
2435     @JsxGetter
2436     public Function getOnscroll() {
2437         return getEventHandler(Event.TYPE_SCROLL);
2438     }
2439 
2440     /**
2441      * Sets the {@code onscroll} event handler.
2442      * @param onscroll the {@code onscroll} event handler
2443      */
2444     @JsxSetter
2445     public void setOnscroll(final Object onscroll) {
2446         setHandlerForJavaScript(Event.TYPE_SCROLL, onscroll);
2447     }
2448 
2449     /**
2450      * Returns the {@code onkeydown} event handler.
2451      * @return the {@code onkeydown} event handler
2452      */
2453     @JsxGetter
2454     public Function getOnkeydown() {
2455         return getEventHandler(Event.TYPE_KEY_DOWN);
2456     }
2457 
2458     /**
2459      * Sets the {@code onkeydown} event handler.
2460      * @param onkeydown the {@code onkeydown} event handler
2461      */
2462     @JsxSetter
2463     public void setOnkeydown(final Object onkeydown) {
2464         setHandlerForJavaScript(Event.TYPE_KEY_DOWN, onkeydown);
2465     }
2466 
2467     /**
2468      * Returns the {@code onwebkitanimationstart} event handler.
2469      * @return the {@code onwebkitanimationstart} event handler
2470      */
2471     @JsxGetter({CHROME, EDGE})
2472     public Function getOnwebkitanimationstart() {
2473         return getEventHandler(Event.TYPE_WEBANIMATIONSTART);
2474     }
2475 
2476     /**
2477      * Sets the {@code onwebkitanimationstart} event handler.
2478      * @param onwebkitanimationstart the {@code onwebkitanimationstart} event handler
2479      */
2480     @JsxSetter({CHROME, EDGE})
2481     public void setOnwebkitanimationstart(final Object onwebkitanimationstart) {
2482         setHandlerForJavaScript(Event.TYPE_WEBANIMATIONSTART, onwebkitanimationstart);
2483     }
2484 
2485     /**
2486      * Returns the {@code onkeyup} event handler.
2487      * @return the {@code onkeyup} event handler
2488      */
2489     @JsxGetter
2490     public Function getOnkeyup() {
2491         return getEventHandler(Event.TYPE_KEY_UP);
2492     }
2493 
2494     /**
2495      * Sets the {@code onkeyup} event handler.
2496      * @param onkeyup the {@code onkeyup} event handler
2497      */
2498     @JsxSetter
2499     public void setOnkeyup(final Object onkeyup) {
2500         setHandlerForJavaScript(Event.TYPE_KEY_UP, onkeyup);
2501     }
2502 
2503     /**
2504      * Returns the {@code onreset} event handler.
2505      * @return the {@code onreset} event handler
2506      */
2507     @JsxGetter
2508     public Function getOnreset() {
2509         return getEventHandler(Event.TYPE_RESET);
2510     }
2511 
2512     /**
2513      * Sets the {@code onreset} event handler.
2514      * @param onreset the {@code onreset} event handler
2515      */
2516     @JsxSetter
2517     public void setOnreset(final Object onreset) {
2518         setHandlerForJavaScript(Event.TYPE_RESET, onreset);
2519     }
2520 
2521     /**
2522      * Returns the {@code onkeypress} event handler.
2523      * @return the {@code onkeypress} event handler
2524      */
2525     @JsxGetter
2526     public Function getOnkeypress() {
2527         return getEventHandler(Event.TYPE_KEY_PRESS);
2528     }
2529 
2530     /**
2531      * Sets the {@code onkeypress} event handler.
2532      * @param onkeypress the {@code onkeypress} event handler
2533      */
2534     @JsxSetter
2535     public void setOnkeypress(final Object onkeypress) {
2536         setHandlerForJavaScript(Event.TYPE_KEY_PRESS, onkeypress);
2537     }
2538 
2539     /**
2540      * Returns the {@code ondrag} event handler.
2541      * @return the {@code ondrag} event handler
2542      */
2543     @JsxGetter
2544     public Function getOndrag() {
2545         return getEventHandler(Event.TYPE_DRAG);
2546     }
2547 
2548     /**
2549      * Sets the {@code ondrag} event handler.
2550      * @param ondrag the {@code ondrag} event handler
2551      */
2552     @JsxSetter
2553     public void setOndrag(final Object ondrag) {
2554         setHandlerForJavaScript(Event.TYPE_DRAG, ondrag);
2555     }
2556 
2557     /**
2558      * Returns the {@code onseeked} event handler.
2559      * @return the {@code onseeked} event handler
2560      */
2561     @JsxGetter
2562     public Function getOnseeked() {
2563         return getEventHandler(Event.TYPE_SEEKED);
2564     }
2565 
2566     /**
2567      * Sets the {@code onseeked} event handler.
2568      * @param onseeked the {@code onseeked} event handler
2569      */
2570     @JsxSetter
2571     public void setOnseeked(final Object onseeked) {
2572         setHandlerForJavaScript(Event.TYPE_SEEKED, onseeked);
2573     }
2574 
2575     /**
2576      * Returns the {@code onoffline} event handler.
2577      * @return the {@code onoffline} event handler
2578      */
2579     @JsxGetter
2580     public Function getOnoffline() {
2581         return getEventHandler(Event.TYPE_OFFLINE);
2582     }
2583 
2584     /**
2585      * Sets the {@code onoffline} event handler.
2586      * @param onoffline the {@code onoffline} event handler
2587      */
2588     @JsxSetter
2589     public void setOnoffline(final Object onoffline) {
2590         setHandlerForJavaScript(Event.TYPE_OFFLINE, onoffline);
2591     }
2592 
2593     /**
2594      * Returns the {@code ondeviceorientation} event handler.
2595      * @return the {@code ondeviceorientation} event handler
2596      */
2597     @JsxGetter
2598     public Function getOndeviceorientation() {
2599         return getEventHandler(Event.TYPE_DEVICEORIENTATION);
2600     }
2601 
2602     /**
2603      * Sets the {@code ondeviceorientation} event handler.
2604      * @param ondeviceorientation the {@code ondeviceorientation} event handler
2605      */
2606     @JsxSetter
2607     public void setOndeviceorientation(final Object ondeviceorientation) {
2608         setHandlerForJavaScript(Event.TYPE_DEVICEORIENTATION, ondeviceorientation);
2609     }
2610 
2611     /**
2612      * Returns the {@code ontoggle} event handler.
2613      * @return the {@code ontoggle} event handler
2614      */
2615     @JsxGetter({CHROME, EDGE})
2616     public Function getOntoggle() {
2617         return getEventHandler(Event.TYPE_TOGGLE);
2618     }
2619 
2620     /**
2621      * Sets the {@code ontoggle} event handler.
2622      * @param ontoggle the {@code ontoggle} event handler
2623      */
2624     @JsxSetter({CHROME, EDGE})
2625     public void setOntoggle(final Object ontoggle) {
2626         setHandlerForJavaScript(Event.TYPE_TOGGLE, ontoggle);
2627     }
2628 
2629     /**
2630      * Returns the {@code onplay} event handler.
2631      * @return the {@code onplay} event handler
2632      */
2633     @JsxGetter
2634     public Function getOnplay() {
2635         return getEventHandler(Event.TYPE_PLAY);
2636     }
2637 
2638     /**
2639      * Sets the {@code onplay} event handler.
2640      * @param onplay the {@code onplay} event handler
2641      */
2642     @JsxSetter
2643     public void setOnplay(final Object onplay) {
2644         setHandlerForJavaScript(Event.TYPE_PLAY, onplay);
2645     }
2646 
2647     /**
2648      * Returns the {@code oncontextmenu} event handler.
2649      * @return the {@code oncontextmenu} event handler
2650      */
2651     @JsxGetter
2652     public Function getOncontextmenu() {
2653         return getEventHandler(MouseEvent.TYPE_CONTEXT_MENU);
2654     }
2655 
2656     /**
2657      * Sets the {@code oncontextmenu} event handler.
2658      * @param oncontextmenu the {@code oncontextmenu} event handler
2659      */
2660     @JsxSetter
2661     public void setOncontextmenu(final Object oncontextmenu) {
2662         setHandlerForJavaScript(MouseEvent.TYPE_CONTEXT_MENU, oncontextmenu);
2663     }
2664 
2665     /**
2666      * Returns the {@code onmousemove} event handler.
2667      * @return the {@code onmousemove} event handler
2668      */
2669     @JsxGetter
2670     public Function getOnmousemove() {
2671         return getEventHandler(MouseEvent.TYPE_MOUSE_MOVE);
2672     }
2673 
2674     /**
2675      * Sets the {@code onmousemove} event handler.
2676      * @param onmousemove the {@code onmousemove} event handler
2677      */
2678     @JsxSetter
2679     public void setOnmousemove(final Object onmousemove) {
2680         setHandlerForJavaScript(MouseEvent.TYPE_MOUSE_MOVE, onmousemove);
2681     }
2682 
2683     /**
2684      * Returns the {@code onpointermove} event handler.
2685      * @return the {@code onpointermove} event handler
2686      */
2687     @JsxGetter({CHROME, EDGE})
2688     public Function getOnpointermove() {
2689         return getEventHandler(Event.TYPE_POINTERMOVE);
2690     }
2691 
2692     /**
2693      * Sets the {@code onpointermove} event handler.
2694      * @param onpointermove the {@code onpointermove} event handler
2695      */
2696     @JsxSetter({CHROME, EDGE})
2697     public void setOnpointermove(final Object onpointermove) {
2698         setHandlerForJavaScript(Event.TYPE_POINTERMOVE, onpointermove);
2699     }
2700 
2701     /**
2702      * Returns the {@code onmouseover} event handler.
2703      * @return the {@code onmouseover} event handler
2704      */
2705     @JsxGetter
2706     public Function getOnmouseover() {
2707         return getEventHandler(MouseEvent.TYPE_MOUSE_OVER);
2708     }
2709 
2710     /**
2711      * Sets the {@code onmouseover} event handler.
2712      * @param onmouseover the {@code onmouseover} event handler
2713      */
2714     @JsxSetter
2715     public void setOnmouseover(final Object onmouseover) {
2716         setHandlerForJavaScript(MouseEvent.TYPE_MOUSE_OVER, onmouseover);
2717     }
2718 
2719     /**
2720      * Returns the {@code onlostpointercapture} event handler.
2721      * @return the {@code onlostpointercapture} event handler
2722      */
2723     @JsxGetter({CHROME, EDGE})
2724     public Function getOnlostpointercapture() {
2725         return getEventHandler(Event.TYPE_LOSTPOINTERCAPTURE);
2726     }
2727 
2728     /**
2729      * Sets the {@code onlostpointercapture} event handler.
2730      * @param onlostpointercapture the {@code onlostpointercapture} event handler
2731      */
2732     @JsxSetter({CHROME, EDGE})
2733     public void setOnlostpointercapture(final Object onlostpointercapture) {
2734         setHandlerForJavaScript(Event.TYPE_LOSTPOINTERCAPTURE, onlostpointercapture);
2735     }
2736 
2737     /**
2738      * Returns the {@code onpointerover} event handler.
2739      * @return the {@code onpointerover} event handler
2740      */
2741     @JsxGetter({CHROME, EDGE})
2742     public Function getOnpointerover() {
2743         return getEventHandler(Event.TYPE_POINTEROVER);
2744     }
2745 
2746     /**
2747      * Sets the {@code onpointerover} event handler.
2748      * @param onpointerover the {@code onpointerover} event handler
2749      */
2750     @JsxSetter({CHROME, EDGE})
2751     public void setOnpointerover(final Object onpointerover) {
2752         setHandlerForJavaScript(Event.TYPE_POINTEROVER, onpointerover);
2753     }
2754 
2755     /**
2756      * Returns the {@code onclose} event handler.
2757      * @return the {@code onclose} event handler
2758      */
2759     @JsxGetter({CHROME, EDGE})
2760     public Function getOnclose() {
2761         return getEventHandler(Event.TYPE_CLOSE);
2762     }
2763 
2764     /**
2765      * Sets the {@code onclose} event handler.
2766      * @param onclose the {@code onclose} event handler
2767      */
2768     @JsxSetter({CHROME, EDGE})
2769     public void setOnclose(final Object onclose) {
2770         setHandlerForJavaScript(Event.TYPE_CLOSE, onclose);
2771     }
2772 
2773     /**
2774      * Returns the {@code onanimationend} event handler.
2775      * @return the {@code onanimationend} event handler
2776      */
2777     @JsxGetter
2778     public Function getOnanimationend() {
2779         return getEventHandler(Event.TYPE_ANIMATIONEND);
2780     }
2781 
2782     /**
2783      * Sets the {@code onanimationend} event handler.
2784      * @param onanimationend the {@code onanimationend} event handler
2785      */
2786     @JsxSetter
2787     public void setOnanimationend(final Object onanimationend) {
2788         setHandlerForJavaScript(Event.TYPE_ANIMATIONEND, onanimationend);
2789     }
2790 
2791     /**
2792      * Returns the {@code ondragenter} event handler.
2793      * @return the {@code ondragenter} event handler
2794      */
2795     @JsxGetter
2796     public Function getOndragenter() {
2797         return getEventHandler(Event.TYPE_DRAGENTER);
2798     }
2799 
2800     /**
2801      * Sets the {@code ondragenter} event handler.
2802      * @param ondragenter the {@code ondragenter} event handler
2803      */
2804     @JsxSetter
2805     public void setOndragenter(final Object ondragenter) {
2806         setHandlerForJavaScript(Event.TYPE_DRAGENTER, ondragenter);
2807     }
2808 
2809     /**
2810      * Returns the {@code onafterprint} event handler.
2811      * @return the {@code onafterprint} event handler
2812      */
2813     @JsxGetter({FF, FF_ESR})
2814     public Function getOnafterprint() {
2815         return getEventHandler(Event.TYPE_AFTERPRINT);
2816     }
2817 
2818     /**
2819      * Sets the {@code onafterprint} event handler.
2820      * @param onafterprint the {@code onafterprint} event handler
2821      */
2822     @JsxSetter({FF, FF_ESR})
2823     public void setOnafterprint(final Object onafterprint) {
2824         setHandlerForJavaScript(Event.TYPE_AFTERPRINT, onafterprint);
2825     }
2826 
2827     /**
2828      * Returns the {@code onmozfullscreenerror} event handler.
2829      * @return the {@code onmozfullscreenerror} event handler
2830      */
2831     @JsxGetter({FF, FF_ESR})
2832     public Function getOnmozfullscreenerror() {
2833         return getEventHandler(Event.TYPE_MOZFULLSCREENERROR);
2834     }
2835 
2836     /**
2837      * Sets the {@code onmozfullscreenerror} event handler.
2838      * @param onmozfullscreenerror the {@code onmozfullscreenerror} event handler
2839      */
2840     @JsxSetter({FF, FF_ESR})
2841     public void setOnmozfullscreenerror(final Object onmozfullscreenerror) {
2842         setHandlerForJavaScript(Event.TYPE_MOZFULLSCREENERROR, onmozfullscreenerror);
2843     }
2844 
2845     /**
2846      * Returns the {@code onmouseleave} event handler.
2847      * @return the {@code onmouseleave} event handler
2848      */
2849     @JsxGetter
2850     public Function getOnmouseleave() {
2851         return getEventHandler(Event.TYPE_MOUSELEAVE);
2852     }
2853 
2854     /**
2855      * Sets the {@code onmouseleave} event handler.
2856      * @param onmouseleave the {@code onmouseleave} event handler
2857      */
2858     @JsxSetter
2859     public void setOnmouseleave(final Object onmouseleave) {
2860         setHandlerForJavaScript(Event.TYPE_MOUSELEAVE, onmouseleave);
2861     }
2862 
2863     /**
2864      * Returns the {@code onmousewheel} event handler.
2865      * @return the {@code onmousewheel} event handler
2866      */
2867     @JsxGetter({CHROME, EDGE})
2868     public Function getOnmousewheel() {
2869         return getEventHandler(Event.TYPE_MOUSEWHEEL);
2870     }
2871 
2872     /**
2873      * Sets the {@code onmousewheel} event handler.
2874      * @param onmousewheel the {@code onmousewheel} event handler
2875      */
2876     @JsxSetter({CHROME, EDGE})
2877     public void setOnmousewheel(final Object onmousewheel) {
2878         setHandlerForJavaScript(Event.TYPE_MOUSEWHEEL, onmousewheel);
2879     }
2880 
2881     /**
2882      * Returns the {@code onseeking} event handler.
2883      * @return the {@code onseeking} event handler
2884      */
2885     @JsxGetter
2886     public Function getOnseeking() {
2887         return getEventHandler(Event.TYPE_SEEKING);
2888     }
2889 
2890     /**
2891      * Sets the {@code onseeking} event handler.
2892      * @param onseeking the {@code onseeking} event handler
2893      */
2894     @JsxSetter
2895     public void setOnseeking(final Object onseeking) {
2896         setHandlerForJavaScript(Event.TYPE_SEEKING, onseeking);
2897     }
2898 
2899     /**
2900      * Returns the {@code oncuechange} event handler.
2901      * @return the {@code oncuechange} event handler
2902      */
2903     @JsxGetter({CHROME, EDGE})
2904     public Function getOncuechange() {
2905         return getEventHandler(Event.TYPE_CUECHANGE);
2906     }
2907 
2908     /**
2909      * Sets the {@code oncuechange} event handler.
2910      * @param oncuechange the {@code oncuechange} event handler
2911      */
2912     @JsxSetter({CHROME, EDGE})
2913     public void setOncuechange(final Object oncuechange) {
2914         setHandlerForJavaScript(Event.TYPE_CUECHANGE, oncuechange);
2915     }
2916 
2917     /**
2918      * Returns the {@code onpageshow} event handler.
2919      * @return the {@code onpageshow} event handler
2920      */
2921     @JsxGetter
2922     public Function getOnpageshow() {
2923         return getEventHandler(Event.TYPE_PAGESHOW);
2924     }
2925 
2926     /**
2927      * Sets the {@code onpageshow} event handler.
2928      * @param onpageshow the {@code onpageshow} event handler
2929      */
2930     @JsxSetter
2931     public void setOnpageshow(final Object onpageshow) {
2932         setHandlerForJavaScript(Event.TYPE_PAGESHOW, onpageshow);
2933     }
2934 
2935     /**
2936      * Returns the {@code onmozfullscreenchange} event handler.
2937      * @return the {@code onmozfullscreenchange} event handler
2938      */
2939     @JsxGetter({FF, FF_ESR})
2940     public Function getOnmozfullscreenchange() {
2941         return getEventHandler(Event.TYPE_MOZFULLSCREENCHANGE);
2942     }
2943 
2944     /**
2945      * Sets the {@code onmozfullscreenchange} event handler.
2946      * @param onmozfullscreenchange the {@code onmozfullscreenchange} event handler
2947      */
2948     @JsxSetter({FF, FF_ESR})
2949     public void setOnmozfullscreenchange(final Object onmozfullscreenchange) {
2950         setHandlerForJavaScript(Event.TYPE_MOZFULLSCREENCHANGE, onmozfullscreenchange);
2951     }
2952 
2953     /**
2954      * Returns the {@code ondurationchange} event handler.
2955      * @return the {@code ondurationchange} event handler
2956      */
2957     @JsxGetter
2958     public Function getOndurationchange() {
2959         return getEventHandler(Event.TYPE_DURATIONCHANGE);
2960     }
2961 
2962     /**
2963      * Sets the {@code ondurationchange} event handler.
2964      * @param ondurationchange the {@code ondurationchange} event handler
2965      */
2966     @JsxSetter
2967     public void setOndurationchange(final Object ondurationchange) {
2968         setHandlerForJavaScript(Event.TYPE_DURATIONCHANGE, ondurationchange);
2969     }
2970 
2971     /**
2972      * Returns the {@code onplaying} event handler.
2973      * @return the {@code onplaying} event handler
2974      */
2975     @JsxGetter
2976     public Function getOnplaying() {
2977         return getEventHandler(Event.TYPE_PLAYING);
2978     }
2979 
2980     /**
2981      * Sets the {@code onplaying} event handler.
2982      * @param onplaying the {@code onplaying} event handler
2983      */
2984     @JsxSetter
2985     public void setOnplaying(final Object onplaying) {
2986         setHandlerForJavaScript(Event.TYPE_PLAYING, onplaying);
2987     }
2988 
2989     /**
2990      * Returns the {@code onended} event handler.
2991      * @return the {@code onended} event handler
2992      */
2993     @JsxGetter
2994     public Function getOnended() {
2995         return getEventHandler(Event.TYPE_ENDED);
2996     }
2997 
2998     /**
2999      * Sets the {@code onended} event handler.
3000      * @param onended the {@code onended} event handler
3001      */
3002     @JsxSetter
3003     public void setOnended(final Object onended) {
3004         setHandlerForJavaScript(Event.TYPE_ENDED, onended);
3005     }
3006 
3007     /**
3008      * Returns the {@code onloadeddata} event handler.
3009      * @return the {@code onloadeddata} event handler
3010      */
3011     @JsxGetter
3012     public Function getOnloadeddata() {
3013         return getEventHandler(Event.TYPE_LOADEDDATA);
3014     }
3015 
3016     /**
3017      * Sets the {@code onloadeddata} event handler.
3018      * @param onloadeddata the {@code onloadeddata} event handler
3019      */
3020     @JsxSetter
3021     public void setOnloadeddata(final Object onloadeddata) {
3022         setHandlerForJavaScript(Event.TYPE_LOADEDDATA, onloadeddata);
3023     }
3024 
3025     /**
3026      * Returns the {@code onunhandledrejection} event handler.
3027      * @return the {@code onunhandledrejection} event handler
3028      */
3029     @JsxGetter({CHROME, EDGE})
3030     public Function getOnunhandledrejection() {
3031         return getEventHandler(Event.TYPE_UNHANDLEDREJECTION);
3032     }
3033 
3034     /**
3035      * Sets the {@code onunhandledrejection} event handler.
3036      * @param onunhandledrejection the {@code onunhandledrejection} event handler
3037      */
3038     @JsxSetter({CHROME, EDGE})
3039     public void setOnunhandledrejection(final Object onunhandledrejection) {
3040         setHandlerForJavaScript(Event.TYPE_UNHANDLEDREJECTION, onunhandledrejection);
3041     }
3042 
3043     /**
3044      * Returns the {@code onmouseout} event handler.
3045      * @return the {@code onmouseout} event handler
3046      */
3047     @JsxGetter
3048     public Function getOnmouseout() {
3049         return getEventHandler(MouseEvent.TYPE_MOUSE_OUT);
3050     }
3051 
3052     /**
3053      * Sets the {@code onmouseout} event handler.
3054      * @param onmouseout the {@code onmouseout} event handler
3055      */
3056     @JsxSetter
3057     public void setOnmouseout(final Object onmouseout) {
3058         setHandlerForJavaScript(MouseEvent.TYPE_MOUSE_OUT, onmouseout);
3059     }
3060 
3061     /**
3062      * Returns the {@code onsuspend} event handler.
3063      * @return the {@code onsuspend} event handler
3064      */
3065     @JsxGetter
3066     public Function getOnsuspend() {
3067         return getEventHandler(Event.TYPE_SUSPEND);
3068     }
3069 
3070     /**
3071      * Sets the {@code onsuspend} event handler.
3072      * @param onsuspend the {@code onsuspend} event handler
3073      */
3074     @JsxSetter
3075     public void setOnsuspend(final Object onsuspend) {
3076         setHandlerForJavaScript(Event.TYPE_SUSPEND, onsuspend);
3077     }
3078 
3079     /**
3080      * Returns the {@code onwaiting} event handler.
3081      * @return the {@code onwaiting} event handler
3082      */
3083     @JsxGetter
3084     public Function getOnwaiting() {
3085         return getEventHandler(Event.TYPE_WAITING);
3086     }
3087 
3088     /**
3089      * Sets the {@code onwaiting} event handler.
3090      * @param onwaiting the {@code onwaiting} event handler
3091      */
3092     @JsxSetter
3093     public void setOnwaiting(final Object onwaiting) {
3094         setHandlerForJavaScript(Event.TYPE_WAITING, onwaiting);
3095     }
3096 
3097     /**
3098      * Returns the {@code oncanplay} event handler.
3099      * @return the {@code oncanplay} event handler
3100      */
3101     @JsxGetter
3102     public Function getOncanplay() {
3103         return getEventHandler(Event.TYPE_CANPLAY);
3104     }
3105 
3106     /**
3107      * Sets the {@code oncanplay} event handler.
3108      * @param oncanplay the {@code oncanplay} event handler
3109      */
3110     @JsxSetter
3111     public void setOncanplay(final Object oncanplay) {
3112         setHandlerForJavaScript(Event.TYPE_CANPLAY, oncanplay);
3113     }
3114 
3115     /**
3116      * Returns the {@code onmousedown} event handler.
3117      * @return the {@code onmousedown} event handler
3118      */
3119     @JsxGetter
3120     public Function getOnmousedown() {
3121         return getEventHandler(MouseEvent.TYPE_MOUSE_DOWN);
3122     }
3123 
3124     /**
3125      * Sets the {@code onmousedown} event handler.
3126      * @param onmousedown the {@code onmousedown} event handler
3127      */
3128     @JsxSetter
3129     public void setOnmousedown(final Object onmousedown) {
3130         setHandlerForJavaScript(MouseEvent.TYPE_MOUSE_DOWN, onmousedown);
3131     }
3132 
3133     /**
3134      * Returns the {@code onlanguagechange} event handler.
3135      * @return the {@code onlanguagechange} event handler
3136      */
3137     @JsxGetter
3138     public Function getOnlanguagechange() {
3139         return getEventHandler(Event.TYPE_LANGUAGECHANGE);
3140     }
3141 
3142     /**
3143      * Sets the {@code onlanguagechange} event handler.
3144      * @param onlanguagechange the {@code onlanguagechange} event handler
3145      */
3146     @JsxSetter
3147     public void setOnlanguagechange(final Object onlanguagechange) {
3148         setHandlerForJavaScript(Event.TYPE_LANGUAGECHANGE, onlanguagechange);
3149     }
3150 
3151     /**
3152      * Returns the {@code onemptied} event handler.
3153      * @return the {@code onemptied} event handler
3154      */
3155     @JsxGetter
3156     public Function getOnemptied() {
3157         return getEventHandler(Event.TYPE_EMPTIED);
3158     }
3159 
3160     /**
3161      * Sets the {@code onemptied} event handler.
3162      * @param onemptied the {@code onemptied} event handler
3163      */
3164     @JsxSetter
3165     public void setOnemptied(final Object onemptied) {
3166         setHandlerForJavaScript(Event.TYPE_EMPTIED, onemptied);
3167     }
3168 
3169     /**
3170      * Returns the {@code onrejectionhandled} event handler.
3171      * @return the {@code onrejectionhandled} event handler
3172      */
3173     @JsxGetter({CHROME, EDGE})
3174     public Function getOnrejectionhandled() {
3175         return getEventHandler(Event.TYPE_REJECTIONHANDLED);
3176     }
3177 
3178     /**
3179      * Sets the {@code onrejectionhandled} event handler.
3180      * @param onrejectionhandled the {@code onrejectionhandled} event handler
3181      */
3182     @JsxSetter({CHROME, EDGE})
3183     public void setOnrejectionhandled(final Object onrejectionhandled) {
3184         setHandlerForJavaScript(Event.TYPE_REJECTIONHANDLED, onrejectionhandled);
3185     }
3186 
3187     /**
3188      * Returns the {@code onpointercancel} event handler.
3189      * @return the {@code onpointercancel} event handler
3190      */
3191     @JsxGetter({CHROME, EDGE})
3192     public Function getOnpointercancel() {
3193         return getEventHandler(Event.TYPE_POINTERCANCEL);
3194     }
3195 
3196     /**
3197      * Sets the {@code onpointercancel} event handler.
3198      * @param onpointercancel the {@code onpointercancel} event handler
3199      */
3200     @JsxSetter({CHROME, EDGE})
3201     public void setOnpointercancel(final Object onpointercancel) {
3202         setHandlerForJavaScript(Event.TYPE_POINTERCANCEL, onpointercancel);
3203     }
3204 
3205     /**
3206      * Returns the {@code onresize} event handler.
3207      * @return the {@code onresize} event handler
3208      */
3209     @JsxGetter
3210     public Function getOnresize() {
3211         return getEventHandler(Event.TYPE_RESIZE);
3212     }
3213 
3214     /**
3215      * Sets the {@code onresize} event handler.
3216      * @param onresize the {@code onresize} event handler
3217      */
3218     @JsxSetter
3219     public void setOnresize(final Object onresize) {
3220         setHandlerForJavaScript(Event.TYPE_RESIZE, onresize);
3221     }
3222 
3223     /**
3224      * Returns the {@code onpause} event handler.
3225      * @return the {@code onpause} event handler
3226      */
3227     @JsxGetter
3228     public Function getOnpause() {
3229         return getEventHandler(Event.TYPE_PAUSE);
3230     }
3231 
3232     /**
3233      * Sets the {@code onpause} event handler.
3234      * @param onpause the {@code onpause} event handler
3235      */
3236     @JsxSetter
3237     public void setOnpause(final Object onpause) {
3238         setHandlerForJavaScript(Event.TYPE_PAUSE, onpause);
3239     }
3240 
3241     /**
3242      * Returns the {@code onloadstart} event handler.
3243      * @return the {@code onloadstart} event handler
3244      */
3245     @JsxGetter
3246     public Function getOnloadstart() {
3247         return getEventHandler(Event.TYPE_LOAD_START);
3248     }
3249 
3250     /**
3251      * Sets the {@code onloadstart} event handler.
3252      * @param onloadstart the {@code onloadstart} event handler
3253      */
3254     @JsxSetter
3255     public void setOnloadstart(final Object onloadstart) {
3256         setHandlerForJavaScript(Event.TYPE_LOAD_START, onloadstart);
3257     }
3258 
3259     /**
3260      * Returns the {@code onprogress} event handler.
3261      * @return the {@code onprogress} event handler
3262      */
3263     @JsxGetter
3264     public Function getOnprogress() {
3265         return getEventHandler(Event.TYPE_PROGRESS);
3266     }
3267 
3268     /**
3269      * Sets the {@code onprogress} event handler.
3270      * @param onprogress the {@code onprogress} event handler
3271      */
3272     @JsxSetter
3273     public void setOnprogress(final Object onprogress) {
3274         setHandlerForJavaScript(Event.TYPE_PROGRESS, onprogress);
3275     }
3276 
3277     /**
3278      * Returns the {@code onpointerup} event handler.
3279      * @return the {@code onpointerup} event handler
3280      */
3281     @JsxGetter({CHROME, EDGE})
3282     public Function getOnpointerup() {
3283         return getEventHandler(Event.TYPE_POINTERUP);
3284     }
3285 
3286     /**
3287      * Sets the {@code onpointerup} event handler.
3288      * @param onpointerup the {@code onpointerup} event handler
3289      */
3290     @JsxSetter({CHROME, EDGE})
3291     public void setOnpointerup(final Object onpointerup) {
3292         setHandlerForJavaScript(Event.TYPE_POINTERUP, onpointerup);
3293     }
3294 
3295     /**
3296      * Returns the {@code onwheel} event handler.
3297      * @return the {@code onwheel} event handler
3298      */
3299     @JsxGetter
3300     public Function getOnwheel() {
3301         return getEventHandler(Event.TYPE_WHEEL);
3302     }
3303 
3304     /**
3305      * Sets the {@code onwheel} event handler.
3306      * @param onwheel the {@code onwheel} event handler
3307      */
3308     @JsxSetter
3309     public void setOnwheel(final Object onwheel) {
3310         setHandlerForJavaScript(Event.TYPE_WHEEL, onwheel);
3311     }
3312 
3313     /**
3314      * Returns the {@code onpointerleave} event handler.
3315      * @return the {@code onpointerleave} event handler
3316      */
3317     @JsxGetter({CHROME, EDGE})
3318     public Function getOnpointerleave() {
3319         return getEventHandler(Event.TYPE_POINTERLEAVE);
3320     }
3321 
3322     /**
3323      * Sets the {@code onpointerleave} event handler.
3324      * @param onpointerleave the {@code onpointerleave} event handler
3325      */
3326     @JsxSetter({CHROME, EDGE})
3327     public void setOnpointerleave(final Object onpointerleave) {
3328         setHandlerForJavaScript(Event.TYPE_POINTERLEAVE, onpointerleave);
3329     }
3330 
3331     /**
3332      * Returns the {@code onbeforeprint} event handler.
3333      * @return the {@code onbeforeprint} event handler
3334      */
3335     @JsxGetter({FF, FF_ESR})
3336     public Function getOnbeforeprint() {
3337         return getEventHandler(Event.TYPE_BEFOREPRINT);
3338     }
3339 
3340     /**
3341      * Sets the {@code onbeforeprint} event handler.
3342      * @param onbeforeprint the {@code onbeforeprint} event handler
3343      */
3344     @JsxSetter({FF, FF_ESR})
3345     public void setOnbeforeprint(final Object onbeforeprint) {
3346         setHandlerForJavaScript(Event.TYPE_BEFOREPRINT, onbeforeprint);
3347     }
3348 
3349     /**
3350      * Returns the {@code onstorage} event handler.
3351      * @return the {@code onstorage} event handler
3352      */
3353     @JsxGetter
3354     public Function getOnstorage() {
3355         return getEventHandler(Event.TYPE_STORAGE);
3356     }
3357 
3358     /**
3359      * Sets the {@code onstorage} event handler.
3360      * @param onstorage the {@code onstorage} event handler
3361      */
3362     @JsxSetter
3363     public void setOnstorage(final Object onstorage) {
3364         setHandlerForJavaScript(Event.TYPE_STORAGE, onstorage);
3365     }
3366 
3367     /**
3368      * Returns the {@code onanimationstart} event handler.
3369      * @return the {@code onanimationstart} event handler
3370      */
3371     @JsxGetter
3372     public Function getOnanimationstart() {
3373         return getEventHandler(Event.TYPE_ANIMATIONSTART);
3374     }
3375 
3376     /**
3377      * Sets the {@code onanimationstart} event handler.
3378      * @param onanimationstart the {@code onanimationstart} event handler
3379      */
3380     @JsxSetter
3381     public void setOnanimationstart(final Object onanimationstart) {
3382         setHandlerForJavaScript(Event.TYPE_ANIMATIONSTART, onanimationstart);
3383     }
3384 
3385     /**
3386      * Returns the {@code ontimeupdate} event handler.
3387      * @return the {@code ontimeupdate} event handler
3388      */
3389     @JsxGetter
3390     public Function getOntimeupdate() {
3391         return getEventHandler(Event.TYPE_TIMEUPDATE);
3392     }
3393 
3394     /**
3395      * Sets the {@code ontimeupdate} event handler.
3396      * @param ontimeupdate the {@code ontimeupdate} event handler
3397      */
3398     @JsxSetter
3399     public void setOntimeupdate(final Object ontimeupdate) {
3400         setHandlerForJavaScript(Event.TYPE_TIMEUPDATE, ontimeupdate);
3401     }
3402 
3403     /**
3404      * Returns the {@code onpagehide} event handler.
3405      * @return the {@code onpagehide} event handler
3406      */
3407     @JsxGetter
3408     public Function getOnpagehide() {
3409         return getEventHandler(Event.TYPE_PAGEHIDE);
3410     }
3411 
3412     /**
3413      * Sets the {@code onpagehide} event handler.
3414      * @param onpagehide the {@code onpagehide} event handler
3415      */
3416     @JsxSetter
3417     public void setOnpagehide(final Object onpagehide) {
3418         setHandlerForJavaScript(Event.TYPE_PAGEHIDE, onpagehide);
3419     }
3420 
3421     /**
3422      * Returns the {@code onwebkitanimationiteration} event handler.
3423      * @return the {@code onwebkitanimationiteration} event handler
3424      */
3425     @JsxGetter({CHROME, EDGE})
3426     public Function getOnwebkitanimationiteration() {
3427         return getEventHandler(Event.TYPE_WEBKITANIMATIONITERATION);
3428     }
3429 
3430     /**
3431      * Sets the {@code onwebkitanimationiteration} event handler.
3432      * @param onwebkitanimationiteration the {@code onwebkitanimationiteration} event handler
3433      */
3434     @JsxSetter({CHROME, EDGE})
3435     public void setOnwebkitanimationiteration(final Object onwebkitanimationiteration) {
3436         setHandlerForJavaScript(Event.TYPE_WEBKITANIMATIONITERATION, onwebkitanimationiteration);
3437     }
3438 
3439     /**
3440      * Returns the {@code onabort} event handler.
3441      * @return the {@code onabort} event handler
3442      */
3443     @JsxGetter
3444     public Function getOnabort() {
3445         return getEventHandler(Event.TYPE_ABORT);
3446     }
3447 
3448     /**
3449      * Sets the {@code onabort} event handler.
3450      * @param onabort the {@code onabort} event handler
3451      */
3452     @JsxSetter
3453     public void setOnabort(final Object onabort) {
3454         setHandlerForJavaScript(Event.TYPE_ABORT, onabort);
3455     }
3456 
3457     /**
3458      * Returns the {@code onloadedmetadata} event handler.
3459      * @return the {@code onloadedmetadata} event handler
3460      */
3461     @JsxGetter
3462     public Function getOnloadedmetadata() {
3463         return getEventHandler(Event.TYPE_LOADEDMETADATA);
3464     }
3465 
3466     /**
3467      * Sets the {@code onloadedmetadata} event handler.
3468      * @param onloadedmetadata the {@code onloadedmetadata} event handler
3469      */
3470     @JsxSetter
3471     public void setOnloadedmetadata(final Object onloadedmetadata) {
3472         setHandlerForJavaScript(Event.TYPE_LOADEDMETADATA, onloadedmetadata);
3473     }
3474 
3475     /**
3476      * Returns the {@code onmouseup} event handler.
3477      * @return the {@code onmouseup} event handler
3478      */
3479     @JsxGetter
3480     public Function getOnmouseup() {
3481         return getEventHandler(MouseEvent.TYPE_MOUSE_UP);
3482     }
3483 
3484     /**
3485      * Sets the {@code onmouseup} event handler.
3486      * @param onmouseup the {@code onmouseup} event handler
3487      */
3488     @JsxSetter
3489     public void setOnmouseup(final Object onmouseup) {
3490         setHandlerForJavaScript(MouseEvent.TYPE_MOUSE_UP, onmouseup);
3491     }
3492 
3493     /**
3494      * Returns the {@code ondragover} event handler.
3495      * @return the {@code ondragover} event handler
3496      */
3497     @JsxGetter
3498     public Function getOndragover() {
3499         return getEventHandler(Event.TYPE_DRAGOVER);
3500     }
3501 
3502     /**
3503      * Sets the {@code ondragover} event handler.
3504      * @param ondragover the {@code ondragover} event handler
3505      */
3506     @JsxSetter
3507     public void setOndragover(final Object ondragover) {
3508         setHandlerForJavaScript(Event.TYPE_DRAGOVER, ondragover);
3509     }
3510 
3511     /**
3512      * Returns the {@code ononline} event handler.
3513      * @return the {@code ononline} event handler
3514      */
3515     @JsxGetter
3516     public Function getOnonline() {
3517         return getEventHandler(Event.TYPE_ONLINE);
3518     }
3519 
3520     /**
3521      * Sets the {@code ononline} event handler.
3522      * @param ononline the {@code ononline} event handler
3523      */
3524     @JsxSetter
3525     public void setOnonline(final Object ononline) {
3526         setHandlerForJavaScript(Event.TYPE_ONLINE, ononline);
3527     }
3528 
3529     /**
3530      * Returns the {@code onsearch} event handler.
3531      * @return the {@code onsearch} event handler
3532      */
3533     @JsxGetter({CHROME, EDGE})
3534     public Function getOnsearch() {
3535         return getEventHandler(Event.TYPE_SEARCH);
3536     }
3537 
3538     /**
3539      * Sets the {@code onsearch} event handler.
3540      * @param onsearch the {@code onsearch} event handler
3541      */
3542     @JsxSetter({CHROME, EDGE})
3543     public void setOnsearch(final Object onsearch) {
3544         setHandlerForJavaScript(Event.TYPE_SEARCH, onsearch);
3545     }
3546 
3547     /**
3548      * Returns the {@code oninput} event handler.
3549      * @return the {@code oninput} event handler
3550      */
3551     @JsxGetter
3552     public Function getOninput() {
3553         return getEventHandler(Event.TYPE_INPUT);
3554     }
3555 
3556     /**
3557      * Sets the {@code oninput} event handler.
3558      * @param oninput the {@code oninput} event handler
3559      */
3560     @JsxSetter
3561     public void setOninput(final Object oninput) {
3562         setHandlerForJavaScript(Event.TYPE_INPUT, oninput);
3563     }
3564 
3565     /**
3566      * Returns the {@code onwebkittransitionend} event handler.
3567      * @return the {@code onwebkittransitionend} event handler
3568      */
3569     @JsxGetter({CHROME, EDGE})
3570     public Function getOnwebkittransitionend() {
3571         return getEventHandler(Event.TYPE_WEBKITTRANSITIONEND);
3572     }
3573 
3574     /**
3575      * Sets the {@code onwebkittransitionend} event handler.
3576      * @param onwebkittransitionend the {@code onwebkittransitionend} event handler
3577      */
3578     @JsxSetter({CHROME, EDGE})
3579     public void setOnwebkittransitionend(final Object onwebkittransitionend) {
3580         setHandlerForJavaScript(Event.TYPE_WEBKITTRANSITIONEND, onwebkittransitionend);
3581     }
3582 
3583     /**
3584      * Returns the {@code ondevicemotion} event handler.
3585      * @return the {@code ondevicemotion} event handler
3586      */
3587     @JsxGetter
3588     public Function getOndevicemotion() {
3589         return getEventHandler(Event.TYPE_DEVICEMOTION);
3590     }
3591 
3592     /**
3593      * Sets the {@code ondevicemotion} event handler.
3594      * @param ondevicemotion the {@code ondevicemotion} event handler
3595      */
3596     @JsxSetter
3597     public void setOndevicemotion(final Object ondevicemotion) {
3598         setHandlerForJavaScript(Event.TYPE_DEVICEMOTION, ondevicemotion);
3599     }
3600 
3601     /**
3602      * Returns the {@code onstalled} event handler.
3603      * @return the {@code onstalled} event handler
3604      */
3605     @JsxGetter
3606     public Function getOnstalled() {
3607         return getEventHandler(Event.TYPE_STALLED);
3608     }
3609 
3610     /**
3611      * Sets the {@code onstalled} event handler.
3612      * @param onstalled the {@code onstalled} event handler
3613      */
3614     @JsxSetter
3615     public void setOnstalled(final Object onstalled) {
3616         setHandlerForJavaScript(Event.TYPE_STALLED, onstalled);
3617     }
3618 
3619     /**
3620      * Returns the {@code onmouseenter} event handler.
3621      * @return the {@code onmouseenter} event handler
3622      */
3623     @JsxGetter
3624     public Function getOnmouseenter() {
3625         return getEventHandler(Event.TYPE_MOUDEENTER);
3626     }
3627 
3628     /**
3629      * Sets the {@code onmouseenter} event handler.
3630      * @param onmouseenter the {@code onmouseenter} event handler
3631      */
3632     @JsxSetter
3633     public void setOnmouseenter(final Object onmouseenter) {
3634         setHandlerForJavaScript(Event.TYPE_MOUDEENTER, onmouseenter);
3635     }
3636 
3637     /**
3638      * Returns the {@code ondragleave} event handler.
3639      * @return the {@code ondragleave} event handler
3640      */
3641     @JsxGetter
3642     public Function getOndragleave() {
3643         return getEventHandler(Event.TYPE_DRAGLEAVE);
3644     }
3645 
3646     /**
3647      * Sets the {@code ondragleave} event handler.
3648      * @param ondragleave the {@code ondragleave} event handler
3649      */
3650     @JsxSetter
3651     public void setOndragleave(final Object ondragleave) {
3652         setHandlerForJavaScript(Event.TYPE_DRAGLEAVE, ondragleave);
3653     }
3654 
3655     /**
3656      * Returns the {@code onpointerdown} event handler.
3657      * @return the {@code onpointerdown} event handler
3658      */
3659     @JsxGetter({CHROME, EDGE})
3660     public Function getOnpointerdown() {
3661         return getEventHandler(Event.TYPE_POINTERDOWN);
3662     }
3663 
3664     /**
3665      * Sets the {@code onpointerdown} event handler.
3666      * @param onpointerdown the {@code onpointerdown} event handler
3667      */
3668     @JsxSetter({CHROME, EDGE})
3669     public void setOnpointerdown(final Object onpointerdown) {
3670         setHandlerForJavaScript(Event.TYPE_POINTERDOWN, onpointerdown);
3671     }
3672 
3673     /**
3674      * Returns the {@code ondrop} event handler.
3675      * @return the {@code ondrop} event handler
3676      */
3677     @JsxGetter
3678     public Function getOndrop() {
3679         return getEventHandler(Event.TYPE_DROP);
3680     }
3681 
3682     /**
3683      * Sets the {@code ondrop} event handler.
3684      * @param ondrop the {@code ondrop} event handler
3685      */
3686     @JsxSetter
3687     public void setOndrop(final Object ondrop) {
3688         setHandlerForJavaScript(Event.TYPE_DROP, ondrop);
3689     }
3690 
3691     /**
3692      * Returns the {@code onunload} event handler.
3693      * @return the {@code onunload} event handler
3694      */
3695     @JsxGetter
3696     public Function getOnunload() {
3697         return getEventHandler(Event.TYPE_UNLOAD);
3698     }
3699 
3700     /**
3701      * Sets the {@code onunload} event handler.
3702      * @param onunload the {@code onunload} event handler
3703      */
3704     @JsxSetter
3705     public void setOnunload(final Object onunload) {
3706         setHandlerForJavaScript(Event.TYPE_UNLOAD, onunload);
3707     }
3708 
3709     /**
3710      * Returns the {@code onwebkitanimationend} event handler.
3711      * @return the {@code onwebkitanimationend} event handler
3712      */
3713     @JsxGetter({CHROME, EDGE})
3714     public Function getOnwebkitanimationend() {
3715         return getEventHandler(Event.TYPE_WEBKITANIMATIONEND);
3716     }
3717 
3718     /**
3719      * Sets the {@code onwebkitanimationend} event handler.
3720      * @param onwebkitanimationend the {@code onwebkitanimationend} event handler
3721      */
3722     @JsxSetter({CHROME, EDGE})
3723     public void setOnwebkitanimationend(final Object onwebkitanimationend) {
3724         setHandlerForJavaScript(Event.TYPE_WEBKITANIMATIONEND, onwebkitanimationend);
3725     }
3726 
3727     /**
3728      * Returns the {@code ondragstart} event handler.
3729      * @return the {@code ondragstart} event handler
3730      */
3731     @JsxGetter
3732     public Function getOndragstart() {
3733         return getEventHandler(Event.TYPE_DRAGSTART);
3734     }
3735 
3736     /**
3737      * Sets the {@code ondragstart} event handler.
3738      * @param ondragstart the {@code ondragstart} event handler
3739      */
3740     @JsxSetter
3741     public void setOndragstart(final Object ondragstart) {
3742         setHandlerForJavaScript(Event.TYPE_DRAGSTART, ondragstart);
3743     }
3744 
3745     /**
3746      * Returns the {@code ontransitionend} event handler.
3747      * @return the {@code ontransitionend} event handler
3748      */
3749     @JsxGetter({CHROME, EDGE})
3750     public Function getOntransitionend() {
3751         return getEventHandler(Event.TYPE_TRANSITIONEND);
3752     }
3753 
3754     /**
3755      * Sets the {@code ontransitionend} event handler.
3756      * @param ontransitionend the {@code ontransitionend} event handler
3757      */
3758     @JsxSetter({CHROME, EDGE})
3759     public void setOntransitionend(final Object ontransitionend) {
3760         setHandlerForJavaScript(Event.TYPE_TRANSITIONEND, ontransitionend);
3761     }
3762 
3763     /**
3764      * Returns the {@code ondeviceorientationabsolute} event handler.
3765      * @return the {@code ondeviceorientationabsolute} event handler
3766      */
3767     @JsxGetter({CHROME, EDGE})
3768     public Function getOndeviceorientationabsolute() {
3769         return getEventHandler(Event.TYPE_DEVICEORIENTATIONABSOLUTE);
3770     }
3771 
3772     /**
3773      * Sets the {@code ondeviceorientationabsolute} event handler.
3774      * @param ondeviceorientationabsolute the {@code ondeviceorientationabsolute} event handler
3775      */
3776     @JsxSetter({CHROME, EDGE})
3777     public void setOndeviceorientationabsolute(final Object ondeviceorientationabsolute) {
3778         setHandlerForJavaScript(Event.TYPE_DEVICEORIENTATIONABSOLUTE, ondeviceorientationabsolute);
3779     }
3780 
3781     /**
3782      * Returns the {@code onvolumechange} event handler.
3783      * @return the {@code onvolumechange} event handler
3784      */
3785     @JsxGetter
3786     public Function getOnvolumechange() {
3787         return getEventHandler(Event.TYPE_VOLUMECHANGE);
3788     }
3789 
3790     /**
3791      * Sets the {@code onvolumechange} event handler.
3792      * @param onvolumechange the {@code onvolumechange} event handler
3793      */
3794     @JsxSetter
3795     public void setOnvolumechange(final Object onvolumechange) {
3796         setHandlerForJavaScript(Event.TYPE_VOLUMECHANGE, onvolumechange);
3797     }
3798 
3799     /**
3800      * Returns the {@code ongotpointercapture} event handler.
3801      * @return the {@code ongotpointercapture} event handler
3802      */
3803     @JsxGetter({CHROME, EDGE})
3804     public Function getOngotpointercapture() {
3805         return getEventHandler(Event.TYPE_GOTPOINTERCAPTURE);
3806     }
3807 
3808     /**
3809      * Sets the {@code ongotpointercapture} event handler.
3810      * @param ongotpointercapture the {@code ongotpointercapture} event handler
3811      */
3812     @JsxSetter({CHROME, EDGE})
3813     public void setOngotpointercapture(final Object ongotpointercapture) {
3814         setHandlerForJavaScript(Event.TYPE_GOTPOINTERCAPTURE, ongotpointercapture);
3815     }
3816 
3817     /**
3818      * Returns the {@code onpopstate} event handler.
3819      * @return the {@code onpopstate} event handler
3820      */
3821     @JsxGetter
3822     public Function getOnpopstate() {
3823         return getEventHandler(Event.TYPE_POPSTATE);
3824     }
3825 
3826     /**
3827      * Sets the {@code onpopstate} event handler.
3828      * @param onpopstate the {@code onpopstate} event handler
3829      */
3830     @JsxSetter
3831     public void setOnpopstate(final Object onpopstate) {
3832         setHandlerForJavaScript(Event.TYPE_POPSTATE, onpopstate);
3833     }
3834 
3835     /**
3836      * {@inheritDoc}
3837      * optimized version
3838      */
3839     @Override
3840     public BrowserVersion getBrowserVersion() {
3841         return getWebWindow().getWebClient().getBrowserVersion();
3842     }
3843 
3844     @Override
3845     public void put(final String name, final Scriptable start, final Object value) {
3846         // see https://dom.spec.whatwg.org/#window-current-event
3847         // because event is replaceable we need this hack here
3848         if ("event".equals(name)) {
3849             final Slot slot = querySlot(Context.getCurrentContext(), "event");
3850             if (slot instanceof AccessorSlot) {
3851                 delete("event");
3852             }
3853         }
3854         super.put(name, start, value);
3855     }
3856 
3857     /**
3858      * Returns a boolean indicating whether the current context is secure (true) or not (false).
3859      * @return a boolean indicating whether the current context is secure (true) or not (false).
3860      */
3861     @JsxGetter
3862     public boolean isIsSecureContext() {
3863         final Page page = getWebWindow().getEnclosedPage();
3864         if (page != null) {
3865             final String protocol = page.getUrl().getProtocol();
3866             if ("https".equals(protocol)
3867                     || "wss".equals(protocol)
3868                     || "file".equals(protocol)) {
3869                 return true;
3870             }
3871 
3872             final String host = page.getUrl().getHost();
3873             if ("localhost".equals(host)
3874                     || "localhost.".equals(host)
3875                     || host.endsWith(".localhost")
3876                     || host.endsWith(".localhost.")) {
3877                 return true;
3878             }
3879         }
3880 
3881         return false;
3882     }
3883 }
3884 
3885 class HTMLCollectionFrames extends HTMLCollection {
3886     private static final Log LOG = LogFactory.getLog(HTMLCollectionFrames.class);
3887 
3888     HTMLCollectionFrames(final HtmlPage page) {
3889         super(page, false);
3890         this.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> node instanceof BaseFrameElement);
3891     }
3892 
3893     @Override
3894     protected Scriptable getScriptableForElement(final Object obj) {
3895         final WebWindow window;
3896         if (obj instanceof BaseFrameElement element) {
3897             window = element.getEnclosedWindow();
3898         }
3899         else {
3900             window = ((FrameWindow) obj).getFrameElement().getEnclosedWindow();
3901         }
3902 
3903         return window.getScriptableObject();
3904     }
3905 
3906     @Override
3907     protected Object getWithPreemption(final String name) {
3908         final List<DomNode> elements = getElements();
3909 
3910         for (final Object next : elements) {
3911             final BaseFrameElement frameElt = (BaseFrameElement) next;
3912             final WebWindow window = frameElt.getEnclosedWindow();
3913             if (name.equals(window.getName())) {
3914                 if (LOG.isDebugEnabled()) {
3915                     LOG.debug("Property \"" + name + "\" evaluated (by name) to " + window);
3916                 }
3917                 return getScriptableForElement(window);
3918             }
3919         }
3920 
3921         return NOT_FOUND;
3922     }
3923 }