• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / httpunit / 636

05 Dec 2025 03:27AM UTC coverage: 80.509%. Remained the same
636

push

github

hazendaz
Cleanup more old since tags

you guessed it, at this point going to jautodoc the rest so the warnings on builds go away ;)

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8249 of 10132 relevant lines covered (81.42%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.8
/src/main/java/com/meterware/httpunit/javascript/JavaScript.java
1
/*
2
 * MIT License
3
 *
4
 * Copyright 2011-2025 Russell Gold
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
7
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
9
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions
12
 * of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
15
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
17
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18
 * DEALINGS IN THE SOFTWARE.
19
 */
20
package com.meterware.httpunit.javascript;
21

22
import com.meterware.httpunit.ClientProperties;
23
import com.meterware.httpunit.HTMLPage;
24
import com.meterware.httpunit.HttpUnitOptions;
25
import com.meterware.httpunit.HttpUnitUtils;
26
import com.meterware.httpunit.WebForm;
27
import com.meterware.httpunit.WebImage;
28
import com.meterware.httpunit.WebLink;
29
import com.meterware.httpunit.WebResponse;
30
import com.meterware.httpunit.javascript.events.EventException;
31
import com.meterware.httpunit.javascript.events.EventTarget;
32
import com.meterware.httpunit.scripting.DocumentElement;
33
import com.meterware.httpunit.scripting.FormScriptable;
34
import com.meterware.httpunit.scripting.IdentifiedDelegate;
35
import com.meterware.httpunit.scripting.Input;
36
import com.meterware.httpunit.scripting.NamedDelegate;
37
import com.meterware.httpunit.scripting.ScriptableDelegate;
38
import com.meterware.httpunit.scripting.ScriptingEngine;
39
import com.meterware.httpunit.scripting.ScriptingHandler;
40
import com.meterware.httpunit.scripting.SelectionOption;
41
import com.meterware.httpunit.scripting.SelectionOptions;
42

43
import java.io.IOException;
44
import java.lang.reflect.InvocationTargetException;
45
import java.net.URL;
46
import java.util.HashMap;
47
import java.util.HashSet;
48
import java.util.Map;
49
import java.util.Set;
50

51
import org.mozilla.javascript.Context;
52
import org.mozilla.javascript.EvaluatorException;
53
import org.mozilla.javascript.JavaScriptException;
54
import org.mozilla.javascript.Scriptable;
55
import org.mozilla.javascript.ScriptableObject;
56
import org.mozilla.javascript.Undefined;
57
import org.xml.sax.SAXException;
58

59
/**
60
 * This class is the Rhino-compatible implementation of the JavaScript DOM objects.
61
 **/
62
public class JavaScript {
×
63

64
    private static boolean _throwExceptionsOnError = true;
1✔
65

66
    public static boolean isThrowExceptionsOnError() {
67
        return _throwExceptionsOnError;
1✔
68
    }
69

70
    public static void setThrowExceptionsOnError(boolean throwExceptionsOnError) {
71
        _throwExceptionsOnError = throwExceptionsOnError;
1✔
72
    }
1✔
73

74
    /**
75
     * Initiates JavaScript execution for the specified web response.
76
     */
77
    public static void run(WebResponse response) throws IllegalAccessException, InstantiationException,
78
            InvocationTargetException, EvaluatorException, EvaluatorException, SAXException, JavaScriptException {
79
        Context context = Context.enter();
1✔
80
        // suggest bug fix for large java scripts see
81
        // bug report [ 1216567 ] Exception for large javascripts
82
        // by Grzegorz Lukasik
83
        // and
84

85
        context.setOptimizationLevel(HttpUnitOptions.getJavaScriptOptimizationLevel());
1✔
86
        Scriptable scope = context.initStandardObjects(null);
1✔
87
        initHTMLObjects(scope);
1✔
88

89
        Window w = (Window) context.newObject(scope, "Window");
1✔
90
        w.initialize(null, response.getScriptableObject());
1✔
91
    }
1✔
92

93
    /**
94
     * Runs the onload event for the specified web response.
95
     */
96
    public static void load(WebResponse response) throws EvaluatorException, InstantiationException,
97
            IllegalAccessException, InvocationTargetException, JavaScriptException, SAXException, EvaluatorException {
98
        if (!(response.getScriptableObject().getScriptEngine() instanceof JavaScriptEngine)) {
1!
99
            run(response);
×
100
        }
101
        response.getScriptableObject().load();
1✔
102
    }
1✔
103

104
    private static void initHTMLObjects(Scriptable scope)
105
            throws IllegalAccessException, InstantiationException, InvocationTargetException, EvaluatorException {
106
        ScriptableObject.defineClass(scope, Window.class);
1✔
107
        ScriptableObject.defineClass(scope, Document.class);
1✔
108
        ScriptableObject.defineClass(scope, Style.class);
1✔
109
        ScriptableObject.defineClass(scope, Location.class);
1✔
110
        ScriptableObject.defineClass(scope, Navigator.class);
1✔
111
        ScriptableObject.defineClass(scope, Screen.class);
1✔
112
        ScriptableObject.defineClass(scope, Link.class);
1✔
113
        ScriptableObject.defineClass(scope, Form.class);
1✔
114
        ScriptableObject.defineClass(scope, Control.class);
1✔
115
        ScriptableObject.defineClass(scope, Link.class);
1✔
116
        ScriptableObject.defineClass(scope, Image.class);
1✔
117
        ScriptableObject.defineClass(scope, Options.class);
1✔
118
        ScriptableObject.defineClass(scope, Option.class);
1✔
119
        ScriptableObject.defineClass(scope, ElementArray.class);
1✔
120
        ScriptableObject.defineClass(scope, HTMLElement.class);
1✔
121
    }
1✔
122

123
    /**
124
     * abstract Engine for JavaScript
125
     */
126
    abstract static class JavaScriptEngine extends ScriptingEngineImpl implements EventTarget {
1✔
127

128
        private static final long serialVersionUID = 1L;
129
        protected ScriptableDelegate _scriptable;
130
        protected JavaScriptEngine _parent;
131
        protected Map _eventListeners = new HashMap<>(); // Map<String,Set<EventListener>>
1✔
132
        protected Map _eventCaptureListeners = new HashMap<>(); // Map<String,Set<EventListener>>
1✔
133

134
        /**
135
         * initialize JavaScript for the given ScriptEngine
136
         *
137
         * @parent - the Script Engine to use
138
         *
139
         * @scriptable - the scriptable object to do the initialization for
140
         */
141
        void initialize(JavaScriptEngine parent, ScriptableDelegate scriptable)
142
                throws SAXException, JavaScriptException, EvaluatorException {
143
            _scriptable = scriptable;
1✔
144
            _scriptable.setScriptEngine(this);
1✔
145
            _parent = parent;
1✔
146
            if (parent != null) {
1✔
147
                setParentScope(parent);
1✔
148
            }
149
        }
1✔
150

151
        String getName() {
152
            return _scriptable instanceof NamedDelegate ? ((NamedDelegate) _scriptable).getName() : "";
1!
153
        }
154

155
        String getID() {
156
            return _scriptable instanceof IdentifiedDelegate ? ((IdentifiedDelegate) _scriptable).getID() : "";
1✔
157
        }
158

159
        /**
160
         * get the event Handler script for the event e.g. onchange, onmousedown, onclick, onmouseup execute the script
161
         * if it's assigned by calling doEvent for the script
162
         *
163
         * @param eventName
164
         *
165
         * @return
166
         */
167
        @Override
168
        public boolean handleEvent(String eventName) {
169
            return _scriptable.handleEvent(eventName);
×
170
        }
171

172
        @Override
173
        public boolean has(String propertyName, Scriptable scriptable) {
174
            return super.has(propertyName, scriptable) || _scriptable != null && _scriptable.get(propertyName) != null;
1✔
175
        }
176

177
        @Override
178
        public Object get(String propertyName, Scriptable scriptable) {
179
            Object result = super.get(propertyName, scriptable);
1✔
180
            if (result != NOT_FOUND) {
1✔
181
                return result;
1✔
182
            }
183
            if (_scriptable == null) {
1✔
184
                return NOT_FOUND;
1✔
185
            }
186

187
            return convertIfNeeded(_scriptable.get(propertyName));
1✔
188

189
        }
190

191
        @Override
192
        public Object get(int i, Scriptable scriptable) {
193
            Object result = super.get(i, scriptable);
1✔
194
            if (result != NOT_FOUND) {
1!
195
                return result;
×
196
            }
197
            if (_scriptable == null) {
1!
198
                return NOT_FOUND;
×
199
            }
200

201
            return convertIfNeeded(_scriptable.get(i));
1✔
202
        }
203

204
        private Object convertIfNeeded(final Object property) {
205
            if (property == null) {
1✔
206
                return NOT_FOUND;
1✔
207
            }
208

209
            if (property instanceof ScriptableDelegate[]) {
1✔
210
                return toScriptable((ScriptableDelegate[]) property);
1✔
211
            }
212
            if (!(property instanceof ScriptableDelegate)) {
1✔
213
                return property;
1✔
214
            }
215
            return toScriptable((ScriptableDelegate) property);
1✔
216
        }
217

218
        private Object toScriptable(ScriptableDelegate[] list) {
219
            Object[] delegates = new Object[list.length];
1✔
220
            for (int i = 0; i < delegates.length; i++) {
1✔
221
                delegates[i] = toScriptable(list[i]);
1✔
222
            }
223
            return Context.getCurrentContext().newArray(this, delegates);
1✔
224
        }
225

226
        @Override
227
        public void put(String propertyName, Scriptable scriptable, Object value) {
228
            if (_scriptable == null || _scriptable.get(propertyName) == null) {
1✔
229
                super.put(propertyName, scriptable, value);
1✔
230
            } else {
231
                _scriptable.set(propertyName, value);
1✔
232
            }
233
        }
1✔
234

235
        @Override
236
        public String toString() {
237
            return (_scriptable == null ? "prototype " : "") + getClassName();
×
238
        }
239

240
        @Override
241
        public ScriptingEngine newScriptingEngine(ScriptableDelegate child) {
242
            try {
243
                return (ScriptingEngine) toScriptable(child);
1✔
244
            } catch (Exception e) {
×
245
                HttpUnitUtils.handleException(e);
×
246
                throw new RuntimeException(e.toString());
×
247
            }
248
        }
249

250
        @Override
251
        public void clearCaches() {
252
        }
×
253

254
        protected static String toStringIfNotUndefined(Object object) {
255
            return object == null || Undefined.instance.equals(object) ? null : object.toString();
1!
256
        }
257

258
        /**
259
         * Converts a scriptable delegate obtained from a subobject into the appropriate Rhino-compatible Scriptable.
260
         **/
261
        final Object toScriptable(ScriptableDelegate delegate) {
262
            if (delegate == null) {
1!
263
                return NOT_FOUND;
×
264
            }
265
            if (delegate.getScriptEngine() instanceof Scriptable) {
1✔
266
                return delegate.getScriptEngine();
1✔
267
            }
268
            try {
269
                JavaScriptEngine element = (JavaScriptEngine) Context.getCurrentContext().newObject(this,
1✔
270
                        getScriptableClassName(delegate));
1✔
271
                element.initialize(this, delegate);
1✔
272
                return element;
1✔
273
            } catch (RuntimeException e) {
×
274
                throw e;
×
275
            } catch (Exception e) {
×
276
                throw new RhinoException(e);
×
277
            }
278
        }
279

280
        /**
281
         * get the classname of the given ScriptableDelegate
282
         *
283
         * @param delegate
284
         *            - the object to get the class name for
285
         *
286
         * @return - the simple local class name for the delegate e.g. Window, Document, Form, Link, Image, Options,
287
         *         Option, Control, HTMLElement
288
         *
289
         * @throws an
290
         *             IllegalArgumentException if the delegate is not known
291
         */
292
        private String getScriptableClassName(ScriptableDelegate delegate) {
293
            if (delegate instanceof WebResponse.Scriptable) {
1✔
294
                return "Window";
1✔
295
            }
296
            if (delegate instanceof HTMLPage.Scriptable) {
1✔
297
                return "Document";
1✔
298
            }
299
            if (delegate instanceof FormScriptable) {
1✔
300
                return "Form";
1✔
301
            }
302
            if (delegate instanceof WebLink.Scriptable) {
1✔
303
                return "Link";
1✔
304
            }
305
            if (delegate instanceof WebImage.Scriptable) {
1✔
306
                return "Image";
1✔
307
            }
308
            if (delegate instanceof SelectionOptions) {
1✔
309
                return "Options";
1✔
310
            }
311
            if (delegate instanceof SelectionOption) {
1✔
312
                return "Option";
1✔
313
            }
314
            if (delegate instanceof Input) {
1✔
315
                return "Control";
1✔
316
            }
317
            if (delegate instanceof DocumentElement) {
1!
318
                return "HTMLElement";
1✔
319
            }
320

321
            throw new IllegalArgumentException("Unknown ScriptableDelegate class: " + delegate.getClass());
×
322
        }
323

324
        protected ElementArray toElementArray(ScriptingHandler[] scriptables) {
325
            JavaScriptEngine[] elements = new JavaScriptEngine[scriptables.length];
1✔
326
            for (int i = 0; i < elements.length; i++) {
1✔
327
                elements[i] = (JavaScriptEngine) toScriptable((ScriptableDelegate) scriptables[i]);
1✔
328
            }
329
            ElementArray result = ElementArray.newElementArray(this);
1✔
330
            result.initialize(elements);
1✔
331
            return result;
1✔
332
        }
333

334
        /**
335
         * {@inheritDoc}
336
         */
337
        @Override
338
        public void jsFunction_addEventListener(String type, Scriptable listener, boolean useCapture) {
339
            if (useCapture) {
×
340
                Set set = (Set) _eventCaptureListeners.get(type); // Set<Scriptable>
×
341
                if (set == null) {
×
342
                    set = new HashSet<>();
×
343
                    _eventCaptureListeners.put(type, set);
×
344
                }
345
                set.add(listener);
×
346
            } else {
×
347
                Set set = (Set) _eventListeners.get(type); // Set<Scriptable>
×
348
                if (set == null) {
×
349
                    set = new HashSet<>();
×
350
                    _eventListeners.put(type, set);
×
351
                }
352
                set.add(listener);
×
353
            }
354
            // System.out.println(getClassName()+".addEventListener("+type+")");
355
        }
×
356

357
        /**
358
         * {@inheritDoc}
359
         */
360
        @Override
361
        public boolean jsFunction_dispatchEvent(Scriptable evt) throws EventException {
362
            // TODO implement event dispatching & listener invocation
363
            // System.out.println(getClassName()+".dispatchEvent("+evt.get("type",evt)+")");
364
            return true;
×
365
        }
366

367
        /**
368
         * {@inheritDoc}
369
         */
370
        @Override
371
        public void jsFunction_removeEventListener(String type, Scriptable listener, boolean useCapture) {
372
            if (useCapture) {
×
373
                Set set = (Set) _eventCaptureListeners.get(type); // Set<EventListener>
×
374
                if (set != null) {
×
375
                    set.remove(listener);
×
376
                }
377
            } else {
×
378
                Set set = (Set) _eventListeners.get(type); // Set<EventListener>
×
379
                if (set != null) {
×
380
                    set.remove(listener);
×
381
                }
382
            }
383
            // System.out.println(getClassName()+".removeEventListener("+type+")");
384
        }
×
385
    }
386

387
    /**
388
     * Window functions
389
     */
390
    static public class Window extends JavaScriptEngine {
1✔
391

392
        private static final long serialVersionUID = 1L;
393
        private Document _document;
394
        private Navigator _navigator;
395
        private Location _location;
396
        private Screen _screen;
397
        private ElementArray _frames;
398

399
        @Override
400
        public String getClassName() {
401
            return "Window";
1✔
402
        }
403

404
        public Window jsGet_window() {
405
            return this;
1✔
406
        }
407

408
        public Window jsGet_self() {
409
            return this;
×
410
        }
411

412
        public Document jsGet_document() {
413
            if (_document == null) {
1✔
414
                _document = (Document) toScriptable(getDelegate().getDocument());
1✔
415
            }
416
            return _document;
1✔
417
        }
418

419
        public Scriptable jsGet_frames() throws SAXException, JavaScriptException, EvaluatorException {
420
            if (_frames == null) {
1✔
421
                WebResponse.Scriptable[] scriptables = getDelegate().getFrames();
1✔
422
                Window[] frames = new Window[scriptables.length];
1✔
423
                for (int i = 0; i < frames.length; i++) {
1✔
424
                    frames[i] = (Window) toScriptable(scriptables[i]);
1✔
425
                }
426
                _frames = (ElementArray) Context.getCurrentContext().newObject(this, "ElementArray");
1✔
427
                _frames.initialize(frames);
1✔
428
            }
429
            return _frames;
1✔
430
        }
431

432
        public Navigator jsGet_navigator() {
433
            return _navigator;
1✔
434
        }
435

436
        public Screen jsGet_screen() {
437
            return _screen;
1✔
438
        }
439

440
        public Location jsGet_location() {
441
            return _location;
1✔
442
        }
443

444
        public void jsSet_location(String relativeURL) throws IOException, SAXException {
445
            setLocation(relativeURL);
1✔
446
        }
1✔
447

448
        void setLocation(String relativeURL) throws IOException, SAXException {
449
            getDelegate().setLocation(relativeURL);
1✔
450
        }
1✔
451

452
        /**
453
         * initialize JavaScript for the given ScriptEngine
454
         *
455
         * @parent - the Script Engine to use
456
         *
457
         * @scriptable - the scriptable object to do the initialization for
458
         */
459
        @Override
460
        void initialize(JavaScriptEngine parent, ScriptableDelegate scriptable)
461
                throws JavaScriptException, EvaluatorException, SAXException {
462
            super.initialize(parent, scriptable);
1✔
463

464
            _location = (Location) Context.getCurrentContext().newObject(this, "Location");
1✔
465
            _location.initialize(this, ((WebResponse.Scriptable) scriptable).getURL());
1✔
466

467
            _navigator = (Navigator) Context.getCurrentContext().newObject(this, "Navigator");
1✔
468
            _navigator.setClientProperties(getDelegate().getClientProperties());
1✔
469

470
            _screen = (Screen) Context.getCurrentContext().newObject(this, "Screen");
1✔
471
            _screen.setClientProperties(getDelegate().getClientProperties());
1✔
472
        }
1✔
473

474
        /**
475
         * javascript alert handling
476
         *
477
         * @param message
478
         *            - the alert message
479
         */
480
        public void jsFunction_alert(String message) {
481
            getDelegate().alertUser(message);
1✔
482
        }
1✔
483

484
        /**
485
         * javascript built in function "toLowerCase"
486
         *
487
         * @param s
488
         */
489
        public String jsFunction_toLowerCase(String s) {
490
            return s.toLowerCase();
1✔
491
        }
492

493
        public boolean jsFunction_confirm(String message) {
494
            return getDelegate().getConfirmationResponse(message);
1✔
495
        }
496

497
        public String jsFunction_prompt(String message, String defaultResponse) {
498
            return getDelegate().getUserResponse(message, defaultResponse);
1✔
499
        }
500

501
        public void jsFunction_moveTo(int x, int y) {
502
        }
×
503

504
        public void jsFunction_scrollTo(int x, int y) {
505
        }
×
506

507
        public void jsFunction_focus() {
508
        }
×
509

510
        public void jsFunction_setTimeout() {
511
        }
×
512

513
        public void jsFunction_close() {
514
            getDelegate().closeWindow();
1✔
515
        }
1✔
516

517
        public Window jsFunction_open(Object url, String name, String features, boolean replace)
518
                throws JavaScriptException, EvaluatorException, IOException, SAXException {
519
            WebResponse.Scriptable delegate = getDelegate().open(toStringIfNotUndefined(url), name, features, replace);
1✔
520
            return delegate == null ? null : (Window) toScriptable(delegate);
1✔
521
        }
522

523
        /** The global "event" object is not supported, so return null (instead of causing '"event" is not defined') */
524
        public Location jsGet_event() {
525
            return null;
×
526
        }
527

528
        @Override
529
        public void clearCaches() {
530
            if (_document != null) {
1✔
531
                _document.clearCaches();
1✔
532
            }
533
        }
1✔
534

535
        @Override
536
        protected String getDocumentWriteBuffer() {
537
            return jsGet_document().getWriteBuffer().toString();
1✔
538
        }
539

540
        @Override
541
        protected void discardDocumentWriteBuffer() {
542
            jsGet_document().clearWriteBuffer();
1✔
543
        }
1✔
544

545
        private WebResponse.Scriptable getDelegate() {
546
            return (WebResponse.Scriptable) _scriptable;
1✔
547
        }
548
    }
549

550
    /**
551
     * Document script handling
552
     */
553
    static public class Document extends JavaScriptEngine {
1✔
554

555
        private static final long serialVersionUID = 1L;
556
        private ElementArray _forms;
557
        private ElementArray _links;
558
        private ElementArray _images;
559
        private StringBuilder _writeBuffer;
560
        private String _mimeType;
561

562
        @Override
563
        public String getClassName() {
564
            return "Document";
1✔
565
        }
566

567
        @Override
568
        public void clearCaches() {
569
            _forms = _links = _images = null;
1✔
570
        }
1✔
571

572
        public String jsGet_title() throws SAXException {
573
            return getDelegate().getTitle();
1✔
574
        }
575

576
        public Scriptable jsGet_images() throws SAXException {
577
            if (_images == null) {
1✔
578
                _images = toElementArray(getDelegate().getImages());
1✔
579
            }
580
            return _images;
1✔
581
        }
582

583
        public Scriptable jsGet_links() throws SAXException {
584
            if (_links == null) {
1✔
585
                _links = toElementArray(getDelegate().getLinks());
1✔
586
            }
587
            return _links;
1✔
588
        }
589

590
        public Scriptable jsGet_forms() throws SAXException {
591
            if (_forms == null) {
1✔
592
                _forms = toElementArray(getDelegate().getForms());
1✔
593
            }
594
            return _forms;
1✔
595
        }
596

597
        public Object jsFunction_getElementById(String id) {
598
            ScriptableDelegate elementWithID = getDelegate().getElementWithID(id);
1✔
599
            return elementWithID == null ? null : toScriptable(elementWithID);
1✔
600
        }
601

602
        public Object jsFunction_getElementsByName(String name) {
603
            return toElementArray(getDelegate().getElementsByName(name));
1✔
604
        }
605

606
        public Object jsFunction_getElementsByTagName(String name) {
607
            return toElementArray(getDelegate().getElementsByTagName(name));
1✔
608
        }
609

610
        public Object jsGet_location() {
611
            return _parent == null ? NOT_FOUND : getWindow().jsGet_location();
1!
612
        }
613

614
        public void jsSet_location(String urlString) throws IOException, SAXException {
615
            if (urlString.startsWith("color")) {
1!
616
                return;
×
617
            }
618
            getWindow().setLocation(urlString);
1✔
619
        }
1✔
620

621
        public String jsGet_cookie() {
622
            return getDelegate().getCookie();
1✔
623
        }
624

625
        public void jsSet_cookie(String cookieSpec) {
626
            final int equalsIndex = cookieSpec.indexOf('=');
1✔
627
            if (equalsIndex < 0) {
1✔
628
                return;
1✔
629
            }
630
            int endIndex = cookieSpec.indexOf(";", equalsIndex);
1✔
631
            if (endIndex < 0) {
1!
632
                endIndex = cookieSpec.length();
×
633
            }
634
            String name = cookieSpec.substring(0, equalsIndex);
1✔
635
            String value = cookieSpec.substring(equalsIndex + 1, endIndex);
1✔
636
            getDelegate().setCookie(name, value);
1✔
637
        }
1✔
638

639
        private Window getWindow() {
640
            return (Window) _parent;
1✔
641
        }
642

643
        public void jsFunction_open(Object mimeType) {
644
            _mimeType = toStringIfNotUndefined(mimeType);
1✔
645
        }
1✔
646

647
        public void jsFunction_close() {
648
            if (getDelegate().replaceText(getWriteBuffer().toString(), _mimeType == null ? "text/html" : _mimeType)) {
1✔
649
                getWriteBuffer().setLength(0);
1✔
650
            }
651
        }
1✔
652

653
        public void jsFunction_write(String string) {
654
            getWriteBuffer().append(string);
1✔
655
        }
1✔
656

657
        public void jsFunction_writeln(String string) {
658
            getWriteBuffer().append(string).append((char) 0x0D).append((char) 0x0A);
1✔
659
        }
1✔
660

661
        protected StringBuilder getWriteBuffer() {
662
            if (_writeBuffer == null) {
1✔
663
                _writeBuffer = new StringBuilder();
1✔
664
            }
665
            return _writeBuffer;
1✔
666
        }
667

668
        protected void clearWriteBuffer() {
669
            _writeBuffer = null;
1✔
670
        }
1✔
671

672
        private HTMLPage.Scriptable getDelegate() {
673
            return (HTMLPage.Scriptable) _scriptable;
1✔
674
        }
675

676
        @Override
677
        public void jsFunction_addEventListener(String type, Scriptable listener, boolean useCapture) {
678
            // TODO Auto-generated method stub
679

680
        }
×
681

682
        @Override
683
        public boolean jsFunction_dispatchEvent(Scriptable evt) throws EventException {
684
            // TODO Auto-generated method stub
685
            return false;
×
686
        }
687

688
        @Override
689
        public void jsFunction_removeEventListener(String type, Scriptable listener, boolean useCapture) {
690
            // TODO Auto-generated method stub
691

692
        }
×
693

694
    }
695

696
    static public class Location extends JavaScriptEngine {
1✔
697

698
        private static final long serialVersionUID = 1L;
699
        private URL _url;
700
        private Window _window;
701

702
        @Override
703
        public String getClassName() {
704
            return "Location";
1✔
705
        }
706

707
        void initialize(Window window, URL url) {
708
            _window = window;
1✔
709
            _url = url;
1✔
710
        }
1✔
711

712
        public void jsFunction_replace(String urlString) throws IOException, SAXException {
713
            _window.setLocation(urlString);
1✔
714
        }
1✔
715

716
        public String jsGet_href() {
717
            return toString();
1✔
718
        }
719

720
        public void jsSet_href(String urlString) throws SAXException, IOException {
721
            _window.setLocation(urlString);
1✔
722
        }
1✔
723

724
        public String jsGet_protocol() {
725
            return _url.getProtocol() + ':';
1✔
726
        }
727

728
        public String jsGet_host() {
729
            return _url.getHost() + ':' + _url.getPort();
1✔
730
        }
731

732
        public String jsGet_hostname() {
733
            return _url.getHost();
1✔
734
        }
735

736
        public String jsGet_port() {
737
            return String.valueOf(_url.getPort());
1✔
738
        }
739

740
        public String jsGet_pathname() {
741
            return _url.getPath();
1✔
742
        }
743

744
        public void jsSet_pathname(String newPath) throws SAXException, IOException {
745
            if (!newPath.startsWith("/")) {
1!
746
                newPath = '/' + newPath;
×
747
            }
748
            URL newURL = new URL(_url, newPath);
1✔
749
            _window.setLocation(newURL.toExternalForm());
1✔
750
        }
1✔
751

752
        public String jsGet_search() {
753
            return '?' + _url.getQuery();
1✔
754
        }
755

756
        public void jsSet_search(String newSearch) throws SAXException, IOException {
757
            if (!newSearch.startsWith("?")) {
1!
758
                newSearch = '?' + newSearch;
×
759
            }
760
            _window.setLocation(jsGet_protocol() + "//" + jsGet_host() + jsGet_pathname() + newSearch);
1✔
761
        }
1✔
762

763
        /**
764
         * Returns the default value of this scriptable object. In this case, it returns simply the URL as a string.
765
         * Note that this method is necessary, since Rhino will only call the toString method directly if there are no
766
         * Rhino methods defined (jsGet_*, jsFunction_*, etc.)
767
         */
768
        @Override
769
        public Object getDefaultValue(Class typeHint) {
770
            return _url.toExternalForm();
1✔
771
        }
772

773
        @Override
774
        public String toString() {
775
            return _url.toExternalForm();
1✔
776
        }
777

778
    }
779

780
    static public class Style extends JavaScriptEngine {
1✔
781

782
        private static final long serialVersionUID = 1L;
783
        private String _display = "inline";
1✔
784
        private String _visibility = "visible";
1✔
785

786
        @Override
787
        public String getClassName() {
788
            return "Style";
1✔
789
        }
790

791
        public String jsGet_display() {
792
            return _display;
1✔
793
        }
794

795
        public void jsSet_display(String display) {
796
            _display = display;
1✔
797
        }
1✔
798

799
        public String jsGet_visibility() {
800
            return _visibility;
1✔
801
        }
802

803
        public void jsSet_visibility(String visibility) {
804
            _visibility = visibility;
1✔
805
        }
1✔
806
    }
807

808
    static public class Navigator extends JavaScriptEngine {
1✔
809

810
        private static final long serialVersionUID = 1L;
811
        private ClientProperties _clientProperties;
812

813
        @Override
814
        public String getClassName() {
815
            return "Navigator";
1✔
816
        }
817

818
        void setClientProperties(ClientProperties clientProperties) {
819
            _clientProperties = clientProperties;
1✔
820
        }
1✔
821

822
        public String jsGet_appName() {
823
            return _clientProperties.getApplicationName();
1✔
824
        }
825

826
        public String jsGet_appCodeName() {
827
            return _clientProperties.getApplicationCodeName();
1✔
828
        }
829

830
        public String jsGet_appVersion() {
831
            return _clientProperties.getApplicationVersion();
1✔
832
        }
833

834
        public String jsGet_userAgent() {
835
            return _clientProperties.getUserAgent();
1✔
836
        }
837

838
        public String jsGet_platform() {
839
            return _clientProperties.getPlatform();
1✔
840
        }
841

842
        public Object[] jsGet_plugins() {
843
            return new Object[0];
1✔
844
        }
845

846
        public boolean jsFunction_javaEnabled() {
847
            return false; // no support is provided for applets at present
1✔
848
        }
849

850
    }
851

852
    static public class Screen extends JavaScriptEngine {
1✔
853

854
        private static final long serialVersionUID = 1L;
855
        private ClientProperties _clientProperties;
856

857
        void setClientProperties(ClientProperties clientProperties) {
858
            _clientProperties = clientProperties;
1✔
859
        }
1✔
860

861
        @Override
862
        public String getClassName() {
863
            return "Screen";
1✔
864
        }
865

866
        public int jsGet_availWidth() {
867
            return _clientProperties.getAvailableScreenWidth();
1✔
868
        }
869

870
        public int jsGet_availHeight() {
871
            return _clientProperties.getAvailHeight();
1✔
872
        }
873

874
    }
875

876
    static public class ElementArray extends ScriptableObject {
877

878
        private static final long serialVersionUID = 1L;
879
        private JavaScriptEngine[] _contents = new HTMLElement[0];
1✔
880

881
        static ElementArray newElementArray(Scriptable parent) {
882
            try {
883
                return (ElementArray) Context.getCurrentContext().newObject(parent, "ElementArray");
1✔
884
            } catch (EvaluatorException | JavaScriptException e) {
×
885
                throw new RhinoException(e);
×
886
            }
887
        }
888

889
        public ElementArray() {
1✔
890
        }
1✔
891

892
        void initialize(JavaScriptEngine[] contents) {
893
            _contents = contents;
1✔
894
        }
1✔
895

896
        public int jsGet_length() {
897
            return _contents.length;
1✔
898
        }
899

900
        @Override
901
        public String getClassName() {
902
            return "ElementArray";
1✔
903
        }
904

905
        @Override
906
        public Object get(int i, Scriptable scriptable) {
907
            if (i >= 0 && i < _contents.length) {
1!
908
                return _contents[i];
1✔
909
            }
910
            return super.get(i, scriptable);
×
911
        }
912

913
        @Override
914
        public Object get(String name, Scriptable scriptable) {
915
            for (JavaScriptEngine content : _contents) {
1✔
916
                if (name.equalsIgnoreCase(content.getID())) {
1✔
917
                    return content;
1✔
918
                }
919
            }
920
            for (JavaScriptEngine content : _contents) {
1✔
921
                if (name.equalsIgnoreCase(content.getName())) {
1✔
922
                    return content;
1✔
923
                }
924
            }
925
            return super.get(name, scriptable);
1✔
926
        }
927

928
        protected JavaScriptEngine[] getContents() {
929
            return _contents;
×
930
        }
931
    }
932

933
    /**
934
     * HTML Element support for JavaScript
935
     */
936
    static public class HTMLElement extends JavaScriptEngine {
1✔
937

938
        private static final long serialVersionUID = 1L;
939
        private Style _style;
940
        private Document _document;
941

942
        @Override
943
        public String getClassName() {
944
            return "HTMLElement";
1✔
945
        }
946

947
        public Document jsGet_document() {
948
            return _document;
1✔
949
        }
950

951
        public Style jsGet_style() {
952
            return _style;
1✔
953
        }
954

955
        /**
956
         * arbitrary attribute access
957
         *
958
         * @param attributeName
959
         *
960
         * @return
961
         */
962
        public Object jsFunction_getAttribute(String attributeName) {
963
            return _scriptable.get(attributeName);
×
964
        }
965

966
        @Override
967
        void initialize(JavaScriptEngine parent, ScriptableDelegate scriptable)
968
                throws JavaScriptException, EvaluatorException, SAXException {
969
            super.initialize(parent, scriptable);
1✔
970
            _document = (Document) parent;
1✔
971
            _style = (Style) Context.getCurrentContext().newObject(this, "Style");
1✔
972
        }
1✔
973

974
    }
975

976
    static public class Image extends HTMLElement {
1✔
977

978
        private static final long serialVersionUID = 1L;
979

980
        @Override
981
        public String getClassName() {
982
            return "Image";
1✔
983
        }
984
    }
985

986
    static public class Link extends HTMLElement {
1✔
987

988
        private static final long serialVersionUID = 1L;
989

990
        @Override
991
        public Document jsGet_document() {
992
            return super.jsGet_document();
1✔
993
        }
994

995
        @Override
996
        public String getClassName() {
997
            return "Link";
1✔
998
        }
999
    }
1000

1001
    /**
1002
     * Form functions
1003
     */
1004
    static public class Form extends HTMLElement {
1✔
1005

1006
        private static final long serialVersionUID = 1L;
1007
        private ElementArray _controls;
1008

1009
        @Override
1010
        public String getClassName() {
1011
            return "Form";
1✔
1012
        }
1013

1014
        public String jsGet_name() {
1015
            return getDelegate().getName();
1✔
1016
        }
1017

1018
        /**
1019
         * @param name
1020
         */
1021
        public void jsSet_name(String name) {
1022
            getDelegate().set("name", name);
1✔
1023
        }
1✔
1024

1025
        public String jsGet_action() {
1026
            return getDelegate().getAction();
×
1027
        }
1028

1029
        public void jsSet_action(String action) {
1030
            getDelegate().setAction(action);
×
1031
        }
×
1032

1033
        public Scriptable jsGet_elements() throws EvaluatorException, JavaScriptException {
1034
            if (_controls == null) {
1✔
1035
                initializeControls();
1✔
1036
            }
1037
            return _controls;
1✔
1038
        }
1039

1040
        public Object jsFunction_getElementsByTagName(String name) throws SAXException {
1041
            return toElementArray(getDelegate().getElementsByTagName(name));
1✔
1042
        }
1043

1044
        public void jsFunction_submit() throws IOException, SAXException {
1045
            getDelegate().submit();
1✔
1046
        }
1✔
1047

1048
        public void jsFunction_reset() throws IOException, SAXException {
1049
            getDelegate().reset();
1✔
1050
        }
1✔
1051

1052
        private void initializeControls() throws EvaluatorException, JavaScriptException {
1053
            ScriptableDelegate[] scriptables = getDelegate().getElementDelegates();
1✔
1054
            Control[] controls = new Control[scriptables.length];
1✔
1055
            for (int i = 0; i < controls.length; i++) {
1✔
1056
                controls[i] = (Control) toScriptable(scriptables[i]);
1✔
1057
            }
1058
            _controls = (ElementArray) Context.getCurrentContext().newObject(this, "ElementArray");
1✔
1059
            _controls.initialize(controls);
1✔
1060
        }
1✔
1061

1062
        private WebForm.Scriptable getDelegate() {
1063
            return (WebForm.Scriptable) _scriptable;
1✔
1064
        }
1065

1066
    }
1067

1068
    /**
1069
     * Javascript support for any control
1070
     */
1071
    static public class Control extends JavaScriptEngine {
1✔
1072

1073
        private static final long serialVersionUID = 1L;
1074
        private Form _form;
1075

1076
        @Override
1077
        public String getClassName() {
1078
            return "Control";
1✔
1079
        }
1080

1081
        public Form jsGet_form() {
1082
            return _form;
1✔
1083
        }
1084

1085
        public void jsFunction_focus() {
1086
        }
×
1087

1088
        public void jsFunction_select() {
1089
        }
×
1090

1091
        /**
1092
         * click via javascript
1093
         *
1094
         * @throws IOException
1095
         * @throws SAXException
1096
         */
1097
        public void jsFunction_click() throws IOException, SAXException {
1098
            getDelegate().click();
1✔
1099
        }
1✔
1100

1101
        private Input getDelegate() {
1102
            return (Input) _scriptable;
1✔
1103
        }
1104

1105
        /** Support getting value of arbitrary attribute */
1106
        public Object jsFunction_getAttribute(String attributeName) throws JavaScriptException {
1107
            return getDelegate().get(attributeName);
1✔
1108
        }
1109

1110
        /** Support getting value of arbitrary attribute */
1111
        public void jsFunction_setAttribute(String attributeName, Object value) throws JavaScriptException {
1112
            getDelegate().setAttribute(attributeName, value);
1✔
1113
        }
1✔
1114

1115
        /** Support getting value of arbitrary attribute */
1116
        public void jsFunction_removeAttribute(String attributeName) throws JavaScriptException {
1117
            getDelegate().removeAttribute(attributeName);
×
1118
        }
×
1119

1120
        /** Allow calling onchange() from within a JavaScript function */
1121
        public void jsFunction_onchange() throws JavaScriptException {
1122
            Input myInput = this.getDelegate();
1✔
1123
            myInput.sendOnChangeEvent();
1✔
1124
        }
1✔
1125

1126
        @Override
1127
        void initialize(JavaScriptEngine parent, ScriptableDelegate scriptable)
1128
                throws JavaScriptException, EvaluatorException, SAXException {
1129
            super.initialize(parent, scriptable);
1✔
1130
            if (parent instanceof Form) {
1✔
1131
                _form = (Form) parent;
1✔
1132
            }
1133
        }
1✔
1134

1135
    }
1136

1137
    static public class Options extends JavaScriptEngine {
1✔
1138

1139
        private static final long serialVersionUID = 1L;
1140

1141
        @Override
1142
        public String getClassName() {
1143
            return "Options";
1✔
1144
        }
1145

1146
        public int jsGet_length() {
1147
            return getDelegate().getLength();
1✔
1148
        }
1149

1150
        public void jsSet_length(int length) {
1151
            getDelegate().setLength(length);
1✔
1152
        }
1✔
1153

1154
        @Override
1155
        public void put(int i, Scriptable scriptable, Object object) {
1156
            if (object == null) {
1✔
1157
                getDelegate().put(i, null);
1✔
1158
            } else {
1159
                if (!(object instanceof Option)) {
1!
1160
                    throw new IllegalArgumentException("May only add an Option to this array");
×
1161
                }
1162
                Option option = (Option) object;
1✔
1163
                getDelegate().put(i, option.getDelegate());
1✔
1164
            }
1165
        }
1✔
1166

1167
        private SelectionOptions getDelegate() {
1168
            return (SelectionOptions) _scriptable;
1✔
1169
        }
1170

1171
    }
1172

1173
    static public class Option extends JavaScriptEngine {
1✔
1174

1175
        private static final long serialVersionUID = 1L;
1176

1177
        @Override
1178
        public String getClassName() {
1179
            return "Option";
1✔
1180
        }
1181

1182
        public void jsConstructor(String text, String value, boolean defaultSelected, boolean selected) {
1183
            _scriptable = WebResponse.newDelegate("Option");
1✔
1184
            getDelegate().initialize(text, value, defaultSelected, selected);
1✔
1185
        }
1✔
1186

1187
        public int jsGet_index() {
1188
            return getDelegate().getIndex();
1✔
1189
        }
1190

1191
        public String jsGet_text() {
1192
            return getDelegate().getText();
1✔
1193
        }
1194

1195
        public void jsSet_text(String text) {
1196
            getDelegate().setText(text);
1✔
1197
        }
1✔
1198

1199
        public String jsGet_value() {
1200
            return getDelegate().getValue();
1✔
1201
        }
1202

1203
        public void jsSet_value(String value) {
1204
            getDelegate().setValue(value);
1✔
1205
        }
1✔
1206

1207
        public boolean jsGet_selected() {
1208
            return getDelegate().isSelected();
1✔
1209
        }
1210

1211
        public void jsSet_selected(boolean selected) {
1212
            getDelegate().setSelected(selected);
1✔
1213
        }
1✔
1214

1215
        public boolean jsGet_defaultSelected() {
1216
            return getDelegate().isDefaultSelected();
×
1217
        }
1218

1219
        SelectionOption getDelegate() {
1220
            return (SelectionOption) _scriptable;
1✔
1221
        }
1222
    }
1223

1224
}
1225

1226
/**
1227
 * special exception for the Rhino Javscript engine
1228
 */
1229
class RhinoException extends RuntimeException {
1230

1231
    private static final long serialVersionUID = 1L;
1232
    private Exception _cause;
1233

1234
    public RhinoException(Exception cause) {
×
1235
        _cause = cause;
×
1236
    }
×
1237

1238
    @Override
1239
    public String getMessage() {
1240
        return "Rhino exception: " + _cause;
×
1241
    }
1242
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc