Fri, 03 May 2013 16:01:33 +0200
8013871: mem usage histograms enabled with compiler logging level set to more specific than or equals to info when --print-mem-usage flag is used
Reviewed-by: jlaskey, hannesw
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.com */
263 @Property(attributes = Attribute.NOT_ENUMERABLE)
264 public volatile Object com;
266 /** Nashorn extension: Java access - global.edu */
267 @Property(attributes = Attribute.NOT_ENUMERABLE)
268 public volatile Object edu;
270 /** Nashorn extension: Java access - global.java */
271 @Property(attributes = Attribute.NOT_ENUMERABLE)
272 public volatile Object java;
274 /** Nashorn extension: Java access - global.javafx */
275 @Property(attributes = Attribute.NOT_ENUMERABLE)
276 public volatile Object javafx;
278 /** Nashorn extension: Java access - global.javax */
279 @Property(attributes = Attribute.NOT_ENUMERABLE)
280 public volatile Object javax;
282 /** Nashorn extension: Java access - global.org */
283 @Property(attributes = Attribute.NOT_ENUMERABLE)
284 public volatile Object org;
286 /** Nashorn extension: Java access - global.javaImporter */
287 @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
288 public volatile Object javaImporter;
290 /** Nashorn extension: global.Java Object constructor. */
291 @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
292 public volatile Object javaApi;
294 /** Nashorn extension: current script's file name */
295 @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
296 public Object __FILE__;
298 /** Nashorn extension: current script's directory */
299 @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
300 public Object __DIR__;
302 /** Nashorn extension: current source line number being executed */
303 @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
304 public Object __LINE__;
306 /** Used as Date.prototype's default value */
307 public NativeDate DEFAULT_DATE;
309 /** Used as RegExp.prototype's default value */
310 public NativeRegExp DEFAULT_REGEXP;
312 /*
313 * Built-in constructor objects: Even if user changes dynamic values of
314 * "Object", "Array" etc., we still want to keep original values of these
315 * constructors here. For example, we need to be able to create array,
316 * regexp literals even after user overwrites global "Array" or "RegExp"
317 * constructor - see also ECMA 262 spec. Annex D.
318 */
319 private ScriptFunction builtinFunction;
320 private ScriptFunction builtinObject;
321 private ScriptFunction builtinArray;
322 private ScriptFunction builtinBoolean;
323 private ScriptFunction builtinDate;
324 private ScriptObject builtinJSON;
325 private ScriptFunction builtinJSAdapter;
326 private ScriptObject builtinMath;
327 private ScriptFunction builtinNumber;
328 private ScriptFunction builtinRegExp;
329 private ScriptFunction builtinString;
330 private ScriptFunction builtinError;
331 private ScriptFunction builtinEval;
332 private ScriptFunction builtinEvalError;
333 private ScriptFunction builtinRangeError;
334 private ScriptFunction builtinReferenceError;
335 private ScriptFunction builtinSyntaxError;
336 private ScriptFunction builtinTypeError;
337 private ScriptFunction builtinURIError;
338 private ScriptObject builtinPackages;
339 private ScriptObject builtinCom;
340 private ScriptObject builtinEdu;
341 private ScriptObject builtinJava;
342 private ScriptObject builtinJavafx;
343 private ScriptObject builtinJavax;
344 private ScriptObject builtinOrg;
345 private ScriptObject builtinJavaImporter;
346 private ScriptObject builtinJavaApi;
347 private ScriptObject builtinArrayBuffer;
348 private ScriptObject builtinInt8Array;
349 private ScriptObject builtinUint8Array;
350 private ScriptObject builtinUint8ClampedArray;
351 private ScriptObject builtinInt16Array;
352 private ScriptObject builtinUint16Array;
353 private ScriptObject builtinInt32Array;
354 private ScriptObject builtinUint32Array;
355 private ScriptObject builtinFloat32Array;
356 private ScriptObject builtinFloat64Array;
358 // Flag to indicate that a split method issued a return statement
359 private int splitState = -1;
361 // class cache
362 private ClassCache classCache;
364 // Used to store the last RegExp result to support deprecated RegExp constructor properties
365 private RegExpResult lastRegExpResult;
367 private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class);
368 private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class);
369 private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
370 private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class);
371 private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
373 private final Context context;
375 /**
376 * Constructor
377 *
378 * @param context the context
379 */
380 public Global(final Context context) {
381 this.context = context;
382 this.setIsScope();
383 /*
384 * Duplicate global's map and use it. This way the initial Map filled
385 * by nasgen (referenced from static field in this class) is retained
386 * 'as is'. This allows multiple globals to be used within a context.
387 */
388 this.setMap(getMap().duplicate());
390 final int cacheSize = context.getEnv()._class_cache_size;
391 if (cacheSize > 0) {
392 classCache = new ClassCache(cacheSize);
393 }
394 }
396 /**
397 * Script access to "current" Global instance
398 *
399 * @return the global singleton
400 */
401 public static Global instance() {
402 ScriptObject global = Context.getGlobal();
403 if (! (global instanceof Global)) {
404 throw new IllegalStateException("no current global instance");
405 }
406 return (Global)global;
407 }
409 /**
410 * Script access to {@link ScriptEnvironment}
411 *
412 * @return the script environment
413 */
414 static ScriptEnvironment getEnv() {
415 return instance().context.getEnv();
416 }
418 /**
419 * Script access to {@link Context}
420 *
421 * @return the context
422 */
423 static Context getThisContext() {
424 return instance().context;
425 }
427 /**
428 * Script access check for strict mode
429 *
430 * @return true if strict mode enabled in {@link Global#getThisContext()}
431 */
432 static boolean isStrict() {
433 return getEnv()._strict;
434 }
436 // GlobalObject interface implementation
438 @Override
439 public void initBuiltinObjects() {
440 if (this.builtinObject != null) {
441 // already initialized, just return
442 return;
443 }
445 init();
446 }
448 @Override
449 public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
450 return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
451 }
453 @Override
454 public Object wrapAsObject(final Object obj) {
455 if (obj instanceof Boolean) {
456 return new NativeBoolean((Boolean)obj);
457 } else if (obj instanceof Number) {
458 return new NativeNumber(((Number)obj).doubleValue());
459 } else if (obj instanceof String || obj instanceof ConsString) {
460 return new NativeString((CharSequence)obj);
461 } else if (obj instanceof Object[]) { // extension
462 return new NativeArray((Object[])obj);
463 } else if (obj instanceof double[]) { // extension
464 return new NativeArray((double[])obj);
465 } else if (obj instanceof long[]) {
466 return new NativeArray((long[])obj);
467 } else if (obj instanceof int[]) {
468 return new NativeArray((int[])obj);
469 } else {
470 // FIXME: more special cases? Map? List?
471 return obj;
472 }
473 }
475 @Override
476 public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
477 if (self instanceof String || self instanceof ConsString) {
478 return NativeString.lookupPrimitive(request, self);
479 } else if (self instanceof Number) {
480 return NativeNumber.lookupPrimitive(request, self);
481 } else if (self instanceof Boolean) {
482 return NativeBoolean.lookupPrimitive(request, self);
483 }
484 throw new IllegalArgumentException("Unsupported primitive: " + self);
485 }
487 @Override
488 public ScriptObject newObject() {
489 return newEmptyInstance();
490 }
492 @Override
493 public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
494 // When the [[DefaultValue]] internal method of O is called with no hint,
495 // then it behaves as if the hint were Number, unless O is a Date object
496 // in which case it behaves as if the hint were String.
497 Class<?> hint = typeHint;
498 if (hint == null) {
499 hint = Number.class;
500 }
502 try {
503 if (hint == String.class) {
505 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
506 if (toString instanceof ScriptFunction) {
507 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
508 if (JSType.isPrimitive(value)) {
509 return value;
510 }
511 }
513 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
514 if (valueOf instanceof ScriptFunction) {
515 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
516 if (JSType.isPrimitive(value)) {
517 return value;
518 }
519 }
520 throw typeError(this, "cannot.get.default.string");
521 }
523 if (hint == Number.class) {
524 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
525 if (valueOf instanceof ScriptFunction) {
526 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
527 if (JSType.isPrimitive(value)) {
528 return value;
529 }
530 }
532 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
533 if (toString instanceof ScriptFunction) {
534 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
535 if (JSType.isPrimitive(value)) {
536 return value;
537 }
538 }
540 throw typeError(this, "cannot.get.default.number");
541 }
542 } catch (final RuntimeException | Error e) {
543 throw e;
544 } catch (final Throwable t) {
545 throw new RuntimeException(t);
546 }
548 return UNDEFINED;
549 }
551 @Override
552 public boolean isError(final ScriptObject sobj) {
553 final ScriptObject errorProto = getErrorPrototype();
554 ScriptObject proto = sobj.getProto();
555 while (proto != null) {
556 if (proto == errorProto) {
557 return true;
558 }
559 proto = proto.getProto();
560 }
561 return false;
562 }
564 @Override
565 public ScriptObject newError(final String msg) {
566 return new NativeError(msg);
567 }
569 @Override
570 public ScriptObject newEvalError(final String msg) {
571 return new NativeEvalError(msg);
572 }
574 @Override
575 public ScriptObject newRangeError(final String msg) {
576 return new NativeRangeError(msg);
577 }
579 @Override
580 public ScriptObject newReferenceError(final String msg) {
581 return new NativeReferenceError(msg);
582 }
584 @Override
585 public ScriptObject newSyntaxError(final String msg) {
586 return new NativeSyntaxError(msg);
587 }
589 @Override
590 public ScriptObject newTypeError(final String msg) {
591 return new NativeTypeError(msg);
592 }
594 @Override
595 public ScriptObject newURIError(final String msg) {
596 return new NativeURIError(msg);
597 }
599 @Override
600 public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
601 return new GenericPropertyDescriptor(configurable, enumerable);
602 }
604 @Override
605 public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
606 return new DataPropertyDescriptor(configurable, enumerable, writable, value);
607 }
609 @Override
610 public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
611 final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set);
613 final boolean strict = context.getEnv()._strict;
615 if (get == null) {
616 desc.delete(PropertyDescriptor.GET, strict);
617 }
619 if (set == null) {
620 desc.delete(PropertyDescriptor.SET, strict);
621 }
623 return desc;
624 }
627 /**
628 * Cache for compiled script classes.
629 */
630 @SuppressWarnings("serial")
631 private static class ClassCache extends LinkedHashMap<Source, SoftReference<Class<?>>> {
632 private final int size;
634 ClassCache(int size) {
635 super(size, 0.75f, true);
636 this.size = size;
637 }
639 @Override
640 protected boolean removeEldestEntry(final Map.Entry<Source, SoftReference<Class<?>>> eldest) {
641 return size() >= size;
642 }
643 }
645 // Class cache management
646 @Override
647 public Class<?> findCachedClass(final Source source) {
648 assert classCache != null : "Class cache used without being initialized";
649 SoftReference<Class<?>> ref = classCache.get(source);
650 if (ref != null) {
651 final Class<?> clazz = ref.get();
652 if (clazz == null) {
653 classCache.remove(source);
654 }
655 return clazz;
656 }
658 return null;
659 }
661 @Override
662 public void cacheClass(final Source source, final Class<?> clazz) {
663 assert classCache != null : "Class cache used without being initialized";
664 classCache.put(source, new SoftReference<Class<?>>(clazz));
665 }
667 /**
668 * This is the eval used when 'indirect' eval call is made.
669 *
670 * var global = this;
671 * global.eval("print('hello')");
672 *
673 * @param self eval scope
674 * @param str eval string
675 *
676 * @return the result of eval
677 */
678 public static Object eval(final Object self, final Object str) {
679 return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
680 }
682 /**
683 * Direct eval
684 *
685 * @param self The scope of eval passed as 'self'
686 * @param str Evaluated code
687 * @param callThis "this" to be passed to the evaluated code
688 * @param location location of the eval call
689 * @param strict is eval called a strict mode code?
690 *
691 * @return the return value of the eval
692 *
693 * This is directly invoked from generated when eval(code) is called in user code
694 */
695 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
696 if (!(str instanceof String || str instanceof ConsString)) {
697 return str;
698 }
699 final Global global = Global.instance();
700 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
702 return global.context.eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
703 }
705 /**
706 * Global print implementation - Nashorn extension
707 *
708 * @param self scope
709 * @param objects arguments to print
710 *
711 * @return result of print (undefined)
712 */
713 public static Object print(final Object self, final Object... objects) {
714 return printImpl(false, objects);
715 }
717 /**
718 * Global println implementation - Nashorn extension
719 *
720 * @param self scope
721 * @param objects arguments to print
722 *
723 * @return result of println (undefined)
724 */
725 public static Object println(final Object self, final Object... objects) {
726 return printImpl(true, objects);
727 }
729 /**
730 * Global load implementation - Nashorn extension
731 *
732 * @param self scope
733 * @param source source to load
734 *
735 * @return result of load (undefined)
736 *
737 * @throws IOException if source could not be read
738 */
739 public static Object load(final Object self, final Object source) throws IOException {
740 final Global global = Global.instance();
741 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
742 return global.context.load(scope, source);
743 }
745 /**
746 * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
747 *
748 * @param self self reference
749 * @param code exit code
750 *
751 * @return undefined (will never be reacheD)
752 */
753 public static Object exit(final Object self, final Object code) {
754 System.exit(JSType.toInt32(code));
755 return UNDEFINED;
756 }
758 ScriptObject getFunctionPrototype() {
759 return ScriptFunction.getPrototype(builtinFunction);
760 }
762 ScriptObject getObjectPrototype() {
763 return ScriptFunction.getPrototype(builtinObject);
764 }
766 ScriptObject getArrayPrototype() {
767 return ScriptFunction.getPrototype(builtinArray);
768 }
770 ScriptObject getBooleanPrototype() {
771 return ScriptFunction.getPrototype(builtinBoolean);
772 }
774 ScriptObject getNumberPrototype() {
775 return ScriptFunction.getPrototype(builtinNumber);
776 }
778 ScriptObject getDatePrototype() {
779 return ScriptFunction.getPrototype(builtinDate);
780 }
782 ScriptObject getRegExpPrototype() {
783 return ScriptFunction.getPrototype(builtinRegExp);
784 }
786 ScriptObject getStringPrototype() {
787 return ScriptFunction.getPrototype(builtinString);
788 }
790 ScriptObject getErrorPrototype() {
791 return ScriptFunction.getPrototype(builtinError);
792 }
794 ScriptObject getEvalErrorPrototype() {
795 return ScriptFunction.getPrototype(builtinEvalError);
796 }
798 ScriptObject getRangeErrorPrototype() {
799 return ScriptFunction.getPrototype(builtinRangeError);
800 }
802 ScriptObject getReferenceErrorPrototype() {
803 return ScriptFunction.getPrototype(builtinReferenceError);
804 }
806 ScriptObject getSyntaxErrorPrototype() {
807 return ScriptFunction.getPrototype(builtinSyntaxError);
808 }
810 ScriptObject getTypeErrorPrototype() {
811 return ScriptFunction.getPrototype(builtinTypeError);
812 }
814 ScriptObject getURIErrorPrototype() {
815 return ScriptFunction.getPrototype(builtinURIError);
816 }
818 ScriptObject getJavaImporterPrototype() {
819 return ScriptFunction.getPrototype(builtinJavaImporter);
820 }
822 ScriptObject getJSAdapterPrototype() {
823 return ScriptFunction.getPrototype(builtinJSAdapter);
824 }
826 ScriptObject getArrayBufferPrototype() {
827 return ScriptFunction.getPrototype(builtinArrayBuffer);
828 }
830 ScriptObject getInt8ArrayPrototype() {
831 return ScriptFunction.getPrototype(builtinInt8Array);
832 }
834 ScriptObject getUint8ArrayPrototype() {
835 return ScriptFunction.getPrototype(builtinUint8Array);
836 }
838 ScriptObject getUint8ClampedArrayPrototype() {
839 return ScriptFunction.getPrototype(builtinUint8ClampedArray);
840 }
842 ScriptObject getInt16ArrayPrototype() {
843 return ScriptFunction.getPrototype(builtinInt16Array);
844 }
846 ScriptObject getUint16ArrayPrototype() {
847 return ScriptFunction.getPrototype(builtinUint16Array);
848 }
850 ScriptObject getInt32ArrayPrototype() {
851 return ScriptFunction.getPrototype(builtinInt32Array);
852 }
854 ScriptObject getUint32ArrayPrototype() {
855 return ScriptFunction.getPrototype(builtinUint32Array);
856 }
858 ScriptObject getFloat32ArrayPrototype() {
859 return ScriptFunction.getPrototype(builtinFloat32Array);
860 }
862 ScriptObject getFloat64ArrayPrototype() {
863 return ScriptFunction.getPrototype(builtinFloat64Array);
864 }
866 private ScriptFunction getBuiltinArray() {
867 return builtinArray;
868 }
871 /**
872 * Called from compiled script code to test if builtin has been overridden
873 *
874 * @return true if builtin array has not been overridden
875 */
876 public static boolean isBuiltinArray() {
877 final Global instance = Global.instance();
878 return instance.array == instance.getBuiltinArray();
879 }
881 private ScriptFunction getBuiltinBoolean() {
882 return builtinBoolean;
883 }
885 /**
886 * Called from compiled script code to test if builtin has been overridden
887 *
888 * @return true if builtin boolean has not been overridden
889 */
890 public static boolean isBuiltinBoolean() {
891 final Global instance = Global.instance();
892 return instance._boolean == instance.getBuiltinBoolean();
893 }
895 private ScriptFunction getBuiltinDate() {
896 return builtinDate;
897 }
899 /**
900 * Called from compiled script code to test if builtin has been overridden
901 *
902 * @return true if builtin date has not been overridden
903 */
904 public static boolean isBuiltinDate() {
905 final Global instance = Global.instance();
906 return instance.date == instance.getBuiltinDate();
907 }
909 private ScriptFunction getBuiltinError() {
910 return builtinError;
911 }
913 /**
914 * Called from compiled script code to test if builtin has been overridden
915 *
916 * @return true if builtin error has not been overridden
917 */
918 public static boolean isBuiltinError() {
919 final Global instance = Global.instance();
920 return instance.error == instance.getBuiltinError();
921 }
923 private ScriptFunction getBuiltinEvalError() {
924 return builtinEvalError;
925 }
927 /**
928 * Called from compiled script code to test if builtin has been overridden
929 *
930 * @return true if builtin eval error has not been overridden
931 */
932 public static boolean isBuiltinEvalError() {
933 final Global instance = Global.instance();
934 return instance.evalError == instance.getBuiltinEvalError();
935 }
937 private ScriptFunction getBuiltinFunction() {
938 return builtinFunction;
939 }
941 /**
942 * Called from compiled script code to test if builtin has been overridden
943 *
944 * @return true if builtin function has not been overridden
945 */
946 public static boolean isBuiltinFunction() {
947 final Global instance = Global.instance();
948 return instance.function == instance.getBuiltinFunction();
949 }
951 private ScriptFunction getBuiltinJSAdapter() {
952 return builtinJSAdapter;
953 }
955 /**
956 * Called from compiled script code to test if builtin has been overridden
957 *
958 * @return true if builtin JSAdapter has not been overridden
959 */
960 public static boolean isBuiltinJSAdapter() {
961 final Global instance = Global.instance();
962 return instance.jsadapter == instance.getBuiltinJSAdapter();
963 }
965 private ScriptObject getBuiltinJSON() {
966 return builtinJSON;
967 }
969 /**
970 * Called from compiled script code to test if builtin has been overridden
971 *
972 * @return true if builtin JSON has has not been overridden
973 */
974 public static boolean isBuiltinJSON() {
975 final Global instance = Global.instance();
976 return instance.json == instance.getBuiltinJSON();
977 }
979 private ScriptObject getBuiltinJava() {
980 return builtinJava;
981 }
983 /**
984 * Called from compiled script code to test if builtin has been overridden
985 *
986 * @return true if builtin Java has not been overridden
987 */
988 public static boolean isBuiltinJava() {
989 final Global instance = Global.instance();
990 return instance.java == instance.getBuiltinJava();
991 }
993 private ScriptObject getBuiltinJavax() {
994 return builtinJavax;
995 }
997 /**
998 * Called from compiled script code to test if builtin has been overridden
999 *
1000 * @return true if builtin Javax has not been overridden
1001 */
1002 public static boolean isBuiltinJavax() {
1003 final Global instance = Global.instance();
1004 return instance.javax == instance.getBuiltinJavax();
1005 }
1007 private ScriptObject getBuiltinJavaImporter() {
1008 return builtinJavaImporter;
1009 }
1011 /**
1012 * Called from compiled script code to test if builtin has been overridden
1013 *
1014 * @return true if builtin Java importer has not been overridden
1015 */
1016 public static boolean isBuiltinJavaImporter() {
1017 final Global instance = Global.instance();
1018 return instance.javaImporter == instance.getBuiltinJavaImporter();
1019 }
1021 private ScriptObject getBuiltinMath() {
1022 return builtinMath;
1023 }
1025 /**
1026 * Called from compiled script code to test if builtin has been overridden
1027 *
1028 * @return true if builtin math has not been overridden
1029 */
1030 public static boolean isBuiltinMath() {
1031 final Global instance = Global.instance();
1032 return instance.math == instance.getBuiltinMath();
1033 }
1035 private ScriptFunction getBuiltinNumber() {
1036 return builtinNumber;
1037 }
1039 /**
1040 * Called from compiled script code to test if builtin has been overridden
1041 *
1042 * @return true if builtin number has not been overridden
1043 */
1044 public static boolean isBuiltinNumber() {
1045 final Global instance = Global.instance();
1046 return instance.number == instance.getBuiltinNumber();
1047 }
1049 private ScriptFunction getBuiltinObject() {
1050 return builtinObject;
1051 }
1053 /**
1054 * Called from compiled script code to test if builtin has been overridden
1055 *
1056 * @return true if builtin object has not been overridden
1057 */
1058 public static boolean isBuiltinObject() {
1059 final Global instance = Global.instance();
1060 return instance.object == instance.getBuiltinObject();
1061 }
1063 private ScriptObject getBuiltinPackages() {
1064 return builtinPackages;
1065 }
1067 /**
1068 * Called from compiled script code to test if builtin has been overridden
1069 *
1070 * @return true if builtin package has not been overridden
1071 */
1072 public static boolean isBuiltinPackages() {
1073 final Global instance = Global.instance();
1074 return instance.packages == instance.getBuiltinPackages();
1075 }
1077 private ScriptFunction getBuiltinRangeError() {
1078 return builtinRangeError;
1079 }
1081 /**
1082 * Called from compiled script code to test if builtin has been overridden
1083 *
1084 * @return true if builtin range error has not been overridden
1085 */
1086 public static boolean isBuiltinRangeError() {
1087 final Global instance = Global.instance();
1088 return instance.rangeError == instance.getBuiltinRangeError();
1089 }
1091 private ScriptFunction getBuiltinReferenceError() {
1092 return builtinReferenceError;
1093 }
1095 /**
1096 * Called from compiled script code to test if builtin has been overridden
1097 *
1098 * @return true if builtin reference error has not been overridden
1099 */
1100 public static boolean isBuiltinReferenceError() {
1101 final Global instance = Global.instance();
1102 return instance.referenceError == instance.getBuiltinReferenceError();
1103 }
1105 private ScriptFunction getBuiltinRegExp() {
1106 return builtinRegExp;
1107 }
1109 /**
1110 * Called from compiled script code to test if builtin has been overridden
1111 *
1112 * @return true if builtin regexp has not been overridden
1113 */
1114 public static boolean isBuiltinRegExp() {
1115 final Global instance = Global.instance();
1116 return instance.regexp == instance.getBuiltinRegExp();
1117 }
1119 private ScriptFunction getBuiltinString() {
1120 return builtinString;
1121 }
1123 /**
1124 * Called from compiled script code to test if builtin has been overridden
1125 *
1126 * @return true if builtin Java has not been overridden
1127 */
1128 public static boolean isBuiltinString() {
1129 final Global instance = Global.instance();
1130 return instance.string == instance.getBuiltinString();
1131 }
1133 private ScriptFunction getBuiltinSyntaxError() {
1134 return builtinSyntaxError;
1135 }
1137 /**
1138 * Called from compiled script code to test if builtin has been overridden
1139 *
1140 * @return true if builtin syntax error has not been overridden
1141 */
1142 public static boolean isBuiltinSyntaxError() {
1143 final Global instance = Global.instance();
1144 return instance.syntaxError == instance.getBuiltinSyntaxError();
1145 }
1147 private ScriptFunction getBuiltinTypeError() {
1148 return builtinTypeError;
1149 }
1151 /**
1152 * Called from compiled script code to test if builtin has been overridden
1153 *
1154 * @return true if builtin type error has not been overridden
1155 */
1156 public static boolean isBuiltinTypeError() {
1157 final Global instance = Global.instance();
1158 return instance.typeError == instance.getBuiltinTypeError();
1159 }
1161 private ScriptFunction getBuiltinURIError() {
1162 return builtinURIError;
1163 }
1165 /**
1166 * Called from compiled script code to test if builtin has been overridden
1167 *
1168 * @return true if builtin URI error has not been overridden
1169 */
1170 public static boolean isBuiltinURIError() {
1171 final Global instance = Global.instance();
1172 return instance.uriError == instance.getBuiltinURIError();
1173 }
1175 @Override
1176 public String getClassName() {
1177 return "global";
1178 }
1180 /**
1181 * Copy function used to clone NativeRegExp objects.
1182 *
1183 * @param regexp a NativeRegExp to clone
1184 *
1185 * @return copy of the given regexp object
1186 */
1187 public static Object regExpCopy(final Object regexp) {
1188 return new NativeRegExp((NativeRegExp)regexp);
1189 }
1191 /**
1192 * Convert given object to NativeRegExp type.
1193 *
1194 * @param obj object to be converted
1195 * @return NativeRegExp instance
1196 */
1197 public static NativeRegExp toRegExp(final Object obj) {
1198 if (obj instanceof NativeRegExp) {
1199 return (NativeRegExp)obj;
1200 }
1201 return new NativeRegExp(JSType.toString(obj));
1202 }
1204 /**
1205 * ECMA 9.9 ToObject implementation
1206 *
1207 * @param obj an item for which to run ToObject
1208 * @return ToObject version of given item
1209 */
1210 public static Object toObject(final Object obj) {
1211 if (obj == null || obj == UNDEFINED) {
1212 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1213 }
1215 if (obj instanceof ScriptObject) {
1216 return obj;
1217 }
1219 return instance().wrapAsObject(obj);
1220 }
1222 /**
1223 * Allocate a new object array.
1224 *
1225 * @param initial object values.
1226 * @return the new array
1227 */
1228 public static NativeArray allocate(final Object[] initial) {
1229 return new NativeArray(initial);
1230 }
1232 /**
1233 * Allocate a new number array.
1234 *
1235 * @param initial number values.
1236 * @return the new array
1237 */
1238 public static NativeArray allocate(final double[] initial) {
1239 return new NativeArray(initial);
1240 }
1242 /**
1243 * Allocate a new long array.
1244 *
1245 * @param initial number values.
1246 * @return the new array
1247 */
1248 public static NativeArray allocate(final long[] initial) {
1249 return new NativeArray(initial);
1250 }
1252 /**
1253 * Allocate a new integer array.
1254 *
1255 * @param initial number values.
1256 * @return the new array
1257 */
1258 public static NativeArray allocate(final int[] initial) {
1259 return new NativeArray(initial);
1260 }
1262 /**
1263 * Allocate a new object array for arguments.
1264 *
1265 * @param arguments initial arguments passed.
1266 * @param callee reference to the function that uses arguments object
1267 * @param numParams actual number of declared parameters
1268 *
1269 * @return the new array
1270 */
1271 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1272 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1273 }
1275 /**
1276 * Called from generated to check if given function is the builtin 'eval'. If
1277 * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1278 *
1279 * @param fn function object that is checked
1280 * @return true if fn is the builtin eval
1281 */
1282 public static boolean isEval(final Object fn) {
1283 return fn == Global.instance().builtinEval;
1284 }
1286 /**
1287 * Create a new RegExp object.
1288 *
1289 * @param expression Regular expression.
1290 * @param options Search options.
1291 *
1292 * @return New RegExp object.
1293 */
1294 public static Object newRegExp(final String expression, final String options) {
1295 if (options == null) {
1296 return new NativeRegExp(expression);
1297 }
1298 return new NativeRegExp(expression, options);
1299 }
1301 /**
1302 * Get the object prototype
1303 *
1304 * @return the object prototype
1305 */
1306 public static ScriptObject objectPrototype() {
1307 return Global.instance().getObjectPrototype();
1308 }
1310 /**
1311 * Create a new empty object instance.
1312 *
1313 * @return New empty object.
1314 */
1315 public static ScriptObject newEmptyInstance() {
1316 final ScriptObject sobj = new JO();
1317 sobj.setProto(objectPrototype());
1318 return sobj;
1319 }
1321 /**
1322 * Check if a given object is a ScriptObject, raises an exception if this is
1323 * not the case
1324 *
1325 * @param obj and object to check
1326 */
1327 public static void checkObject(final Object obj) {
1328 if (!(obj instanceof ScriptObject)) {
1329 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1330 }
1331 }
1333 /**
1334 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1335 * if this object is null or undefined.
1336 *
1337 * @param obj an object to check
1338 */
1339 public static void checkObjectCoercible(final Object obj) {
1340 if (obj == null || obj == UNDEFINED) {
1341 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1342 }
1343 }
1345 /**
1346 * Get the current split state.
1347 *
1348 * @return current split state
1349 */
1350 @Override
1351 public int getSplitState() {
1352 return splitState;
1353 }
1355 /**
1356 * Set the current split state.
1357 *
1358 * @param state current split state
1359 */
1360 @Override
1361 public void setSplitState(final int state) {
1362 splitState = state;
1363 }
1365 private void init() {
1366 assert Context.getGlobal() == this : "this global is not set as current";
1368 final ScriptEnvironment env = context.getEnv();
1369 // initialize Function and Object constructor
1370 initFunctionAndObject();
1372 // Now fix Global's own proto.
1373 this.setProto(getObjectPrototype());
1375 // initialize global function properties
1376 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1378 this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT);
1379 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1380 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN);
1381 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE);
1382 this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI);
1383 this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1384 this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI);
1385 this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1386 this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE);
1387 this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
1388 this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN);
1389 this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
1390 this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT);
1391 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
1393 // built-in constructors
1394 this.builtinArray = (ScriptFunction)initConstructor("Array");
1395 this.builtinBoolean = (ScriptFunction)initConstructor("Boolean");
1396 this.builtinDate = (ScriptFunction)initConstructor("Date");
1397 this.builtinJSON = initConstructor("JSON");
1398 this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
1399 this.builtinMath = initConstructor("Math");
1400 this.builtinNumber = (ScriptFunction)initConstructor("Number");
1401 this.builtinRegExp = (ScriptFunction)initConstructor("RegExp");
1402 this.builtinString = (ScriptFunction)initConstructor("String");
1404 // initialize String.prototype.length to 0
1405 // add String.prototype.length
1406 final ScriptObject stringPrototype = getStringPrototype();
1407 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1409 // add Array.prototype.length
1410 final ScriptObject arrayPrototype = getArrayPrototype();
1411 arrayPrototype.addOwnProperty("length", Attribute.NOT_ENUMERABLE|Attribute.NOT_CONFIGURABLE, 0.0);
1413 this.DEFAULT_DATE = new NativeDate(Double.NaN);
1415 // initialize default regexp object
1416 this.DEFAULT_REGEXP = new NativeRegExp("(?:)");
1418 // RegExp.prototype should behave like a RegExp object. So copy the
1419 // properties.
1420 final ScriptObject regExpProto = getRegExpPrototype();
1421 regExpProto.addBoundProperties(DEFAULT_REGEXP);
1423 // Error stuff
1424 initErrorObjects();
1426 // java access
1427 initJavaAccess();
1429 initTypedArray();
1431 if (env._scripting) {
1432 initScripting();
1433 }
1435 if (Context.DEBUG && System.getSecurityManager() == null) {
1436 initDebug();
1437 }
1439 copyBuiltins();
1441 // initialized with strings so that typeof will work as expected.
1442 this.__FILE__ = "";
1443 this.__DIR__ = "";
1444 this.__LINE__ = 0.0;
1446 // expose script (command line) arguments as "arguments" property of global
1447 final List<String> arguments = env.getArguments();
1448 final Object argsObj = wrapAsObject(arguments.toArray());
1450 addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
1451 if (env._scripting) {
1452 // synonym for "arguments" in scripting mode
1453 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
1454 }
1455 }
1457 private void initErrorObjects() {
1458 // Error objects
1459 this.builtinError = (ScriptFunction)initConstructor("Error");
1460 final ScriptObject errorProto = getErrorPrototype();
1461 final boolean strict = Global.isStrict();
1463 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1464 final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1465 final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1466 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1467 final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1468 final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1469 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1470 final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1471 final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1472 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1473 final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1474 final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1475 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1477 // ECMA 15.11.4.2 Error.prototype.name
1478 // Error.prototype.name = "Error";
1479 errorProto.set(NativeError.NAME, "Error", strict);
1480 // ECMA 15.11.4.3 Error.prototype.message
1481 // Error.prototype.message = "";
1482 errorProto.set(NativeError.MESSAGE, "", strict);
1484 this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1485 this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1486 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1487 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1488 this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1489 this.builtinURIError = initErrorSubtype("URIError", errorProto);
1490 }
1492 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1493 final ScriptObject cons = initConstructor(name);
1494 final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1495 final boolean strict = Global.isStrict();
1496 prototype.set(NativeError.NAME, name, strict);
1497 prototype.set(NativeError.MESSAGE, "", strict);
1498 prototype.setProto(errorProto);
1499 return (ScriptFunction)cons;
1500 }
1502 private void initJavaAccess() {
1503 final ScriptObject objectProto = getObjectPrototype();
1504 this.builtinPackages = new NativeJavaPackage("", objectProto);
1505 this.builtinCom = new NativeJavaPackage("com", objectProto);
1506 this.builtinEdu = new NativeJavaPackage("edu", objectProto);
1507 this.builtinJava = new NativeJavaPackage("java", objectProto);
1508 this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
1509 this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1510 this.builtinOrg = new NativeJavaPackage("org", objectProto);
1511 this.builtinJavaImporter = initConstructor("JavaImporter");
1512 this.builtinJavaApi = initConstructor("Java");
1513 }
1515 private void initScripting() {
1516 Object value;
1517 value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1518 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1520 value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1521 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1523 final String execName = ScriptingFunctions.EXEC_NAME;
1524 value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1525 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1527 // Nashorn extension: global.echo (scripting-mode-only)
1528 // alias for "print"
1529 value = get("print");
1530 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1532 // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1533 final ScriptObject options = newEmptyInstance();
1534 final ScriptEnvironment scriptEnv = context.getEnv();
1535 copyOptions(options, scriptEnv);
1536 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1538 // Nashorn extension: global.$ENV (scripting-mode-only)
1539 if (System.getSecurityManager() == null) {
1540 // do not fill $ENV if we have a security manager around
1541 // Retrieve current state of ENV variables.
1542 final ScriptObject env = newEmptyInstance();
1543 env.putAll(System.getenv());
1544 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1545 } else {
1546 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1547 }
1549 // add other special properties for exec support
1550 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1551 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1552 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1553 }
1555 private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1556 AccessController.doPrivileged(new PrivilegedAction<Void>() {
1557 @Override
1558 public Void run() {
1559 for (Field f : scriptEnv.getClass().getFields()) {
1560 try {
1561 options.set(f.getName(), f.get(scriptEnv), false);
1562 } catch (final IllegalArgumentException | IllegalAccessException exp) {
1563 throw new RuntimeException(exp);
1564 }
1565 }
1566 return null;
1567 }
1568 });
1569 }
1571 private void initTypedArray() {
1572 this.builtinArrayBuffer = initConstructor("ArrayBuffer");
1573 this.builtinInt8Array = initConstructor("Int8Array");
1574 this.builtinUint8Array = initConstructor("Uint8Array");
1575 this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
1576 this.builtinInt16Array = initConstructor("Int16Array");
1577 this.builtinUint16Array = initConstructor("Uint16Array");
1578 this.builtinInt32Array = initConstructor("Int32Array");
1579 this.builtinUint32Array = initConstructor("Uint32Array");
1580 this.builtinFloat32Array = initConstructor("Float32Array");
1581 this.builtinFloat64Array = initConstructor("Float64Array");
1582 }
1584 private void copyBuiltins() {
1585 this.array = this.builtinArray;
1586 this._boolean = this.builtinBoolean;
1587 this.date = this.builtinDate;
1588 this.error = this.builtinError;
1589 this.evalError = this.builtinEvalError;
1590 this.function = this.builtinFunction;
1591 this.jsadapter = this.builtinJSAdapter;
1592 this.json = this.builtinJSON;
1593 this.com = this.builtinCom;
1594 this.edu = this.builtinEdu;
1595 this.java = this.builtinJava;
1596 this.javafx = this.builtinJavafx;
1597 this.javax = this.builtinJavax;
1598 this.org = this.builtinOrg;
1599 this.javaImporter = this.builtinJavaImporter;
1600 this.javaApi = this.builtinJavaApi;
1601 this.math = this.builtinMath;
1602 this.number = this.builtinNumber;
1603 this.object = this.builtinObject;
1604 this.packages = this.builtinPackages;
1605 this.rangeError = this.builtinRangeError;
1606 this.referenceError = this.builtinReferenceError;
1607 this.regexp = this.builtinRegExp;
1608 this.string = this.builtinString;
1609 this.syntaxError = this.builtinSyntaxError;
1610 this.typeError = this.builtinTypeError;
1611 this.uriError = this.builtinURIError;
1612 this.arrayBuffer = this.builtinArrayBuffer;
1613 this.int8Array = this.builtinInt8Array;
1614 this.uint8Array = this.builtinUint8Array;
1615 this.uint8ClampedArray = this.builtinUint8ClampedArray;
1616 this.int16Array = this.builtinInt16Array;
1617 this.uint16Array = this.builtinUint16Array;
1618 this.int32Array = this.builtinInt32Array;
1619 this.uint32Array = this.builtinUint32Array;
1620 this.float32Array = this.builtinFloat32Array;
1621 this.float64Array = this.builtinFloat64Array;
1622 }
1624 private void initDebug() {
1625 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
1626 }
1628 private static Object printImpl(final boolean newLine, final Object... objects) {
1629 final PrintWriter out = Global.getEnv().getOut();
1631 boolean first = true;
1632 for (final Object object : objects) {
1633 if (first) {
1634 first = false;
1635 } else {
1636 out.print(' ');
1637 }
1639 out.print(JSType.toString(object));
1640 }
1642 if (newLine) {
1643 out.println();
1644 }
1646 out.flush();
1648 return UNDEFINED;
1649 }
1651 /**
1652 * These classes are generated by nasgen tool and so we have to use
1653 * reflection to load and create new instance of these classes.
1654 */
1655 private ScriptObject initConstructor(final String name) {
1656 try {
1657 // Assuming class name pattern for built-in JS constructors.
1658 final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
1660 sb.append("Native");
1661 sb.append(name);
1662 sb.append("$Constructor");
1664 final Class<?> funcClass = Class.forName(sb.toString());
1665 final ScriptObject res = (ScriptObject)funcClass.newInstance();
1667 if (res instanceof ScriptFunction) {
1668 // All global constructor prototypes are not-writable,
1669 // not-enumerable and not-configurable.
1670 final ScriptFunction func = (ScriptFunction)res;
1671 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
1672 }
1674 if (res.getProto() == null) {
1675 res.setProto(getObjectPrototype());
1676 }
1678 return res;
1680 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
1681 throw new RuntimeException(e);
1682 }
1683 }
1685 // Function and Object constructors are inter-dependent. Also,
1686 // Function.prototype
1687 // functions are not properly initialized. We fix the references here.
1688 // NOTE: be careful if you want to re-order the operations here. You may
1689 // have
1690 // to play with object references carefully!!
1691 private void initFunctionAndObject() {
1692 // First-n-foremost is Function
1693 this.builtinFunction = (ScriptFunction)initConstructor("Function");
1695 // create global anonymous function
1696 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
1697 // need to copy over members of Function.prototype to anon function
1698 anon.addBoundProperties(getFunctionPrototype());
1700 // Function.prototype === Object.getPrototypeOf(Function) ===
1701 // <anon-function>
1702 builtinFunction.setProto(anon);
1703 builtinFunction.setPrototype(anon);
1704 anon.set("constructor", builtinFunction, anon.isStrict());
1705 anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
1707 // now initialize Object
1708 this.builtinObject = (ScriptFunction)initConstructor("Object");
1709 final ScriptObject ObjectPrototype = getObjectPrototype();
1710 // Object.getPrototypeOf(Function.prototype) === Object.prototype
1711 anon.setProto(ObjectPrototype);
1713 // Function valued properties of Function.prototype were not properly
1714 // initialized. Because, these were created before global.function and
1715 // global.object were not initialized.
1716 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
1717 for (final jdk.nashorn.internal.runtime.Property property : properties) {
1718 final Object key = property.getKey();
1719 final Object value = builtinFunction.get(key);
1721 if (value instanceof ScriptFunction && value != anon) {
1722 final ScriptFunction func = (ScriptFunction)value;
1723 func.setProto(getFunctionPrototype());
1724 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1725 if (prototype != null) {
1726 prototype.setProto(ObjectPrototype);
1727 }
1728 }
1729 }
1731 // For function valued properties of Object and Object.prototype, make
1732 // sure prototype's proto chain ends with Object.prototype
1733 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
1734 final Object key = property.getKey();
1735 final Object value = builtinObject.get(key);
1737 if (value instanceof ScriptFunction) {
1738 final ScriptFunction func = (ScriptFunction)value;
1739 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1740 if (prototype != null) {
1741 prototype.setProto(ObjectPrototype);
1742 }
1743 }
1744 }
1746 properties = getObjectPrototype().getMap().getProperties();
1747 for (final jdk.nashorn.internal.runtime.Property property : properties) {
1748 final Object key = property.getKey();
1749 final Object value = ObjectPrototype.get(key);
1751 if (key.equals("constructor")) {
1752 continue;
1753 }
1755 if (value instanceof ScriptFunction) {
1756 final ScriptFunction func = (ScriptFunction)value;
1757 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1758 if (prototype != null) {
1759 prototype.setProto(ObjectPrototype);
1760 }
1761 }
1762 }
1763 }
1766 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
1767 return MH.findStatic(MethodHandles.publicLookup(), Global.class, name, MH.type(rtype, types));
1768 }
1770 RegExpResult getLastRegExpResult() {
1771 return lastRegExpResult;
1772 }
1774 void setLastRegExpResult(final RegExpResult regExpResult) {
1775 this.lastRegExpResult = regExpResult;
1776 }
1778 }