Wed, 20 May 2015 14:16:19 +0530
8080598: Javadoc warnings in Global.java after lazy initialization
Reviewed-by: lagergren, 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.lookup.Lookup.MH;
29 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
30 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
31 import static jdk.nashorn.internal.runtime.JSType.isString;
32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
34 import java.io.IOException;
35 import java.io.PrintWriter;
36 import java.lang.invoke.MethodHandle;
37 import java.lang.invoke.MethodHandles;
38 import java.lang.invoke.MethodType;
39 import java.lang.invoke.SwitchPoint;
40 import java.lang.reflect.Field;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Objects;
46 import java.util.concurrent.Callable;
47 import java.util.concurrent.ConcurrentHashMap;
48 import javax.script.ScriptContext;
49 import javax.script.ScriptEngine;
50 import jdk.internal.dynalink.CallSiteDescriptor;
51 import jdk.internal.dynalink.linker.GuardedInvocation;
52 import jdk.internal.dynalink.linker.LinkRequest;
53 import jdk.nashorn.api.scripting.ClassFilter;
54 import jdk.nashorn.api.scripting.ScriptObjectMirror;
55 import jdk.nashorn.internal.lookup.Lookup;
56 import jdk.nashorn.internal.objects.annotations.Attribute;
57 import jdk.nashorn.internal.objects.annotations.Getter;
58 import jdk.nashorn.internal.objects.annotations.Property;
59 import jdk.nashorn.internal.objects.annotations.ScriptClass;
60 import jdk.nashorn.internal.objects.annotations.Setter;
61 import jdk.nashorn.internal.runtime.Context;
62 import jdk.nashorn.internal.runtime.ECMAErrors;
63 import jdk.nashorn.internal.runtime.FindProperty;
64 import jdk.nashorn.internal.runtime.GlobalConstants;
65 import jdk.nashorn.internal.runtime.GlobalFunctions;
66 import jdk.nashorn.internal.runtime.JSType;
67 import jdk.nashorn.internal.runtime.NativeJavaPackage;
68 import jdk.nashorn.internal.runtime.PropertyDescriptor;
69 import jdk.nashorn.internal.runtime.PropertyMap;
70 import jdk.nashorn.internal.runtime.Scope;
71 import jdk.nashorn.internal.runtime.ScriptEnvironment;
72 import jdk.nashorn.internal.runtime.ScriptFunction;
73 import jdk.nashorn.internal.runtime.ScriptObject;
74 import jdk.nashorn.internal.runtime.ScriptRuntime;
75 import jdk.nashorn.internal.runtime.ScriptingFunctions;
76 import jdk.nashorn.internal.runtime.Specialization;
77 import jdk.nashorn.internal.runtime.arrays.ArrayData;
78 import jdk.nashorn.internal.runtime.linker.Bootstrap;
79 import jdk.nashorn.internal.runtime.linker.InvokeByName;
80 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
81 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
82 import jdk.nashorn.internal.scripts.JD;
83 import jdk.nashorn.internal.scripts.JO;
84 import jdk.nashorn.tools.ShellFunctions;
86 /**
87 * Representation of global scope.
88 */
89 @ScriptClass("Global")
90 public final class Global extends ScriptObject implements Scope {
91 // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
92 private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
93 private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
94 private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class);
96 // placeholder value for lazily initialized global objects
97 private static final Object LAZY_SENTINEL = new Object();
99 /**
100 * Optimistic builtin names that require switchpoint invalidation
101 * upon assignment. Overly conservative, but works for now, to avoid
102 * any complicated scope checks and especially heavy weight guards
103 * like
104 *
105 * <pre>
106 * public boolean setterGuard(final Object receiver) {
107 * final Global global = Global.instance();
108 * final ScriptObject sobj = global.getFunctionPrototype();
109 * final Object apply = sobj.get("apply");
110 * return apply == receiver;
111 * }
112 * </pre>
113 *
114 * Naturally, checking for builtin classes like NativeFunction is cheaper,
115 * it's when you start adding property checks for said builtins you have
116 * problems with guard speed.
117 */
119 /** Nashorn extension: arguments array */
120 @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
121 public Object arguments;
123 /** ECMA 15.1.2.2 parseInt (string , radix) */
124 @Property(attributes = Attribute.NOT_ENUMERABLE)
125 public Object parseInt;
127 /** ECMA 15.1.2.3 parseFloat (string) */
128 @Property(attributes = Attribute.NOT_ENUMERABLE)
129 public Object parseFloat;
131 /** ECMA 15.1.2.4 isNaN (number) */
132 @Property(attributes = Attribute.NOT_ENUMERABLE)
133 public Object isNaN;
135 /** ECMA 15.1.2.5 isFinite (number) */
136 @Property(attributes = Attribute.NOT_ENUMERABLE)
137 public Object isFinite;
139 /** ECMA 15.1.3.3 encodeURI */
140 @Property(attributes = Attribute.NOT_ENUMERABLE)
141 public Object encodeURI;
143 /** ECMA 15.1.3.4 encodeURIComponent */
144 @Property(attributes = Attribute.NOT_ENUMERABLE)
145 public Object encodeURIComponent;
147 /** ECMA 15.1.3.1 decodeURI */
148 @Property(attributes = Attribute.NOT_ENUMERABLE)
149 public Object decodeURI;
151 /** ECMA 15.1.3.2 decodeURIComponent */
152 @Property(attributes = Attribute.NOT_ENUMERABLE)
153 public Object decodeURIComponent;
155 /** ECMA B.2.1 escape (string) */
156 @Property(attributes = Attribute.NOT_ENUMERABLE)
157 public Object escape;
159 /** ECMA B.2.2 unescape (string) */
160 @Property(attributes = Attribute.NOT_ENUMERABLE)
161 public Object unescape;
163 /** Nashorn extension: global.print */
164 @Property(attributes = Attribute.NOT_ENUMERABLE)
165 public Object print;
167 /** Nashorn extension: global.load */
168 @Property(attributes = Attribute.NOT_ENUMERABLE)
169 public Object load;
171 /** Nashorn extension: global.loadWithNewGlobal */
172 @Property(attributes = Attribute.NOT_ENUMERABLE)
173 public Object loadWithNewGlobal;
175 /** Nashorn extension: global.exit */
176 @Property(attributes = Attribute.NOT_ENUMERABLE)
177 public Object exit;
179 /** Nashorn extension: global.quit */
180 @Property(attributes = Attribute.NOT_ENUMERABLE)
181 public Object quit;
183 /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
184 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
185 public final double NaN = Double.NaN;
187 /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
188 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
189 public final double Infinity = Double.POSITIVE_INFINITY;
191 /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
192 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
193 public final Object undefined = UNDEFINED;
195 /** ECMA 15.1.2.1 eval(x) */
196 @Property(attributes = Attribute.NOT_ENUMERABLE)
197 public Object eval;
199 /** ECMA 15.1.4.1 Object constructor. */
200 @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
201 public volatile Object object;
203 /** ECMA 15.1.4.2 Function constructor. */
204 @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
205 public volatile Object function;
207 /** ECMA 15.1.4.3 Array constructor. */
208 @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
209 public volatile Object array;
211 /** ECMA 15.1.4.4 String constructor */
212 @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
213 public volatile Object string;
215 /** ECMA 15.1.4.5 Boolean constructor */
216 @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
217 public volatile Object _boolean;
219 /** ECMA 15.1.4.6 - Number constructor */
220 @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
221 public volatile Object number;
223 /**
224 * Getter for ECMA 15.1.4.7 Date property
225 *
226 * @param self self reference
227 * @return Date property value
228 */
229 @Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
230 public static Object getDate(final Object self) {
231 final Global global = Global.instanceFrom(self);
232 if (global.date == LAZY_SENTINEL) {
233 global.date = global.getBuiltinDate();
234 }
235 return global.date;
236 }
238 /**
239 * Setter for ECMA 15.1.4.7 Date property
240 *
241 * @param self self reference
242 * @param value value for the Date property
243 */
244 @Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
245 public static void setDate(final Object self, final Object value) {
246 final Global global = Global.instanceFrom(self);
247 global.date = value;
248 }
250 private volatile Object date = LAZY_SENTINEL;
252 /**
253 * Getter for ECMA 15.1.4.8 RegExp property
254 *
255 * @param self self reference
256 * @return RegExp property value
257 */
258 @Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
259 public static Object getRegExp(final Object self) {
260 final Global global = Global.instanceFrom(self);
261 if (global.regexp == LAZY_SENTINEL) {
262 global.regexp = global.getBuiltinRegExp();
263 }
264 return global.regexp;
265 }
267 /**
268 * Setter for ECMA 15.1.4.8 RegExp property
269 *
270 * @param self self reference
271 * @param value value for the RegExp property
272 */
273 @Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
274 public static void setRegExp(final Object self, final Object value) {
275 final Global global = Global.instanceFrom(self);
276 global.regexp = value;
277 }
279 private volatile Object regexp = LAZY_SENTINEL;
281 /**
282 * Getter for ECMA 15.12 - The JSON property
283 * @param self self reference
284 * @return the value of JSON property
285 */
286 @Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
287 public static Object getJSON(final Object self) {
288 final Global global = Global.instanceFrom(self);
289 if (global.json == LAZY_SENTINEL) {
290 global.json = global.getBuiltinJSON();
291 }
292 return global.json;
293 }
295 /**
296 * Setter for ECMA 15.12 - The JSON property
297 * @param self self reference
298 * @param value value for the JSON property
299 */
300 @Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
301 public static void setJSON(final Object self, final Object value) {
302 final Global global = Global.instanceFrom(self);
303 global.json = value;
304 }
306 private volatile Object json = LAZY_SENTINEL;
308 /**
309 * Getter for Nashorn extension: global.JSAdapter
310 * @param self self reference
311 * @return value of the JSAdapter property
312 */
313 @Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
314 public static Object getJSAdapter(final Object self) {
315 final Global global = Global.instanceFrom(self);
316 if (global.jsadapter == LAZY_SENTINEL) {
317 global.jsadapter = global.getBuiltinJSAdapter();
318 }
319 return global.jsadapter;
320 }
322 /**
323 * Setter for Nashorn extension: global.JSAdapter
324 * @param self self reference
325 * @param value value for the JSAdapter property
326 */
327 @Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
328 public static void setJSAdapter(final Object self, final Object value) {
329 final Global global = Global.instanceFrom(self);
330 global.jsadapter = value;
331 }
333 private volatile Object jsadapter = LAZY_SENTINEL;
335 /** ECMA 15.8 - The Math object */
336 @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
337 public volatile Object math;
339 /** Error object */
340 @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
341 public volatile Object error;
343 /**
344 * Getter for the EvalError property
345 * @param self self reference
346 * @return the value of EvalError property
347 */
348 @Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
349 public static Object getEvalError(final Object self) {
350 final Global global = Global.instanceFrom(self);
351 if (global.evalError == LAZY_SENTINEL) {
352 global.evalError = global.getBuiltinEvalError();
353 }
354 return global.evalError;
355 }
357 /**
358 * Setter for the EvalError property
359 * @param self self reference
360 * @param value value of the EvalError property
361 */
362 @Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
363 public static void setEvalError(final Object self, final Object value) {
364 final Global global = Global.instanceFrom(self);
365 global.evalError = value;
366 }
368 private volatile Object evalError = LAZY_SENTINEL;
370 /**
371 * Getter for the RangeError property.
372 * @param self self reference
373 * @return the value of RangeError property
374 */
375 @Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
376 public static Object getRangeError(final Object self) {
377 final Global global = Global.instanceFrom(self);
378 if (global.rangeError == LAZY_SENTINEL) {
379 global.rangeError = global.getBuiltinRangeError();
380 }
381 return global.rangeError;
382 }
385 /**
386 * Setter for the RangeError property.
387 * @param self self reference
388 * @param value value for the RangeError property
389 */
390 @Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
391 public static void setRangeError(final Object self, final Object value) {
392 final Global global = Global.instanceFrom(self);
393 global.rangeError = value;
394 }
396 private volatile Object rangeError = LAZY_SENTINEL;
398 /** ReferenceError object */
399 @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
400 public volatile Object referenceError;
402 /** SyntaxError object */
403 @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
404 public volatile Object syntaxError;
406 /** TypeError object */
407 @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
408 public volatile Object typeError;
410 /**
411 * Getter for the URIError property.
412 * @param self self reference
413 * @return the value of URIError property
414 */
415 @Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
416 public static Object getURIError(final Object self) {
417 final Global global = Global.instanceFrom(self);
418 if (global.uriError == LAZY_SENTINEL) {
419 global.uriError = global.getBuiltinURIError();
420 }
421 return global.uriError;
422 }
424 /**
425 * Setter for the URIError property.
426 * @param self self reference
427 * @param value value for the URIError property
428 */
429 @Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
430 public static void setURIError(final Object self, final Object value) {
431 final Global global = Global.instanceFrom(self);
432 global.uriError = value;
433 }
435 private volatile Object uriError = LAZY_SENTINEL;
437 /**
438 * Getter for the ArrayBuffer property.
439 * @param self self reference
440 * @return the value of the ArrayBuffer property
441 */
442 @Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
443 public static Object getArrayBuffer(final Object self) {
444 final Global global = Global.instanceFrom(self);
445 if (global.arrayBuffer == LAZY_SENTINEL) {
446 global.arrayBuffer = global.getBuiltinArrayBuffer();
447 }
448 return global.arrayBuffer;
449 }
451 /**
452 * Setter for the ArrayBuffer property.
453 * @param self self reference
454 * @param value value of the ArrayBuffer property
455 */
456 @Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
457 public static void setArrayBuffer(final Object self, final Object value) {
458 final Global global = Global.instanceFrom(self);
459 global.arrayBuffer = value;
460 }
462 private volatile Object arrayBuffer;
464 /**
465 * Getter for the DataView property.
466 * @param self self reference
467 * @return the value of the DataView property
468 */
469 @Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
470 public static Object getDataView(final Object self) {
471 final Global global = Global.instanceFrom(self);
472 if (global.dataView == LAZY_SENTINEL) {
473 global.dataView = global.getBuiltinDataView();
474 }
475 return global.dataView;
476 }
479 /**
480 * Setter for the DataView property.
481 * @param self self reference
482 * @param value value of the DataView property
483 */
484 @Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
485 public static void setDataView(final Object self, final Object value) {
486 final Global global = Global.instanceFrom(self);
487 global.dataView = value;
488 }
490 private volatile Object dataView;
492 /**
493 * Getter for the Int8Array property.
494 * @param self self reference
495 * @return the value of the Int8Array property.
496 */
497 @Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
498 public static Object getInt8Array(final Object self) {
499 final Global global = Global.instanceFrom(self);
500 if (global.int8Array == LAZY_SENTINEL) {
501 global.int8Array = global.getBuiltinInt8Array();
502 }
503 return global.int8Array;
504 }
506 /**
507 * Setter for the Int8Array property.
508 * @param self self reference
509 * @param value value of the Int8Array property
510 */
511 @Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
512 public static void setInt8Array(final Object self, final Object value) {
513 final Global global = Global.instanceFrom(self);
514 global.int8Array = value;
515 }
517 private volatile Object int8Array;
519 /**
520 * Getter for the Uin8Array property.
521 * @param self self reference
522 * @return the value of the Uint8Array property
523 */
524 @Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
525 public static Object getUint8Array(final Object self) {
526 final Global global = Global.instanceFrom(self);
527 if (global.uint8Array == LAZY_SENTINEL) {
528 global.uint8Array = global.getBuiltinUint8Array();
529 }
530 return global.uint8Array;
531 }
533 /**
534 * Setter for the Uin8Array property.
535 * @param self self reference
536 * @param value value of the Uin8Array property
537 */
538 @Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
539 public static void setUint8Array(final Object self, final Object value) {
540 final Global global = Global.instanceFrom(self);
541 global.uint8Array = value;
542 }
544 private volatile Object uint8Array;
546 /**
547 * Getter for the Uint8ClampedArray property.
548 * @param self self reference
549 * @return the value of the Uint8ClampedArray property
550 */
551 @Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
552 public static Object getUint8ClampedArray(final Object self) {
553 final Global global = Global.instanceFrom(self);
554 if (global.uint8ClampedArray == LAZY_SENTINEL) {
555 global.uint8ClampedArray = global.getBuiltinUint8ClampedArray();
556 }
557 return global.uint8ClampedArray;
558 }
560 /**
561 * Setter for the Uint8ClampedArray property.
562 * @param self self reference
563 * @param value value of the Uint8ClampedArray property
564 */
565 @Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
566 public static void setUint8ClampedArray(final Object self, final Object value) {
567 final Global global = Global.instanceFrom(self);
568 global.uint8ClampedArray = value;
569 }
571 private volatile Object uint8ClampedArray;
573 /**
574 * Getter for the Int16Array property.
575 * @param self self reference
576 * @return the value of the Int16Array property
577 */
578 @Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
579 public static Object getInt16Array(final Object self) {
580 final Global global = Global.instanceFrom(self);
581 if (global.int16Array == LAZY_SENTINEL) {
582 global.int16Array = global.getBuiltinInt16Array();
583 }
584 return global.int16Array;
585 }
587 /**
588 * Setter for the Int16Array property.
589 * @param self self reference
590 * @param value value of the Int16Array property
591 */
592 @Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
593 public static void setInt16Array(final Object self, final Object value) {
594 final Global global = Global.instanceFrom(self);
595 global.int16Array = value;
596 }
598 private volatile Object int16Array;
600 /**
601 * Getter for the Uint16Array property.
602 * @param self self reference
603 * @return the value of the Uint16Array property
604 */
605 @Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
606 public static Object getUint16Array(final Object self) {
607 final Global global = Global.instanceFrom(self);
608 if (global.uint16Array == LAZY_SENTINEL) {
609 global.uint16Array = global.getBuiltinUint16Array();
610 }
611 return global.uint16Array;
612 }
614 /**
615 * Setter for the Uint16Array property.
616 * @param self self reference
617 * @param value value of the Uint16Array property
618 */
619 @Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
620 public static void setUint16Array(final Object self, final Object value) {
621 final Global global = Global.instanceFrom(self);
622 global.uint16Array = value;
623 }
625 private volatile Object uint16Array;
627 /**
628 * Getter for the Int32Array property.
629 *
630 * @param self self reference
631 * @return the value of the Int32Array property
632 */
633 @Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
634 public static Object getInt32Array(final Object self) {
635 final Global global = Global.instanceFrom(self);
636 if (global.int32Array == LAZY_SENTINEL) {
637 global.int32Array = global.getBuiltinInt32Array();
638 }
639 return global.int32Array;
640 }
643 /**
644 * Setter for the Int32Array property.
645 *
646 * @param self self reference
647 * @param value value of the Int32Array property
648 */
649 @Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
650 public static void setInt32Array(final Object self, final Object value) {
651 final Global global = Global.instanceFrom(self);
652 global.int32Array = value;
653 }
655 private volatile Object int32Array;
657 /**
658 * Getter of the Uint32Array property.
659 *
660 * @param self self reference
661 * @return the value of the Uint32Array property
662 */
663 @Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
664 public static Object getUint32Array(final Object self) {
665 final Global global = Global.instanceFrom(self);
666 if (global.uint32Array == LAZY_SENTINEL) {
667 global.uint32Array = global.getBuiltinUint32Array();
668 }
669 return global.uint32Array;
670 }
673 /**
674 * Setter of the Uint32Array property.
675 *
676 * @param self self reference
677 * @param value value of the Uint32Array property
678 */
679 @Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
680 public static void setUint32Array(final Object self, final Object value) {
681 final Global global = Global.instanceFrom(self);
682 global.uint32Array = value;
683 }
685 private volatile Object uint32Array;
687 /**
688 * Getter for the Float32Array property.
689 *
690 * @param self self reference
691 * @return the value of the Float32Array property
692 */
693 @Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
694 public static Object getFloat32Array(final Object self) {
695 final Global global = Global.instanceFrom(self);
696 if (global.float32Array == LAZY_SENTINEL) {
697 global.float32Array = global.getBuiltinFloat32Array();
698 }
699 return global.float32Array;
700 }
702 /**
703 * Setter for the Float32Array property.
704 *
705 * @param self self reference
706 * @param value value of the Float32Array property
707 */
708 @Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
709 public static void setFloat32Array(final Object self, final Object value) {
710 final Global global = Global.instanceFrom(self);
711 global.float32Array = value;
712 }
714 private volatile Object float32Array;
716 /**
717 * Getter for the Float64Array property.
718 *
719 * @param self self reference
720 * @return the value of the Float64Array property
721 */
722 @Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
723 public static Object getFloat64Array(final Object self) {
724 final Global global = Global.instanceFrom(self);
725 if (global.float64Array == LAZY_SENTINEL) {
726 global.float64Array = global.getBuiltinFloat64Array();
727 }
728 return global.float64Array;
729 }
731 /**
732 * Setter for the Float64Array property.
733 *
734 * @param self self reference
735 * @param value value of the Float64Array property
736 */
737 @Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
738 public static void setFloat64Array(final Object self, final Object value) {
739 final Global global = Global.instanceFrom(self);
740 global.float64Array = value;
741 }
743 private volatile Object float64Array;
745 /** Nashorn extension: Java access - global.Packages */
746 @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
747 public volatile Object packages;
749 /** Nashorn extension: Java access - global.com */
750 @Property(attributes = Attribute.NOT_ENUMERABLE)
751 public volatile Object com;
753 /** Nashorn extension: Java access - global.edu */
754 @Property(attributes = Attribute.NOT_ENUMERABLE)
755 public volatile Object edu;
757 /** Nashorn extension: Java access - global.java */
758 @Property(attributes = Attribute.NOT_ENUMERABLE)
759 public volatile Object java;
761 /** Nashorn extension: Java access - global.javafx */
762 @Property(attributes = Attribute.NOT_ENUMERABLE)
763 public volatile Object javafx;
765 /** Nashorn extension: Java access - global.javax */
766 @Property(attributes = Attribute.NOT_ENUMERABLE)
767 public volatile Object javax;
769 /** Nashorn extension: Java access - global.org */
770 @Property(attributes = Attribute.NOT_ENUMERABLE)
771 public volatile Object org;
773 /**
774 * Getter for the Nashorn extension: Java access - global.javaImporter.
775 *
776 * @param self self reference
777 * @return the value of the JavaImporter property
778 */
779 @Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
780 public static Object getJavaImporter(final Object self) {
781 final Global global = Global.instanceFrom(self);
782 if (global.javaImporter == LAZY_SENTINEL) {
783 global.javaImporter = global.getBuiltinJavaImporter();
784 }
785 return global.javaImporter;
786 }
788 /**
789 * Setter for the Nashorn extension: Java access - global.javaImporter.
790 *
791 * @param self self reference
792 * @param value value of the JavaImporter property
793 */
794 @Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
795 public static void setJavaImporter(final Object self, final Object value) {
796 final Global global = Global.instanceFrom(self);
797 global.javaImporter = value;
798 }
800 private volatile Object javaImporter;
802 /**
803 * Getter for the Nashorn extension: global.Java property.
804 *
805 * @param self self reference
806 * @return the value of the Java property
807 */
808 @Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
809 public static Object getJavaApi(final Object self) {
810 final Global global = Global.instanceFrom(self);
811 if (global.javaApi == LAZY_SENTINEL) {
812 global.javaApi = global.getBuiltinJavaApi();
813 }
814 return global.javaApi;
815 }
817 /**
818 * Setter for the Nashorn extension: global.Java property.
819 *
820 * @param self self reference
821 * @param value value of the Java property
822 */
823 @Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
824 public static void setJavaApi(final Object self, final Object value) {
825 final Global global = Global.instanceFrom(self);
826 global.javaApi = value;
827 }
829 private volatile Object javaApi;
831 /** Nashorn extension: current script's file name */
832 @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
833 public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
835 /** Nashorn extension: current script's directory */
836 @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
837 public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
839 /** Nashorn extension: current source line number being executed */
840 @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
841 public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
843 private volatile NativeDate DEFAULT_DATE;
845 /** Used as Date.prototype's default value */
846 NativeDate getDefaultDate() {
847 return DEFAULT_DATE;
848 }
850 private volatile NativeRegExp DEFAULT_REGEXP;
852 /** Used as RegExp.prototype's default value */
853 NativeRegExp getDefaultRegExp() {
854 return DEFAULT_REGEXP;
855 }
857 /*
858 * Built-in constructor objects: Even if user changes dynamic values of
859 * "Object", "Array" etc., we still want to keep original values of these
860 * constructors here. For example, we need to be able to create array,
861 * regexp literals even after user overwrites global "Array" or "RegExp"
862 * constructor - see also ECMA 262 spec. Annex D.
863 */
864 private ScriptFunction builtinFunction;
865 private ScriptFunction builtinObject;
866 private ScriptFunction builtinArray;
867 private ScriptFunction builtinBoolean;
868 private ScriptFunction builtinDate;
869 private ScriptObject builtinJSON;
870 private ScriptFunction builtinJSAdapter;
871 private ScriptObject builtinMath;
872 private ScriptFunction builtinNumber;
873 private ScriptFunction builtinRegExp;
874 private ScriptFunction builtinString;
875 private ScriptFunction builtinError;
876 private ScriptFunction builtinEval;
877 private ScriptFunction builtinEvalError;
878 private ScriptFunction builtinRangeError;
879 private ScriptFunction builtinReferenceError;
880 private ScriptFunction builtinSyntaxError;
881 private ScriptFunction builtinTypeError;
882 private ScriptFunction builtinURIError;
883 private ScriptObject builtinPackages;
884 private ScriptObject builtinCom;
885 private ScriptObject builtinEdu;
886 private ScriptObject builtinJava;
887 private ScriptObject builtinJavafx;
888 private ScriptObject builtinJavax;
889 private ScriptObject builtinOrg;
890 private ScriptFunction builtinJavaImporter;
891 private ScriptObject builtinJavaApi;
892 private ScriptFunction builtinArrayBuffer;
893 private ScriptFunction builtinDataView;
894 private ScriptFunction builtinInt8Array;
895 private ScriptFunction builtinUint8Array;
896 private ScriptFunction builtinUint8ClampedArray;
897 private ScriptFunction builtinInt16Array;
898 private ScriptFunction builtinUint16Array;
899 private ScriptFunction builtinInt32Array;
900 private ScriptFunction builtinUint32Array;
901 private ScriptFunction builtinFloat32Array;
902 private ScriptFunction builtinFloat64Array;
904 /*
905 * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
906 */
907 private ScriptFunction typeErrorThrower;
909 // Flag to indicate that a split method issued a return statement
910 private int splitState = -1;
912 // Used to store the last RegExp result to support deprecated RegExp constructor properties
913 private RegExpResult lastRegExpResult;
915 private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class);
916 private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
917 private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class);
918 private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class);
919 private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class);
920 private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class);
921 private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class);
922 private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class);
924 // initialized by nasgen
925 private static PropertyMap $nasgenmap$;
927 // context to which this global belongs to
928 private final Context context;
930 // current ScriptContext to use - can be null.
931 private ScriptContext scontext;
932 // current ScriptEngine associated - can be null.
933 private ScriptEngine engine;
935 // ES6 global lexical scope.
936 private final LexicalScope lexicalScope;
938 // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
939 private SwitchPoint lexicalScopeSwitchPoint;
941 /**
942 * Set the current script context
943 * @param scontext script context
944 */
945 public void setScriptContext(final ScriptContext scontext) {
946 this.scontext = scontext;
947 }
949 @Override
950 protected Context getContext() {
951 return context;
952 }
954 @Override
955 protected boolean useDualFields() {
956 return context.useDualFields();
957 }
959 // performs initialization checks for Global constructor and returns the
960 // PropertyMap, if everything is fine.
961 private static PropertyMap checkAndGetMap(final Context context) {
962 // security check first
963 final SecurityManager sm = System.getSecurityManager();
964 if (sm != null) {
965 sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
966 }
968 Objects.requireNonNull(context);
970 return $nasgenmap$;
971 }
973 /**
974 * Constructor
975 *
976 * @param context the context
977 */
978 public Global(final Context context) {
979 super(checkAndGetMap(context));
980 this.context = context;
981 this.setIsScope();
982 this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
983 }
985 /**
986 * Script access to "current" Global instance
987 *
988 * @return the global singleton
989 */
990 public static Global instance() {
991 final Global global = Context.getGlobal();
992 Objects.requireNonNull(global);
993 return global;
994 }
996 private static Global instanceFrom(final Object self) {
997 return self instanceof Global? (Global)self : instance();
998 }
1000 /**
1001 * Check if we have a Global instance
1002 * @return true if one exists
1003 */
1004 public static boolean hasInstance() {
1005 return Context.getGlobal() != null;
1006 }
1008 /**
1009 * Script access to {@link ScriptEnvironment}
1010 *
1011 * @return the script environment
1012 */
1013 static ScriptEnvironment getEnv() {
1014 return instance().getContext().getEnv();
1015 }
1017 /**
1018 * Script access to {@link Context}
1019 *
1020 * @return the context
1021 */
1022 static Context getThisContext() {
1023 return instance().getContext();
1024 }
1026 // Runtime interface to Global
1028 /**
1029 * Is there a class filter in the current Context?
1030 * @return class filter
1031 */
1032 public ClassFilter getClassFilter() {
1033 return context.getClassFilter();
1034 }
1036 /**
1037 * Is this global of the given Context?
1038 * @param ctxt the context
1039 * @return true if this global belongs to the given Context
1040 */
1041 public boolean isOfContext(final Context ctxt) {
1042 return this.context == ctxt;
1043 }
1045 /**
1046 * Does this global belong to a strict Context?
1047 * @return true if this global belongs to a strict Context
1048 */
1049 public boolean isStrictContext() {
1050 return context.getEnv()._strict;
1051 }
1053 /**
1054 * Initialize standard builtin objects like "Object", "Array", "Function" etc.
1055 * as well as our extension builtin objects like "Java", "JSAdapter" as properties
1056 * of the global scope object.
1057 *
1058 * @param engine ScriptEngine to initialize
1059 */
1060 @SuppressWarnings("hiding")
1061 public void initBuiltinObjects(final ScriptEngine engine) {
1062 if (this.builtinObject != null) {
1063 // already initialized, just return
1064 return;
1065 }
1067 this.engine = engine;
1068 init(engine);
1069 }
1071 /**
1072 * Wrap a Java object as corresponding script object
1073 *
1074 * @param obj object to wrap
1075 * @return wrapped object
1076 */
1077 public Object wrapAsObject(final Object obj) {
1078 if (obj instanceof Boolean) {
1079 return new NativeBoolean((Boolean)obj, this);
1080 } else if (obj instanceof Number) {
1081 return new NativeNumber(((Number)obj).doubleValue(), this);
1082 } else if (isString(obj)) {
1083 return new NativeString((CharSequence)obj, this);
1084 } else if (obj instanceof Object[]) { // extension
1085 return new NativeArray(ArrayData.allocate((Object[])obj), this);
1086 } else if (obj instanceof double[]) { // extension
1087 return new NativeArray(ArrayData.allocate((double[])obj), this);
1088 } else if (obj instanceof long[]) {
1089 return new NativeArray(ArrayData.allocate((long[])obj), this);
1090 } else if (obj instanceof int[]) {
1091 return new NativeArray(ArrayData.allocate((int[]) obj), this);
1092 } else if (obj instanceof ArrayData) {
1093 return new NativeArray((ArrayData) obj, this);
1094 } else {
1095 // FIXME: more special cases? Map? List?
1096 return obj;
1097 }
1098 }
1100 /**
1101 * Lookup helper for JS primitive types
1102 *
1103 * @param request the link request for the dynamic call site.
1104 * @param self self reference
1105 *
1106 * @return guarded invocation
1107 */
1108 public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
1109 if (isString(self)) {
1110 return NativeString.lookupPrimitive(request, self);
1111 } else if (self instanceof Number) {
1112 return NativeNumber.lookupPrimitive(request, self);
1113 } else if (self instanceof Boolean) {
1114 return NativeBoolean.lookupPrimitive(request, self);
1115 }
1116 throw new IllegalArgumentException("Unsupported primitive: " + self);
1117 }
1119 /**
1120 * Returns a method handle that creates a wrapper object for a JS primitive value.
1121 *
1122 * @param self receiver object
1123 * @return method handle to create wrapper objects for primitive receiver
1124 */
1125 public static MethodHandle getPrimitiveWrapFilter(final Object self) {
1126 if (isString(self)) {
1127 return NativeString.WRAPFILTER;
1128 } else if (self instanceof Number) {
1129 return NativeNumber.WRAPFILTER;
1130 } else if (self instanceof Boolean) {
1131 return NativeBoolean.WRAPFILTER;
1132 }
1133 throw new IllegalArgumentException("Unsupported primitive: " + self);
1134 }
1137 /**
1138 * Create a new empty script object
1139 *
1140 * @return the new ScriptObject
1141 */
1142 public ScriptObject newObject() {
1143 return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype());
1144 }
1146 /**
1147 * Default value of given type
1148 *
1149 * @param sobj script object
1150 * @param typeHint type hint
1151 *
1152 * @return default value
1153 */
1154 public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
1155 // When the [[DefaultValue]] internal method of O is called with no hint,
1156 // then it behaves as if the hint were Number, unless O is a Date object
1157 // in which case it behaves as if the hint were String.
1158 Class<?> hint = typeHint;
1159 if (hint == null) {
1160 hint = Number.class;
1161 }
1163 try {
1164 if (hint == String.class) {
1166 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1168 if (Bootstrap.isCallable(toString)) {
1169 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1170 if (JSType.isPrimitive(value)) {
1171 return value;
1172 }
1173 }
1175 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1176 if (Bootstrap.isCallable(valueOf)) {
1177 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1178 if (JSType.isPrimitive(value)) {
1179 return value;
1180 }
1181 }
1182 throw typeError(this, "cannot.get.default.string");
1183 }
1185 if (hint == Number.class) {
1186 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1187 if (Bootstrap.isCallable(valueOf)) {
1188 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1189 if (JSType.isPrimitive(value)) {
1190 return value;
1191 }
1192 }
1194 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1195 if (Bootstrap.isCallable(toString)) {
1196 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1197 if (JSType.isPrimitive(value)) {
1198 return value;
1199 }
1200 }
1202 throw typeError(this, "cannot.get.default.number");
1203 }
1204 } catch (final RuntimeException | Error e) {
1205 throw e;
1206 } catch (final Throwable t) {
1207 throw new RuntimeException(t);
1208 }
1210 return UNDEFINED;
1211 }
1213 /**
1214 * Is the given ScriptObject an ECMAScript Error object?
1215 *
1216 * @param sobj the object being checked
1217 * @return true if sobj is an Error object
1218 */
1219 public boolean isError(final ScriptObject sobj) {
1220 final ScriptObject errorProto = getErrorPrototype();
1221 ScriptObject proto = sobj.getProto();
1222 while (proto != null) {
1223 if (proto == errorProto) {
1224 return true;
1225 }
1226 proto = proto.getProto();
1227 }
1228 return false;
1229 }
1231 /**
1232 * Create a new ECMAScript Error object.
1233 *
1234 * @param msg error message
1235 * @return newly created Error object
1236 */
1237 public ScriptObject newError(final String msg) {
1238 return new NativeError(msg, this);
1239 }
1241 /**
1242 * Create a new ECMAScript EvalError object.
1243 *
1244 * @param msg error message
1245 * @return newly created EvalError object
1246 */
1247 public ScriptObject newEvalError(final String msg) {
1248 return new NativeEvalError(msg, this);
1249 }
1251 /**
1252 * Create a new ECMAScript RangeError object.
1253 *
1254 * @param msg error message
1255 * @return newly created RangeError object
1256 */
1257 public ScriptObject newRangeError(final String msg) {
1258 return new NativeRangeError(msg, this);
1259 }
1261 /**
1262 * Create a new ECMAScript ReferenceError object.
1263 *
1264 * @param msg error message
1265 * @return newly created ReferenceError object
1266 */
1267 public ScriptObject newReferenceError(final String msg) {
1268 return new NativeReferenceError(msg, this);
1269 }
1271 /**
1272 * Create a new ECMAScript SyntaxError object.
1273 *
1274 * @param msg error message
1275 * @return newly created SyntaxError object
1276 */
1277 public ScriptObject newSyntaxError(final String msg) {
1278 return new NativeSyntaxError(msg, this);
1279 }
1281 /**
1282 * Create a new ECMAScript TypeError object.
1283 *
1284 * @param msg error message
1285 * @return newly created TypeError object
1286 */
1287 public ScriptObject newTypeError(final String msg) {
1288 return new NativeTypeError(msg, this);
1289 }
1291 /**
1292 * Create a new ECMAScript URIError object.
1293 *
1294 * @param msg error message
1295 * @return newly created URIError object
1296 */
1297 public ScriptObject newURIError(final String msg) {
1298 return new NativeURIError(msg, this);
1299 }
1301 /**
1302 * Create a new ECMAScript GenericDescriptor object.
1303 *
1304 * @param configurable is the property configurable?
1305 * @param enumerable is the property enumerable?
1306 * @return newly created GenericDescriptor object
1307 */
1308 public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
1309 return new GenericPropertyDescriptor(configurable, enumerable, this);
1310 }
1312 /**
1313 * Create a new ECMAScript DatePropertyDescriptor object.
1314 *
1315 * @param value of the data property
1316 * @param configurable is the property configurable?
1317 * @param enumerable is the property enumerable?
1318 * @param writable is the property writable?
1319 * @return newly created DataPropertyDescriptor object
1320 */
1321 public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
1322 return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
1323 }
1325 /**
1326 * Create a new ECMAScript AccessorPropertyDescriptor object.
1327 *
1328 * @param get getter function of the user accessor property
1329 * @param set setter function of the user accessor property
1330 * @param configurable is the property configurable?
1331 * @param enumerable is the property enumerable?
1332 * @return newly created AccessorPropertyDescriptor object
1333 */
1334 public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
1335 final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
1337 if (get == null) {
1338 desc.delete(PropertyDescriptor.GET, false);
1339 }
1341 if (set == null) {
1342 desc.delete(PropertyDescriptor.SET, false);
1343 }
1345 return desc;
1346 }
1348 private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
1349 final T obj = map.get(key);
1350 if (obj != null) {
1351 return obj;
1352 }
1354 try {
1355 final T newObj = creator.call();
1356 final T existingObj = map.putIfAbsent(key, newObj);
1357 return existingObj != null ? existingObj : newObj;
1358 } catch (final Exception exp) {
1359 throw new RuntimeException(exp);
1360 }
1361 }
1363 private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
1366 /**
1367 * Get cached InvokeByName object for the given key
1368 * @param key key to be associated with InvokeByName object
1369 * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
1370 * @return InvokeByName object associated with the key.
1371 */
1372 public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
1373 return getLazilyCreatedValue(key, creator, namedInvokers);
1374 }
1376 private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
1378 /**
1379 * Get cached dynamic method handle for the given key
1380 * @param key key to be associated with dynamic method handle
1381 * @param creator if method handle is absent 'creator' is called to make one (lazy init)
1382 * @return dynamic method handle associated with the key.
1383 */
1384 public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
1385 return getLazilyCreatedValue(key, creator, dynamicInvokers);
1386 }
1388 /**
1389 * Hook to search missing variables in ScriptContext if available
1390 * @param self used to detect if scope call or not (this function is 'strict')
1391 * @param name name of the variable missing
1392 * @return value of the missing variable or undefined (or TypeError for scope search)
1393 */
1394 public static Object __noSuchProperty__(final Object self, final Object name) {
1395 final Global global = Global.instance();
1396 final ScriptContext sctxt = global.scontext;
1397 final String nameStr = name.toString();
1399 if (sctxt != null) {
1400 final int scope = sctxt.getAttributesScope(nameStr);
1401 if (scope != -1) {
1402 return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
1403 }
1404 }
1406 switch (nameStr) {
1407 case "context":
1408 return sctxt;
1409 case "engine":
1410 return global.engine;
1411 default:
1412 break;
1413 }
1415 if (self == UNDEFINED) {
1416 // scope access and so throw ReferenceError
1417 throw referenceError(global, "not.defined", nameStr);
1418 }
1420 return UNDEFINED;
1421 }
1423 /**
1424 * This is the eval used when 'indirect' eval call is made.
1425 *
1426 * var global = this;
1427 * global.eval("print('hello')");
1428 *
1429 * @param self eval scope
1430 * @param str eval string
1431 *
1432 * @return the result of eval
1433 */
1434 public static Object eval(final Object self, final Object str) {
1435 return directEval(self, str, UNDEFINED, UNDEFINED, false);
1436 }
1438 /**
1439 * Direct eval
1440 *
1441 * @param self The scope of eval passed as 'self'
1442 * @param str Evaluated code
1443 * @param callThis "this" to be passed to the evaluated code
1444 * @param location location of the eval call
1445 * @param strict is eval called a strict mode code?
1446 *
1447 * @return the return value of the eval
1448 *
1449 * This is directly invoked from generated when eval(code) is called in user code
1450 */
1451 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
1452 if (!isString(str)) {
1453 return str;
1454 }
1455 final Global global = Global.instanceFrom(self);
1456 final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
1458 return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
1459 }
1461 /**
1462 * Global print implementation - Nashorn extension
1463 *
1464 * @param self scope
1465 * @param objects arguments to print
1466 *
1467 * @return result of print (undefined)
1468 */
1469 public static Object print(final Object self, final Object... objects) {
1470 return Global.instanceFrom(self).printImpl(false, objects);
1471 }
1473 /**
1474 * Global println implementation - Nashorn extension
1475 *
1476 * @param self scope
1477 * @param objects arguments to print
1478 *
1479 * @return result of println (undefined)
1480 */
1481 public static Object println(final Object self, final Object... objects) {
1482 return Global.instanceFrom(self).printImpl(true, objects);
1483 }
1485 /**
1486 * Global load implementation - Nashorn extension
1487 *
1488 * @param self scope
1489 * @param source source to load
1490 *
1491 * @return result of load (undefined)
1492 *
1493 * @throws IOException if source could not be read
1494 */
1495 public static Object load(final Object self, final Object source) throws IOException {
1496 final Global global = Global.instanceFrom(self);
1497 final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
1498 return global.getContext().load(scope, source);
1499 }
1501 /**
1502 * Global loadWithNewGlobal implementation - Nashorn extension
1503 *
1504 * @param self scope
1505 * @param args from plus (optional) arguments to be passed to the loaded script
1506 *
1507 * @return result of load (may be undefined)
1508 *
1509 * @throws IOException if source could not be read
1510 */
1511 public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
1512 final Global global = Global.instanceFrom(self);
1513 final int length = args.length;
1514 final boolean hasArgs = 0 < length;
1515 final Object from = hasArgs ? args[0] : UNDEFINED;
1516 final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1518 return global.getContext().loadWithNewGlobal(from, arguments);
1519 }
1521 /**
1522 * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1523 *
1524 * @param self self reference
1525 * @param code exit code
1526 *
1527 * @return undefined (will never be reached)
1528 */
1529 public static Object exit(final Object self, final Object code) {
1530 System.exit(JSType.toInt32(code));
1531 return UNDEFINED;
1532 }
1534 // builtin prototype accessors
1536 /**
1537 * Get the builtin Object prototype.
1538 * @return the object prototype.
1539 */
1540 public ScriptObject getObjectPrototype() {
1541 return ScriptFunction.getPrototype(builtinObject);
1542 }
1544 ScriptObject getFunctionPrototype() {
1545 return ScriptFunction.getPrototype(builtinFunction);
1546 }
1548 ScriptObject getArrayPrototype() {
1549 return ScriptFunction.getPrototype(builtinArray);
1550 }
1552 ScriptObject getBooleanPrototype() {
1553 return ScriptFunction.getPrototype(builtinBoolean);
1554 }
1556 ScriptObject getNumberPrototype() {
1557 return ScriptFunction.getPrototype(builtinNumber);
1558 }
1560 ScriptObject getDatePrototype() {
1561 return ScriptFunction.getPrototype(getBuiltinDate());
1562 }
1564 ScriptObject getRegExpPrototype() {
1565 return ScriptFunction.getPrototype(getBuiltinRegExp());
1566 }
1568 ScriptObject getStringPrototype() {
1569 return ScriptFunction.getPrototype(builtinString);
1570 }
1572 ScriptObject getErrorPrototype() {
1573 return ScriptFunction.getPrototype(builtinError);
1574 }
1576 ScriptObject getEvalErrorPrototype() {
1577 return ScriptFunction.getPrototype(getBuiltinEvalError());
1578 }
1580 ScriptObject getRangeErrorPrototype() {
1581 return ScriptFunction.getPrototype(getBuiltinRangeError());
1582 }
1584 ScriptObject getReferenceErrorPrototype() {
1585 return ScriptFunction.getPrototype(builtinReferenceError);
1586 }
1588 ScriptObject getSyntaxErrorPrototype() {
1589 return ScriptFunction.getPrototype(builtinSyntaxError);
1590 }
1592 ScriptObject getTypeErrorPrototype() {
1593 return ScriptFunction.getPrototype(builtinTypeError);
1594 }
1596 ScriptObject getURIErrorPrototype() {
1597 return ScriptFunction.getPrototype(getBuiltinURIError());
1598 }
1600 ScriptObject getJavaImporterPrototype() {
1601 return ScriptFunction.getPrototype(getBuiltinJavaImporter());
1602 }
1604 ScriptObject getJSAdapterPrototype() {
1605 return ScriptFunction.getPrototype(getBuiltinJSAdapter());
1606 }
1608 private synchronized ScriptFunction getBuiltinArrayBuffer() {
1609 if (this.builtinArrayBuffer == null) {
1610 this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
1611 }
1612 return this.builtinArrayBuffer;
1613 }
1615 ScriptObject getArrayBufferPrototype() {
1616 return ScriptFunction.getPrototype(getBuiltinArrayBuffer());
1617 }
1619 private synchronized ScriptFunction getBuiltinDataView() {
1620 if (this.builtinDataView == null) {
1621 this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
1622 }
1623 return this.builtinDataView;
1624 }
1626 ScriptObject getDataViewPrototype() {
1627 return ScriptFunction.getPrototype(getBuiltinDataView());
1628 }
1630 private synchronized ScriptFunction getBuiltinInt8Array() {
1631 if (this.builtinInt8Array == null) {
1632 this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
1633 }
1634 return this.builtinInt8Array;
1635 }
1637 ScriptObject getInt8ArrayPrototype() {
1638 return ScriptFunction.getPrototype(getBuiltinInt8Array());
1639 }
1641 private synchronized ScriptFunction getBuiltinUint8Array() {
1642 if (this.builtinUint8Array == null) {
1643 this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
1644 }
1645 return this.builtinUint8Array;
1646 }
1648 ScriptObject getUint8ArrayPrototype() {
1649 return ScriptFunction.getPrototype(getBuiltinUint8Array());
1650 }
1652 private synchronized ScriptFunction getBuiltinUint8ClampedArray() {
1653 if (this.builtinUint8ClampedArray == null) {
1654 this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
1655 }
1656 return this.builtinUint8ClampedArray;
1657 }
1659 ScriptObject getUint8ClampedArrayPrototype() {
1660 return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray());
1661 }
1663 private synchronized ScriptFunction getBuiltinInt16Array() {
1664 if (this.builtinInt16Array == null) {
1665 this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
1666 }
1667 return this.builtinInt16Array;
1668 }
1670 ScriptObject getInt16ArrayPrototype() {
1671 return ScriptFunction.getPrototype(getBuiltinInt16Array());
1672 }
1674 private synchronized ScriptFunction getBuiltinUint16Array() {
1675 if (this.builtinUint16Array == null) {
1676 this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
1677 }
1678 return this.builtinUint16Array;
1679 }
1681 ScriptObject getUint16ArrayPrototype() {
1682 return ScriptFunction.getPrototype(getBuiltinUint16Array());
1683 }
1685 private synchronized ScriptFunction getBuiltinInt32Array() {
1686 if (this.builtinInt32Array == null) {
1687 this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
1688 }
1689 return this.builtinInt32Array;
1690 }
1692 ScriptObject getInt32ArrayPrototype() {
1693 return ScriptFunction.getPrototype(getBuiltinInt32Array());
1694 }
1696 private synchronized ScriptFunction getBuiltinUint32Array() {
1697 if (this.builtinUint32Array == null) {
1698 this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
1699 }
1700 return this.builtinUint32Array;
1701 }
1703 ScriptObject getUint32ArrayPrototype() {
1704 return ScriptFunction.getPrototype(getBuiltinUint32Array());
1705 }
1707 private synchronized ScriptFunction getBuiltinFloat32Array() {
1708 if (this.builtinFloat32Array == null) {
1709 this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
1710 }
1711 return this.builtinFloat32Array;
1712 }
1714 ScriptObject getFloat32ArrayPrototype() {
1715 return ScriptFunction.getPrototype(getBuiltinFloat32Array());
1716 }
1718 private synchronized ScriptFunction getBuiltinFloat64Array() {
1719 if (this.builtinFloat64Array == null) {
1720 this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
1721 }
1722 return this.builtinFloat64Array;
1723 }
1725 ScriptObject getFloat64ArrayPrototype() {
1726 return ScriptFunction.getPrototype(getBuiltinFloat64Array());
1727 }
1729 private ScriptFunction getBuiltinArray() {
1730 return builtinArray;
1731 }
1733 ScriptFunction getTypeErrorThrower() {
1734 return typeErrorThrower;
1735 }
1737 /**
1738 * Called from compiled script code to test if builtin has been overridden
1739 *
1740 * @return true if builtin array has not been overridden
1741 */
1742 public static boolean isBuiltinArray() {
1743 final Global instance = Global.instance();
1744 return instance.array == instance.getBuiltinArray();
1745 }
1747 private ScriptFunction getBuiltinBoolean() {
1748 return builtinBoolean;
1749 }
1751 /**
1752 * Called from compiled script code to test if builtin has been overridden
1753 *
1754 * @return true if builtin boolean has not been overridden
1755 */
1756 public static boolean isBuiltinBoolean() {
1757 final Global instance = Global.instance();
1758 return instance._boolean == instance.getBuiltinBoolean();
1759 }
1761 private synchronized ScriptFunction getBuiltinDate() {
1762 if (this.builtinDate == null) {
1763 this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
1764 final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate);
1765 // initialize default date
1766 this.DEFAULT_DATE = new NativeDate(NaN, dateProto);
1767 }
1768 return this.builtinDate;
1769 }
1771 /**
1772 * Called from compiled script code to test if builtin has been overridden
1773 *
1774 * @return true if builtin date has not been overridden
1775 */
1776 public static boolean isBuiltinDate() {
1777 final Global instance = Global.instance();
1778 return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate();
1779 }
1781 private ScriptFunction getBuiltinError() {
1782 return builtinError;
1783 }
1785 /**
1786 * Called from compiled script code to test if builtin has been overridden
1787 *
1788 * @return true if builtin error has not been overridden
1789 */
1790 public static boolean isBuiltinError() {
1791 final Global instance = Global.instance();
1792 return instance.error == instance.getBuiltinError();
1793 }
1795 private synchronized ScriptFunction getBuiltinEvalError() {
1796 if (this.builtinEvalError == null) {
1797 this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
1798 }
1799 return this.builtinEvalError;
1800 }
1802 /**
1803 * Called from compiled script code to test if builtin has been overridden
1804 *
1805 * @return true if builtin eval error has not been overridden
1806 */
1807 public static boolean isBuiltinEvalError() {
1808 final Global instance = Global.instance();
1809 return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError();
1810 }
1812 private ScriptFunction getBuiltinFunction() {
1813 return builtinFunction;
1814 }
1816 /**
1817 * Called from compiled script code to test if builtin has been overridden
1818 *
1819 * @return true if builtin function has not been overridden
1820 */
1821 public static boolean isBuiltinFunction() {
1822 final Global instance = Global.instance();
1823 return instance.function == instance.getBuiltinFunction();
1824 }
1826 /**
1827 * Get the switchpoint used to check property changes for Function.prototype.apply
1828 * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
1829 */
1830 public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
1831 return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
1832 }
1834 private static boolean isBuiltinFunctionProperty(final String name) {
1835 final Global instance = Global.instance();
1836 final ScriptFunction builtinFunction = instance.getBuiltinFunction();
1837 if (builtinFunction == null) {
1838 return false; //conservative for compile-only mode
1839 }
1840 final boolean isBuiltinFunction = instance.function == builtinFunction;
1841 return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
1842 }
1844 /**
1845 * Check if the Function.prototype.apply has not been replaced
1846 * @return true if Function.prototype.apply has been replaced
1847 */
1848 public static boolean isBuiltinFunctionPrototypeApply() {
1849 return isBuiltinFunctionProperty("apply");
1850 }
1852 /**
1853 * Check if the Function.prototype.apply has not been replaced
1854 * @return true if Function.prototype.call has been replaced
1855 */
1856 public static boolean isBuiltinFunctionPrototypeCall() {
1857 return isBuiltinFunctionProperty("call");
1858 }
1860 private synchronized ScriptFunction getBuiltinJSAdapter() {
1861 if (this.builtinJSAdapter == null) {
1862 this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
1863 }
1864 return builtinJSAdapter;
1865 }
1867 /**
1868 * Called from compiled script code to test if builtin has been overridden
1869 *
1870 * @return true if builtin JSAdapter has not been overridden
1871 */
1872 public static boolean isBuiltinJSAdapter() {
1873 final Global instance = Global.instance();
1874 return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter();
1875 }
1877 private synchronized ScriptObject getBuiltinJSON() {
1878 if (this.builtinJSON == null) {
1879 this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
1880 }
1881 return this.builtinJSON;
1882 }
1884 /**
1885 * Called from compiled script code to test if builtin has been overridden
1886 *
1887 * @return true if builtin JSON has has not been overridden
1888 */
1889 public static boolean isBuiltinJSON() {
1890 final Global instance = Global.instance();
1891 return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON();
1892 }
1894 private ScriptObject getBuiltinJava() {
1895 return builtinJava;
1896 }
1898 /**
1899 * Called from compiled script code to test if builtin has been overridden
1900 *
1901 * @return true if builtin Java has not been overridden
1902 */
1903 public static boolean isBuiltinJava() {
1904 final Global instance = Global.instance();
1905 return instance.java == instance.getBuiltinJava();
1906 }
1908 private ScriptObject getBuiltinJavax() {
1909 return builtinJavax;
1910 }
1912 /**
1913 * Called from compiled script code to test if builtin has been overridden
1914 *
1915 * @return true if builtin Javax has not been overridden
1916 */
1917 public static boolean isBuiltinJavax() {
1918 final Global instance = Global.instance();
1919 return instance.javax == instance.getBuiltinJavax();
1920 }
1922 private synchronized ScriptFunction getBuiltinJavaImporter() {
1923 if (this.builtinJavaImporter == null) {
1924 this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
1925 }
1926 return this.builtinJavaImporter;
1927 }
1929 private synchronized ScriptObject getBuiltinJavaApi() {
1930 if (this.builtinJavaApi == null) {
1931 this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
1932 }
1933 return this.builtinJavaApi;
1934 }
1936 /**
1937 * Called from compiled script code to test if builtin has been overridden
1938 *
1939 * @return true if builtin Java importer has not been overridden
1940 */
1941 public static boolean isBuiltinJavaImporter() {
1942 final Global instance = Global.instance();
1943 return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter();
1944 }
1946 /**
1947 * Called from compiled script code to test if builtin has been overridden
1948 *
1949 * @return true if builtin math has not been overridden
1950 */
1951 public static boolean isBuiltinMath() {
1952 final Global instance = Global.instance();
1953 return instance.math == instance.builtinMath;
1954 }
1956 private ScriptFunction getBuiltinNumber() {
1957 return builtinNumber;
1958 }
1960 /**
1961 * Called from compiled script code to test if builtin has been overridden
1962 *
1963 * @return true if builtin number has not been overridden
1964 */
1965 public static boolean isBuiltinNumber() {
1966 final Global instance = Global.instance();
1967 return instance.number == instance.getBuiltinNumber();
1968 }
1970 private ScriptFunction getBuiltinObject() {
1971 return builtinObject;
1972 }
1974 /**
1975 * Called from compiled script code to test if builtin has been overridden
1976 *
1977 * @return true if builtin object has not been overridden
1978 */
1979 public static boolean isBuiltinObject() {
1980 final Global instance = Global.instance();
1981 return instance.object == instance.getBuiltinObject();
1982 }
1984 private ScriptObject getBuiltinPackages() {
1985 return builtinPackages;
1986 }
1988 /**
1989 * Called from compiled script code to test if builtin has been overridden
1990 *
1991 * @return true if builtin package has not been overridden
1992 */
1993 public static boolean isBuiltinPackages() {
1994 final Global instance = Global.instance();
1995 return instance.packages == instance.getBuiltinPackages();
1996 }
1998 private synchronized ScriptFunction getBuiltinRangeError() {
1999 if (this.builtinRangeError == null) {
2000 this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
2001 }
2002 return builtinRangeError;
2003 }
2005 /**
2006 * Called from compiled script code to test if builtin has been overridden
2007 *
2008 * @return true if builtin range error has not been overridden
2009 */
2010 public static boolean isBuiltinRangeError() {
2011 final Global instance = Global.instance();
2012 return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError();
2013 }
2015 private synchronized ScriptFunction getBuiltinReferenceError() {
2016 return builtinReferenceError;
2017 }
2019 /**
2020 * Called from compiled script code to test if builtin has been overridden
2021 *
2022 * @return true if builtin reference error has not been overridden
2023 */
2024 public static boolean isBuiltinReferenceError() {
2025 final Global instance = Global.instance();
2026 return instance.referenceError == instance.getBuiltinReferenceError();
2027 }
2029 private synchronized ScriptFunction getBuiltinRegExp() {
2030 if (this.builtinRegExp == null) {
2031 this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
2032 final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
2033 // initialize default regexp object
2034 this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
2035 // RegExp.prototype should behave like a RegExp object. So copy the
2036 // properties.
2037 regExpProto.addBoundProperties(DEFAULT_REGEXP);
2038 }
2039 return builtinRegExp;
2040 }
2042 /**
2043 * Called from compiled script code to test if builtin has been overridden
2044 *
2045 * @return true if builtin regexp has not been overridden
2046 */
2047 public static boolean isBuiltinRegExp() {
2048 final Global instance = Global.instance();
2049 return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp();
2050 }
2052 private ScriptFunction getBuiltinString() {
2053 return builtinString;
2054 }
2056 /**
2057 * Called from compiled script code to test if builtin has been overridden
2058 *
2059 * @return true if builtin Java has not been overridden
2060 */
2061 public static boolean isBuiltinString() {
2062 final Global instance = Global.instance();
2063 return instance.string == instance.getBuiltinString();
2064 }
2066 private ScriptFunction getBuiltinSyntaxError() {
2067 return builtinSyntaxError;
2068 }
2070 /**
2071 * Called from compiled script code to test if builtin has been overridden
2072 *
2073 * @return true if builtin syntax error has not been overridden
2074 */
2075 public static boolean isBuiltinSyntaxError() {
2076 final Global instance = Global.instance();
2077 return instance.syntaxError == instance.getBuiltinSyntaxError();
2078 }
2080 private ScriptFunction getBuiltinTypeError() {
2081 return builtinTypeError;
2082 }
2084 /**
2085 * Called from compiled script code to test if builtin has been overridden
2086 *
2087 * @return true if builtin type error has not been overridden
2088 */
2089 public static boolean isBuiltinTypeError() {
2090 final Global instance = Global.instance();
2091 return instance.typeError == instance.getBuiltinTypeError();
2092 }
2094 private synchronized ScriptFunction getBuiltinURIError() {
2095 if (this.builtinURIError == null) {
2096 this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
2097 }
2098 return this.builtinURIError;
2099 }
2101 /**
2102 * Called from compiled script code to test if builtin has been overridden
2103 *
2104 * @return true if builtin URI error has not been overridden
2105 */
2106 public static boolean isBuiltinURIError() {
2107 final Global instance = Global.instance();
2108 return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError();
2109 }
2111 @Override
2112 public String getClassName() {
2113 return "global";
2114 }
2116 /**
2117 * Copy function used to clone NativeRegExp objects.
2118 *
2119 * @param regexp a NativeRegExp to clone
2120 *
2121 * @return copy of the given regexp object
2122 */
2123 public static Object regExpCopy(final Object regexp) {
2124 return new NativeRegExp((NativeRegExp)regexp);
2125 }
2127 /**
2128 * Convert given object to NativeRegExp type.
2129 *
2130 * @param obj object to be converted
2131 * @return NativeRegExp instance
2132 */
2133 public static NativeRegExp toRegExp(final Object obj) {
2134 if (obj instanceof NativeRegExp) {
2135 return (NativeRegExp)obj;
2136 }
2137 return new NativeRegExp(JSType.toString(obj));
2138 }
2140 /**
2141 * ECMA 9.9 ToObject implementation
2142 *
2143 * @param obj an item for which to run ToObject
2144 * @return ToObject version of given item
2145 */
2146 public static Object toObject(final Object obj) {
2147 if (obj == null || obj == UNDEFINED) {
2148 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2149 }
2151 if (obj instanceof ScriptObject) {
2152 return obj;
2153 }
2155 return instance().wrapAsObject(obj);
2156 }
2158 /**
2159 * Allocate a new object array.
2160 *
2161 * @param initial object values.
2162 * @return the new array
2163 */
2164 public static NativeArray allocate(final Object[] initial) {
2165 ArrayData arrayData = ArrayData.allocate(initial);
2167 for (int index = 0; index < initial.length; index++) {
2168 final Object value = initial[index];
2170 if (value == ScriptRuntime.EMPTY) {
2171 arrayData = arrayData.delete(index);
2172 }
2173 }
2175 return new NativeArray(arrayData);
2176 }
2178 /**
2179 * Allocate a new number array.
2180 *
2181 * @param initial number values.
2182 * @return the new array
2183 */
2184 public static NativeArray allocate(final double[] initial) {
2185 return new NativeArray(ArrayData.allocate(initial));
2186 }
2188 /**
2189 * Allocate a new long array.
2190 *
2191 * @param initial number values.
2192 * @return the new array
2193 */
2194 public static NativeArray allocate(final long[] initial) {
2195 return new NativeArray(ArrayData.allocate(initial));
2196 }
2198 /**
2199 * Allocate a new integer array.
2200 *
2201 * @param initial number values.
2202 * @return the new array
2203 */
2204 public static NativeArray allocate(final int[] initial) {
2205 return new NativeArray(ArrayData.allocate(initial));
2206 }
2208 /**
2209 * Allocate a new object array for arguments.
2210 *
2211 * @param arguments initial arguments passed.
2212 * @param callee reference to the function that uses arguments object
2213 * @param numParams actual number of declared parameters
2214 *
2215 * @return the new array
2216 */
2217 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
2218 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
2219 }
2221 /**
2222 * Called from generated to check if given function is the builtin 'eval'. If
2223 * eval is used in a script, a lot of optimizations and assumptions cannot be done.
2224 *
2225 * @param fn function object that is checked
2226 * @return true if fn is the builtin eval
2227 */
2228 public static boolean isEval(final Object fn) {
2229 return fn == Global.instance().builtinEval;
2230 }
2232 /**
2233 * Called from generated to replace a location property placeholder with the actual location property value.
2234 *
2235 * @param placeholder the value tested for being a placeholder for a location property
2236 * @param locationProperty the actual value for the location property
2237 * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
2238 */
2239 public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
2240 return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
2241 }
2243 /**
2244 * Called from runtime internals to check if the passed value is a location property placeholder.
2245 * @param placeholder the value tested for being a placeholder for a location property
2246 * @return true if the value is a placeholder, false otherwise.
2247 */
2248 public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
2249 return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
2250 }
2252 /**
2253 * Create a new RegExp object.
2254 *
2255 * @param expression Regular expression.
2256 * @param options Search options.
2257 *
2258 * @return New RegExp object.
2259 */
2260 public static Object newRegExp(final String expression, final String options) {
2261 if (options == null) {
2262 return new NativeRegExp(expression);
2263 }
2264 return new NativeRegExp(expression, options);
2265 }
2267 /**
2268 * Get the object prototype
2269 *
2270 * @return the object prototype
2271 */
2272 public static ScriptObject objectPrototype() {
2273 return Global.instance().getObjectPrototype();
2274 }
2276 /**
2277 * Create a new empty object instance.
2278 *
2279 * @return New empty object.
2280 */
2281 public static ScriptObject newEmptyInstance() {
2282 return Global.instance().newObject();
2283 }
2285 /**
2286 * Check if a given object is a ScriptObject, raises an exception if this is
2287 * not the case
2288 *
2289 * @param obj and object to check
2290 * @return the script object
2291 */
2292 public static ScriptObject checkObject(final Object obj) {
2293 if (!(obj instanceof ScriptObject)) {
2294 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2295 }
2296 return (ScriptObject)obj;
2297 }
2299 /**
2300 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
2301 * if this object is null or undefined.
2302 *
2303 * @param obj an object to check
2304 */
2305 public static void checkObjectCoercible(final Object obj) {
2306 if (obj == null || obj == UNDEFINED) {
2307 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2308 }
2309 }
2311 /**
2312 * Get the current split state.
2313 *
2314 * @return current split state
2315 */
2316 @Override
2317 public int getSplitState() {
2318 return splitState;
2319 }
2321 /**
2322 * Set the current split state.
2323 *
2324 * @param state current split state
2325 */
2326 @Override
2327 public void setSplitState(final int state) {
2328 splitState = state;
2329 }
2331 /**
2332 * Return the ES6 global scope for lexically declared bindings.
2333 * @return the ES6 lexical global scope.
2334 */
2335 public final ScriptObject getLexicalScope() {
2336 assert context.getEnv()._es6;
2337 return lexicalScope;
2338 }
2340 @Override
2341 public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
2342 PropertyMap ownMap = getMap();
2343 LexicalScope lexScope = null;
2344 PropertyMap lexicalMap = null;
2345 boolean hasLexicalDefinitions = false;
2347 if (context.getEnv()._es6) {
2348 lexScope = (LexicalScope) getLexicalScope();
2349 lexicalMap = lexScope.getMap();
2351 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2352 if (property.isLexicalBinding()) {
2353 hasLexicalDefinitions = true;
2354 }
2355 // ES6 15.1.8 steps 6. and 7.
2356 final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
2357 if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
2358 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2359 }
2360 final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
2361 if (lexicalProperty != null && !property.isConfigurable()) {
2362 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2363 }
2364 }
2365 }
2367 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2368 if (property.isLexicalBinding()) {
2369 assert lexScope != null;
2370 lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property);
2372 if (ownMap.findProperty(property.getKey()) != null) {
2373 // If property exists in the global object invalidate any global constant call sites.
2374 invalidateGlobalConstant(property.getKey());
2375 }
2376 } else {
2377 ownMap = addBoundProperty(ownMap, source, property);
2378 }
2379 }
2381 setMap(ownMap);
2383 if (hasLexicalDefinitions) {
2384 assert lexScope != null;
2385 lexScope.setMap(lexicalMap);
2386 invalidateLexicalSwitchPoint();
2387 }
2388 }
2390 @Override
2391 public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2392 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2393 final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2395 if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
2396 if (lexicalScope.hasOwnProperty(name)) {
2397 return lexicalScope.findGetMethod(desc, request, operator);
2398 }
2399 }
2401 final GuardedInvocation invocation = super.findGetMethod(desc, request, operator);
2403 // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
2404 // because those are invalidated per-key in the addBoundProperties method above.
2405 // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
2406 // assuming this only applies to global constants. If other non-inherited properties will
2407 // start using switchpoints some time in the future we'll have to revisit this.
2408 if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
2409 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2410 }
2412 return invocation;
2413 }
2415 @Override
2416 protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
2417 if (lexicalScope != null && start != this && start.isScope()) {
2418 final FindProperty find = lexicalScope.findProperty(key, false);
2419 if (find != null) {
2420 return find;
2421 }
2422 }
2423 return super.findProperty(key, deep, start);
2424 }
2426 @Override
2427 public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2428 final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2430 if (lexicalScope != null && isScope) {
2431 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2432 if (lexicalScope.hasOwnProperty(name)) {
2433 return lexicalScope.findSetMethod(desc, request);
2434 }
2435 }
2437 final GuardedInvocation invocation = super.findSetMethod(desc, request);
2439 if (isScope && context.getEnv()._es6) {
2440 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2441 }
2443 return invocation;
2444 }
2446 /**
2447 * Adds jjs shell interactive mode builtin functions to global scope.
2448 */
2449 public void addShellBuiltins() {
2450 Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT);
2451 addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
2453 value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT);
2454 addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
2455 }
2457 private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
2458 SwitchPoint switchPoint = lexicalScopeSwitchPoint;
2459 if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
2460 switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
2461 }
2462 return switchPoint;
2463 }
2465 private synchronized void invalidateLexicalSwitchPoint() {
2466 if (lexicalScopeSwitchPoint != null) {
2467 context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
2468 SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
2469 }
2470 }
2473 @SuppressWarnings("unused")
2474 private static Object lexicalScopeFilter(final Object self) {
2475 if (self instanceof Global) {
2476 return ((Global) self).getLexicalScope();
2477 }
2478 return self;
2479 }
2481 private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
2482 final T func = initConstructor(name, clazz);
2483 tagBuiltinProperties(name, func);
2484 return func;
2485 }
2487 @SuppressWarnings("hiding")
2488 private void init(final ScriptEngine engine) {
2489 assert Context.getGlobal() == this : "this global is not set as current";
2491 final ScriptEnvironment env = getContext().getEnv();
2493 // initialize Function and Object constructor
2494 initFunctionAndObject();
2496 // Now fix Global's own proto.
2497 this.setInitialProto(getObjectPrototype());
2499 // initialize global function properties
2500 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
2502 this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT,
2503 new Specialization[] {
2504 new Specialization(GlobalFunctions.PARSEINT_Z),
2505 new Specialization(GlobalFunctions.PARSEINT_I),
2506 new Specialization(GlobalFunctions.PARSEINT_J),
2507 new Specialization(GlobalFunctions.PARSEINT_OI),
2508 new Specialization(GlobalFunctions.PARSEINT_O) });
2509 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2510 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN,
2511 new Specialization[] {
2512 new Specialization(GlobalFunctions.IS_NAN_I),
2513 new Specialization(GlobalFunctions.IS_NAN_J),
2514 new Specialization(GlobalFunctions.IS_NAN_D) });
2515 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2516 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN);
2517 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE);
2518 this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI);
2519 this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
2520 this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI);
2521 this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
2522 this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE);
2523 this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
2524 this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN);
2525 this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
2526 this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
2527 this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT);
2528 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
2530 // built-in constructors
2531 this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
2532 this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
2533 this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
2534 this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class);
2535 this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class);
2537 // initialize String.prototype.length to 0
2538 // add String.prototype.length
2539 final ScriptObject stringPrototype = getStringPrototype();
2540 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
2542 // set isArray flag on Array.prototype
2543 final ScriptObject arrayPrototype = getArrayPrototype();
2544 arrayPrototype.setIsArray();
2546 // Error stuff
2547 initErrorObjects();
2549 // java access
2550 if (! env._no_java) {
2551 this.javaApi = LAZY_SENTINEL;
2552 this.javaImporter = LAZY_SENTINEL;
2553 initJavaAccess();
2554 }
2556 if (! env._no_typed_arrays) {
2557 this.arrayBuffer = LAZY_SENTINEL;
2558 this.dataView = LAZY_SENTINEL;
2559 this.int8Array = LAZY_SENTINEL;
2560 this.uint8Array = LAZY_SENTINEL;
2561 this.uint8ClampedArray = LAZY_SENTINEL;
2562 this.int16Array = LAZY_SENTINEL;
2563 this.uint16Array = LAZY_SENTINEL;
2564 this.int32Array = LAZY_SENTINEL;
2565 this.uint32Array = LAZY_SENTINEL;
2566 this.float32Array = LAZY_SENTINEL;
2567 this.float64Array = LAZY_SENTINEL;
2568 }
2570 if (env._scripting) {
2571 initScripting(env);
2572 }
2574 if (Context.DEBUG) {
2575 boolean debugOkay;
2576 final SecurityManager sm = System.getSecurityManager();
2577 if (sm != null) {
2578 try {
2579 sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
2580 debugOkay = true;
2581 } catch (final SecurityException ignored) {
2582 // if no permission, don't initialize Debug object
2583 debugOkay = false;
2584 }
2586 } else {
2587 debugOkay = true;
2588 }
2590 if (debugOkay) {
2591 initDebug();
2592 }
2593 }
2595 copyBuiltins();
2597 // expose script (command line) arguments as "arguments" property of global
2598 arguments = wrapAsObject(env.getArguments().toArray());
2599 if (env._scripting) {
2600 // synonym for "arguments" in scripting mode
2601 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
2602 }
2604 if (engine != null) {
2605 // default file name
2606 addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
2607 // __noSuchProperty__ hook for ScriptContext search of missing variables
2608 final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
2609 addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
2610 }
2611 }
2613 private void initErrorObjects() {
2614 // Error objects
2615 this.builtinError = initConstructor("Error", ScriptFunction.class);
2616 final ScriptObject errorProto = getErrorPrototype();
2618 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
2619 final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
2620 final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
2621 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
2622 final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
2623 final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
2624 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
2625 final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
2626 final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
2627 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
2628 final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
2629 final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
2630 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
2632 // ECMA 15.11.4.2 Error.prototype.name
2633 // Error.prototype.name = "Error";
2634 errorProto.set(NativeError.NAME, "Error", 0);
2635 // ECMA 15.11.4.3 Error.prototype.message
2636 // Error.prototype.message = "";
2637 errorProto.set(NativeError.MESSAGE, "", 0);
2639 tagBuiltinProperties("Error", builtinError);
2641 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2642 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2643 this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
2644 }
2646 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2647 final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2648 final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2649 prototype.set(NativeError.NAME, name, 0);
2650 prototype.set(NativeError.MESSAGE, "", 0);
2651 prototype.setInitialProto(errorProto);
2652 tagBuiltinProperties(name, cons);
2653 return cons;
2654 }
2656 private void initJavaAccess() {
2657 final ScriptObject objectProto = getObjectPrototype();
2658 this.builtinPackages = new NativeJavaPackage("", objectProto);
2659 this.builtinCom = new NativeJavaPackage("com", objectProto);
2660 this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2661 this.builtinJava = new NativeJavaPackage("java", objectProto);
2662 this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2663 this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2664 this.builtinOrg = new NativeJavaPackage("org", objectProto);
2665 }
2667 private void initScripting(final ScriptEnvironment scriptEnv) {
2668 Object value;
2669 value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
2670 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2672 value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
2673 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2675 final String execName = ScriptingFunctions.EXEC_NAME;
2676 value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
2677 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2679 // Nashorn extension: global.echo (scripting-mode-only)
2680 // alias for "print"
2681 value = get("print");
2682 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2684 // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2685 final ScriptObject options = newObject();
2686 copyOptions(options, scriptEnv);
2687 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2689 // Nashorn extension: global.$ENV (scripting-mode-only)
2690 if (System.getSecurityManager() == null) {
2691 // do not fill $ENV if we have a security manager around
2692 // Retrieve current state of ENV variables.
2693 final ScriptObject env = newObject();
2694 env.putAll(System.getenv(), scriptEnv._strict);
2695 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2696 } else {
2697 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2698 }
2700 // add other special properties for exec support
2701 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2702 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2703 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2704 }
2706 private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2707 for (final Field f : scriptEnv.getClass().getFields()) {
2708 try {
2709 options.set(f.getName(), f.get(scriptEnv), 0);
2710 } catch (final IllegalArgumentException | IllegalAccessException exp) {
2711 throw new RuntimeException(exp);
2712 }
2713 }
2714 }
2716 private void copyBuiltins() {
2717 this.array = this.builtinArray;
2718 this._boolean = this.builtinBoolean;
2719 this.error = this.builtinError;
2720 this.function = this.builtinFunction;
2721 this.com = this.builtinCom;
2722 this.edu = this.builtinEdu;
2723 this.java = this.builtinJava;
2724 this.javafx = this.builtinJavafx;
2725 this.javax = this.builtinJavax;
2726 this.org = this.builtinOrg;
2727 this.math = this.builtinMath;
2728 this.number = this.builtinNumber;
2729 this.object = this.builtinObject;
2730 this.packages = this.builtinPackages;
2731 this.referenceError = this.builtinReferenceError;
2732 this.string = this.builtinString;
2733 this.syntaxError = this.builtinSyntaxError;
2734 this.typeError = this.builtinTypeError;
2735 }
2737 private void initDebug() {
2738 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2739 }
2741 private Object printImpl(final boolean newLine, final Object... objects) {
2742 @SuppressWarnings("resource")
2743 final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
2744 final StringBuilder sb = new StringBuilder();
2746 for (final Object obj : objects) {
2747 if (sb.length() != 0) {
2748 sb.append(' ');
2749 }
2751 sb.append(JSType.toString(obj));
2752 }
2754 // Print all at once to ensure thread friendly result.
2755 if (newLine) {
2756 out.println(sb.toString());
2757 } else {
2758 out.print(sb.toString());
2759 }
2761 out.flush();
2763 return UNDEFINED;
2764 }
2766 private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2767 try {
2768 // Assuming class name pattern for built-in JS constructors.
2769 final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2771 sb.append("Native");
2772 sb.append(name);
2773 sb.append("$Constructor");
2775 final Class<?> funcClass = Class.forName(sb.toString());
2776 final T res = clazz.cast(funcClass.newInstance());
2778 if (res instanceof ScriptFunction) {
2779 // All global constructor prototypes are not-writable,
2780 // not-enumerable and not-configurable.
2781 final ScriptFunction func = (ScriptFunction)res;
2782 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2783 }
2785 if (res.getProto() == null) {
2786 res.setInitialProto(getObjectPrototype());
2787 }
2789 res.setIsBuiltin();
2791 return res;
2792 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2793 throw new RuntimeException(e);
2794 }
2795 }
2797 private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2798 final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2800 list.addAll(Arrays.asList(func.getMap().getProperties()));
2802 if (func instanceof ScriptFunction) {
2803 final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2804 if (proto != null) {
2805 list.addAll(Arrays.asList(proto.getMap().getProperties()));
2806 }
2807 }
2809 final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2810 if (prop != null) {
2811 list.add(prop);
2812 }
2814 return list;
2815 }
2817 /**
2818 * Given a builtin object, traverse its properties recursively and associate them with a name that
2819 * will be a key to their invalidation switchpoint.
2820 * @param name name for key
2821 * @param func builtin script object
2822 */
2823 private void tagBuiltinProperties(final String name, final ScriptObject func) {
2824 SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2825 if (sp == null) {
2826 sp = context.newBuiltinSwitchPoint(name);
2827 }
2829 //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2830 //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2831 for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2832 prop.setBuiltinSwitchPoint(sp);
2833 }
2834 }
2836 // Function and Object constructors are inter-dependent. Also,
2837 // Function.prototype
2838 // functions are not properly initialized. We fix the references here.
2839 // NOTE: be careful if you want to re-order the operations here. You may
2840 // have
2841 // to play with object references carefully!!
2842 private void initFunctionAndObject() {
2843 // First-n-foremost is Function
2845 this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2847 // create global anonymous function
2848 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2849 // need to copy over members of Function.prototype to anon function
2850 anon.addBoundProperties(getFunctionPrototype());
2852 // Function.prototype === Object.getPrototypeOf(Function) ===
2853 // <anon-function>
2854 builtinFunction.setInitialProto(anon);
2855 builtinFunction.setPrototype(anon);
2856 anon.set("constructor", builtinFunction, 0);
2857 anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2859 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2860 this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2861 typeErrorThrower.setPrototype(UNDEFINED);
2862 // Non-constructor built-in functions do not have "prototype" property
2863 typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2864 typeErrorThrower.preventExtensions();
2866 // now initialize Object
2867 this.builtinObject = initConstructor("Object", ScriptFunction.class);
2868 final ScriptObject ObjectPrototype = getObjectPrototype();
2869 // Object.getPrototypeOf(Function.prototype) === Object.prototype
2870 anon.setInitialProto(ObjectPrototype);
2872 // ES6 draft compliant __proto__ property of Object.prototype
2873 // accessors on Object.prototype for "__proto__"
2874 final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2875 final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2876 ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2878 // Function valued properties of Function.prototype were not properly
2879 // initialized. Because, these were created before global.function and
2880 // global.object were not initialized.
2881 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2882 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2883 final Object key = property.getKey();
2884 final Object value = builtinFunction.get(key);
2886 if (value instanceof ScriptFunction && value != anon) {
2887 final ScriptFunction func = (ScriptFunction)value;
2888 func.setInitialProto(getFunctionPrototype());
2889 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2890 if (prototype != null) {
2891 prototype.setInitialProto(ObjectPrototype);
2892 }
2893 }
2894 }
2896 // For function valued properties of Object and Object.prototype, make
2897 // sure prototype's proto chain ends with Object.prototype
2898 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2899 final Object key = property.getKey();
2900 final Object value = builtinObject.get(key);
2902 if (value instanceof ScriptFunction) {
2903 final ScriptFunction func = (ScriptFunction)value;
2904 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2905 if (prototype != null) {
2906 prototype.setInitialProto(ObjectPrototype);
2907 }
2908 }
2909 }
2911 properties = getObjectPrototype().getMap().getProperties();
2913 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2914 final Object key = property.getKey();
2915 if (key.equals("constructor")) {
2916 continue;
2917 }
2919 final Object value = ObjectPrototype.get(key);
2920 if (value instanceof ScriptFunction) {
2921 final ScriptFunction func = (ScriptFunction)value;
2922 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2923 if (prototype != null) {
2924 prototype.setInitialProto(ObjectPrototype);
2925 }
2926 }
2927 }
2929 tagBuiltinProperties("Object", builtinObject);
2930 tagBuiltinProperties("Function", builtinFunction);
2931 tagBuiltinProperties("Function", anon);
2932 }
2934 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2935 return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2936 }
2938 RegExpResult getLastRegExpResult() {
2939 return lastRegExpResult;
2940 }
2942 void setLastRegExpResult(final RegExpResult regExpResult) {
2943 this.lastRegExpResult = regExpResult;
2944 }
2946 @Override
2947 protected boolean isGlobal() {
2948 return true;
2949 }
2951 /**
2952 * A class representing the ES6 global lexical scope.
2953 */
2954 private static class LexicalScope extends ScriptObject {
2956 LexicalScope(final Global global) {
2957 super(global, PropertyMap.newMap());
2958 }
2960 @Override
2961 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2962 return filterInvocation(super.findGetMethod(desc, request, operator));
2963 }
2965 @Override
2966 protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2967 return filterInvocation(super.findSetMethod(desc, request));
2968 }
2970 @Override
2971 protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
2972 // We override this method just to make it callable by Global
2973 return super.addBoundProperty(propMap, source, property);
2974 }
2976 private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
2977 final MethodType type = invocation.getInvocation().type();
2978 return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
2979 }
2980 }
2982 }