Tue, 12 Mar 2013 18:12:42 +0530
8009757: Package access clean up and refactoring
Reviewed-by: jlaskey, lagergren, attila
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.runtime.ECMAErrors.typeError;
29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
30 import static jdk.nashorn.internal.lookup.Lookup.MH;
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.ref.SoftReference;
37 import java.lang.reflect.Field;
38 import java.security.AccessController;
39 import java.security.PrivilegedAction;
40 import java.util.LinkedHashMap;
41 import java.util.List;
42 import java.util.Map;
43 import jdk.internal.dynalink.linker.GuardedInvocation;
44 import jdk.internal.dynalink.linker.LinkRequest;
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.GlobalObject;
52 import jdk.nashorn.internal.runtime.JSType;
53 import jdk.nashorn.internal.runtime.NativeJavaPackage;
54 import jdk.nashorn.internal.runtime.ScriptEnvironment;
55 import jdk.nashorn.internal.runtime.PropertyDescriptor;
56 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
57 import jdk.nashorn.internal.runtime.Scope;
58 import jdk.nashorn.internal.runtime.ScriptFunction;
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.Source;
63 import jdk.nashorn.internal.runtime.linker.InvokeByName;
64 import jdk.nashorn.internal.scripts.JO;
66 /**
67 * Representation of global scope.
68 */
69 @ScriptClass("Global")
70 public final class Global extends ScriptObject implements GlobalObject, Scope {
71 private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
72 private static final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class);
74 /** ECMA 15.1.2.2 parseInt (string , radix) */
75 @Property(attributes = Attribute.NOT_ENUMERABLE)
76 public Object parseInt;
78 /** ECMA 15.1.2.3 parseFloat (string) */
79 @Property(attributes = Attribute.NOT_ENUMERABLE)
80 public Object parseFloat;
82 /** ECMA 15.1.2.4 isNaN (number) */
83 @Property(attributes = Attribute.NOT_ENUMERABLE)
84 public Object isNaN;
86 /** ECMA 15.1.2.5 isFinite (number) */
87 @Property(attributes = Attribute.NOT_ENUMERABLE)
88 public Object isFinite;
90 /** ECMA 15.1.3.3 encodeURI */
91 @Property(attributes = Attribute.NOT_ENUMERABLE)
92 public Object encodeURI;
94 /** ECMA 15.1.3.4 encodeURIComponent */
95 @Property(attributes = Attribute.NOT_ENUMERABLE)
96 public Object encodeURIComponent;
98 /** ECMA 15.1.3.1 decodeURI */
99 @Property(attributes = Attribute.NOT_ENUMERABLE)
100 public Object decodeURI;
102 /** ECMA 15.1.3.2 decodeURIComponent */
103 @Property(attributes = Attribute.NOT_ENUMERABLE)
104 public Object decodeURIComponent;
106 /** ECMA B.2.1 escape (string) */
107 @Property(attributes = Attribute.NOT_ENUMERABLE)
108 public Object escape;
110 /** ECMA B.2.2 unescape (string) */
111 @Property(attributes = Attribute.NOT_ENUMERABLE)
112 public Object unescape;
114 /** Nashorn extension: global.print */
115 @Property(attributes = Attribute.NOT_ENUMERABLE)
116 public Object print;
118 /** Nashorn extension: global.load */
119 @Property(attributes = Attribute.NOT_ENUMERABLE)
120 public Object load;
122 /** Nashorn extension: global.exit */
123 @Property(attributes = Attribute.NOT_ENUMERABLE)
124 public Object exit;
126 /** Nashorn extension: global.quit */
127 @Property(attributes = Attribute.NOT_ENUMERABLE)
128 public Object quit;
130 /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
131 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
132 public final Object NaN = Double.NaN;
134 /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
135 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
136 public final Object Infinity = Double.POSITIVE_INFINITY;
138 /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
139 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
140 public final Object undefined = UNDEFINED;
142 /** ECMA 15.1.2.1 eval(x) */
143 @Property(attributes = Attribute.NOT_ENUMERABLE)
144 public Object eval;
146 /** ECMA 15.1.4.1 Object constructor. */
147 @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
148 public volatile Object object;
150 /** ECMA 15.1.4.2 Function constructor. */
151 @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
152 public volatile Object function;
154 /** ECMA 15.1.4.3 Array constructor. */
155 @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
156 public volatile Object array;
158 /** ECMA 15.1.4.4 String constructor */
159 @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
160 public volatile Object string;
162 /** ECMA 15.1.4.5 Boolean constructor */
163 @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
164 public volatile Object _boolean;
166 /** ECMA 15.1.4.6 - Number constructor */
167 @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
168 public volatile Object number;
170 /** ECMA 15.1.4.7 Date constructor */
171 @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
172 public volatile Object date;
174 /** ECMA 15.1.4.8 RegExp constructor */
175 @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
176 public volatile Object regexp;
178 /** ECMA 15.12 - The JSON object */
179 @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
180 public volatile Object json;
182 /** Nashorn extension: global.JSAdapter */
183 @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
184 public volatile Object jsadapter;
186 /** ECMA 15.8 - The Math object */
187 @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
188 public volatile Object math;
190 /** Error object */
191 @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
192 public volatile Object error;
194 /** EvalError object */
195 @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
196 public volatile Object evalError;
198 /** RangeError object */
199 @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
200 public volatile Object rangeError;
202 /** ReferenceError object */
203 @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
204 public volatile Object referenceError;
206 /** SyntaxError object */
207 @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
208 public volatile Object syntaxError;
210 /** TypeError object */
211 @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
212 public volatile Object typeError;
214 /** URIError object */
215 @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
216 public volatile Object uriError;
218 /** ArrayBuffer object */
219 @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
220 public volatile Object arrayBuffer;
222 /** TypedArray (int8) */
223 @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
224 public volatile Object int8Array;
226 /** TypedArray (uint8) */
227 @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
228 public volatile Object uint8Array;
230 /** TypedArray (uint8) - Clamped */
231 @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
232 public volatile Object uint8ClampedArray;
234 /** TypedArray (int16) */
235 @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
236 public volatile Object int16Array;
238 /** TypedArray (uint16) */
239 @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
240 public volatile Object uint16Array;
242 /** TypedArray (int32) */
243 @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
244 public volatile Object int32Array;
246 /** TypedArray (uint32) */
247 @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
248 public volatile Object uint32Array;
250 /** TypedArray (float32) */
251 @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
252 public volatile Object float32Array;
254 /** TypedArray (float64) */
255 @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
256 public volatile Object float64Array;
258 /** Nashorn extension: Java access - global.Packages */
259 @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
260 public volatile Object packages;
262 /** Nashorn extension: Java access - global.java */
263 @Property(attributes = Attribute.NOT_ENUMERABLE)
264 public volatile Object java;
266 /** Nashorn extension: Java access - global.javax */
267 @Property(attributes = Attribute.NOT_ENUMERABLE)
268 public Object javax;
270 /** Nashorn extension: Java access - global.javaImporter */
271 @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
272 public volatile Object javaImporter;
274 /** Nashorn extension: global.Java Object constructor. */
275 @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
276 public volatile Object javaApi;
278 /** Nashorn extension: current script's file name */
279 @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
280 public Object __FILE__;
282 /** Nashorn extension: current script's directory */
283 @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
284 public Object __DIR__;
286 /** Nashorn extension: current source line number being executed */
287 @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
288 public Object __LINE__;
290 /** Used as Date.prototype's default value */
291 public NativeDate DEFAULT_DATE;
293 /** Used as RegExp.prototype's default value */
294 public NativeRegExp DEFAULT_REGEXP;
296 /*
297 * Built-in constructor objects: Even if user changes dynamic values of
298 * "Object", "Array" etc., we still want to keep original values of these
299 * constructors here. For example, we need to be able to create array,
300 * regexp literals even after user overwrites global "Array" or "RegExp"
301 * constructor - see also ECMA 262 spec. Annex D.
302 */
303 private ScriptFunction builtinFunction;
304 private ScriptFunction builtinObject;
305 private ScriptFunction builtinArray;
306 private ScriptFunction builtinBoolean;
307 private ScriptFunction builtinDate;
308 private ScriptObject builtinJSON;
309 private ScriptFunction builtinJSAdapter;
310 private ScriptObject builtinMath;
311 private ScriptFunction builtinNumber;
312 private ScriptFunction builtinRegExp;
313 private ScriptFunction builtinString;
314 private ScriptFunction builtinError;
315 private ScriptFunction builtinEval;
316 private ScriptFunction builtinEvalError;
317 private ScriptFunction builtinRangeError;
318 private ScriptFunction builtinReferenceError;
319 private ScriptFunction builtinSyntaxError;
320 private ScriptFunction builtinTypeError;
321 private ScriptFunction builtinURIError;
322 private ScriptObject builtinPackages;
323 private ScriptObject builtinJava;
324 private ScriptObject builtinJavax;
325 private ScriptObject builtinJavaImporter;
326 private ScriptObject builtinJavaApi;
327 private ScriptObject builtinArrayBuffer;
328 private ScriptObject builtinInt8Array;
329 private ScriptObject builtinUint8Array;
330 private ScriptObject builtinUint8ClampedArray;
331 private ScriptObject builtinInt16Array;
332 private ScriptObject builtinUint16Array;
333 private ScriptObject builtinInt32Array;
334 private ScriptObject builtinUint32Array;
335 private ScriptObject builtinFloat32Array;
336 private ScriptObject builtinFloat64Array;
338 // Flag to indicate that a split method issued a return statement
339 private int splitState = -1;
341 // class cache
342 private ClassCache classCache;
344 // Used to store the last RegExp result to support deprecated RegExp constructor properties
345 private RegExpResult lastRegExpResult;
347 private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class);
348 private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class);
349 private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
350 private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class);
351 private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
353 private final Context context;
355 /**
356 * Constructor
357 *
358 * @param context the context
359 */
360 public Global(final Context context) {
361 this.context = context;
362 this.setIsScope();
363 /*
364 * Duplicate global's map and use it. This way the initial Map filled
365 * by nasgen (referenced from static field in this class) is retained
366 * 'as is'. This allows multiple globals to be used within a context.
367 */
368 this.setMap(getMap().duplicate());
370 final int cacheSize = context.getEnv()._class_cache_size;
371 if (cacheSize > 0) {
372 classCache = new ClassCache(cacheSize);
373 }
374 }
376 /**
377 * Script access to "current" Global instance
378 *
379 * @return the global singleton
380 */
381 public static Global instance() {
382 ScriptObject global = Context.getGlobal();
383 if (! (global instanceof Global)) {
384 throw new IllegalStateException("no current global instance");
385 }
386 return (Global)global;
387 }
389 /**
390 * Script access to {@link ScriptEnvironment}
391 *
392 * @return the script environment
393 */
394 static ScriptEnvironment getEnv() {
395 return instance().context.getEnv();
396 }
398 /**
399 * Script access to {@link Context}
400 *
401 * @return the context
402 */
403 static Context getThisContext() {
404 return instance().context;
405 }
407 /**
408 * Script access check for strict mode
409 *
410 * @return true if strict mode enabled in {@link Global#getThisContext()}
411 */
412 static boolean isStrict() {
413 return getEnv()._strict;
414 }
416 // GlobalObject interface implementation
418 @Override
419 public void initBuiltinObjects() {
420 if (this.builtinObject != null) {
421 // already initialized, just return
422 return;
423 }
425 init();
426 }
428 @Override
429 public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
430 return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
431 }
433 @Override
434 public Object wrapAsObject(final Object obj) {
435 if (obj instanceof Boolean) {
436 return new NativeBoolean((Boolean)obj);
437 } else if (obj instanceof Number) {
438 return new NativeNumber(((Number)obj).doubleValue());
439 } else if (obj instanceof String || obj instanceof ConsString) {
440 return new NativeString((CharSequence)obj);
441 } else if (obj instanceof Object[]) { // extension
442 return new NativeArray((Object[])obj);
443 } else if (obj instanceof double[]) { // extension
444 return new NativeArray((double[])obj);
445 } else if (obj instanceof long[]) {
446 return new NativeArray((long[])obj);
447 } else if (obj instanceof int[]) {
448 return new NativeArray((int[])obj);
449 } else {
450 // FIXME: more special cases? Map? List?
451 return obj;
452 }
453 }
455 @Override
456 public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
457 if (self instanceof String || self instanceof ConsString) {
458 return NativeString.lookupPrimitive(request, self);
459 } else if (self instanceof Number) {
460 return NativeNumber.lookupPrimitive(request, self);
461 } else if (self instanceof Boolean) {
462 return NativeBoolean.lookupPrimitive(request, self);
463 }
464 throw new IllegalArgumentException("Unsupported primitive: " + self);
465 }
467 @Override
468 public ScriptObject newObject() {
469 return newEmptyInstance();
470 }
472 @Override
473 public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
474 // When the [[DefaultValue]] internal method of O is called with no hint,
475 // then it behaves as if the hint were Number, unless O is a Date object
476 // in which case it behaves as if the hint were String.
477 Class<?> hint = typeHint;
478 if (hint == null) {
479 hint = Number.class;
480 }
482 try {
483 if (hint == String.class) {
485 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
486 if (toString instanceof ScriptFunction) {
487 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
488 if (JSType.isPrimitive(value)) {
489 return value;
490 }
491 }
493 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
494 if (valueOf instanceof ScriptFunction) {
495 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
496 if (JSType.isPrimitive(value)) {
497 return value;
498 }
499 }
500 throw typeError(this, "cannot.get.default.string");
501 }
503 if (hint == Number.class) {
504 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
505 if (valueOf instanceof ScriptFunction) {
506 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
507 if (JSType.isPrimitive(value)) {
508 return value;
509 }
510 }
512 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
513 if (toString instanceof ScriptFunction) {
514 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
515 if (JSType.isPrimitive(value)) {
516 return value;
517 }
518 }
520 throw typeError(this, "cannot.get.default.number");
521 }
522 } catch (final RuntimeException | Error e) {
523 throw e;
524 } catch (final Throwable t) {
525 throw new RuntimeException(t);
526 }
528 return UNDEFINED;
529 }
531 @Override
532 public boolean isError(final ScriptObject sobj) {
533 final ScriptObject errorProto = getErrorPrototype();
534 ScriptObject proto = sobj.getProto();
535 while (proto != null) {
536 if (proto == errorProto) {
537 return true;
538 }
539 proto = proto.getProto();
540 }
541 return false;
542 }
544 @Override
545 public ScriptObject newError(final String msg) {
546 return new NativeError(msg);
547 }
549 @Override
550 public ScriptObject newEvalError(final String msg) {
551 return new NativeEvalError(msg);
552 }
554 @Override
555 public ScriptObject newRangeError(final String msg) {
556 return new NativeRangeError(msg);
557 }
559 @Override
560 public ScriptObject newReferenceError(final String msg) {
561 return new NativeReferenceError(msg);
562 }
564 @Override
565 public ScriptObject newSyntaxError(final String msg) {
566 return new NativeSyntaxError(msg);
567 }
569 @Override
570 public ScriptObject newTypeError(final String msg) {
571 return new NativeTypeError(msg);
572 }
574 @Override
575 public ScriptObject newURIError(final String msg) {
576 return new NativeURIError(msg);
577 }
579 @Override
580 public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
581 return new GenericPropertyDescriptor(configurable, enumerable);
582 }
584 @Override
585 public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
586 return new DataPropertyDescriptor(configurable, enumerable, writable, value);
587 }
589 @Override
590 public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
591 final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set);
593 final boolean strict = context.getEnv()._strict;
595 if (get == null) {
596 desc.delete(PropertyDescriptor.GET, strict);
597 }
599 if (set == null) {
600 desc.delete(PropertyDescriptor.SET, strict);
601 }
603 return desc;
604 }
607 /**
608 * Cache for compiled script classes.
609 */
610 @SuppressWarnings("serial")
611 private static class ClassCache extends LinkedHashMap<Source, SoftReference<Class<?>>> {
612 private final int size;
614 ClassCache(int size) {
615 super(size, 0.75f, true);
616 this.size = size;
617 }
619 @Override
620 protected boolean removeEldestEntry(final Map.Entry<Source, SoftReference<Class<?>>> eldest) {
621 return size() >= size;
622 }
623 }
625 // Class cache management
626 @Override
627 public Class<?> findCachedClass(final Source source) {
628 assert classCache != null : "Class cache used without being initialized";
629 SoftReference<Class<?>> ref = classCache.get(source);
630 if (ref != null) {
631 final Class<?> clazz = ref.get();
632 if (clazz == null) {
633 classCache.remove(source);
634 }
635 return clazz;
636 }
638 return null;
639 }
641 @Override
642 public void cacheClass(final Source source, final Class<?> clazz) {
643 assert classCache != null : "Class cache used without being initialized";
644 classCache.put(source, new SoftReference<Class<?>>(clazz));
645 }
647 /**
648 * This is the eval used when 'indirect' eval call is made.
649 *
650 * var global = this;
651 * global.eval("print('hello')");
652 *
653 * @param self eval scope
654 * @param str eval string
655 *
656 * @return the result of eval
657 */
658 public static Object eval(final Object self, final Object str) {
659 return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
660 }
662 /**
663 * Direct eval
664 *
665 * @param self The scope of eval passed as 'self'
666 * @param str Evaluated code
667 * @param callThis "this" to be passed to the evaluated code
668 * @param location location of the eval call
669 * @param strict is eval called a strict mode code?
670 *
671 * @return the return value of the eval
672 *
673 * This is directly invoked from generated when eval(code) is called in user code
674 */
675 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
676 if (!(str instanceof String || str instanceof ConsString)) {
677 return str;
678 }
679 final Global global = Global.instance();
680 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
682 return global.context.eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
683 }
685 /**
686 * Global print implementation - Nashorn extension
687 *
688 * @param self scope
689 * @param objects arguments to print
690 *
691 * @return result of print (undefined)
692 */
693 public static Object print(final Object self, final Object... objects) {
694 return printImpl(false, objects);
695 }
697 /**
698 * Global println implementation - Nashorn extension
699 *
700 * @param self scope
701 * @param objects arguments to print
702 *
703 * @return result of println (undefined)
704 */
705 public static Object println(final Object self, final Object... objects) {
706 return printImpl(true, objects);
707 }
709 /**
710 * Global load implementation - Nashorn extension
711 *
712 * @param self scope
713 * @param source source to load
714 *
715 * @return result of load (undefined)
716 *
717 * @throws IOException if source could not be read
718 */
719 public static Object load(final Object self, final Object source) throws IOException {
720 final Global global = Global.instance();
721 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
722 return global.context.load(scope, source);
723 }
725 /**
726 * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
727 *
728 * @param self self reference
729 * @param code exit code
730 *
731 * @return undefined (will never be reacheD)
732 */
733 public static Object exit(final Object self, final Object code) {
734 System.exit(JSType.toInt32(code));
735 return UNDEFINED;
736 }
738 ScriptObject getFunctionPrototype() {
739 return ScriptFunction.getPrototype(builtinFunction);
740 }
742 ScriptObject getObjectPrototype() {
743 return ScriptFunction.getPrototype(builtinObject);
744 }
746 ScriptObject getArrayPrototype() {
747 return ScriptFunction.getPrototype(builtinArray);
748 }
750 ScriptObject getBooleanPrototype() {
751 return ScriptFunction.getPrototype(builtinBoolean);
752 }
754 ScriptObject getNumberPrototype() {
755 return ScriptFunction.getPrototype(builtinNumber);
756 }
758 ScriptObject getDatePrototype() {
759 return ScriptFunction.getPrototype(builtinDate);
760 }
762 ScriptObject getRegExpPrototype() {
763 return ScriptFunction.getPrototype(builtinRegExp);
764 }
766 ScriptObject getStringPrototype() {
767 return ScriptFunction.getPrototype(builtinString);
768 }
770 ScriptObject getErrorPrototype() {
771 return ScriptFunction.getPrototype(builtinError);
772 }
774 ScriptObject getEvalErrorPrototype() {
775 return ScriptFunction.getPrototype(builtinEvalError);
776 }
778 ScriptObject getRangeErrorPrototype() {
779 return ScriptFunction.getPrototype(builtinRangeError);
780 }
782 ScriptObject getReferenceErrorPrototype() {
783 return ScriptFunction.getPrototype(builtinReferenceError);
784 }
786 ScriptObject getSyntaxErrorPrototype() {
787 return ScriptFunction.getPrototype(builtinSyntaxError);
788 }
790 ScriptObject getTypeErrorPrototype() {
791 return ScriptFunction.getPrototype(builtinTypeError);
792 }
794 ScriptObject getURIErrorPrototype() {
795 return ScriptFunction.getPrototype(builtinURIError);
796 }
798 ScriptObject getJavaImporterPrototype() {
799 return ScriptFunction.getPrototype(builtinJavaImporter);
800 }
802 ScriptObject getJSAdapterPrototype() {
803 return ScriptFunction.getPrototype(builtinJSAdapter);
804 }
806 ScriptObject getArrayBufferPrototype() {
807 return ScriptFunction.getPrototype(builtinArrayBuffer);
808 }
810 ScriptObject getInt8ArrayPrototype() {
811 return ScriptFunction.getPrototype(builtinInt8Array);
812 }
814 ScriptObject getUint8ArrayPrototype() {
815 return ScriptFunction.getPrototype(builtinUint8Array);
816 }
818 ScriptObject getUint8ClampedArrayPrototype() {
819 return ScriptFunction.getPrototype(builtinUint8ClampedArray);
820 }
822 ScriptObject getInt16ArrayPrototype() {
823 return ScriptFunction.getPrototype(builtinInt16Array);
824 }
826 ScriptObject getUint16ArrayPrototype() {
827 return ScriptFunction.getPrototype(builtinUint16Array);
828 }
830 ScriptObject getInt32ArrayPrototype() {
831 return ScriptFunction.getPrototype(builtinInt32Array);
832 }
834 ScriptObject getUint32ArrayPrototype() {
835 return ScriptFunction.getPrototype(builtinUint32Array);
836 }
838 ScriptObject getFloat32ArrayPrototype() {
839 return ScriptFunction.getPrototype(builtinFloat32Array);
840 }
842 ScriptObject getFloat64ArrayPrototype() {
843 return ScriptFunction.getPrototype(builtinFloat64Array);
844 }
846 private ScriptFunction getBuiltinArray() {
847 return builtinArray;
848 }
851 /**
852 * Called from compiled script code to test if builtin has been overridden
853 *
854 * @return true if builtin array has not been overridden
855 */
856 public static boolean isBuiltinArray() {
857 final Global instance = Global.instance();
858 return instance.array == instance.getBuiltinArray();
859 }
861 private ScriptFunction getBuiltinBoolean() {
862 return builtinBoolean;
863 }
865 /**
866 * Called from compiled script code to test if builtin has been overridden
867 *
868 * @return true if builtin boolean has not been overridden
869 */
870 public static boolean isBuiltinBoolean() {
871 final Global instance = Global.instance();
872 return instance._boolean == instance.getBuiltinBoolean();
873 }
875 private ScriptFunction getBuiltinDate() {
876 return builtinDate;
877 }
879 /**
880 * Called from compiled script code to test if builtin has been overridden
881 *
882 * @return true if builtin date has not been overridden
883 */
884 public static boolean isBuiltinDate() {
885 final Global instance = Global.instance();
886 return instance.date == instance.getBuiltinDate();
887 }
889 private ScriptFunction getBuiltinError() {
890 return builtinError;
891 }
893 /**
894 * Called from compiled script code to test if builtin has been overridden
895 *
896 * @return true if builtin error has not been overridden
897 */
898 public static boolean isBuiltinError() {
899 final Global instance = Global.instance();
900 return instance.error == instance.getBuiltinError();
901 }
903 private ScriptFunction getBuiltinEvalError() {
904 return builtinEvalError;
905 }
907 /**
908 * Called from compiled script code to test if builtin has been overridden
909 *
910 * @return true if builtin eval error has not been overridden
911 */
912 public static boolean isBuiltinEvalError() {
913 final Global instance = Global.instance();
914 return instance.evalError == instance.getBuiltinEvalError();
915 }
917 private ScriptFunction getBuiltinFunction() {
918 return builtinFunction;
919 }
921 /**
922 * Called from compiled script code to test if builtin has been overridden
923 *
924 * @return true if builtin function has not been overridden
925 */
926 public static boolean isBuiltinFunction() {
927 final Global instance = Global.instance();
928 return instance.function == instance.getBuiltinFunction();
929 }
931 private ScriptFunction getBuiltinJSAdapter() {
932 return builtinJSAdapter;
933 }
935 /**
936 * Called from compiled script code to test if builtin has been overridden
937 *
938 * @return true if builtin JSAdapter has not been overridden
939 */
940 public static boolean isBuiltinJSAdapter() {
941 final Global instance = Global.instance();
942 return instance.jsadapter == instance.getBuiltinJSAdapter();
943 }
945 private ScriptObject getBuiltinJSON() {
946 return builtinJSON;
947 }
949 /**
950 * Called from compiled script code to test if builtin has been overridden
951 *
952 * @return true if builtin JSON has has not been overridden
953 */
954 public static boolean isBuiltinJSON() {
955 final Global instance = Global.instance();
956 return instance.json == instance.getBuiltinJSON();
957 }
959 private ScriptObject getBuiltinJava() {
960 return builtinJava;
961 }
963 /**
964 * Called from compiled script code to test if builtin has been overridden
965 *
966 * @return true if builtin Java has not been overridden
967 */
968 public static boolean isBuiltinJava() {
969 final Global instance = Global.instance();
970 return instance.java == instance.getBuiltinJava();
971 }
973 private ScriptObject getBuiltinJavax() {
974 return builtinJavax;
975 }
977 /**
978 * Called from compiled script code to test if builtin has been overridden
979 *
980 * @return true if builtin Javax has not been overridden
981 */
982 public static boolean isBuiltinJavax() {
983 final Global instance = Global.instance();
984 return instance.javax == instance.getBuiltinJavax();
985 }
987 private ScriptObject getBuiltinJavaImporter() {
988 return builtinJavaImporter;
989 }
991 /**
992 * Called from compiled script code to test if builtin has been overridden
993 *
994 * @return true if builtin Java importer has not been overridden
995 */
996 public static boolean isBuiltinJavaImporter() {
997 final Global instance = Global.instance();
998 return instance.javaImporter == instance.getBuiltinJavaImporter();
999 }
1001 private ScriptObject getBuiltinMath() {
1002 return builtinMath;
1003 }
1005 /**
1006 * Called from compiled script code to test if builtin has been overridden
1007 *
1008 * @return true if builtin math has not been overridden
1009 */
1010 public static boolean isBuiltinMath() {
1011 final Global instance = Global.instance();
1012 return instance.math == instance.getBuiltinMath();
1013 }
1015 private ScriptFunction getBuiltinNumber() {
1016 return builtinNumber;
1017 }
1019 /**
1020 * Called from compiled script code to test if builtin has been overridden
1021 *
1022 * @return true if builtin number has not been overridden
1023 */
1024 public static boolean isBuiltinNumber() {
1025 final Global instance = Global.instance();
1026 return instance.number == instance.getBuiltinNumber();
1027 }
1029 private ScriptFunction getBuiltinObject() {
1030 return builtinObject;
1031 }
1033 /**
1034 * Called from compiled script code to test if builtin has been overridden
1035 *
1036 * @return true if builtin object has not been overridden
1037 */
1038 public static boolean isBuiltinObject() {
1039 final Global instance = Global.instance();
1040 return instance.object == instance.getBuiltinObject();
1041 }
1043 private ScriptObject getBuiltinPackages() {
1044 return builtinPackages;
1045 }
1047 /**
1048 * Called from compiled script code to test if builtin has been overridden
1049 *
1050 * @return true if builtin package has not been overridden
1051 */
1052 public static boolean isBuiltinPackages() {
1053 final Global instance = Global.instance();
1054 return instance.packages == instance.getBuiltinPackages();
1055 }
1057 private ScriptFunction getBuiltinRangeError() {
1058 return builtinRangeError;
1059 }
1061 /**
1062 * Called from compiled script code to test if builtin has been overridden
1063 *
1064 * @return true if builtin range error has not been overridden
1065 */
1066 public static boolean isBuiltinRangeError() {
1067 final Global instance = Global.instance();
1068 return instance.rangeError == instance.getBuiltinRangeError();
1069 }
1071 private ScriptFunction getBuiltinReferenceError() {
1072 return builtinReferenceError;
1073 }
1075 /**
1076 * Called from compiled script code to test if builtin has been overridden
1077 *
1078 * @return true if builtin reference error has not been overridden
1079 */
1080 public static boolean isBuiltinReferenceError() {
1081 final Global instance = Global.instance();
1082 return instance.referenceError == instance.getBuiltinReferenceError();
1083 }
1085 private ScriptFunction getBuiltinRegExp() {
1086 return builtinRegExp;
1087 }
1089 /**
1090 * Called from compiled script code to test if builtin has been overridden
1091 *
1092 * @return true if builtin regexp has not been overridden
1093 */
1094 public static boolean isBuiltinRegExp() {
1095 final Global instance = Global.instance();
1096 return instance.regexp == instance.getBuiltinRegExp();
1097 }
1099 private ScriptFunction getBuiltinString() {
1100 return builtinString;
1101 }
1103 /**
1104 * Called from compiled script code to test if builtin has been overridden
1105 *
1106 * @return true if builtin Java has not been overridden
1107 */
1108 public static boolean isBuiltinString() {
1109 final Global instance = Global.instance();
1110 return instance.string == instance.getBuiltinString();
1111 }
1113 private ScriptFunction getBuiltinSyntaxError() {
1114 return builtinSyntaxError;
1115 }
1117 /**
1118 * Called from compiled script code to test if builtin has been overridden
1119 *
1120 * @return true if builtin syntax error has not been overridden
1121 */
1122 public static boolean isBuiltinSyntaxError() {
1123 final Global instance = Global.instance();
1124 return instance.syntaxError == instance.getBuiltinSyntaxError();
1125 }
1127 private ScriptFunction getBuiltinTypeError() {
1128 return builtinTypeError;
1129 }
1131 /**
1132 * Called from compiled script code to test if builtin has been overridden
1133 *
1134 * @return true if builtin type error has not been overridden
1135 */
1136 public static boolean isBuiltinTypeError() {
1137 final Global instance = Global.instance();
1138 return instance.typeError == instance.getBuiltinTypeError();
1139 }
1141 private ScriptFunction getBuiltinURIError() {
1142 return builtinURIError;
1143 }
1145 /**
1146 * Called from compiled script code to test if builtin has been overridden
1147 *
1148 * @return true if builtin URI error has not been overridden
1149 */
1150 public static boolean isBuiltinURIError() {
1151 final Global instance = Global.instance();
1152 return instance.uriError == instance.getBuiltinURIError();
1153 }
1155 @Override
1156 public String getClassName() {
1157 return "global";
1158 }
1160 /**
1161 * Copy function used to clone NativeRegExp objects.
1162 *
1163 * @param regexp a NativeRegExp to clone
1164 *
1165 * @return copy of the given regexp object
1166 */
1167 public static Object regExpCopy(final Object regexp) {
1168 return new NativeRegExp((NativeRegExp)regexp);
1169 }
1171 /**
1172 * Convert given object to NativeRegExp type.
1173 *
1174 * @param obj object to be converted
1175 * @return NativeRegExp instance
1176 */
1177 public static NativeRegExp toRegExp(final Object obj) {
1178 if (obj instanceof NativeRegExp) {
1179 return (NativeRegExp)obj;
1180 }
1181 return new NativeRegExp(JSType.toString(obj));
1182 }
1184 /**
1185 * ECMA 9.9 ToObject implementation
1186 *
1187 * @param obj an item for which to run ToObject
1188 * @return ToObject version of given item
1189 */
1190 public static Object toObject(final Object obj) {
1191 if (obj == null || obj == UNDEFINED) {
1192 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1193 }
1195 if (obj instanceof ScriptObject) {
1196 return obj;
1197 }
1199 return instance().wrapAsObject(obj);
1200 }
1202 /**
1203 * Allocate a new object array.
1204 *
1205 * @param initial object values.
1206 * @return the new array
1207 */
1208 public static NativeArray allocate(final Object[] initial) {
1209 return new NativeArray(initial);
1210 }
1212 /**
1213 * Allocate a new number array.
1214 *
1215 * @param initial number values.
1216 * @return the new array
1217 */
1218 public static NativeArray allocate(final double[] initial) {
1219 return new NativeArray(initial);
1220 }
1222 /**
1223 * Allocate a new long array.
1224 *
1225 * @param initial number values.
1226 * @return the new array
1227 */
1228 public static NativeArray allocate(final long[] initial) {
1229 return new NativeArray(initial);
1230 }
1232 /**
1233 * Allocate a new integer array.
1234 *
1235 * @param initial number values.
1236 * @return the new array
1237 */
1238 public static NativeArray allocate(final int[] initial) {
1239 return new NativeArray(initial);
1240 }
1242 /**
1243 * Allocate a new object array for arguments.
1244 *
1245 * @param arguments initial arguments passed.
1246 * @param callee reference to the function that uses arguments object
1247 * @param numParams actual number of declared parameters
1248 *
1249 * @return the new array
1250 */
1251 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1252 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1253 }
1255 /**
1256 * Called from generated to check if given function is the builtin 'eval'. If
1257 * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1258 *
1259 * @param fn function object that is checked
1260 * @return true if fn is the builtin eval
1261 */
1262 public static boolean isEval(final Object fn) {
1263 return fn == Global.instance().builtinEval;
1264 }
1266 /**
1267 * Create a new RegExp object.
1268 *
1269 * @param expression Regular expression.
1270 * @param options Search options.
1271 *
1272 * @return New RegExp object.
1273 */
1274 public static Object newRegExp(final String expression, final String options) {
1275 if (options == null) {
1276 return new NativeRegExp(expression);
1277 }
1278 return new NativeRegExp(expression, options);
1279 }
1281 /**
1282 * Get the object prototype
1283 *
1284 * @return the object prototype
1285 */
1286 public static ScriptObject objectPrototype() {
1287 return Global.instance().getObjectPrototype();
1288 }
1290 /**
1291 * Create a new empty object instance.
1292 *
1293 * @return New empty object.
1294 */
1295 public static ScriptObject newEmptyInstance() {
1296 final ScriptObject sobj = new JO();
1297 sobj.setProto(objectPrototype());
1298 return sobj;
1299 }
1301 /**
1302 * Check if a given object is a ScriptObject, raises an exception if this is
1303 * not the case
1304 *
1305 * @param obj and object to check
1306 */
1307 public static void checkObject(final Object obj) {
1308 if (!(obj instanceof ScriptObject)) {
1309 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1310 }
1311 }
1313 /**
1314 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1315 * if this object is null or undefined.
1316 *
1317 * @param obj an object to check
1318 */
1319 public static void checkObjectCoercible(final Object obj) {
1320 if (obj == null || obj == UNDEFINED) {
1321 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1322 }
1323 }
1325 /**
1326 * Get the current split state.
1327 *
1328 * @return current split state
1329 */
1330 @Override
1331 public int getSplitState() {
1332 return splitState;
1333 }
1335 /**
1336 * Set the current split state.
1337 *
1338 * @param state current split state
1339 */
1340 @Override
1341 public void setSplitState(final int state) {
1342 splitState = state;
1343 }
1345 private void init() {
1346 assert Context.getGlobal() == this : "this global is not set as current";
1348 final ScriptEnvironment env = context.getEnv();
1349 // initialize Function and Object constructor
1350 initFunctionAndObject();
1352 // Now fix Global's own proto.
1353 this.setProto(getObjectPrototype());
1355 // initialize global function properties
1356 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1358 this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT);
1359 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1360 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN);
1361 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE);
1362 this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI);
1363 this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1364 this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI);
1365 this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1366 this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE);
1367 this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
1368 this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN);
1369 this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
1370 this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT);
1371 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
1373 // built-in constructors
1374 this.builtinArray = (ScriptFunction)initConstructor("Array");
1375 this.builtinBoolean = (ScriptFunction)initConstructor("Boolean");
1376 this.builtinDate = (ScriptFunction)initConstructor("Date");
1377 this.builtinJSON = initConstructor("JSON");
1378 this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
1379 this.builtinMath = initConstructor("Math");
1380 this.builtinNumber = (ScriptFunction)initConstructor("Number");
1381 this.builtinRegExp = (ScriptFunction)initConstructor("RegExp");
1382 this.builtinString = (ScriptFunction)initConstructor("String");
1384 // initialize String.prototype.length to 0
1385 // add String.prototype.length
1386 final ScriptObject stringPrototype = getStringPrototype();
1387 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1389 // add Array.prototype.length
1390 final ScriptObject arrayPrototype = getArrayPrototype();
1391 arrayPrototype.addOwnProperty("length", Attribute.NOT_ENUMERABLE|Attribute.NOT_CONFIGURABLE, 0.0);
1393 this.DEFAULT_DATE = new NativeDate(Double.NaN);
1395 // initialize default regexp object
1396 this.DEFAULT_REGEXP = new NativeRegExp("(?:)");
1398 // RegExp.prototype should behave like a RegExp object. So copy the
1399 // properties.
1400 final ScriptObject regExpProto = getRegExpPrototype();
1401 regExpProto.addBoundProperties(DEFAULT_REGEXP);
1403 // Error stuff
1404 initErrorObjects();
1406 // java access
1407 initJavaAccess();
1409 initTypedArray();
1411 if (env._scripting) {
1412 initScripting();
1413 }
1415 if (Context.DEBUG && System.getSecurityManager() == null) {
1416 initDebug();
1417 }
1419 copyBuiltins();
1421 // initialized with strings so that typeof will work as expected.
1422 this.__FILE__ = "";
1423 this.__DIR__ = "";
1424 this.__LINE__ = 0.0;
1426 // expose script (command line) arguments as "arguments" property of global
1427 final List<String> arguments = env.getArguments();
1428 final Object argsObj = wrapAsObject(arguments.toArray());
1430 addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
1431 if (env._scripting) {
1432 // synonym for "arguments" in scripting mode
1433 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
1434 }
1435 }
1437 private void initErrorObjects() {
1438 // Error objects
1439 this.builtinError = (ScriptFunction)initConstructor("Error");
1440 final ScriptObject errorProto = getErrorPrototype();
1441 final boolean strict = Global.isStrict();
1443 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1444 final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1445 final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1446 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1447 final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1448 final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1449 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1450 final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1451 final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1452 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1453 final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1454 final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1455 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1457 // ECMA 15.11.4.2 Error.prototype.name
1458 // Error.prototype.name = "Error";
1459 errorProto.set(NativeError.NAME, "Error", strict);
1460 // ECMA 15.11.4.3 Error.prototype.message
1461 // Error.prototype.message = "";
1462 errorProto.set(NativeError.MESSAGE, "", strict);
1464 this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1465 this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1466 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1467 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1468 this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1469 this.builtinURIError = initErrorSubtype("URIError", errorProto);
1470 }
1472 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1473 final ScriptObject cons = initConstructor(name);
1474 final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1475 final boolean strict = Global.isStrict();
1476 prototype.set(NativeError.NAME, name, strict);
1477 prototype.set(NativeError.MESSAGE, "", strict);
1478 prototype.setProto(errorProto);
1479 return (ScriptFunction)cons;
1480 }
1482 private void initJavaAccess() {
1483 final ScriptObject objectProto = getObjectPrototype();
1484 this.builtinPackages = new NativeJavaPackage("", objectProto);
1485 this.builtinJava = new NativeJavaPackage("java", objectProto);
1486 this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1487 this.builtinJavaImporter = initConstructor("JavaImporter");
1488 this.builtinJavaApi = initConstructor("Java");
1489 }
1491 private void initScripting() {
1492 Object value;
1493 value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1494 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1496 value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1497 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1499 final String execName = ScriptingFunctions.EXEC_NAME;
1500 value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1501 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1503 // Nashorn extension: global.echo (scripting-mode-only)
1504 // alias for "print"
1505 value = get("print");
1506 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1508 // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1509 final ScriptObject options = newEmptyInstance();
1510 final ScriptEnvironment scriptEnv = context.getEnv();
1511 copyOptions(options, scriptEnv);
1512 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1514 // Nashorn extension: global.$ENV (scripting-mode-only)
1515 if (System.getSecurityManager() == null) {
1516 // do not fill $ENV if we have a security manager around
1517 // Retrieve current state of ENV variables.
1518 final ScriptObject env = newEmptyInstance();
1519 env.putAll(System.getenv());
1520 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1521 } else {
1522 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1523 }
1525 // add other special properties for exec support
1526 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1527 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1528 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1529 }
1531 private void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1532 AccessController.doPrivileged(new PrivilegedAction<Void>() {
1533 public Void run() {
1534 for (Field f : scriptEnv.getClass().getFields()) {
1535 try {
1536 options.set(f.getName(), f.get(scriptEnv), false);
1537 } catch (final IllegalArgumentException | IllegalAccessException exp) {
1538 throw new RuntimeException(exp);
1539 }
1540 }
1541 return null;
1542 }
1543 });
1544 }
1546 private void initTypedArray() {
1547 this.builtinArrayBuffer = initConstructor("ArrayBuffer");
1548 this.builtinInt8Array = initConstructor("Int8Array");
1549 this.builtinUint8Array = initConstructor("Uint8Array");
1550 this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
1551 this.builtinInt16Array = initConstructor("Int16Array");
1552 this.builtinUint16Array = initConstructor("Uint16Array");
1553 this.builtinInt32Array = initConstructor("Int32Array");
1554 this.builtinUint32Array = initConstructor("Uint32Array");
1555 this.builtinFloat32Array = initConstructor("Float32Array");
1556 this.builtinFloat64Array = initConstructor("Float64Array");
1557 }
1559 private void copyBuiltins() {
1560 this.array = this.builtinArray;
1561 this._boolean = this.builtinBoolean;
1562 this.date = this.builtinDate;
1563 this.error = this.builtinError;
1564 this.evalError = this.builtinEvalError;
1565 this.function = this.builtinFunction;
1566 this.jsadapter = this.builtinJSAdapter;
1567 this.json = this.builtinJSON;
1568 this.java = this.builtinJava;
1569 this.javax = this.builtinJavax;
1570 this.javaImporter = this.builtinJavaImporter;
1571 this.javaApi = this.builtinJavaApi;
1572 this.math = this.builtinMath;
1573 this.number = this.builtinNumber;
1574 this.object = this.builtinObject;
1575 this.packages = this.builtinPackages;
1576 this.rangeError = this.builtinRangeError;
1577 this.referenceError = this.builtinReferenceError;
1578 this.regexp = this.builtinRegExp;
1579 this.string = this.builtinString;
1580 this.syntaxError = this.builtinSyntaxError;
1581 this.typeError = this.builtinTypeError;
1582 this.uriError = this.builtinURIError;
1583 this.arrayBuffer = this.builtinArrayBuffer;
1584 this.int8Array = this.builtinInt8Array;
1585 this.uint8Array = this.builtinUint8Array;
1586 this.uint8ClampedArray = this.builtinUint8ClampedArray;
1587 this.int16Array = this.builtinInt16Array;
1588 this.uint16Array = this.builtinUint16Array;
1589 this.int32Array = this.builtinInt32Array;
1590 this.uint32Array = this.builtinUint32Array;
1591 this.float32Array = this.builtinFloat32Array;
1592 this.float64Array = this.builtinFloat64Array;
1593 }
1595 private void initDebug() {
1596 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
1597 }
1599 @SuppressWarnings("resource")
1600 private static Object printImpl(final boolean newLine, final Object... objects) {
1601 final PrintWriter out = Global.getEnv().getOut();
1603 boolean first = true;
1604 for (final Object object : objects) {
1605 if (first) {
1606 first = false;
1607 } else {
1608 out.print(' ');
1609 }
1611 out.print(JSType.toString(object));
1612 }
1614 if (newLine) {
1615 out.println();
1616 }
1618 out.flush();
1620 return UNDEFINED;
1621 }
1623 /**
1624 * These classes are generated by nasgen tool and so we have to use
1625 * reflection to load and create new instance of these classes.
1626 */
1627 private ScriptObject initConstructor(final String name) {
1628 try {
1629 // Assuming class name pattern for built-in JS constructors.
1630 final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
1632 sb.append("Native");
1633 sb.append(name);
1634 sb.append("$Constructor");
1636 final Class<?> funcClass = Class.forName(sb.toString());
1637 final ScriptObject res = (ScriptObject)funcClass.newInstance();
1639 if (res instanceof ScriptFunction) {
1640 // All global constructor prototypes are not-writable,
1641 // not-enumerable and not-configurable.
1642 final ScriptFunction func = (ScriptFunction)res;
1643 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
1644 }
1646 if (res.getProto() == null) {
1647 res.setProto(getObjectPrototype());
1648 }
1650 return res;
1652 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
1653 throw new RuntimeException(e);
1654 }
1655 }
1657 // Function and Object constructors are inter-dependent. Also,
1658 // Function.prototype
1659 // functions are not properly initialized. We fix the references here.
1660 // NOTE: be careful if you want to re-order the operations here. You may
1661 // have
1662 // to play with object references carefully!!
1663 private void initFunctionAndObject() {
1664 // First-n-foremost is Function
1665 this.builtinFunction = (ScriptFunction)initConstructor("Function");
1667 // create global anonymous function
1668 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
1669 // need to copy over members of Function.prototype to anon function
1670 anon.addBoundProperties(getFunctionPrototype());
1672 // Function.prototype === Object.getPrototypeOf(Function) ===
1673 // <anon-function>
1674 builtinFunction.setProto(anon);
1675 builtinFunction.setPrototype(anon);
1676 anon.set("constructor", builtinFunction, anon.isStrict());
1677 anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
1679 // now initialize Object
1680 this.builtinObject = (ScriptFunction)initConstructor("Object");
1681 final ScriptObject ObjectPrototype = getObjectPrototype();
1682 // Object.getPrototypeOf(Function.prototype) === Object.prototype
1683 anon.setProto(ObjectPrototype);
1685 // Function valued properties of Function.prototype were not properly
1686 // initialized. Because, these were created before global.function and
1687 // global.object were not initialized.
1688 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
1689 for (final jdk.nashorn.internal.runtime.Property property : properties) {
1690 final Object key = property.getKey();
1691 final Object value = builtinFunction.get(key);
1693 if (value instanceof ScriptFunction && value != anon) {
1694 final ScriptFunction func = (ScriptFunction)value;
1695 func.setProto(getFunctionPrototype());
1696 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1697 if (prototype != null) {
1698 prototype.setProto(ObjectPrototype);
1699 }
1700 }
1701 }
1703 // For function valued properties of Object and Object.prototype, make
1704 // sure prototype's proto chain ends with Object.prototype
1705 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
1706 final Object key = property.getKey();
1707 final Object value = builtinObject.get(key);
1709 if (value instanceof ScriptFunction) {
1710 final ScriptFunction func = (ScriptFunction)value;
1711 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1712 if (prototype != null) {
1713 prototype.setProto(ObjectPrototype);
1714 }
1715 }
1716 }
1718 properties = getObjectPrototype().getMap().getProperties();
1719 for (final jdk.nashorn.internal.runtime.Property property : properties) {
1720 final Object key = property.getKey();
1721 final Object value = ObjectPrototype.get(key);
1723 if (key.equals("constructor")) {
1724 continue;
1725 }
1727 if (value instanceof ScriptFunction) {
1728 final ScriptFunction func = (ScriptFunction)value;
1729 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1730 if (prototype != null) {
1731 prototype.setProto(ObjectPrototype);
1732 }
1733 }
1734 }
1735 }
1738 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
1739 return MH.findStatic(MethodHandles.publicLookup(), Global.class, name, MH.type(rtype, types));
1740 }
1742 RegExpResult getLastRegExpResult() {
1743 return lastRegExpResult;
1744 }
1746 void setLastRegExpResult(final RegExpResult regExpResult) {
1747 this.lastRegExpResult = regExpResult;
1748 }
1750 }