Thu, 31 Aug 2017 15:30:47 +0800
merge
1 /*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package jdk.nashorn.internal.objects;
28 import static jdk.nashorn.internal.lookup.Lookup.MH;
29 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
30 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
32 import java.io.IOException;
33 import java.io.PrintWriter;
34 import java.lang.invoke.MethodHandle;
35 import java.lang.invoke.MethodHandles;
36 import java.lang.reflect.Field;
37 import java.util.Arrays;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.concurrent.Callable;
41 import java.util.concurrent.ConcurrentHashMap;
42 import jdk.internal.dynalink.linker.GuardedInvocation;
43 import jdk.internal.dynalink.linker.LinkRequest;
44 import jdk.nashorn.internal.lookup.Lookup;
45 import jdk.nashorn.internal.objects.annotations.Attribute;
46 import jdk.nashorn.internal.objects.annotations.Property;
47 import jdk.nashorn.internal.objects.annotations.ScriptClass;
48 import jdk.nashorn.internal.runtime.ConsString;
49 import jdk.nashorn.internal.runtime.Context;
50 import jdk.nashorn.internal.runtime.GlobalFunctions;
51 import jdk.nashorn.internal.runtime.JSType;
52 import jdk.nashorn.internal.runtime.NativeJavaPackage;
53 import jdk.nashorn.internal.runtime.PropertyDescriptor;
54 import jdk.nashorn.internal.runtime.PropertyMap;
55 import jdk.nashorn.internal.runtime.Scope;
56 import jdk.nashorn.internal.runtime.ScriptEnvironment;
57 import jdk.nashorn.internal.runtime.ScriptFunction;
58 import jdk.nashorn.internal.runtime.ScriptFunctionData;
59 import jdk.nashorn.internal.runtime.ScriptObject;
60 import jdk.nashorn.internal.runtime.ScriptRuntime;
61 import jdk.nashorn.internal.runtime.ScriptingFunctions;
62 import jdk.nashorn.internal.runtime.arrays.ArrayData;
63 import jdk.nashorn.internal.runtime.linker.Bootstrap;
64 import jdk.nashorn.internal.runtime.linker.InvokeByName;
65 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
66 import jdk.nashorn.internal.scripts.JO;
68 /**
69 * Representation of global scope.
70 */
71 @ScriptClass("Global")
72 public final class Global extends ScriptObject implements Scope {
73 private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
74 private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class);
76 /** ECMA 15.1.2.2 parseInt (string , radix) */
77 @Property(attributes = Attribute.NOT_ENUMERABLE)
78 public Object parseInt;
80 /** ECMA 15.1.2.3 parseFloat (string) */
81 @Property(attributes = Attribute.NOT_ENUMERABLE)
82 public Object parseFloat;
84 /** ECMA 15.1.2.4 isNaN (number) */
85 @Property(attributes = Attribute.NOT_ENUMERABLE)
86 public Object isNaN;
88 /** ECMA 15.1.2.5 isFinite (number) */
89 @Property(attributes = Attribute.NOT_ENUMERABLE)
90 public Object isFinite;
92 /** ECMA 15.1.3.3 encodeURI */
93 @Property(attributes = Attribute.NOT_ENUMERABLE)
94 public Object encodeURI;
96 /** ECMA 15.1.3.4 encodeURIComponent */
97 @Property(attributes = Attribute.NOT_ENUMERABLE)
98 public Object encodeURIComponent;
100 /** ECMA 15.1.3.1 decodeURI */
101 @Property(attributes = Attribute.NOT_ENUMERABLE)
102 public Object decodeURI;
104 /** ECMA 15.1.3.2 decodeURIComponent */
105 @Property(attributes = Attribute.NOT_ENUMERABLE)
106 public Object decodeURIComponent;
108 /** ECMA B.2.1 escape (string) */
109 @Property(attributes = Attribute.NOT_ENUMERABLE)
110 public Object escape;
112 /** ECMA B.2.2 unescape (string) */
113 @Property(attributes = Attribute.NOT_ENUMERABLE)
114 public Object unescape;
116 /** Nashorn extension: global.print */
117 @Property(attributes = Attribute.NOT_ENUMERABLE)
118 public Object print;
120 /** Nashorn extension: global.load */
121 @Property(attributes = Attribute.NOT_ENUMERABLE)
122 public Object load;
124 /** Nashorn extension: global.loadWithNewGlobal */
125 @Property(attributes = Attribute.NOT_ENUMERABLE)
126 public Object loadWithNewGlobal;
128 /** Nashorn extension: global.exit */
129 @Property(attributes = Attribute.NOT_ENUMERABLE)
130 public Object exit;
132 /** Nashorn extension: global.quit */
133 @Property(attributes = Attribute.NOT_ENUMERABLE)
134 public Object quit;
136 /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
137 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
138 public final Object NaN = Double.NaN;
140 /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
141 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
142 public final Object Infinity = Double.POSITIVE_INFINITY;
144 /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
145 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
146 public final Object undefined = UNDEFINED;
148 /** ECMA 15.1.2.1 eval(x) */
149 @Property(attributes = Attribute.NOT_ENUMERABLE)
150 public Object eval;
152 /** ECMA 15.1.4.1 Object constructor. */
153 @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
154 public volatile Object object;
156 /** ECMA 15.1.4.2 Function constructor. */
157 @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
158 public volatile Object function;
160 /** ECMA 15.1.4.3 Array constructor. */
161 @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
162 public volatile Object array;
164 /** ECMA 15.1.4.4 String constructor */
165 @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
166 public volatile Object string;
168 /** ECMA 15.1.4.5 Boolean constructor */
169 @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
170 public volatile Object _boolean;
172 /** ECMA 15.1.4.6 - Number constructor */
173 @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
174 public volatile Object number;
176 /** ECMA 15.1.4.7 Date constructor */
177 @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
178 public volatile Object date;
180 /** ECMA 15.1.4.8 RegExp constructor */
181 @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
182 public volatile Object regexp;
184 /** ECMA 15.12 - The JSON object */
185 @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
186 public volatile Object json;
188 /** Nashorn extension: global.JSAdapter */
189 @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
190 public volatile Object jsadapter;
192 /** ECMA 15.8 - The Math object */
193 @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
194 public volatile Object math;
196 /** Error object */
197 @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
198 public volatile Object error;
200 /** EvalError object */
201 @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
202 public volatile Object evalError;
204 /** RangeError object */
205 @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
206 public volatile Object rangeError;
208 /** ReferenceError object */
209 @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
210 public volatile Object referenceError;
212 /** SyntaxError object */
213 @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
214 public volatile Object syntaxError;
216 /** TypeError object */
217 @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
218 public volatile Object typeError;
220 /** URIError object */
221 @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
222 public volatile Object uriError;
224 /** ArrayBuffer object */
225 @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
226 public volatile Object arrayBuffer;
228 /** DataView object */
229 @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
230 public volatile Object dataView;
232 /** TypedArray (int8) */
233 @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
234 public volatile Object int8Array;
236 /** TypedArray (uint8) */
237 @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
238 public volatile Object uint8Array;
240 /** TypedArray (uint8) - Clamped */
241 @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
242 public volatile Object uint8ClampedArray;
244 /** TypedArray (int16) */
245 @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
246 public volatile Object int16Array;
248 /** TypedArray (uint16) */
249 @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
250 public volatile Object uint16Array;
252 /** TypedArray (int32) */
253 @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
254 public volatile Object int32Array;
256 /** TypedArray (uint32) */
257 @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
258 public volatile Object uint32Array;
260 /** TypedArray (float32) */
261 @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
262 public volatile Object float32Array;
264 /** TypedArray (float64) */
265 @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
266 public volatile Object float64Array;
268 /** Nashorn extension: Java access - global.Packages */
269 @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
270 public volatile Object packages;
272 /** Nashorn extension: Java access - global.com */
273 @Property(attributes = Attribute.NOT_ENUMERABLE)
274 public volatile Object com;
276 /** Nashorn extension: Java access - global.edu */
277 @Property(attributes = Attribute.NOT_ENUMERABLE)
278 public volatile Object edu;
280 /** Nashorn extension: Java access - global.java */
281 @Property(attributes = Attribute.NOT_ENUMERABLE)
282 public volatile Object java;
284 /** Nashorn extension: Java access - global.javafx */
285 @Property(attributes = Attribute.NOT_ENUMERABLE)
286 public volatile Object javafx;
288 /** Nashorn extension: Java access - global.javax */
289 @Property(attributes = Attribute.NOT_ENUMERABLE)
290 public volatile Object javax;
292 /** Nashorn extension: Java access - global.org */
293 @Property(attributes = Attribute.NOT_ENUMERABLE)
294 public volatile Object org;
296 /** Nashorn extension: Java access - global.javaImporter */
297 @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
298 public volatile Object javaImporter;
300 /** Nashorn extension: global.Java Object constructor. */
301 @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
302 public volatile Object javaApi;
304 /** Nashorn extension: current script's file name */
305 @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
306 public Object __FILE__;
308 /** Nashorn extension: current script's directory */
309 @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
310 public Object __DIR__;
312 /** Nashorn extension: current source line number being executed */
313 @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
314 public Object __LINE__;
316 /** Used as Date.prototype's default value */
317 public NativeDate DEFAULT_DATE;
319 /** Used as RegExp.prototype's default value */
320 public NativeRegExp DEFAULT_REGEXP;
322 /*
323 * Built-in constructor objects: Even if user changes dynamic values of
324 * "Object", "Array" etc., we still want to keep original values of these
325 * constructors here. For example, we need to be able to create array,
326 * regexp literals even after user overwrites global "Array" or "RegExp"
327 * constructor - see also ECMA 262 spec. Annex D.
328 */
329 private ScriptFunction builtinFunction;
330 private ScriptFunction builtinObject;
331 private ScriptFunction builtinArray;
332 private ScriptFunction builtinBoolean;
333 private ScriptFunction builtinDate;
334 private ScriptObject builtinJSON;
335 private ScriptFunction builtinJSAdapter;
336 private ScriptObject builtinMath;
337 private ScriptFunction builtinNumber;
338 private ScriptFunction builtinRegExp;
339 private ScriptFunction builtinString;
340 private ScriptFunction builtinError;
341 private ScriptFunction builtinEval;
342 private ScriptFunction builtinEvalError;
343 private ScriptFunction builtinRangeError;
344 private ScriptFunction builtinReferenceError;
345 private ScriptFunction builtinSyntaxError;
346 private ScriptFunction builtinTypeError;
347 private ScriptFunction builtinURIError;
348 private ScriptObject builtinPackages;
349 private ScriptObject builtinCom;
350 private ScriptObject builtinEdu;
351 private ScriptObject builtinJava;
352 private ScriptObject builtinJavafx;
353 private ScriptObject builtinJavax;
354 private ScriptObject builtinOrg;
355 private ScriptObject builtinJavaImporter;
356 private ScriptObject builtinJavaApi;
357 private ScriptObject builtinArrayBuffer;
358 private ScriptObject builtinDataView;
359 private ScriptObject builtinInt8Array;
360 private ScriptObject builtinUint8Array;
361 private ScriptObject builtinUint8ClampedArray;
362 private ScriptObject builtinInt16Array;
363 private ScriptObject builtinUint16Array;
364 private ScriptObject builtinInt32Array;
365 private ScriptObject builtinUint32Array;
366 private ScriptObject builtinFloat32Array;
367 private ScriptObject builtinFloat64Array;
369 /*
370 * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
371 */
372 private ScriptFunction typeErrorThrower;
374 // Flag to indicate that a split method issued a return statement
375 private int splitState = -1;
377 // Used to store the last RegExp result to support deprecated RegExp constructor properties
378 private RegExpResult lastRegExpResult;
380 private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class);
381 private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class);
382 private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
383 private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class);
384 private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
385 private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
387 // initialized by nasgen
388 private static PropertyMap $nasgenmap$;
390 // context to which this global belongs to
391 private final Context context;
393 @Override
394 protected Context getContext() {
395 return context;
396 }
398 // performs initialization checks for Global constructor and returns the
399 // PropertyMap, if everything is fine.
400 private static PropertyMap checkAndGetMap(final Context context) {
401 // security check first
402 final SecurityManager sm = System.getSecurityManager();
403 if (sm != null) {
404 sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
405 }
407 // null check on context
408 context.getClass();
410 /*
411 * Duplicate global's map and use it. This way the initial Map filled
412 * by nasgen (referenced from static field in this class) is retained
413 * 'as is' (as that one is process wide singleton.
414 */
415 return $nasgenmap$.duplicate();
416 }
418 /**
419 * Constructor
420 *
421 * @param context the context
422 */
423 public Global(final Context context) {
424 super(checkAndGetMap(context));
425 this.context = context;
426 this.setIsScope();
427 }
429 /**
430 * Script access to "current" Global instance
431 *
432 * @return the global singleton
433 */
434 public static Global instance() {
435 Global global = Context.getGlobal();
436 global.getClass(); // null check
437 return global;
438 }
440 /**
441 * Script access to {@link ScriptEnvironment}
442 *
443 * @return the script environment
444 */
445 static ScriptEnvironment getEnv() {
446 return instance().getContext().getEnv();
447 }
449 /**
450 * Script access to {@link Context}
451 *
452 * @return the context
453 */
454 static Context getThisContext() {
455 return instance().getContext();
456 }
458 // Runtime interface to Global
460 /**
461 * Is this global of the given Context?
462 * @param ctxt the context
463 * @return true if this global belongs to the given Context
464 */
465 public boolean isOfContext(final Context ctxt) {
466 return this.context == ctxt;
467 }
469 /**
470 * Does this global belong to a strict Context?
471 * @return true if this global belongs to a strict Context
472 */
473 public boolean isStrictContext() {
474 return context.getEnv()._strict;
475 }
477 /**
478 * Initialize standard builtin objects like "Object", "Array", "Function" etc.
479 * as well as our extension builtin objects like "Java", "JSAdapter" as properties
480 * of the global scope object.
481 */
482 public void initBuiltinObjects() {
483 if (this.builtinObject != null) {
484 // already initialized, just return
485 return;
486 }
488 init();
489 }
491 /**
492 * Create a new ScriptFunction object
493 *
494 * @param name function name
495 * @param handle invocation handle for function
496 * @param scope the scope
497 * @param strict are we in strict mode
498 *
499 * @return new script function
500 */
501 public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
502 return new ScriptFunctionImpl(name, handle, scope, null, strict ? ScriptFunctionData.IS_STRICT_CONSTRUCTOR : ScriptFunctionData.IS_CONSTRUCTOR);
503 }
505 /**
506 * Wrap a Java object as corresponding script object
507 *
508 * @param obj object to wrap
509 * @return wrapped object
510 */
511 public Object wrapAsObject(final Object obj) {
512 if (obj instanceof Boolean) {
513 return new NativeBoolean((Boolean)obj, this);
514 } else if (obj instanceof Number) {
515 return new NativeNumber(((Number)obj).doubleValue(), this);
516 } else if (obj instanceof String || obj instanceof ConsString) {
517 return new NativeString((CharSequence)obj, this);
518 } else if (obj instanceof Object[]) { // extension
519 return new NativeArray((Object[])obj);
520 } else if (obj instanceof double[]) { // extension
521 return new NativeArray((double[])obj);
522 } else if (obj instanceof long[]) {
523 return new NativeArray((long[])obj);
524 } else if (obj instanceof int[]) {
525 return new NativeArray((int[])obj);
526 } else {
527 // FIXME: more special cases? Map? List?
528 return obj;
529 }
530 }
532 /**
533 * Lookup helper for JS primitive types
534 *
535 * @param request the link request for the dynamic call site.
536 * @param self self reference
537 *
538 * @return guarded invocation
539 */
540 public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
541 if (self instanceof String || self instanceof ConsString) {
542 return NativeString.lookupPrimitive(request, self);
543 } else if (self instanceof Number) {
544 return NativeNumber.lookupPrimitive(request, self);
545 } else if (self instanceof Boolean) {
546 return NativeBoolean.lookupPrimitive(request, self);
547 }
548 throw new IllegalArgumentException("Unsupported primitive: " + self);
549 }
551 /**
552 * Create a new empty script object
553 *
554 * @return the new ScriptObject
555 */
556 public ScriptObject newObject() {
557 return new JO(getObjectPrototype(), JO.getInitialMap());
558 }
560 /**
561 * Default value of given type
562 *
563 * @param sobj script object
564 * @param typeHint type hint
565 *
566 * @return default value
567 */
568 public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
569 // When the [[DefaultValue]] internal method of O is called with no hint,
570 // then it behaves as if the hint were Number, unless O is a Date object
571 // in which case it behaves as if the hint were String.
572 Class<?> hint = typeHint;
573 if (hint == null) {
574 hint = Number.class;
575 }
577 try {
578 if (hint == String.class) {
580 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
582 if (Bootstrap.isCallable(toString)) {
583 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
584 if (JSType.isPrimitive(value)) {
585 return value;
586 }
587 }
589 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
590 if (Bootstrap.isCallable(valueOf)) {
591 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
592 if (JSType.isPrimitive(value)) {
593 return value;
594 }
595 }
596 throw typeError(this, "cannot.get.default.string");
597 }
599 if (hint == Number.class) {
600 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
601 if (Bootstrap.isCallable(valueOf)) {
602 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
603 if (JSType.isPrimitive(value)) {
604 return value;
605 }
606 }
608 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
609 if (Bootstrap.isCallable(toString)) {
610 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
611 if (JSType.isPrimitive(value)) {
612 return value;
613 }
614 }
616 throw typeError(this, "cannot.get.default.number");
617 }
618 } catch (final RuntimeException | Error e) {
619 throw e;
620 } catch (final Throwable t) {
621 throw new RuntimeException(t);
622 }
624 return UNDEFINED;
625 }
627 /**
628 * Is the given ScriptObject an ECMAScript Error object?
629 *
630 * @param sobj the object being checked
631 * @return true if sobj is an Error object
632 */
633 public boolean isError(final ScriptObject sobj) {
634 final ScriptObject errorProto = getErrorPrototype();
635 ScriptObject proto = sobj.getProto();
636 while (proto != null) {
637 if (proto == errorProto) {
638 return true;
639 }
640 proto = proto.getProto();
641 }
642 return false;
643 }
645 /**
646 * Create a new ECMAScript Error object.
647 *
648 * @param msg error message
649 * @return newly created Error object
650 */
651 public ScriptObject newError(final String msg) {
652 return new NativeError(msg, this);
653 }
655 /**
656 * Create a new ECMAScript EvalError object.
657 *
658 * @param msg error message
659 * @return newly created EvalError object
660 */
661 public ScriptObject newEvalError(final String msg) {
662 return new NativeEvalError(msg, this);
663 }
665 /**
666 * Create a new ECMAScript RangeError object.
667 *
668 * @param msg error message
669 * @return newly created RangeError object
670 */
671 public ScriptObject newRangeError(final String msg) {
672 return new NativeRangeError(msg, this);
673 }
675 /**
676 * Create a new ECMAScript ReferenceError object.
677 *
678 * @param msg error message
679 * @return newly created ReferenceError object
680 */
681 public ScriptObject newReferenceError(final String msg) {
682 return new NativeReferenceError(msg, this);
683 }
685 /**
686 * Create a new ECMAScript SyntaxError object.
687 *
688 * @param msg error message
689 * @return newly created SyntaxError object
690 */
691 public ScriptObject newSyntaxError(final String msg) {
692 return new NativeSyntaxError(msg, this);
693 }
695 /**
696 * Create a new ECMAScript TypeError object.
697 *
698 * @param msg error message
699 * @return newly created TypeError object
700 */
701 public ScriptObject newTypeError(final String msg) {
702 return new NativeTypeError(msg, this);
703 }
705 /**
706 * Create a new ECMAScript URIError object.
707 *
708 * @param msg error message
709 * @return newly created URIError object
710 */
711 public ScriptObject newURIError(final String msg) {
712 return new NativeURIError(msg, this);
713 }
715 /**
716 * Create a new ECMAScript GenericDescriptor object.
717 *
718 * @param configurable is the property configurable?
719 * @param enumerable is the property enumerable?
720 * @return newly created GenericDescriptor object
721 */
722 public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
723 return new GenericPropertyDescriptor(configurable, enumerable, this);
724 }
726 /**
727 * Create a new ECMAScript DatePropertyDescriptor object.
728 *
729 * @param value of the data property
730 * @param configurable is the property configurable?
731 * @param enumerable is the property enumerable?
732 * @return newly created DataPropertyDescriptor object
733 */
734 public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
735 return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
736 }
738 /**
739 * Create a new ECMAScript AccessorPropertyDescriptor object.
740 *
741 * @param get getter function of the user accessor property
742 * @param set setter function of the user accessor property
743 * @param configurable is the property configurable?
744 * @param enumerable is the property enumerable?
745 * @return newly created AccessorPropertyDescriptor object
746 */
747 public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
748 final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
750 if (get == null) {
751 desc.delete(PropertyDescriptor.GET, false);
752 }
754 if (set == null) {
755 desc.delete(PropertyDescriptor.SET, false);
756 }
758 return desc;
759 }
762 private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
763 final T obj = map.get(key);
764 if (obj != null) {
765 return obj;
766 }
768 try {
769 final T newObj = creator.call();
770 final T existingObj = map.putIfAbsent(key, newObj);
771 return existingObj != null ? existingObj : newObj;
772 } catch (final Exception exp) {
773 throw new RuntimeException(exp);
774 }
775 }
777 private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
780 /**
781 * Get cached InvokeByName object for the given key
782 * @param key key to be associated with InvokeByName object
783 * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
784 * @return InvokeByName object associated with the key.
785 */
786 public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
787 return getLazilyCreatedValue(key, creator, namedInvokers);
788 }
790 private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
792 /**
793 * Get cached dynamic method handle for the given key
794 * @param key key to be associated with dynamic method handle
795 * @param creator if method handle is absent 'creator' is called to make one (lazy init)
796 * @return dynamic method handle associated with the key.
797 */
798 public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
799 return getLazilyCreatedValue(key, creator, dynamicInvokers);
800 }
802 /**
803 * This is the eval used when 'indirect' eval call is made.
804 *
805 * var global = this;
806 * global.eval("print('hello')");
807 *
808 * @param self eval scope
809 * @param str eval string
810 *
811 * @return the result of eval
812 */
813 public static Object eval(final Object self, final Object str) {
814 return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
815 }
817 /**
818 * Direct eval
819 *
820 * @param self The scope of eval passed as 'self'
821 * @param str Evaluated code
822 * @param callThis "this" to be passed to the evaluated code
823 * @param location location of the eval call
824 * @param strict is eval called a strict mode code?
825 *
826 * @return the return value of the eval
827 *
828 * This is directly invoked from generated when eval(code) is called in user code
829 */
830 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
831 if (!(str instanceof String || str instanceof ConsString)) {
832 return str;
833 }
834 final Global global = Global.instance();
835 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
837 return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
838 }
840 /**
841 * Global print implementation - Nashorn extension
842 *
843 * @param self scope
844 * @param objects arguments to print
845 *
846 * @return result of print (undefined)
847 */
848 public static Object print(final Object self, final Object... objects) {
849 return printImpl(false, objects);
850 }
852 /**
853 * Global println implementation - Nashorn extension
854 *
855 * @param self scope
856 * @param objects arguments to print
857 *
858 * @return result of println (undefined)
859 */
860 public static Object println(final Object self, final Object... objects) {
861 return printImpl(true, objects);
862 }
864 /**
865 * Global load implementation - Nashorn extension
866 *
867 * @param self scope
868 * @param source source to load
869 *
870 * @return result of load (undefined)
871 *
872 * @throws IOException if source could not be read
873 */
874 public static Object load(final Object self, final Object source) throws IOException {
875 final Global global = Global.instance();
876 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
877 return global.getContext().load(scope, source);
878 }
880 /**
881 * Global loadWithNewGlobal implementation - Nashorn extension
882 *
883 * @param self scope
884 * @param args from plus (optional) arguments to be passed to the loaded script
885 *
886 * @return result of load (may be undefined)
887 *
888 * @throws IOException if source could not be read
889 */
890 public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
891 final Global global = Global.instance();
892 final int length = args.length;
893 final boolean hasArgs = 0 < length;
894 final Object from = hasArgs ? args[0] : UNDEFINED;
895 final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
897 return global.getContext().loadWithNewGlobal(from, arguments);
898 }
900 /**
901 * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
902 *
903 * @param self self reference
904 * @param code exit code
905 *
906 * @return undefined (will never be reacheD)
907 */
908 public static Object exit(final Object self, final Object code) {
909 System.exit(JSType.toInt32(code));
910 return UNDEFINED;
911 }
913 // builtin prototype accessors
914 ScriptObject getFunctionPrototype() {
915 return ScriptFunction.getPrototype(builtinFunction);
916 }
918 ScriptObject getObjectPrototype() {
919 return ScriptFunction.getPrototype(builtinObject);
920 }
922 ScriptObject getArrayPrototype() {
923 return ScriptFunction.getPrototype(builtinArray);
924 }
926 ScriptObject getBooleanPrototype() {
927 return ScriptFunction.getPrototype(builtinBoolean);
928 }
930 ScriptObject getNumberPrototype() {
931 return ScriptFunction.getPrototype(builtinNumber);
932 }
934 ScriptObject getDatePrototype() {
935 return ScriptFunction.getPrototype(builtinDate);
936 }
938 ScriptObject getRegExpPrototype() {
939 return ScriptFunction.getPrototype(builtinRegExp);
940 }
942 ScriptObject getStringPrototype() {
943 return ScriptFunction.getPrototype(builtinString);
944 }
946 ScriptObject getErrorPrototype() {
947 return ScriptFunction.getPrototype(builtinError);
948 }
950 ScriptObject getEvalErrorPrototype() {
951 return ScriptFunction.getPrototype(builtinEvalError);
952 }
954 ScriptObject getRangeErrorPrototype() {
955 return ScriptFunction.getPrototype(builtinRangeError);
956 }
958 ScriptObject getReferenceErrorPrototype() {
959 return ScriptFunction.getPrototype(builtinReferenceError);
960 }
962 ScriptObject getSyntaxErrorPrototype() {
963 return ScriptFunction.getPrototype(builtinSyntaxError);
964 }
966 ScriptObject getTypeErrorPrototype() {
967 return ScriptFunction.getPrototype(builtinTypeError);
968 }
970 ScriptObject getURIErrorPrototype() {
971 return ScriptFunction.getPrototype(builtinURIError);
972 }
974 ScriptObject getJavaImporterPrototype() {
975 return ScriptFunction.getPrototype(builtinJavaImporter);
976 }
978 ScriptObject getJSAdapterPrototype() {
979 return ScriptFunction.getPrototype(builtinJSAdapter);
980 }
982 ScriptObject getArrayBufferPrototype() {
983 return ScriptFunction.getPrototype(builtinArrayBuffer);
984 }
986 ScriptObject getDataViewPrototype() {
987 return ScriptFunction.getPrototype(builtinDataView);
988 }
990 ScriptObject getInt8ArrayPrototype() {
991 return ScriptFunction.getPrototype(builtinInt8Array);
992 }
994 ScriptObject getUint8ArrayPrototype() {
995 return ScriptFunction.getPrototype(builtinUint8Array);
996 }
998 ScriptObject getUint8ClampedArrayPrototype() {
999 return ScriptFunction.getPrototype(builtinUint8ClampedArray);
1000 }
1002 ScriptObject getInt16ArrayPrototype() {
1003 return ScriptFunction.getPrototype(builtinInt16Array);
1004 }
1006 ScriptObject getUint16ArrayPrototype() {
1007 return ScriptFunction.getPrototype(builtinUint16Array);
1008 }
1010 ScriptObject getInt32ArrayPrototype() {
1011 return ScriptFunction.getPrototype(builtinInt32Array);
1012 }
1014 ScriptObject getUint32ArrayPrototype() {
1015 return ScriptFunction.getPrototype(builtinUint32Array);
1016 }
1018 ScriptObject getFloat32ArrayPrototype() {
1019 return ScriptFunction.getPrototype(builtinFloat32Array);
1020 }
1022 ScriptObject getFloat64ArrayPrototype() {
1023 return ScriptFunction.getPrototype(builtinFloat64Array);
1024 }
1026 private ScriptFunction getBuiltinArray() {
1027 return builtinArray;
1028 }
1030 ScriptFunction getTypeErrorThrower() {
1031 return typeErrorThrower;
1032 }
1034 /**
1035 * Called from compiled script code to test if builtin has been overridden
1036 *
1037 * @return true if builtin array has not been overridden
1038 */
1039 public static boolean isBuiltinArray() {
1040 final Global instance = Global.instance();
1041 return instance.array == instance.getBuiltinArray();
1042 }
1044 private ScriptFunction getBuiltinBoolean() {
1045 return builtinBoolean;
1046 }
1048 /**
1049 * Called from compiled script code to test if builtin has been overridden
1050 *
1051 * @return true if builtin boolean has not been overridden
1052 */
1053 public static boolean isBuiltinBoolean() {
1054 final Global instance = Global.instance();
1055 return instance._boolean == instance.getBuiltinBoolean();
1056 }
1058 private ScriptFunction getBuiltinDate() {
1059 return builtinDate;
1060 }
1062 /**
1063 * Called from compiled script code to test if builtin has been overridden
1064 *
1065 * @return true if builtin date has not been overridden
1066 */
1067 public static boolean isBuiltinDate() {
1068 final Global instance = Global.instance();
1069 return instance.date == instance.getBuiltinDate();
1070 }
1072 private ScriptFunction getBuiltinError() {
1073 return builtinError;
1074 }
1076 /**
1077 * Called from compiled script code to test if builtin has been overridden
1078 *
1079 * @return true if builtin error has not been overridden
1080 */
1081 public static boolean isBuiltinError() {
1082 final Global instance = Global.instance();
1083 return instance.error == instance.getBuiltinError();
1084 }
1086 private ScriptFunction getBuiltinEvalError() {
1087 return builtinEvalError;
1088 }
1090 /**
1091 * Called from compiled script code to test if builtin has been overridden
1092 *
1093 * @return true if builtin eval error has not been overridden
1094 */
1095 public static boolean isBuiltinEvalError() {
1096 final Global instance = Global.instance();
1097 return instance.evalError == instance.getBuiltinEvalError();
1098 }
1100 private ScriptFunction getBuiltinFunction() {
1101 return builtinFunction;
1102 }
1104 /**
1105 * Called from compiled script code to test if builtin has been overridden
1106 *
1107 * @return true if builtin function has not been overridden
1108 */
1109 public static boolean isBuiltinFunction() {
1110 final Global instance = Global.instance();
1111 return instance.function == instance.getBuiltinFunction();
1112 }
1114 private ScriptFunction getBuiltinJSAdapter() {
1115 return builtinJSAdapter;
1116 }
1118 /**
1119 * Called from compiled script code to test if builtin has been overridden
1120 *
1121 * @return true if builtin JSAdapter has not been overridden
1122 */
1123 public static boolean isBuiltinJSAdapter() {
1124 final Global instance = Global.instance();
1125 return instance.jsadapter == instance.getBuiltinJSAdapter();
1126 }
1128 private ScriptObject getBuiltinJSON() {
1129 return builtinJSON;
1130 }
1132 /**
1133 * Called from compiled script code to test if builtin has been overridden
1134 *
1135 * @return true if builtin JSON has has not been overridden
1136 */
1137 public static boolean isBuiltinJSON() {
1138 final Global instance = Global.instance();
1139 return instance.json == instance.getBuiltinJSON();
1140 }
1142 private ScriptObject getBuiltinJava() {
1143 return builtinJava;
1144 }
1146 /**
1147 * Called from compiled script code to test if builtin has been overridden
1148 *
1149 * @return true if builtin Java has not been overridden
1150 */
1151 public static boolean isBuiltinJava() {
1152 final Global instance = Global.instance();
1153 return instance.java == instance.getBuiltinJava();
1154 }
1156 private ScriptObject getBuiltinJavax() {
1157 return builtinJavax;
1158 }
1160 /**
1161 * Called from compiled script code to test if builtin has been overridden
1162 *
1163 * @return true if builtin Javax has not been overridden
1164 */
1165 public static boolean isBuiltinJavax() {
1166 final Global instance = Global.instance();
1167 return instance.javax == instance.getBuiltinJavax();
1168 }
1170 private ScriptObject getBuiltinJavaImporter() {
1171 return builtinJavaImporter;
1172 }
1174 /**
1175 * Called from compiled script code to test if builtin has been overridden
1176 *
1177 * @return true if builtin Java importer has not been overridden
1178 */
1179 public static boolean isBuiltinJavaImporter() {
1180 final Global instance = Global.instance();
1181 return instance.javaImporter == instance.getBuiltinJavaImporter();
1182 }
1184 private ScriptObject getBuiltinMath() {
1185 return builtinMath;
1186 }
1188 /**
1189 * Called from compiled script code to test if builtin has been overridden
1190 *
1191 * @return true if builtin math has not been overridden
1192 */
1193 public static boolean isBuiltinMath() {
1194 final Global instance = Global.instance();
1195 return instance.math == instance.getBuiltinMath();
1196 }
1198 private ScriptFunction getBuiltinNumber() {
1199 return builtinNumber;
1200 }
1202 /**
1203 * Called from compiled script code to test if builtin has been overridden
1204 *
1205 * @return true if builtin number has not been overridden
1206 */
1207 public static boolean isBuiltinNumber() {
1208 final Global instance = Global.instance();
1209 return instance.number == instance.getBuiltinNumber();
1210 }
1212 private ScriptFunction getBuiltinObject() {
1213 return builtinObject;
1214 }
1216 /**
1217 * Called from compiled script code to test if builtin has been overridden
1218 *
1219 * @return true if builtin object has not been overridden
1220 */
1221 public static boolean isBuiltinObject() {
1222 final Global instance = Global.instance();
1223 return instance.object == instance.getBuiltinObject();
1224 }
1226 private ScriptObject getBuiltinPackages() {
1227 return builtinPackages;
1228 }
1230 /**
1231 * Called from compiled script code to test if builtin has been overridden
1232 *
1233 * @return true if builtin package has not been overridden
1234 */
1235 public static boolean isBuiltinPackages() {
1236 final Global instance = Global.instance();
1237 return instance.packages == instance.getBuiltinPackages();
1238 }
1240 private ScriptFunction getBuiltinRangeError() {
1241 return builtinRangeError;
1242 }
1244 /**
1245 * Called from compiled script code to test if builtin has been overridden
1246 *
1247 * @return true if builtin range error has not been overridden
1248 */
1249 public static boolean isBuiltinRangeError() {
1250 final Global instance = Global.instance();
1251 return instance.rangeError == instance.getBuiltinRangeError();
1252 }
1254 private ScriptFunction getBuiltinReferenceError() {
1255 return builtinReferenceError;
1256 }
1258 /**
1259 * Called from compiled script code to test if builtin has been overridden
1260 *
1261 * @return true if builtin reference error has not been overridden
1262 */
1263 public static boolean isBuiltinReferenceError() {
1264 final Global instance = Global.instance();
1265 return instance.referenceError == instance.getBuiltinReferenceError();
1266 }
1268 private ScriptFunction getBuiltinRegExp() {
1269 return builtinRegExp;
1270 }
1272 /**
1273 * Called from compiled script code to test if builtin has been overridden
1274 *
1275 * @return true if builtin regexp has not been overridden
1276 */
1277 public static boolean isBuiltinRegExp() {
1278 final Global instance = Global.instance();
1279 return instance.regexp == instance.getBuiltinRegExp();
1280 }
1282 private ScriptFunction getBuiltinString() {
1283 return builtinString;
1284 }
1286 /**
1287 * Called from compiled script code to test if builtin has been overridden
1288 *
1289 * @return true if builtin Java has not been overridden
1290 */
1291 public static boolean isBuiltinString() {
1292 final Global instance = Global.instance();
1293 return instance.string == instance.getBuiltinString();
1294 }
1296 private ScriptFunction getBuiltinSyntaxError() {
1297 return builtinSyntaxError;
1298 }
1300 /**
1301 * Called from compiled script code to test if builtin has been overridden
1302 *
1303 * @return true if builtin syntax error has not been overridden
1304 */
1305 public static boolean isBuiltinSyntaxError() {
1306 final Global instance = Global.instance();
1307 return instance.syntaxError == instance.getBuiltinSyntaxError();
1308 }
1310 private ScriptFunction getBuiltinTypeError() {
1311 return builtinTypeError;
1312 }
1314 /**
1315 * Called from compiled script code to test if builtin has been overridden
1316 *
1317 * @return true if builtin type error has not been overridden
1318 */
1319 public static boolean isBuiltinTypeError() {
1320 final Global instance = Global.instance();
1321 return instance.typeError == instance.getBuiltinTypeError();
1322 }
1324 private ScriptFunction getBuiltinURIError() {
1325 return builtinURIError;
1326 }
1328 /**
1329 * Called from compiled script code to test if builtin has been overridden
1330 *
1331 * @return true if builtin URI error has not been overridden
1332 */
1333 public static boolean isBuiltinURIError() {
1334 final Global instance = Global.instance();
1335 return instance.uriError == instance.getBuiltinURIError();
1336 }
1338 @Override
1339 public String getClassName() {
1340 return "global";
1341 }
1343 /**
1344 * Copy function used to clone NativeRegExp objects.
1345 *
1346 * @param regexp a NativeRegExp to clone
1347 *
1348 * @return copy of the given regexp object
1349 */
1350 public static Object regExpCopy(final Object regexp) {
1351 return new NativeRegExp((NativeRegExp)regexp);
1352 }
1354 /**
1355 * Convert given object to NativeRegExp type.
1356 *
1357 * @param obj object to be converted
1358 * @return NativeRegExp instance
1359 */
1360 public static NativeRegExp toRegExp(final Object obj) {
1361 if (obj instanceof NativeRegExp) {
1362 return (NativeRegExp)obj;
1363 }
1364 return new NativeRegExp(JSType.toString(obj));
1365 }
1367 /**
1368 * ECMA 9.9 ToObject implementation
1369 *
1370 * @param obj an item for which to run ToObject
1371 * @return ToObject version of given item
1372 */
1373 public static Object toObject(final Object obj) {
1374 if (obj == null || obj == UNDEFINED) {
1375 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1376 }
1378 if (obj instanceof ScriptObject) {
1379 return obj;
1380 }
1382 return instance().wrapAsObject(obj);
1383 }
1385 /**
1386 * Allocate a new object array.
1387 *
1388 * @param initial object values.
1389 * @return the new array
1390 */
1391 public static NativeArray allocate(final Object[] initial) {
1392 ArrayData arrayData = ArrayData.allocate(initial);
1394 for (int index = 0; index < initial.length; index++) {
1395 final Object value = initial[index];
1397 if (value == ScriptRuntime.EMPTY) {
1398 arrayData = arrayData.delete(index);
1399 }
1400 }
1402 return new NativeArray(arrayData);
1403 }
1405 /**
1406 * Allocate a new number array.
1407 *
1408 * @param initial number values.
1409 * @return the new array
1410 */
1411 public static NativeArray allocate(final double[] initial) {
1412 return new NativeArray(ArrayData.allocate(initial));
1413 }
1415 /**
1416 * Allocate a new long array.
1417 *
1418 * @param initial number values.
1419 * @return the new array
1420 */
1421 public static NativeArray allocate(final long[] initial) {
1422 return new NativeArray(ArrayData.allocate(initial));
1423 }
1425 /**
1426 * Allocate a new integer array.
1427 *
1428 * @param initial number values.
1429 * @return the new array
1430 */
1431 public static NativeArray allocate(final int[] initial) {
1432 return new NativeArray(ArrayData.allocate(initial));
1433 }
1435 /**
1436 * Allocate a new object array for arguments.
1437 *
1438 * @param arguments initial arguments passed.
1439 * @param callee reference to the function that uses arguments object
1440 * @param numParams actual number of declared parameters
1441 *
1442 * @return the new array
1443 */
1444 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1445 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1446 }
1448 /**
1449 * Called from generated to check if given function is the builtin 'eval'. If
1450 * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1451 *
1452 * @param fn function object that is checked
1453 * @return true if fn is the builtin eval
1454 */
1455 public static boolean isEval(final Object fn) {
1456 return fn == Global.instance().builtinEval;
1457 }
1459 /**
1460 * Create a new RegExp object.
1461 *
1462 * @param expression Regular expression.
1463 * @param options Search options.
1464 *
1465 * @return New RegExp object.
1466 */
1467 public static Object newRegExp(final String expression, final String options) {
1468 if (options == null) {
1469 return new NativeRegExp(expression);
1470 }
1471 return new NativeRegExp(expression, options);
1472 }
1474 /**
1475 * Get the object prototype
1476 *
1477 * @return the object prototype
1478 */
1479 public static ScriptObject objectPrototype() {
1480 return Global.instance().getObjectPrototype();
1481 }
1483 /**
1484 * Create a new empty object instance.
1485 *
1486 * @return New empty object.
1487 */
1488 public static ScriptObject newEmptyInstance() {
1489 return Global.instance().newObject();
1490 }
1492 /**
1493 * Check if a given object is a ScriptObject, raises an exception if this is
1494 * not the case
1495 *
1496 * @param obj and object to check
1497 */
1498 public static void checkObject(final Object obj) {
1499 if (!(obj instanceof ScriptObject)) {
1500 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1501 }
1502 }
1504 /**
1505 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1506 * if this object is null or undefined.
1507 *
1508 * @param obj an object to check
1509 */
1510 public static void checkObjectCoercible(final Object obj) {
1511 if (obj == null || obj == UNDEFINED) {
1512 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1513 }
1514 }
1516 /**
1517 * Get the current split state.
1518 *
1519 * @return current split state
1520 */
1521 @Override
1522 public int getSplitState() {
1523 return splitState;
1524 }
1526 /**
1527 * Set the current split state.
1528 *
1529 * @param state current split state
1530 */
1531 @Override
1532 public void setSplitState(final int state) {
1533 splitState = state;
1534 }
1536 private void init() {
1537 assert Context.getGlobal() == this : "this global is not set as current";
1539 final ScriptEnvironment env = getContext().getEnv();
1541 // initialize Function and Object constructor
1542 initFunctionAndObject();
1544 // Now fix Global's own proto.
1545 this.setInitialProto(getObjectPrototype());
1547 // initialize global function properties
1548 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1550 this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT);
1551 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1552 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN);
1553 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE);
1554 this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI);
1555 this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1556 this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI);
1557 this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1558 this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE);
1559 this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
1560 this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN);
1561 this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
1562 this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
1563 this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT);
1564 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
1566 // built-in constructors
1567 this.builtinArray = (ScriptFunction)initConstructor("Array");
1568 this.builtinBoolean = (ScriptFunction)initConstructor("Boolean");
1569 this.builtinDate = (ScriptFunction)initConstructor("Date");
1570 this.builtinJSON = initConstructor("JSON");
1571 this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
1572 this.builtinMath = initConstructor("Math");
1573 this.builtinNumber = (ScriptFunction)initConstructor("Number");
1574 this.builtinRegExp = (ScriptFunction)initConstructor("RegExp");
1575 this.builtinString = (ScriptFunction)initConstructor("String");
1577 // initialize String.prototype.length to 0
1578 // add String.prototype.length
1579 final ScriptObject stringPrototype = getStringPrototype();
1580 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1582 // set isArray flag on Array.prototype
1583 final ScriptObject arrayPrototype = getArrayPrototype();
1584 arrayPrototype.setIsArray();
1586 this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
1588 // initialize default regexp object
1589 this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
1591 // RegExp.prototype should behave like a RegExp object. So copy the
1592 // properties.
1593 final ScriptObject regExpProto = getRegExpPrototype();
1594 regExpProto.addBoundProperties(DEFAULT_REGEXP);
1596 // Error stuff
1597 initErrorObjects();
1599 // java access
1600 if (! env._no_java) {
1601 initJavaAccess();
1602 }
1604 if (! env._no_typed_arrays) {
1605 initTypedArray();
1606 }
1608 if (env._scripting) {
1609 initScripting(env);
1610 }
1612 if (Context.DEBUG) {
1613 boolean debugOkay;
1614 final SecurityManager sm = System.getSecurityManager();
1615 if (sm != null) {
1616 try {
1617 sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
1618 debugOkay = true;
1619 } catch (final SecurityException ignored) {
1620 // if no permission, don't initialize Debug object
1621 debugOkay = false;
1622 }
1624 } else {
1625 debugOkay = true;
1626 }
1628 if (debugOkay) {
1629 initDebug();
1630 }
1631 }
1633 copyBuiltins();
1635 // initialized with strings so that typeof will work as expected.
1636 this.__FILE__ = "";
1637 this.__DIR__ = "";
1638 this.__LINE__ = 0.0;
1640 // expose script (command line) arguments as "arguments" property of global
1641 final List<String> arguments = env.getArguments();
1642 final Object argsObj = wrapAsObject(arguments.toArray());
1644 addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
1645 if (env._scripting) {
1646 // synonym for "arguments" in scripting mode
1647 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
1648 }
1649 }
1651 private void initErrorObjects() {
1652 // Error objects
1653 this.builtinError = (ScriptFunction)initConstructor("Error");
1654 final ScriptObject errorProto = getErrorPrototype();
1656 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1657 final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1658 final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1659 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1660 final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1661 final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1662 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1663 final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1664 final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1665 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1666 final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1667 final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1668 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1670 // ECMA 15.11.4.2 Error.prototype.name
1671 // Error.prototype.name = "Error";
1672 errorProto.set(NativeError.NAME, "Error", false);
1673 // ECMA 15.11.4.3 Error.prototype.message
1674 // Error.prototype.message = "";
1675 errorProto.set(NativeError.MESSAGE, "", false);
1677 this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1678 this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1679 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1680 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1681 this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1682 this.builtinURIError = initErrorSubtype("URIError", errorProto);
1683 }
1685 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1686 final ScriptObject cons = initConstructor(name);
1687 final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1688 prototype.set(NativeError.NAME, name, false);
1689 prototype.set(NativeError.MESSAGE, "", false);
1690 prototype.setInitialProto(errorProto);
1691 return (ScriptFunction)cons;
1692 }
1694 private void initJavaAccess() {
1695 final ScriptObject objectProto = getObjectPrototype();
1696 this.builtinPackages = new NativeJavaPackage("", objectProto);
1697 this.builtinCom = new NativeJavaPackage("com", objectProto);
1698 this.builtinEdu = new NativeJavaPackage("edu", objectProto);
1699 this.builtinJava = new NativeJavaPackage("java", objectProto);
1700 this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
1701 this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1702 this.builtinOrg = new NativeJavaPackage("org", objectProto);
1703 this.builtinJavaImporter = initConstructor("JavaImporter");
1704 this.builtinJavaApi = initConstructor("Java");
1705 }
1707 private void initScripting(final ScriptEnvironment scriptEnv) {
1708 Object value;
1709 value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1710 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1712 value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1713 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1715 final String execName = ScriptingFunctions.EXEC_NAME;
1716 value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1717 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1719 // Nashorn extension: global.echo (scripting-mode-only)
1720 // alias for "print"
1721 value = get("print");
1722 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1724 // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1725 final ScriptObject options = newObject();
1726 copyOptions(options, scriptEnv);
1727 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1729 // Nashorn extension: global.$ENV (scripting-mode-only)
1730 if (System.getSecurityManager() == null) {
1731 // do not fill $ENV if we have a security manager around
1732 // Retrieve current state of ENV variables.
1733 final ScriptObject env = newObject();
1734 env.putAll(System.getenv(), scriptEnv._strict);
1735 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1736 } else {
1737 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1738 }
1740 // add other special properties for exec support
1741 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1742 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1743 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1744 }
1746 private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1747 for (Field f : scriptEnv.getClass().getFields()) {
1748 try {
1749 options.set(f.getName(), f.get(scriptEnv), false);
1750 } catch (final IllegalArgumentException | IllegalAccessException exp) {
1751 throw new RuntimeException(exp);
1752 }
1753 }
1754 }
1756 private void initTypedArray() {
1757 this.builtinArrayBuffer = initConstructor("ArrayBuffer");
1758 this.builtinDataView = initConstructor("DataView");
1759 this.builtinInt8Array = initConstructor("Int8Array");
1760 this.builtinUint8Array = initConstructor("Uint8Array");
1761 this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
1762 this.builtinInt16Array = initConstructor("Int16Array");
1763 this.builtinUint16Array = initConstructor("Uint16Array");
1764 this.builtinInt32Array = initConstructor("Int32Array");
1765 this.builtinUint32Array = initConstructor("Uint32Array");
1766 this.builtinFloat32Array = initConstructor("Float32Array");
1767 this.builtinFloat64Array = initConstructor("Float64Array");
1768 }
1770 private void copyBuiltins() {
1771 this.array = this.builtinArray;
1772 this._boolean = this.builtinBoolean;
1773 this.date = this.builtinDate;
1774 this.error = this.builtinError;
1775 this.evalError = this.builtinEvalError;
1776 this.function = this.builtinFunction;
1777 this.jsadapter = this.builtinJSAdapter;
1778 this.json = this.builtinJSON;
1779 this.com = this.builtinCom;
1780 this.edu = this.builtinEdu;
1781 this.java = this.builtinJava;
1782 this.javafx = this.builtinJavafx;
1783 this.javax = this.builtinJavax;
1784 this.org = this.builtinOrg;
1785 this.javaImporter = this.builtinJavaImporter;
1786 this.javaApi = this.builtinJavaApi;
1787 this.math = this.builtinMath;
1788 this.number = this.builtinNumber;
1789 this.object = this.builtinObject;
1790 this.packages = this.builtinPackages;
1791 this.rangeError = this.builtinRangeError;
1792 this.referenceError = this.builtinReferenceError;
1793 this.regexp = this.builtinRegExp;
1794 this.string = this.builtinString;
1795 this.syntaxError = this.builtinSyntaxError;
1796 this.typeError = this.builtinTypeError;
1797 this.uriError = this.builtinURIError;
1798 this.arrayBuffer = this.builtinArrayBuffer;
1799 this.dataView = this.builtinDataView;
1800 this.int8Array = this.builtinInt8Array;
1801 this.uint8Array = this.builtinUint8Array;
1802 this.uint8ClampedArray = this.builtinUint8ClampedArray;
1803 this.int16Array = this.builtinInt16Array;
1804 this.uint16Array = this.builtinUint16Array;
1805 this.int32Array = this.builtinInt32Array;
1806 this.uint32Array = this.builtinUint32Array;
1807 this.float32Array = this.builtinFloat32Array;
1808 this.float64Array = this.builtinFloat64Array;
1809 }
1811 private void initDebug() {
1812 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
1813 }
1815 @SuppressWarnings("resource")
1816 private static Object printImpl(final boolean newLine, final Object... objects) {
1817 final PrintWriter out = Global.getEnv().getOut();
1818 final StringBuilder sb = new StringBuilder();
1820 for (final Object object : objects) {
1821 if (sb.length() != 0) {
1822 sb.append(' ');
1823 }
1825 sb.append(JSType.toString(object));
1826 }
1828 // Print all at once to ensure thread friendly result.
1829 if (newLine) {
1830 out.println(sb.toString());
1831 } else {
1832 out.print(sb.toString());
1833 }
1835 out.flush();
1837 return UNDEFINED;
1838 }
1840 /**
1841 * These classes are generated by nasgen tool and so we have to use
1842 * reflection to load and create new instance of these classes.
1843 */
1844 private ScriptObject initConstructor(final String name) {
1845 try {
1846 // Assuming class name pattern for built-in JS constructors.
1847 final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
1849 sb.append("Native");
1850 sb.append(name);
1851 sb.append("$Constructor");
1853 final Class<?> funcClass = Class.forName(sb.toString());
1854 final ScriptObject res = (ScriptObject)funcClass.newInstance();
1856 if (res instanceof ScriptFunction) {
1857 // All global constructor prototypes are not-writable,
1858 // not-enumerable and not-configurable.
1859 final ScriptFunction func = (ScriptFunction)res;
1860 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
1861 }
1863 if (res.getProto() == null) {
1864 res.setInitialProto(getObjectPrototype());
1865 }
1867 return res;
1869 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
1870 throw new RuntimeException(e);
1871 }
1872 }
1874 // Function and Object constructors are inter-dependent. Also,
1875 // Function.prototype
1876 // functions are not properly initialized. We fix the references here.
1877 // NOTE: be careful if you want to re-order the operations here. You may
1878 // have
1879 // to play with object references carefully!!
1880 private void initFunctionAndObject() {
1881 // First-n-foremost is Function
1882 this.builtinFunction = (ScriptFunction)initConstructor("Function");
1884 // create global anonymous function
1885 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
1886 // need to copy over members of Function.prototype to anon function
1887 anon.addBoundProperties(getFunctionPrototype());
1889 // Function.prototype === Object.getPrototypeOf(Function) ===
1890 // <anon-function>
1891 builtinFunction.setInitialProto(anon);
1892 builtinFunction.setPrototype(anon);
1893 anon.set("constructor", builtinFunction, false);
1894 anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
1896 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
1897 this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
1898 typeErrorThrower.setPrototype(UNDEFINED);
1899 // Non-constructor built-in functions do not have "prototype" property
1900 typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
1901 typeErrorThrower.preventExtensions();
1903 // now initialize Object
1904 this.builtinObject = (ScriptFunction)initConstructor("Object");
1905 final ScriptObject ObjectPrototype = getObjectPrototype();
1906 // Object.getPrototypeOf(Function.prototype) === Object.prototype
1907 anon.setInitialProto(ObjectPrototype);
1909 // ES6 draft compliant __proto__ property of Object.prototype
1910 // accessors on Object.prototype for "__proto__"
1911 final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
1912 final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
1913 ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
1916 // Function valued properties of Function.prototype were not properly
1917 // initialized. Because, these were created before global.function and
1918 // global.object were not initialized.
1919 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
1920 for (final jdk.nashorn.internal.runtime.Property property : properties) {
1921 final Object key = property.getKey();
1922 final Object value = builtinFunction.get(key);
1924 if (value instanceof ScriptFunction && value != anon) {
1925 final ScriptFunction func = (ScriptFunction)value;
1926 func.setInitialProto(getFunctionPrototype());
1927 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1928 if (prototype != null) {
1929 prototype.setInitialProto(ObjectPrototype);
1930 }
1931 }
1932 }
1934 // For function valued properties of Object and Object.prototype, make
1935 // sure prototype's proto chain ends with Object.prototype
1936 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
1937 final Object key = property.getKey();
1938 final Object value = builtinObject.get(key);
1940 if (value instanceof ScriptFunction) {
1941 final ScriptFunction func = (ScriptFunction)value;
1942 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1943 if (prototype != null) {
1944 prototype.setInitialProto(ObjectPrototype);
1945 }
1946 }
1947 }
1949 properties = getObjectPrototype().getMap().getProperties();
1950 for (final jdk.nashorn.internal.runtime.Property property : properties) {
1951 final Object key = property.getKey();
1952 final Object value = ObjectPrototype.get(key);
1954 if (key.equals("constructor")) {
1955 continue;
1956 }
1958 if (value instanceof ScriptFunction) {
1959 final ScriptFunction func = (ScriptFunction)value;
1960 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1961 if (prototype != null) {
1962 prototype.setInitialProto(ObjectPrototype);
1963 }
1964 }
1965 }
1966 }
1968 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
1969 return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
1970 }
1972 RegExpResult getLastRegExpResult() {
1973 return lastRegExpResult;
1974 }
1976 void setLastRegExpResult(final RegExpResult regExpResult) {
1977 this.lastRegExpResult = regExpResult;
1978 }
1980 }