Wed, 06 Feb 2013 10:31:58 +0100
8007273: Creation of ScriptFunctions can be refactored
Reviewed-by: 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.runtime.linker.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.util.LinkedHashMap;
38 import java.util.List;
39 import java.util.Map;
40 import jdk.nashorn.internal.objects.annotations.Attribute;
41 import jdk.nashorn.internal.objects.annotations.Property;
42 import jdk.nashorn.internal.objects.annotations.ScriptClass;
43 import jdk.nashorn.internal.runtime.ConsString;
44 import jdk.nashorn.internal.runtime.Context;
45 import jdk.nashorn.internal.runtime.GlobalFunctions;
46 import jdk.nashorn.internal.runtime.GlobalObject;
47 import jdk.nashorn.internal.runtime.JSType;
48 import jdk.nashorn.internal.runtime.NativeJavaPackage;
49 import jdk.nashorn.internal.runtime.OptionsObject;
50 import jdk.nashorn.internal.runtime.PropertyDescriptor;
51 import jdk.nashorn.internal.runtime.Scope;
52 import jdk.nashorn.internal.runtime.ScriptFunction;
53 import jdk.nashorn.internal.runtime.ScriptObject;
54 import jdk.nashorn.internal.runtime.ScriptRuntime;
55 import jdk.nashorn.internal.runtime.ScriptingFunctions;
56 import jdk.nashorn.internal.runtime.Source;
57 import jdk.nashorn.internal.runtime.linker.InvokeByName;
58 import jdk.nashorn.internal.scripts.JO$;
59 import org.dynalang.dynalink.linker.GuardedInvocation;
60 import org.dynalang.dynalink.linker.LinkRequest;
62 /**
63 * Representation of global scope.
64 */
65 @ScriptClass("Global")
66 public final class Global extends ScriptObject implements GlobalObject, Scope {
67 private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
68 private static final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class);
70 /** ECMA 15.1.2.2 parseInt (string , radix) */
71 @Property(attributes = Attribute.NOT_ENUMERABLE)
72 public Object parseInt;
74 /** ECMA 15.1.2.3 parseFloat (string) */
75 @Property(attributes = Attribute.NOT_ENUMERABLE)
76 public Object parseFloat;
78 /** ECMA 15.1.2.4 isNaN (number) */
79 @Property(attributes = Attribute.NOT_ENUMERABLE)
80 public Object isNaN;
82 /** ECMA 15.1.2.5 isFinite (number) */
83 @Property(attributes = Attribute.NOT_ENUMERABLE)
84 public Object isFinite;
86 /** ECMA 15.1.3.3 encodeURI */
87 @Property(attributes = Attribute.NOT_ENUMERABLE)
88 public Object encodeURI;
90 /** ECMA 15.1.3.4 encodeURIComponent */
91 @Property(attributes = Attribute.NOT_ENUMERABLE)
92 public Object encodeURIComponent;
94 /** ECMA 15.1.3.1 decodeURI */
95 @Property(attributes = Attribute.NOT_ENUMERABLE)
96 public Object decodeURI;
98 /** ECMA 15.1.3.2 decodeURIComponent */
99 @Property(attributes = Attribute.NOT_ENUMERABLE)
100 public Object decodeURIComponent;
102 /** ECMA B.2.1 escape (string) */
103 @Property(attributes = Attribute.NOT_ENUMERABLE)
104 public Object escape;
106 /** ECMA B.2.2 unescape (string) */
107 @Property(attributes = Attribute.NOT_ENUMERABLE)
108 public Object unescape;
110 /** Nashorn extension: global.print */
111 @Property(attributes = Attribute.NOT_ENUMERABLE)
112 public Object print;
114 /** Nashorn extension: global.load */
115 @Property(attributes = Attribute.NOT_ENUMERABLE)
116 public Object load;
118 /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
119 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
120 public final Object NaN = Double.NaN;
122 /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
123 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
124 public final Object Infinity = Double.POSITIVE_INFINITY;
126 /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
127 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
128 public final Object undefined = UNDEFINED;
130 /** ECMA 15.1.2.1 eval(x) */
131 @Property(attributes = Attribute.NOT_ENUMERABLE)
132 public Object eval;
134 /** ECMA 15.1.4.1 Object constructor. */
135 @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
136 public volatile Object object;
138 /** ECMA 15.1.4.2 Function constructor. */
139 @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
140 public volatile Object function;
142 /** ECMA 15.1.4.3 Array constructor. */
143 @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
144 public volatile Object array;
146 /** ECMA 15.1.4.4 String constructor */
147 @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
148 public volatile Object string;
150 /** ECMA 15.1.4.5 Boolean constructor */
151 @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
152 public volatile Object _boolean;
154 /** ECMA 15.1.4.6 - Number constructor */
155 @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
156 public volatile Object number;
158 /** ECMA 15.1.4.7 Date constructor */
159 @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
160 public volatile Object date;
162 /** ECMA 15.1.4.8 RegExp constructor */
163 @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
164 public volatile Object regexp;
166 /** ECMA 15.12 - The JSON object */
167 @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
168 public volatile Object json;
170 /** Nashorn extension: global.JSAdapter */
171 @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
172 public volatile Object jsadapter;
174 /** ECMA 15.8 - The Math object */
175 @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
176 public volatile Object math;
178 /** Error object */
179 @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
180 public volatile Object error;
182 /** EvalError object */
183 @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
184 public volatile Object evalError;
186 /** RangeError object */
187 @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
188 public volatile Object rangeError;
190 /** ReferenceError object */
191 @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
192 public volatile Object referenceError;
194 /** SyntaxError object */
195 @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
196 public volatile Object syntaxError;
198 /** TypeError object */
199 @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
200 public volatile Object typeError;
202 /** URIError object */
203 @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
204 public volatile Object uriError;
206 /** ArrayBuffer object */
207 @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
208 public volatile Object arrayBuffer;
210 /** TypedArray (int8) */
211 @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
212 public volatile Object int8Array;
214 /** TypedArray (uint8) */
215 @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
216 public volatile Object uint8Array;
218 /** TypedArray (uint8) - Clamped */
219 @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
220 public volatile Object uint8ClampedArray;
222 /** TypedArray (int16) */
223 @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
224 public volatile Object int16Array;
226 /** TypedArray (uint16) */
227 @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
228 public volatile Object uint16Array;
230 /** TypedArray (int32) */
231 @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
232 public volatile Object int32Array;
234 /** TypedArray (uint32) */
235 @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
236 public volatile Object uint32Array;
238 /** TypedArray (float32) */
239 @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
240 public volatile Object float32Array;
242 /** TypedArray (float64) */
243 @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
244 public volatile Object float64Array;
246 /** Nashorn extension: Java access - global.Packages */
247 @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
248 public volatile Object packages;
250 /** Nashorn extension: Java access - global.java */
251 @Property(attributes = Attribute.NOT_ENUMERABLE)
252 public volatile Object java;
254 /** Nashorn extension: Java access - global.javax */
255 @Property(attributes = Attribute.NOT_ENUMERABLE)
256 public Object javax;
258 /** Nashorn extension: Java access - global.javaImporter */
259 @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
260 public volatile Object javaImporter;
262 /** Nashorn extension: global.Java Object constructor. */
263 @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
264 public volatile Object javaApi;
266 /** Nashorn extension: current script's file name */
267 @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
268 public Object __FILE__;
270 /** Nashorn extension: current script's directory */
271 @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
272 public Object __DIR__;
274 /** Nashorn extension: current source line number being executed */
275 @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
276 public Object __LINE__;
278 /** Used as Date.prototype's default value */
279 public NativeDate DEFAULT_DATE;
281 /** Used as RegExp.prototype's default value */
282 public NativeRegExp DEFAULT_REGEXP;
284 /*
285 * Built-in constructor objects: Even if user changes dynamic values of
286 * "Object", "Array" etc., we still want to keep original values of these
287 * constructors here. For example, we need to be able to create array,
288 * regexp literals even after user overwrites global "Array" or "RegExp"
289 * constructor - see also ECMA 262 spec. Annex D.
290 */
291 private ScriptFunction builtinFunction;
292 private ScriptFunction builtinObject;
293 private ScriptFunction builtinArray;
294 private ScriptFunction builtinBoolean;
295 private ScriptFunction builtinDate;
296 private ScriptObject builtinJSON;
297 private ScriptFunction builtinJSAdapter;
298 private ScriptObject builtinMath;
299 private ScriptFunction builtinNumber;
300 private ScriptFunction builtinRegExp;
301 private ScriptFunction builtinString;
302 private ScriptFunction builtinError;
303 private ScriptFunction builtinEval;
304 private ScriptFunction builtinEvalError;
305 private ScriptFunction builtinRangeError;
306 private ScriptFunction builtinReferenceError;
307 private ScriptFunction builtinSyntaxError;
308 private ScriptFunction builtinTypeError;
309 private ScriptFunction builtinURIError;
310 private ScriptObject builtinPackages;
311 private ScriptObject builtinJava;
312 private ScriptObject builtinJavax;
313 private ScriptObject builtinJavaImporter;
314 private ScriptObject builtinJavaApi;
315 private ScriptObject builtinArrayBuffer;
316 private ScriptObject builtinInt8Array;
317 private ScriptObject builtinUint8Array;
318 private ScriptObject builtinUint8ClampedArray;
319 private ScriptObject builtinInt16Array;
320 private ScriptObject builtinUint16Array;
321 private ScriptObject builtinInt32Array;
322 private ScriptObject builtinUint32Array;
323 private ScriptObject builtinFloat32Array;
324 private ScriptObject builtinFloat64Array;
326 // Flag to indicate that a split method issued a return statement
327 private int splitState = -1;
329 // class cache
330 private ClassCache classCache;
332 private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class);
333 private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class);
334 private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
335 private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class);
337 /**
338 * Constructor
339 */
340 public Global() {
341 this.setIsScope();
342 /*
343 * Duplicate global's map and use it. This way the initial Map filled
344 * by nasgen (referenced from static field in this class) is retained
345 * 'as is'. This allows multiple globals to be used within a context.
346 */
347 this.setMap(getMap().duplicate());
349 final int cacheSize = getContext()._class_cache_size;
350 if (cacheSize > 0) {
351 classCache = new ClassCache(cacheSize);
352 }
353 }
355 /**
356 * Script access to unique context specific Global instance
357 *
358 * @return the global singleton
359 */
360 public static Global instance() {
361 return (Global)Context.getGlobal();
362 }
364 /**
365 * Script access to {@link Context}
366 *
367 * @return the context
368 */
369 static Context getThisContext() {
370 return instance().getContext();
371 }
373 /**
374 * Script access check for strict mode
375 *
376 * @return true if strict mode enabled in {@link Global#getThisContext()}
377 */
378 static boolean isStrict() {
379 return getThisContext()._strict;
380 }
382 // GlobalObject interface implementation
384 @Override
385 public void initBuiltinObjects() {
386 if (this.builtinObject != null) {
387 // already initialized, just return
388 return;
389 }
391 init();
392 }
394 @Override
395 public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
396 return new ScriptFunctionImpl(name, handle, scope, null, strict, false);
397 }
399 @Override
400 public Object wrapAsObject(final Object obj) {
401 if (obj instanceof Boolean) {
402 return new NativeBoolean((Boolean)obj);
403 } else if (obj instanceof Number) {
404 return new NativeNumber(((Number)obj).doubleValue());
405 } else if (obj instanceof String || obj instanceof ConsString) {
406 return new NativeString((CharSequence)obj);
407 } else if (obj instanceof Object[]) { // extension
408 return new NativeArray((Object[])obj);
409 } else if (obj instanceof double[]) { // extension
410 return new NativeArray((double[])obj);
411 } else if (obj instanceof long[]) {
412 return new NativeArray((long[])obj);
413 } else if (obj instanceof int[]) {
414 return new NativeArray((int[])obj);
415 } else {
416 // FIXME: more special cases? Map? List?
417 return obj;
418 }
419 }
421 @Override
422 public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
423 if (self instanceof String || self instanceof ConsString) {
424 return NativeString.lookupPrimitive(request, self);
425 } else if (self instanceof Number) {
426 return NativeNumber.lookupPrimitive(request, self);
427 } else if (self instanceof Boolean) {
428 return NativeBoolean.lookupPrimitive(request, self);
429 }
430 throw new IllegalArgumentException("Unsupported primitive: " + self);
431 }
433 @Override
434 public ScriptObject newObject() {
435 return newEmptyInstance();
436 }
438 @Override
439 public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
440 // When the [[DefaultValue]] internal method of O is called with no hint,
441 // then it behaves as if the hint were Number, unless O is a Date object
442 // in which case it behaves as if the hint were String.
443 Class<?> hint = typeHint;
444 if (hint == null) {
445 hint = Number.class;
446 }
448 try {
449 if (hint == String.class) {
451 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
452 if (toString instanceof ScriptFunction) {
453 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
454 if (JSType.isPrimitive(value)) {
455 return value;
456 }
457 }
459 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
460 if (valueOf instanceof ScriptFunction) {
461 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
462 if (JSType.isPrimitive(value)) {
463 return value;
464 }
465 }
466 typeError(this, "cannot.get.default.string");
467 }
469 if (hint == Number.class) {
470 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
471 if (valueOf instanceof ScriptFunction) {
472 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
473 if (JSType.isPrimitive(value)) {
474 return value;
475 }
476 }
478 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
479 if (toString instanceof ScriptFunction) {
480 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
481 if (JSType.isPrimitive(value)) {
482 return value;
483 }
484 }
486 typeError(this, "cannot.get.default.number");
487 }
488 } catch (final RuntimeException | Error e) {
489 throw e;
490 } catch (final Throwable t) {
491 throw new RuntimeException(t);
492 }
494 return UNDEFINED;
495 }
497 @Override
498 public boolean isError(final ScriptObject sobj) {
499 final ScriptObject errorProto = getErrorPrototype();
500 ScriptObject proto = sobj.getProto();
501 while (proto != null) {
502 if (proto == errorProto) {
503 return true;
504 }
505 proto = proto.getProto();
506 }
507 return false;
508 }
510 @Override
511 public ScriptObject newError(final String msg) {
512 return new NativeError(msg);
513 }
515 @Override
516 public ScriptObject newEvalError(final String msg) {
517 return new NativeEvalError(msg);
518 }
520 @Override
521 public ScriptObject newRangeError(final String msg) {
522 return new NativeRangeError(msg);
523 }
525 @Override
526 public ScriptObject newReferenceError(final String msg) {
527 return new NativeReferenceError(msg);
528 }
530 @Override
531 public ScriptObject newSyntaxError(final String msg) {
532 return new NativeSyntaxError(msg);
533 }
535 @Override
536 public ScriptObject newTypeError(final String msg) {
537 return new NativeTypeError(msg);
538 }
540 @Override
541 public ScriptObject newURIError(final String msg) {
542 return new NativeURIError(msg);
543 }
545 @Override
546 public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
547 return new GenericPropertyDescriptor(configurable, enumerable);
548 }
550 @Override
551 public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
552 return new DataPropertyDescriptor(configurable, enumerable, writable, value);
553 }
555 @Override
556 public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
557 final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set);
559 final boolean strict = getContext()._strict;
561 if (get == null) {
562 desc.delete(PropertyDescriptor.GET, strict);
563 }
565 if (set == null) {
566 desc.delete(PropertyDescriptor.SET, strict);
567 }
569 return desc;
570 }
573 /**
574 * Cache for compiled script classes.
575 */
576 @SuppressWarnings("serial")
577 private static class ClassCache extends LinkedHashMap<Source, SoftReference<Class<?>>> {
578 private final int size;
580 ClassCache(int size) {
581 super(size, 0.75f, true);
582 this.size = size;
583 }
585 @Override
586 protected boolean removeEldestEntry(final Map.Entry<Source, SoftReference<Class<?>>> eldest) {
587 return size() >= size;
588 }
589 }
591 // Class cache management
592 @Override
593 public Class<?> findCachedClass(final Source source) {
594 assert classCache != null : "Class cache used without being initialized";
595 SoftReference<Class<?>> ref = classCache.get(source);
596 if (ref != null) {
597 final Class<?> clazz = ref.get();
598 if (clazz == null) {
599 classCache.remove(source);
600 }
601 return clazz;
602 }
604 return null;
605 }
607 @Override
608 public void cacheClass(final Source source, final Class<?> clazz) {
609 assert classCache != null : "Class cache used without being initialized";
610 classCache.put(source, new SoftReference<Class<?>>(clazz));
611 }
613 /**
614 * This is the eval used when 'indirect' eval call is made.
615 *
616 * var global = this;
617 * global.eval("print('hello')");
618 *
619 * @param self eval scope
620 * @param str eval string
621 *
622 * @return the result of eval
623 */
624 public static Object eval(final Object self, final Object str) {
625 return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
626 }
628 /**
629 * Direct eval
630 *
631 * @param self The scope of eval passed as 'self'
632 * @param str Evaluated code
633 * @param callThis "this" to be passed to the evaluated code
634 * @param location location of the eval call
635 * @param strict is eval called a strict mode code?
636 *
637 * @return the return value of the eval
638 *
639 * This is directly invoked from generated when eval(code) is called in user code
640 */
641 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
642 if (!(str instanceof String || str instanceof ConsString)) {
643 return str;
644 }
645 final Global global = Global.instance();
646 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
648 return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
649 }
651 /**
652 * Global print implementation - Nashorn extension
653 *
654 * @param self scope
655 * @param objects arguments to print
656 *
657 * @return result of print (undefined)
658 */
659 public static Object print(final Object self, final Object... objects) {
660 return printImpl(false, objects);
661 }
663 /**
664 * Global println implementation - Nashorn extension
665 *
666 * @param self scope
667 * @param objects arguments to print
668 *
669 * @return result of println (undefined)
670 */
671 public static Object println(final Object self, final Object... objects) {
672 return printImpl(true, objects);
673 }
675 /**
676 * Global load implementation - Nashorn extension
677 *
678 * @param self scope
679 * @param source source to load
680 *
681 * @return result of load (undefined)
682 *
683 * @throws IOException if source could not be read
684 */
685 public static Object load(final Object self, final Object source) throws IOException {
686 final Global global = Global.instance();
687 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
688 return global.getContext().load(scope, source);
689 }
691 ScriptObject getFunctionPrototype() {
692 return ScriptFunction.getPrototype(builtinFunction);
693 }
695 ScriptObject getObjectPrototype() {
696 return ScriptFunction.getPrototype(builtinObject);
697 }
699 ScriptObject getArrayPrototype() {
700 return ScriptFunction.getPrototype(builtinArray);
701 }
703 ScriptObject getBooleanPrototype() {
704 return ScriptFunction.getPrototype(builtinBoolean);
705 }
707 ScriptObject getNumberPrototype() {
708 return ScriptFunction.getPrototype(builtinNumber);
709 }
711 ScriptObject getDatePrototype() {
712 return ScriptFunction.getPrototype(builtinDate);
713 }
715 ScriptObject getRegExpPrototype() {
716 return ScriptFunction.getPrototype(builtinRegExp);
717 }
719 ScriptObject getStringPrototype() {
720 return ScriptFunction.getPrototype(builtinString);
721 }
723 ScriptObject getErrorPrototype() {
724 return ScriptFunction.getPrototype(builtinError);
725 }
727 ScriptObject getEvalErrorPrototype() {
728 return ScriptFunction.getPrototype(builtinEvalError);
729 }
731 ScriptObject getRangeErrorPrototype() {
732 return ScriptFunction.getPrototype(builtinRangeError);
733 }
735 ScriptObject getReferenceErrorPrototype() {
736 return ScriptFunction.getPrototype(builtinReferenceError);
737 }
739 ScriptObject getSyntaxErrorPrototype() {
740 return ScriptFunction.getPrototype(builtinSyntaxError);
741 }
743 ScriptObject getTypeErrorPrototype() {
744 return ScriptFunction.getPrototype(builtinTypeError);
745 }
747 ScriptObject getURIErrorPrototype() {
748 return ScriptFunction.getPrototype(builtinURIError);
749 }
751 ScriptObject getJavaImporterPrototype() {
752 return ScriptFunction.getPrototype(builtinJavaImporter);
753 }
755 ScriptObject getJSAdapterPrototype() {
756 return ScriptFunction.getPrototype(builtinJSAdapter);
757 }
759 ScriptObject getArrayBufferPrototype() {
760 return ScriptFunction.getPrototype(builtinArrayBuffer);
761 }
763 ScriptObject getInt8ArrayPrototype() {
764 return ScriptFunction.getPrototype(builtinInt8Array);
765 }
767 ScriptObject getUint8ArrayPrototype() {
768 return ScriptFunction.getPrototype(builtinUint8Array);
769 }
771 ScriptObject getUint8ClampedArrayPrototype() {
772 return ScriptFunction.getPrototype(builtinUint8ClampedArray);
773 }
775 ScriptObject getInt16ArrayPrototype() {
776 return ScriptFunction.getPrototype(builtinInt16Array);
777 }
779 ScriptObject getUint16ArrayPrototype() {
780 return ScriptFunction.getPrototype(builtinUint16Array);
781 }
783 ScriptObject getInt32ArrayPrototype() {
784 return ScriptFunction.getPrototype(builtinInt32Array);
785 }
787 ScriptObject getUint32ArrayPrototype() {
788 return ScriptFunction.getPrototype(builtinUint32Array);
789 }
791 ScriptObject getFloat32ArrayPrototype() {
792 return ScriptFunction.getPrototype(builtinFloat32Array);
793 }
795 ScriptObject getFloat64ArrayPrototype() {
796 return ScriptFunction.getPrototype(builtinFloat64Array);
797 }
799 private ScriptFunction getBuiltinArray() {
800 return builtinArray;
801 }
804 /**
805 * Called from compiled script code to test if builtin has been overridden
806 *
807 * @return true if builtin array has not been overridden
808 */
809 public static boolean isBuiltinArray() {
810 final Global instance = Global.instance();
811 return instance.array == instance.getBuiltinArray();
812 }
814 private ScriptFunction getBuiltinBoolean() {
815 return builtinBoolean;
816 }
818 /**
819 * Called from compiled script code to test if builtin has been overridden
820 *
821 * @return true if builtin boolean has not been overridden
822 */
823 public static boolean isBuiltinBoolean() {
824 final Global instance = Global.instance();
825 return instance._boolean == instance.getBuiltinBoolean();
826 }
828 private ScriptFunction getBuiltinDate() {
829 return builtinDate;
830 }
832 /**
833 * Called from compiled script code to test if builtin has been overridden
834 *
835 * @return true if builtin date has not been overridden
836 */
837 public static boolean isBuiltinDate() {
838 final Global instance = Global.instance();
839 return instance.date == instance.getBuiltinDate();
840 }
842 private ScriptFunction getBuiltinError() {
843 return builtinError;
844 }
846 /**
847 * Called from compiled script code to test if builtin has been overridden
848 *
849 * @return true if builtin error has not been overridden
850 */
851 public static boolean isBuiltinError() {
852 final Global instance = Global.instance();
853 return instance.error == instance.getBuiltinError();
854 }
856 private ScriptFunction getBuiltinEvalError() {
857 return builtinEvalError;
858 }
860 /**
861 * Called from compiled script code to test if builtin has been overridden
862 *
863 * @return true if builtin eval error has not been overridden
864 */
865 public static boolean isBuiltinEvalError() {
866 final Global instance = Global.instance();
867 return instance.evalError == instance.getBuiltinEvalError();
868 }
870 private ScriptFunction getBuiltinFunction() {
871 return builtinFunction;
872 }
874 /**
875 * Called from compiled script code to test if builtin has been overridden
876 *
877 * @return true if builtin function has not been overridden
878 */
879 public static boolean isBuiltinFunction() {
880 final Global instance = Global.instance();
881 return instance.function == instance.getBuiltinFunction();
882 }
884 private ScriptFunction getBuiltinJSAdapter() {
885 return builtinJSAdapter;
886 }
888 /**
889 * Called from compiled script code to test if builtin has been overridden
890 *
891 * @return true if builtin JSAdapter has not been overridden
892 */
893 public static boolean isBuiltinJSAdapter() {
894 final Global instance = Global.instance();
895 return instance.jsadapter == instance.getBuiltinJSAdapter();
896 }
898 private ScriptObject getBuiltinJSON() {
899 return builtinJSON;
900 }
902 /**
903 * Called from compiled script code to test if builtin has been overridden
904 *
905 * @return true if builtin JSON has has not been overridden
906 */
907 public static boolean isBuiltinJSON() {
908 final Global instance = Global.instance();
909 return instance.json == instance.getBuiltinJSON();
910 }
912 private ScriptObject getBuiltinJava() {
913 return builtinJava;
914 }
916 /**
917 * Called from compiled script code to test if builtin has been overridden
918 *
919 * @return true if builtin Java has not been overridden
920 */
921 public static boolean isBuiltinJava() {
922 final Global instance = Global.instance();
923 return instance.java == instance.getBuiltinJava();
924 }
926 private ScriptObject getBuiltinJavax() {
927 return builtinJavax;
928 }
930 /**
931 * Called from compiled script code to test if builtin has been overridden
932 *
933 * @return true if builtin Javax has not been overridden
934 */
935 public static boolean isBuiltinJavax() {
936 final Global instance = Global.instance();
937 return instance.javax == instance.getBuiltinJavax();
938 }
940 private ScriptObject getBuiltinJavaImporter() {
941 return builtinJavaImporter;
942 }
944 /**
945 * Called from compiled script code to test if builtin has been overridden
946 *
947 * @return true if builtin Java importer has not been overridden
948 */
949 public static boolean isBuiltinJavaImporter() {
950 final Global instance = Global.instance();
951 return instance.javaImporter == instance.getBuiltinJavaImporter();
952 }
954 private ScriptObject getBuiltinMath() {
955 return builtinMath;
956 }
958 /**
959 * Called from compiled script code to test if builtin has been overridden
960 *
961 * @return true if builtin math has not been overridden
962 */
963 public static boolean isBuiltinMath() {
964 final Global instance = Global.instance();
965 return instance.math == instance.getBuiltinMath();
966 }
968 private ScriptFunction getBuiltinNumber() {
969 return builtinNumber;
970 }
972 /**
973 * Called from compiled script code to test if builtin has been overridden
974 *
975 * @return true if builtin number has not been overridden
976 */
977 public static boolean isBuiltinNumber() {
978 final Global instance = Global.instance();
979 return instance.number == instance.getBuiltinNumber();
980 }
982 private ScriptFunction getBuiltinObject() {
983 return builtinObject;
984 }
986 /**
987 * Called from compiled script code to test if builtin has been overridden
988 *
989 * @return true if builtin object has not been overridden
990 */
991 public static boolean isBuiltinObject() {
992 final Global instance = Global.instance();
993 return instance.object == instance.getBuiltinObject();
994 }
996 private ScriptObject getBuiltinPackages() {
997 return builtinPackages;
998 }
1000 /**
1001 * Called from compiled script code to test if builtin has been overridden
1002 *
1003 * @return true if builtin package has not been overridden
1004 */
1005 public static boolean isBuiltinPackages() {
1006 final Global instance = Global.instance();
1007 return instance.packages == instance.getBuiltinPackages();
1008 }
1010 private ScriptFunction getBuiltinRangeError() {
1011 return builtinRangeError;
1012 }
1014 /**
1015 * Called from compiled script code to test if builtin has been overridden
1016 *
1017 * @return true if builtin range error has not been overridden
1018 */
1019 public static boolean isBuiltinRangeError() {
1020 final Global instance = Global.instance();
1021 return instance.rangeError == instance.getBuiltinRangeError();
1022 }
1024 private ScriptFunction getBuiltinReferenceError() {
1025 return builtinReferenceError;
1026 }
1028 /**
1029 * Called from compiled script code to test if builtin has been overridden
1030 *
1031 * @return true if builtin reference error has not been overridden
1032 */
1033 public static boolean isBuiltinReferenceError() {
1034 final Global instance = Global.instance();
1035 return instance.referenceError == instance.getBuiltinReferenceError();
1036 }
1038 private ScriptFunction getBuiltinRegExp() {
1039 return builtinRegExp;
1040 }
1042 /**
1043 * Called from compiled script code to test if builtin has been overridden
1044 *
1045 * @return true if builtin regexp has not been overridden
1046 */
1047 public static boolean isBuiltinRegExp() {
1048 final Global instance = Global.instance();
1049 return instance.regexp == instance.getBuiltinRegExp();
1050 }
1052 private ScriptFunction getBuiltinString() {
1053 return builtinString;
1054 }
1056 /**
1057 * Called from compiled script code to test if builtin has been overridden
1058 *
1059 * @return true if builtin Java has not been overridden
1060 */
1061 public static boolean isBuiltinString() {
1062 final Global instance = Global.instance();
1063 return instance.string == instance.getBuiltinString();
1064 }
1066 private ScriptFunction getBuiltinSyntaxError() {
1067 return builtinSyntaxError;
1068 }
1070 /**
1071 * Called from compiled script code to test if builtin has been overridden
1072 *
1073 * @return true if builtin syntax error has not been overridden
1074 */
1075 public static boolean isBuiltinSyntaxError() {
1076 final Global instance = Global.instance();
1077 return instance.syntaxError == instance.getBuiltinSyntaxError();
1078 }
1080 private ScriptFunction getBuiltinTypeError() {
1081 return builtinTypeError;
1082 }
1084 /**
1085 * Called from compiled script code to test if builtin has been overridden
1086 *
1087 * @return true if builtin type error has not been overridden
1088 */
1089 public static boolean isBuiltinTypeError() {
1090 final Global instance = Global.instance();
1091 return instance.typeError == instance.getBuiltinTypeError();
1092 }
1094 private ScriptFunction getBuiltinURIError() {
1095 return builtinURIError;
1096 }
1098 /**
1099 * Called from compiled script code to test if builtin has been overridden
1100 *
1101 * @return true if builtin URI error has not been overridden
1102 */
1103 public static boolean isBuiltinURIError() {
1104 final Global instance = Global.instance();
1105 return instance.uriError == instance.getBuiltinURIError();
1106 }
1108 @Override
1109 public String getClassName() {
1110 return "global";
1111 }
1113 /**
1114 * Copy function used to clone NativeRegExp objects.
1115 *
1116 * @param regexp a NativeRegExp to clone
1117 *
1118 * @return copy of the given regexp object
1119 */
1120 public static Object regExpCopy(final Object regexp) {
1121 return new NativeRegExp((NativeRegExp)regexp);
1122 }
1124 /**
1125 * Convert given object to NativeRegExp type.
1126 *
1127 * @param obj object to be converted
1128 * @return NativeRegExp instance
1129 */
1130 public static NativeRegExp toRegExp(final Object obj) {
1131 if (obj instanceof NativeRegExp) {
1132 return (NativeRegExp)obj;
1133 }
1134 return new NativeRegExp(JSType.toString(obj));
1135 }
1137 /**
1138 * ECMA 9.9 ToObject implementation
1139 *
1140 * @param obj an item for which to run ToObject
1141 * @return ToObject version of given item
1142 */
1143 public static Object toObject(final Object obj) {
1144 if (obj == null || obj == UNDEFINED) {
1145 typeError("not.an.object", ScriptRuntime.safeToString(obj));
1146 }
1148 if (obj instanceof ScriptObject) {
1149 return obj;
1150 }
1152 return instance().wrapAsObject(obj);
1153 }
1155 /**
1156 * Allocate a new object array.
1157 *
1158 * @param initial object values.
1159 * @return the new array
1160 */
1161 public static NativeArray allocate(final Object[] initial) {
1162 return new NativeArray(initial);
1163 }
1165 /**
1166 * Allocate a new number array.
1167 *
1168 * @param initial number values.
1169 * @return the new array
1170 */
1171 public static NativeArray allocate(final double[] initial) {
1172 return new NativeArray(initial);
1173 }
1175 /**
1176 * Allocate a new long array.
1177 *
1178 * @param initial number values.
1179 * @return the new array
1180 */
1181 public static NativeArray allocate(final long[] initial) {
1182 return new NativeArray(initial);
1183 }
1185 /**
1186 * Allocate a new integer array.
1187 *
1188 * @param initial number values.
1189 * @return the new array
1190 */
1191 public static NativeArray allocate(final int[] initial) {
1192 return new NativeArray(initial);
1193 }
1195 /**
1196 * Allocate a new object array for arguments.
1197 *
1198 * @param arguments initial arguments passed.
1199 * @param callee reference to the function that uses arguments object
1200 * @param numParams actual number of declared parameters
1201 *
1202 * @return the new array
1203 */
1204 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1205 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1206 }
1208 /**
1209 * Called from generated to check if given function is the builtin 'eval'. If
1210 * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1211 *
1212 * @param fn function object that is checked
1213 * @return true if fn is the builtin eval
1214 */
1215 public static boolean isEval(final Object fn) {
1216 return fn == Global.instance().builtinEval;
1217 }
1219 /**
1220 * Create a new RegExp object.
1221 *
1222 * @param expression Regular expression.
1223 * @param options Search options.
1224 *
1225 * @return New RegExp object.
1226 */
1227 public static Object newRegExp(final String expression, final String options) {
1228 if (options == null) {
1229 return new NativeRegExp(expression);
1230 }
1231 return new NativeRegExp(expression, options);
1232 }
1234 /**
1235 * Get the object prototype
1236 *
1237 * @return the object prototype
1238 */
1239 public static ScriptObject objectPrototype() {
1240 return Global.instance().getObjectPrototype();
1241 }
1243 /**
1244 * Create a new empty object instance.
1245 *
1246 * @return New empty object.
1247 */
1248 public static ScriptObject newEmptyInstance() {
1249 final ScriptObject sobj = new JO$();
1250 sobj.setProto(objectPrototype());
1251 return sobj;
1252 }
1254 /**
1255 * Check if a given object is a ScriptObject, raises an exception if this is
1256 * not the case
1257 *
1258 * @param obj and object to check
1259 */
1260 public static void checkObject(final Object obj) {
1261 if (!(obj instanceof ScriptObject)) {
1262 typeError("not.an.object", ScriptRuntime.safeToString(obj));
1263 }
1264 }
1266 /**
1267 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1268 * if this object is null or undefined.
1269 *
1270 * @param obj an object to check
1271 */
1272 public static void checkObjectCoercible(final Object obj) {
1273 if (obj == null || obj == UNDEFINED) {
1274 typeError("not.an.object", ScriptRuntime.safeToString(obj));
1275 }
1276 }
1278 /**
1279 * Get the current split state.
1280 *
1281 * @return current split state
1282 */
1283 @Override
1284 public int getSplitState() {
1285 return splitState;
1286 }
1288 /**
1289 * Set the current split state.
1290 *
1291 * @param state current split state
1292 */
1293 @Override
1294 public void setSplitState(final int state) {
1295 splitState = state;
1296 }
1298 private void init() {
1299 assert Context.getGlobal() == this : "this global is not set as current";
1301 // initialize Function and Object constructor
1302 initFunctionAndObject();
1304 // Now fix Global's own proto.
1305 this.setProto(getObjectPrototype());
1307 // initialize global function properties
1308 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1309 ((ScriptFunction)this.eval).setArity(1);
1311 this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT);
1312 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1313 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN);
1314 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE);
1315 this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI);
1316 this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1317 this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI);
1318 this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1319 this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE);
1320 this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
1321 this.print = ScriptFunctionImpl.makeFunction("print", getContext()._print_no_newline ? PRINT : PRINTLN);
1322 this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
1324 // built-in constructors
1325 this.builtinArray = (ScriptFunction)initConstructor("Array");
1326 this.builtinBoolean = (ScriptFunction)initConstructor("Boolean");
1327 this.builtinDate = (ScriptFunction)initConstructor("Date");
1328 this.builtinJSON = initConstructor("JSON");
1329 this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
1330 this.builtinMath = initConstructor("Math");
1331 this.builtinNumber = (ScriptFunction)initConstructor("Number");
1332 this.builtinRegExp = (ScriptFunction)initConstructor("RegExp");
1333 this.builtinString = (ScriptFunction)initConstructor("String");
1335 // initialize String.prototype.length to 0
1336 // add String.prototype.length
1337 final ScriptObject stringPrototype = getStringPrototype();
1338 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1340 // add Array.prototype.length
1341 final ScriptObject arrayPrototype = getArrayPrototype();
1342 arrayPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1344 this.DEFAULT_DATE = new NativeDate(Double.NaN);
1346 // initialize default regexp object
1347 this.DEFAULT_REGEXP = new NativeRegExp("(?:)");
1349 // RegExp.prototype should behave like a RegExp object. So copy the
1350 // properties.
1351 final ScriptObject regExpProto = getRegExpPrototype();
1352 regExpProto.addBoundProperties(DEFAULT_REGEXP);
1354 // Error stuff
1355 initErrorObjects();
1357 // java access
1358 initJavaAccess();
1360 initTypedArray();
1362 if (getContext()._scripting) {
1363 initScripting();
1364 }
1366 if (Context.DEBUG && System.getSecurityManager() == null) {
1367 initDebug();
1368 }
1370 copyBuiltins();
1372 // initialized with strings so that typeof will work as expected.
1373 this.__FILE__ = "";
1374 this.__DIR__ = "";
1375 this.__LINE__ = 0.0;
1377 // expose script (command line) arguments as "arguments" property of global
1378 final List<String> arguments = getContext().getOptions().getArguments();
1379 final Object argsObj = wrapAsObject(arguments.toArray());
1381 addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
1382 if (getContext()._scripting) {
1383 // synonym for "arguments" in scripting mode
1384 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
1385 }
1386 }
1388 private void initErrorObjects() {
1389 // Error objects
1390 this.builtinError = (ScriptFunction)initConstructor("Error");
1391 final ScriptObject errorProto = getErrorPrototype();
1392 final boolean strict = Global.isStrict();
1394 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1395 final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1396 final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1397 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1398 final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1399 final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1400 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1401 final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1402 final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1403 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1404 final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1405 final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1406 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1408 // ECMA 15.11.4.2 Error.prototype.name
1409 // Error.prototype.name = "Error";
1410 errorProto.set(NativeError.NAME, "Error", strict);
1411 // ECMA 15.11.4.3 Error.prototype.message
1412 // Error.prototype.message = "";
1413 errorProto.set(NativeError.MESSAGE, "", strict);
1415 this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1416 this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1417 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1418 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1419 this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1420 this.builtinURIError = initErrorSubtype("URIError", errorProto);
1421 }
1423 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1424 final ScriptObject cons = initConstructor(name);
1425 final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1426 final boolean strict = Global.isStrict();
1427 prototype.set(NativeError.NAME, name, strict);
1428 prototype.set(NativeError.MESSAGE, "", strict);
1429 prototype.setProto(errorProto);
1430 return (ScriptFunction)cons;
1431 }
1433 private void initJavaAccess() {
1434 final ScriptObject objectProto = getObjectPrototype();
1435 this.builtinPackages = new NativeJavaPackage("", objectProto);
1436 this.builtinJava = new NativeJavaPackage("java", objectProto);
1437 this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1438 this.builtinJavaImporter = initConstructor("JavaImporter");
1439 this.builtinJavaApi = initConstructor("Java");
1440 }
1442 private void initScripting() {
1443 Object value;
1444 value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1445 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1447 value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1448 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1450 value = ScriptFunctionImpl.makeFunction("quit", ScriptingFunctions.QUIT);
1451 addOwnProperty("quit", Attribute.NOT_ENUMERABLE, value);
1453 final String execName = ScriptingFunctions.EXEC_NAME;
1454 value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1455 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1457 // Nashorn extension: global.echo (scripting-mode-only)
1458 // alias for "print"
1459 value = get("print");
1460 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1462 // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1463 value = new OptionsObject(this.getContext());
1464 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, value);
1466 // Nashorn extension: global.$ENV (scripting-mode-only)
1467 if (System.getSecurityManager() == null) {
1468 // do not fill $ENV if we have a security manager around
1469 // Retrieve current state of ENV variables.
1470 final ScriptObject env = newEmptyInstance();
1471 env.putAll(System.getenv());
1472 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1473 } else {
1474 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1475 }
1477 // add other special properties for exec support
1478 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1479 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1480 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1481 }
1483 private void initTypedArray() {
1484 this.builtinArrayBuffer = initConstructor("ArrayBuffer");
1485 this.builtinInt8Array = initConstructor("Int8Array");
1486 this.builtinUint8Array = initConstructor("Uint8Array");
1487 this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
1488 this.builtinInt16Array = initConstructor("Int16Array");
1489 this.builtinUint16Array = initConstructor("Uint16Array");
1490 this.builtinInt32Array = initConstructor("Int32Array");
1491 this.builtinUint32Array = initConstructor("Uint32Array");
1492 this.builtinFloat32Array = initConstructor("Float32Array");
1493 this.builtinFloat64Array = initConstructor("Float64Array");
1494 }
1496 private void copyBuiltins() {
1497 this.array = this.builtinArray;
1498 this._boolean = this.builtinBoolean;
1499 this.date = this.builtinDate;
1500 this.error = this.builtinError;
1501 this.evalError = this.builtinEvalError;
1502 this.function = this.builtinFunction;
1503 this.jsadapter = this.builtinJSAdapter;
1504 this.json = this.builtinJSON;
1505 this.java = this.builtinJava;
1506 this.javax = this.builtinJavax;
1507 this.javaImporter = this.builtinJavaImporter;
1508 this.javaApi = this.builtinJavaApi;
1509 this.math = this.builtinMath;
1510 this.number = this.builtinNumber;
1511 this.object = this.builtinObject;
1512 this.packages = this.builtinPackages;
1513 this.rangeError = this.builtinRangeError;
1514 this.referenceError = this.builtinReferenceError;
1515 this.regexp = this.builtinRegExp;
1516 this.string = this.builtinString;
1517 this.syntaxError = this.builtinSyntaxError;
1518 this.typeError = this.builtinTypeError;
1519 this.uriError = this.builtinURIError;
1520 this.arrayBuffer = this.builtinArrayBuffer;
1521 this.int8Array = this.builtinInt8Array;
1522 this.uint8Array = this.builtinUint8Array;
1523 this.uint8ClampedArray = this.builtinUint8ClampedArray;
1524 this.int16Array = this.builtinInt16Array;
1525 this.uint16Array = this.builtinUint16Array;
1526 this.int32Array = this.builtinInt32Array;
1527 this.uint32Array = this.builtinUint32Array;
1528 this.float32Array = this.builtinFloat32Array;
1529 this.float64Array = this.builtinFloat64Array;
1530 }
1532 private void initDebug() {
1533 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
1534 }
1536 @SuppressWarnings("resource")
1537 private static Object printImpl(final boolean newLine, final Object... objects) {
1538 final PrintWriter out = Global.getThisContext().getOut();
1540 boolean first = true;
1541 for (final Object object : objects) {
1542 if (first) {
1543 first = false;
1544 } else {
1545 out.print(' ');
1546 }
1548 out.print(JSType.toString(object));
1549 }
1551 if (newLine) {
1552 out.println();
1553 }
1555 out.flush();
1557 return UNDEFINED;
1558 }
1560 /**
1561 * These classes are generated by nasgen tool and so we have to use
1562 * reflection to load and create new instance of these classes.
1563 */
1564 private ScriptObject initConstructor(final String name) {
1565 try {
1566 // Assuming class name pattern for built-in JS constructors.
1567 final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
1569 sb.append("Native");
1570 sb.append(name);
1571 sb.append("$Constructor");
1573 final Class<?> funcClass = Class.forName(sb.toString());
1574 final ScriptObject res = (ScriptObject)funcClass.newInstance();
1576 if (res instanceof ScriptFunction) {
1577 // All global constructor prototypes are not-writable,
1578 // not-enumerable and not-configurable.
1579 final ScriptFunction func = (ScriptFunction)res;
1580 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
1581 }
1583 if (res.getProto() == null) {
1584 res.setProto(getObjectPrototype());
1585 }
1587 return res;
1589 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
1590 throw new RuntimeException(e);
1591 }
1592 }
1594 // Function and Object constructors are inter-dependent. Also,
1595 // Function.prototype
1596 // functions are not properly initialized. We fix the references here.
1597 // NOTE: be careful if you want to re-order the operations here. You may
1598 // have
1599 // to play with object references carefully!!
1600 private void initFunctionAndObject() {
1601 // First-n-foremost is Function
1602 this.builtinFunction = (ScriptFunction)initConstructor("Function");
1604 // create global anonymous function
1605 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
1606 // need to copy over members of Function.prototype to anon function
1607 anon.addBoundProperties(getFunctionPrototype());
1609 // Function.prototype === Object.getPrototypeOf(Function) ===
1610 // <anon-function>
1611 builtinFunction.setProto(anon);
1612 builtinFunction.setPrototype(anon);
1613 anon.set("constructor", builtinFunction, anon.isStrict());
1614 anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
1616 // now initialize Object
1617 this.builtinObject = (ScriptFunction)initConstructor("Object");
1618 final ScriptObject ObjectPrototype = getObjectPrototype();
1619 // Object.getPrototypeOf(Function.prototype) === Object.prototype
1620 anon.setProto(ObjectPrototype);
1622 // Function valued properties of Function.prototype were not properly
1623 // initialized. Because, these were created before global.function and
1624 // global.object were not initialized.
1625 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
1626 for (final jdk.nashorn.internal.runtime.Property property : properties) {
1627 final Object key = property.getKey();
1628 final Object value = builtinFunction.get(key);
1630 if (value instanceof ScriptFunction && value != anon) {
1631 final ScriptFunction func = (ScriptFunction)value;
1632 func.setProto(getFunctionPrototype());
1633 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1634 if (prototype != null) {
1635 prototype.setProto(ObjectPrototype);
1636 }
1637 }
1638 }
1640 // For function valued properties of Object and Object.prototype, make
1641 // sure prototype's proto chain ends with Object.prototype
1642 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
1643 final Object key = property.getKey();
1644 final Object value = builtinObject.get(key);
1646 if (value instanceof ScriptFunction) {
1647 final ScriptFunction func = (ScriptFunction)value;
1648 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1649 if (prototype != null) {
1650 prototype.setProto(ObjectPrototype);
1651 }
1652 }
1653 }
1655 properties = getObjectPrototype().getMap().getProperties();
1656 for (final jdk.nashorn.internal.runtime.Property property : properties) {
1657 final Object key = property.getKey();
1658 final Object value = ObjectPrototype.get(key);
1660 if (key.equals("constructor")) {
1661 continue;
1662 }
1664 if (value instanceof ScriptFunction) {
1665 final ScriptFunction func = (ScriptFunction)value;
1666 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1667 if (prototype != null) {
1668 prototype.setProto(ObjectPrototype);
1669 }
1670 }
1671 }
1672 }
1675 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
1676 return MH.findStatic(MethodHandles.publicLookup(), Global.class, name, MH.type(rtype, types));
1677 }
1678 }