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 */
25
26 package jdk.nashorn.internal.objects;
27
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;
33
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;
85
86 /**
87 * Representation of global scope.
88 */
89 @ScriptClass("Global")
90 public final class Global extends 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);
95
96 // placeholder value for lazily initialized global objects
97 private static final Object LAZY_SENTINEL = new Object();
98
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 */
118
119 /** Nashorn extension: arguments array */
120 @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
121 public Object arguments;
122
123 /** ECMA 15.1.2.2 parseInt (string , radix) */
124 @Property(attributes = Attribute.NOT_ENUMERABLE)
125 public Object parseInt;
126
127 /** ECMA 15.1.2.3 parseFloat (string) */
128 @Property(attributes = Attribute.NOT_ENUMERABLE)
129 public Object parseFloat;
130
131 /** ECMA 15.1.2.4 isNaN (number) */
132 @Property(attributes = Attribute.NOT_ENUMERABLE)
133 public Object isNaN;
134
135 /** ECMA 15.1.2.5 isFinite (number) */
136 @Property(attributes = Attribute.NOT_ENUMERABLE)
137 public Object isFinite;
138
139 /** ECMA 15.1.3.3 encodeURI */
140 @Property(attributes = Attribute.NOT_ENUMERABLE)
141 public Object encodeURI;
142
143 /** ECMA 15.1.3.4 encodeURIComponent */
144 @Property(attributes = Attribute.NOT_ENUMERABLE)
145 public Object encodeURIComponent;
146
147 /** ECMA 15.1.3.1 decodeURI */
148 @Property(attributes = Attribute.NOT_ENUMERABLE)
149 public Object decodeURI;
150
151 /** ECMA 15.1.3.2 decodeURIComponent */
152 @Property(attributes = Attribute.NOT_ENUMERABLE)
153 public Object decodeURIComponent;
154
155 /** ECMA B.2.1 escape (string) */
156 @Property(attributes = Attribute.NOT_ENUMERABLE)
157 public Object escape;
158
159 /** ECMA B.2.2 unescape (string) */
160 @Property(attributes = Attribute.NOT_ENUMERABLE)
161 public Object unescape;
162
163 /** Nashorn extension: global.print */
164 @Property(attributes = Attribute.NOT_ENUMERABLE)
165 public Object print;
166
167 /** Nashorn extension: global.load */
168 @Property(attributes = Attribute.NOT_ENUMERABLE)
169 public Object load;
170
171 /** Nashorn extension: global.loadWithNewGlobal */
172 @Property(attributes = Attribute.NOT_ENUMERABLE)
173 public Object loadWithNewGlobal;
174
175 /** Nashorn extension: global.exit */
176 @Property(attributes = Attribute.NOT_ENUMERABLE)
177 public Object exit;
178
179 /** Nashorn extension: global.quit */
180 @Property(attributes = Attribute.NOT_ENUMERABLE)
181 public Object quit;
182
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;
186
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;
190
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;
194
195 /** ECMA 15.1.2.1 eval(x) */
196 @Property(attributes = Attribute.NOT_ENUMERABLE)
197 public Object eval;
198
199 /** ECMA 15.1.4.1 Object constructor. */
200 @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
201 public volatile Object object;
202
203 /** ECMA 15.1.4.2 Function constructor. */
204 @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
205 public volatile Object function;
206
207 /** ECMA 15.1.4.3 Array constructor. */
208 @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
209 public volatile Object array;
210
211 /** ECMA 15.1.4.4 String constructor */
212 @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
213 public volatile Object string;
214
215 /** ECMA 15.1.4.5 Boolean constructor */
216 @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
217 public volatile Object _boolean;
218
219 /** ECMA 15.1.4.6 - Number constructor */
220 @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
221 public volatile Object number;
222
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 }
237
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 }
249
250 private volatile Object date = LAZY_SENTINEL;
251
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 }
266
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 }
278
279 private volatile Object regexp = LAZY_SENTINEL;
280
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 }
294
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 }
305
306 private volatile Object json = LAZY_SENTINEL;
307
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 }
321
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 }
332
333 private volatile Object jsadapter = LAZY_SENTINEL;
334
335 /** ECMA 15.8 - The Math object */
336 @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
337 public volatile Object math;
338
339 /** Error object */
340 @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
341 public volatile Object error;
342
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 }
356
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 }
367
368 private volatile Object evalError = LAZY_SENTINEL;
369
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 }
383
384
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 }
395
396 private volatile Object rangeError = LAZY_SENTINEL;
397
398 /** ReferenceError object */
399 @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
400 public volatile Object referenceError;
401
402 /** SyntaxError object */
403 @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
404 public volatile Object syntaxError;
405
406 /** TypeError object */
407 @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
408 public volatile Object typeError;
409
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 }
423
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 }
434
435 private volatile Object uriError = LAZY_SENTINEL;
436
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 }
450
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 }
461
462 private volatile Object arrayBuffer;
463
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 }
477
478
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 }
489
490 private volatile Object dataView;
491
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 }
505
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 }
516
517 private volatile Object int8Array;
518
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 }
532
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 }
543
544 private volatile Object uint8Array;
545
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 }
559
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 }
570
571 private volatile Object uint8ClampedArray;
572
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 }
586
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 }
597
598 private volatile Object int16Array;
599
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 }
613
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 }
624
625 private volatile Object uint16Array;
626
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 }
641
642
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 }
654
655 private volatile Object int32Array;
656
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 }
671
672
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 }
684
685 private volatile Object uint32Array;
686
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 }
701
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 }
713
714 private volatile Object float32Array;
715
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 }
730
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 }
742
743 private volatile Object float64Array;
744
745 /** Nashorn extension: Java access - global.Packages */
746 @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
747 public volatile Object packages;
748
749 /** Nashorn extension: Java access - global.com */
750 @Property(attributes = Attribute.NOT_ENUMERABLE)
751 public volatile Object com;
752
753 /** Nashorn extension: Java access - global.edu */
754 @Property(attributes = Attribute.NOT_ENUMERABLE)
755 public volatile Object edu;
756
757 /** Nashorn extension: Java access - global.java */
758 @Property(attributes = Attribute.NOT_ENUMERABLE)
759 public volatile Object java;
760
761 /** Nashorn extension: Java access - global.javafx */
762 @Property(attributes = Attribute.NOT_ENUMERABLE)
763 public volatile Object javafx;
764
765 /** Nashorn extension: Java access - global.javax */
766 @Property(attributes = Attribute.NOT_ENUMERABLE)
767 public volatile Object javax;
768
769 /** Nashorn extension: Java access - global.org */
770 @Property(attributes = Attribute.NOT_ENUMERABLE)
771 public volatile Object org;
772
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 }
787
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 }
799
800 private volatile Object javaImporter;
801
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 }
816
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 }
828
829 private volatile Object javaApi;
830
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;
834
835 /** Nashorn extension: current script's directory */
836 @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
837 public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
838
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;
842
843 private volatile NativeDate DEFAULT_DATE;
844
845 /** Used as Date.prototype's default value */
846 NativeDate getDefaultDate() {
847 return DEFAULT_DATE;
848 }
849
850 private volatile NativeRegExp DEFAULT_REGEXP;
851
852 /** Used as RegExp.prototype's default value */
853 NativeRegExp getDefaultRegExp() {
854 return DEFAULT_REGEXP;
855 }
856
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;
903
904 /*
905 * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
906 */
907 private ScriptFunction typeErrorThrower;
908
909 // Used to store the last RegExp result to support deprecated RegExp constructor properties
910 private RegExpResult lastRegExpResult;
911
912 private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class);
913 private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
914 private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class);
915 private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class);
916 private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class);
917 private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class);
918 private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class);
919 private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class);
920
921 // initialized by nasgen
922 private static PropertyMap $nasgenmap$;
923
924 // context to which this global belongs to
925 private final Context context;
926
927 // current ScriptContext to use - can be null.
928 private ThreadLocal<ScriptContext> scontext;
929 // current ScriptEngine associated - can be null.
930 private ScriptEngine engine;
931 // initial ScriptContext - can be null
932 private volatile ScriptContext initscontext;
933
934 // ES6 global lexical scope.
935 private final LexicalScope lexicalScope;
936
937 // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
938 private SwitchPoint lexicalScopeSwitchPoint;
939
940 /**
941 * Set the current script context
942 * @param ctxt script context
943 */
944 public void setScriptContext(final ScriptContext ctxt) {
945 assert scontext != null;
946 scontext.set(ctxt);
947 }
948
949 /**
950 * Get the current script context
951 * @return current script context
952 */
953 public ScriptContext getScriptContext() {
954 assert scontext != null;
955 return scontext.get();
956 }
957
958 private ScriptContext currentContext() {
959 final ScriptContext sc = scontext != null? scontext.get() : null;
960 return sc == null? initscontext : sc;
961 }
962
963 @Override
964 protected Context getContext() {
965 return context;
966 }
967
968 @Override
969 protected boolean useDualFields() {
970 return context.useDualFields();
971 }
972
973 // performs initialization checks for Global constructor and returns the
974 // PropertyMap, if everything is fine.
975 private static PropertyMap checkAndGetMap(final Context context) {
976 // security check first
977 final SecurityManager sm = System.getSecurityManager();
978 if (sm != null) {
979 sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
980 }
981
982 Objects.requireNonNull(context);
983
984 return $nasgenmap$;
985 }
986
987 /**
988 * Constructor
989 *
990 * @param context the context
991 */
992 public Global(final Context context) {
993 super(checkAndGetMap(context));
994 this.context = context;
995 this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
996 }
997
998 /**
999 * Script access to "current" Global instance
1000 *
1001 * @return the global singleton
1002 */
1003 public static Global instance() {
1004 return Objects.requireNonNull(Context.getGlobal());
1005 }
1006
1007 private static Global instanceFrom(final Object self) {
1008 return self instanceof Global? (Global)self : instance();
1009 }
1010
1011 /**
1012 * Check if we have a Global instance
1013 * @return true if one exists
1014 */
1015 public static boolean hasInstance() {
1016 return Context.getGlobal() != null;
1017 }
1018
1019 /**
1020 * Script access to {@link ScriptEnvironment}
1021 *
1022 * @return the script environment
1023 */
1024 static ScriptEnvironment getEnv() {
1025 return instance().getContext().getEnv();
1026 }
1027
1028 /**
1029 * Script access to {@link Context}
1030 *
1031 * @return the context
1032 */
1033 static Context getThisContext() {
1034 return instance().getContext();
1035 }
1036
1037 // Runtime interface to Global
1038
1039 /**
1040 * Is there a class filter in the current Context?
1041 * @return class filter
1042 */
1043 public ClassFilter getClassFilter() {
1044 return context.getClassFilter();
1045 }
1046
1047 /**
1048 * Is this global of the given Context?
1049 * @param ctxt the context
1050 * @return true if this global belongs to the given Context
1051 */
1052 public boolean isOfContext(final Context ctxt) {
1053 return this.context == ctxt;
1054 }
1055
1056 /**
1057 * Does this global belong to a strict Context?
1058 * @return true if this global belongs to a strict Context
1059 */
1060 public boolean isStrictContext() {
1061 return context.getEnv()._strict;
1062 }
1063
1064 /**
1065 * Initialize standard builtin objects like "Object", "Array", "Function" etc.
1066 * as well as our extension builtin objects like "Java", "JSAdapter" as properties
1067 * of the global scope object.
1068 *
1069 * @param eng ScriptEngine to initialize
1070 * @param ctxt ScriptContext to initialize
1071 */
1072 public void initBuiltinObjects(final ScriptEngine eng, final ScriptContext ctxt) {
1073 if (this.builtinObject != null) {
1074 // already initialized, just return
1075 return;
1076 }
1077
1078 this.engine = eng;
1079 this.initscontext = ctxt;
1080 if (this.engine != null) {
1081 this.scontext = new ThreadLocal<>();
1082 }
1083 init(eng);
1084 }
1085
1086 /**
1087 * Wrap a Java object as corresponding script object
1088 *
1089 * @param obj object to wrap
1090 * @return wrapped object
1091 */
1092 public Object wrapAsObject(final Object obj) {
1093 if (obj instanceof Boolean) {
1094 return new NativeBoolean((Boolean)obj, this);
1095 } else if (obj instanceof Number) {
1096 return new NativeNumber(((Number)obj).doubleValue(), this);
1097 } else if (isString(obj)) {
1098 return new NativeString((CharSequence)obj, this);
1099 } else if (obj instanceof Object[]) { // extension
1100 return new NativeArray(ArrayData.allocate((Object[])obj), this);
1101 } else if (obj instanceof double[]) { // extension
1102 return new NativeArray(ArrayData.allocate((double[])obj), this);
1103 } else if (obj instanceof long[]) {
1104 return new NativeArray(ArrayData.allocate((long[])obj), this);
1105 } else if (obj instanceof int[]) {
1106 return new NativeArray(ArrayData.allocate((int[]) obj), this);
1107 } else if (obj instanceof ArrayData) {
1108 return new NativeArray((ArrayData) obj, this);
1109 } else {
1110 // FIXME: more special cases? Map? List?
1111 return obj;
1112 }
1113 }
1114
1115 /**
1116 * Lookup helper for JS primitive types
1117 *
1118 * @param request the link request for the dynamic call site.
1119 * @param self self reference
1120 *
1121 * @return guarded invocation
1122 */
1123 public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
1124 if (isString(self)) {
1125 return NativeString.lookupPrimitive(request, self);
1126 } else if (self instanceof Number) {
1127 return NativeNumber.lookupPrimitive(request, self);
1128 } else if (self instanceof Boolean) {
1129 return NativeBoolean.lookupPrimitive(request, self);
1130 }
1131 throw new IllegalArgumentException("Unsupported primitive: " + self);
1132 }
1133
1134 /**
1135 * Returns a method handle that creates a wrapper object for a JS primitive value.
1136 *
1137 * @param self receiver object
1138 * @return method handle to create wrapper objects for primitive receiver
1139 */
1140 public static MethodHandle getPrimitiveWrapFilter(final Object self) {
1141 if (isString(self)) {
1142 return NativeString.WRAPFILTER;
1143 } else if (self instanceof Number) {
1144 return NativeNumber.WRAPFILTER;
1145 } else if (self instanceof Boolean) {
1146 return NativeBoolean.WRAPFILTER;
1147 }
1148 throw new IllegalArgumentException("Unsupported primitive: " + self);
1149 }
1150
1151
1152 /**
1153 * Create a new empty script object
1154 *
1155 * @return the new ScriptObject
1156 */
1157 public ScriptObject newObject() {
1158 return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype());
1159 }
1160
1161 /**
1162 * Default value of given type
1163 *
1164 * @param sobj script object
1165 * @param typeHint type hint
1166 *
1167 * @return default value
1168 */
1169 public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
1170 // When the [[DefaultValue]] internal method of O is called with no hint,
1171 // then it behaves as if the hint were Number, unless O is a Date object
1172 // in which case it behaves as if the hint were String.
1173 Class<?> hint = typeHint;
1174 if (hint == null) {
1175 hint = Number.class;
1176 }
1177
1178 try {
1179 if (hint == String.class) {
1180
1181 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1182
1183 if (Bootstrap.isCallable(toString)) {
1184 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1185 if (JSType.isPrimitive(value)) {
1186 return value;
1187 }
1188 }
1189
1190 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1191 if (Bootstrap.isCallable(valueOf)) {
1192 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1193 if (JSType.isPrimitive(value)) {
1194 return value;
1195 }
1196 }
1197 throw typeError(this, "cannot.get.default.string");
1198 }
1199
1200 if (hint == Number.class) {
1201 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1202 if (Bootstrap.isCallable(valueOf)) {
1203 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1204 if (JSType.isPrimitive(value)) {
1205 return value;
1206 }
1207 }
1208
1209 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1210 if (Bootstrap.isCallable(toString)) {
1211 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1212 if (JSType.isPrimitive(value)) {
1213 return value;
1214 }
1215 }
1216
1217 throw typeError(this, "cannot.get.default.number");
1218 }
1219 } catch (final RuntimeException | Error e) {
1220 throw e;
1221 } catch (final Throwable t) {
1222 throw new RuntimeException(t);
1223 }
1224
1225 return UNDEFINED;
1226 }
1227
1228 /**
1229 * Is the given ScriptObject an ECMAScript Error object?
1230 *
1231 * @param sobj the object being checked
1232 * @return true if sobj is an Error object
1233 */
1234 public boolean isError(final ScriptObject sobj) {
1235 final ScriptObject errorProto = getErrorPrototype();
1236 ScriptObject proto = sobj.getProto();
1237 while (proto != null) {
1238 if (proto == errorProto) {
1239 return true;
1240 }
1241 proto = proto.getProto();
1242 }
1243 return false;
1244 }
1245
1246 /**
1247 * Create a new ECMAScript Error object.
1248 *
1249 * @param msg error message
1250 * @return newly created Error object
1251 */
1252 public ScriptObject newError(final String msg) {
1253 return new NativeError(msg, this);
1254 }
1255
1256 /**
1257 * Create a new ECMAScript EvalError object.
1258 *
1259 * @param msg error message
1260 * @return newly created EvalError object
1261 */
1262 public ScriptObject newEvalError(final String msg) {
1263 return new NativeEvalError(msg, this);
1264 }
1265
1266 /**
1267 * Create a new ECMAScript RangeError object.
1268 *
1269 * @param msg error message
1270 * @return newly created RangeError object
1271 */
1272 public ScriptObject newRangeError(final String msg) {
1273 return new NativeRangeError(msg, this);
1274 }
1275
1276 /**
1277 * Create a new ECMAScript ReferenceError object.
1278 *
1279 * @param msg error message
1280 * @return newly created ReferenceError object
1281 */
1282 public ScriptObject newReferenceError(final String msg) {
1283 return new NativeReferenceError(msg, this);
1284 }
1285
1286 /**
1287 * Create a new ECMAScript SyntaxError object.
1288 *
1289 * @param msg error message
1290 * @return newly created SyntaxError object
1291 */
1292 public ScriptObject newSyntaxError(final String msg) {
1293 return new NativeSyntaxError(msg, this);
1294 }
1295
1296 /**
1297 * Create a new ECMAScript TypeError object.
1298 *
1299 * @param msg error message
1300 * @return newly created TypeError object
1301 */
1302 public ScriptObject newTypeError(final String msg) {
1303 return new NativeTypeError(msg, this);
1304 }
1305
1306 /**
1307 * Create a new ECMAScript URIError object.
1308 *
1309 * @param msg error message
1310 * @return newly created URIError object
1311 */
1312 public ScriptObject newURIError(final String msg) {
1313 return new NativeURIError(msg, this);
1314 }
1315
1316 /**
1317 * Create a new ECMAScript GenericDescriptor object.
1318 *
1319 * @param configurable is the property configurable?
1320 * @param enumerable is the property enumerable?
1321 * @return newly created GenericDescriptor object
1322 */
1323 public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
1324 return new GenericPropertyDescriptor(configurable, enumerable, this);
1325 }
1326
1327 /**
1328 * Create a new ECMAScript DatePropertyDescriptor object.
1329 *
1330 * @param value of the data property
1331 * @param configurable is the property configurable?
1332 * @param enumerable is the property enumerable?
1333 * @param writable is the property writable?
1334 * @return newly created DataPropertyDescriptor object
1335 */
1336 public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
1337 return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
1338 }
1339
1340 /**
1341 * Create a new ECMAScript AccessorPropertyDescriptor object.
1342 *
1343 * @param get getter function of the user accessor property
1344 * @param set setter function of the user accessor property
1345 * @param configurable is the property configurable?
1346 * @param enumerable is the property enumerable?
1347 * @return newly created AccessorPropertyDescriptor object
1348 */
1349 public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
1350 final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
1351
1352 if (get == null) {
1353 desc.delete(PropertyDescriptor.GET, false);
1354 }
1355
1356 if (set == null) {
1357 desc.delete(PropertyDescriptor.SET, false);
1358 }
1359
1360 return desc;
1361 }
1362
1363 private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
1364 final T obj = map.get(key);
1365 if (obj != null) {
1366 return obj;
1367 }
1368
1369 try {
1370 final T newObj = creator.call();
1371 final T existingObj = map.putIfAbsent(key, newObj);
1372 return existingObj != null ? existingObj : newObj;
1373 } catch (final Exception exp) {
1374 throw new RuntimeException(exp);
1375 }
1376 }
1377
1378 private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
1379
1380
1381 /**
1382 * Get cached InvokeByName object for the given key
1383 * @param key key to be associated with InvokeByName object
1384 * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
1385 * @return InvokeByName object associated with the key.
1386 */
1387 public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
1388 return getLazilyCreatedValue(key, creator, namedInvokers);
1389 }
1390
1391 private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
1392
1393 /**
1394 * Get cached dynamic method handle for the given key
1395 * @param key key to be associated with dynamic method handle
1396 * @param creator if method handle is absent 'creator' is called to make one (lazy init)
1397 * @return dynamic method handle associated with the key.
1398 */
1399 public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
1400 return getLazilyCreatedValue(key, creator, dynamicInvokers);
1401 }
1402
1403 /**
1404 * Hook to search missing variables in ScriptContext if available
1405 * @param self used to detect if scope call or not (this function is 'strict')
1406 * @param name name of the variable missing
1407 * @return value of the missing variable or undefined (or TypeError for scope search)
1408 */
1409 public static Object __noSuchProperty__(final Object self, final Object name) {
1410 final Global global = Global.instance();
1411 final ScriptContext sctxt = global.currentContext();
1412 final String nameStr = name.toString();
1413
1414 if (sctxt != null) {
1415 final int scope = sctxt.getAttributesScope(nameStr);
1416 if (scope != -1) {
1417 return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
1418 }
1419 }
1420
1421 switch (nameStr) {
1422 case "context":
1423 return sctxt;
1424 case "engine":
1425 return global.engine;
1426 default:
1427 break;
1428 }
1429
1430 if (self == UNDEFINED) {
1431 // scope access and so throw ReferenceError
1432 throw referenceError(global, "not.defined", nameStr);
1433 }
1434
1435 return UNDEFINED;
1436 }
1437
1438 /**
1439 * This is the eval used when 'indirect' eval call is made.
1440 *
1441 * var global = this;
1442 * global.eval("print('hello')");
1443 *
1444 * @param self eval scope
1445 * @param str eval string
1446 *
1447 * @return the result of eval
1448 */
1449 public static Object eval(final Object self, final Object str) {
1450 return directEval(self, str, Global.instanceFrom(self), UNDEFINED, false);
1451 }
1452
1453 /**
1454 * Direct eval
1455 *
1456 * @param self The scope of eval passed as 'self'
1457 * @param str Evaluated code
1458 * @param callThis "this" to be passed to the evaluated code
1459 * @param location location of the eval call
1460 * @param strict is eval called from a strict mode code?
1461 *
1462 * @return the return value of the eval
1463 *
1464 * This is directly invoked from generated when eval(code) is called in user code
1465 */
1466 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
1467 if (!isString(str)) {
1468 return str;
1469 }
1470 final Global global = Global.instanceFrom(self);
1471 final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
1472
1473 return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
1474 }
1475
1476 /**
1477 * Global print implementation - Nashorn extension
1478 *
1479 * @param self scope
1480 * @param objects arguments to print
1481 *
1482 * @return result of print (undefined)
1483 */
1484 public static Object print(final Object self, final Object... objects) {
1485 return Global.instanceFrom(self).printImpl(false, objects);
1486 }
1487
1488 /**
1489 * Global println implementation - Nashorn extension
1490 *
1491 * @param self scope
1492 * @param objects arguments to print
1493 *
1494 * @return result of println (undefined)
1495 */
1496 public static Object println(final Object self, final Object... objects) {
1497 return Global.instanceFrom(self).printImpl(true, objects);
1498 }
1499
1500 /**
1501 * Global load implementation - Nashorn extension.
1502 *
1503 * <p>
1504 * load builtin loads the given script. Script source can be a URL or a File
1505 * or a script object with name and script properties. Evaluated code gets
1506 * global object "this" and uses global object as scope for evaluation.
1507 * </p>
1508 * <p>
1509 * If self is undefined or null or global, then global object is used
1510 * as scope as well as "this" for the evaluated code. If self is any other
1511 * object, then it is indirect load call. With indirect load call, the
1512 * properties of scope are available to evaluated script as variables. Also,
1513 * global scope properties are accessible. Any var, function definition in
1514 * evaluated script goes into an object that is not accessible to user scripts.
1515 * </p>
1516 * Thus the indirect load call is equivalent to the following:
1517 * <pre>
1518 * <code>
1519 * (function (scope, source) {
1520 * with(scope) {
1521 * eval(<script_from_source>);
1522 * }
1523 * })(self, source);
1524 * </code>
1525 * </pre>
1526 *
1527 * @param self scope to use for the script evaluation
1528 * @param source script source
1529 *
1530 * @return result of load (may be undefined)
1531 *
1532 * @throws IOException if source could not be read
1533 */
1534 public static Object load(final Object self, final Object source) throws IOException {
1535 final Global global = Global.instanceFrom(self);
1536 return global.getContext().load(self, source);
1537 }
1538
1539 /**
1540 * Global loadWithNewGlobal implementation - Nashorn extension.
1541 *
1542 * loadWithNewGlobal builtin loads the given script from a URL or a File
1543 * or a script object with name and script properties. Evaluated code gets
1544 * new global object "this" and uses that new global object as scope for evaluation.
1545 *
1546 * @param self self This value is ignored by this function
1547 * @param args optional arguments to be passed to the loaded script
1548 *
1549 * @return result of load (may be undefined)
1550 *
1551 * @throws IOException if source could not be read
1552 */
1553 public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
1554 final Global global = Global.instanceFrom(self);
1555 final int length = args.length;
1556 final boolean hasArgs = 0 < length;
1557 final Object from = hasArgs ? args[0] : UNDEFINED;
1558 final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1559
1560 return global.getContext().loadWithNewGlobal(from, arguments);
1561 }
1562
1563 /**
1564 * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1565 *
1566 * @param self self reference
1567 * @param code exit code
1568 *
1569 * @return undefined (will never be reached)
1570 */
1571 public static Object exit(final Object self, final Object code) {
1572 System.exit(JSType.toInt32(code));
1573 return UNDEFINED;
1574 }
1575
1576 // builtin prototype accessors
1577
1578 /**
1579 * Get the builtin Object prototype.
1580 * @return the object prototype.
1581 */
1582 public ScriptObject getObjectPrototype() {
1583 return ScriptFunction.getPrototype(builtinObject);
1584 }
1585
1586 ScriptObject getFunctionPrototype() {
1587 return ScriptFunction.getPrototype(builtinFunction);
1588 }
1589
1590 ScriptObject getArrayPrototype() {
1591 return ScriptFunction.getPrototype(builtinArray);
1592 }
1593
1594 ScriptObject getBooleanPrototype() {
1595 return ScriptFunction.getPrototype(builtinBoolean);
1596 }
1597
1598 ScriptObject getNumberPrototype() {
1599 return ScriptFunction.getPrototype(builtinNumber);
1600 }
1601
1602 ScriptObject getDatePrototype() {
1603 return ScriptFunction.getPrototype(getBuiltinDate());
1604 }
1605
1606 ScriptObject getRegExpPrototype() {
1607 return ScriptFunction.getPrototype(getBuiltinRegExp());
1608 }
1609
1610 ScriptObject getStringPrototype() {
1611 return ScriptFunction.getPrototype(builtinString);
1612 }
1613
1614 ScriptObject getErrorPrototype() {
1615 return ScriptFunction.getPrototype(builtinError);
1616 }
1617
1618 ScriptObject getEvalErrorPrototype() {
1619 return ScriptFunction.getPrototype(getBuiltinEvalError());
1620 }
1621
1622 ScriptObject getRangeErrorPrototype() {
1623 return ScriptFunction.getPrototype(getBuiltinRangeError());
1624 }
1625
1626 ScriptObject getReferenceErrorPrototype() {
1627 return ScriptFunction.getPrototype(builtinReferenceError);
1628 }
1629
1630 ScriptObject getSyntaxErrorPrototype() {
1631 return ScriptFunction.getPrototype(builtinSyntaxError);
1632 }
1633
1634 ScriptObject getTypeErrorPrototype() {
1635 return ScriptFunction.getPrototype(builtinTypeError);
1636 }
1637
1638 ScriptObject getURIErrorPrototype() {
1639 return ScriptFunction.getPrototype(getBuiltinURIError());
1640 }
1641
1642 ScriptObject getJavaImporterPrototype() {
1643 return ScriptFunction.getPrototype(getBuiltinJavaImporter());
1644 }
1645
1646 ScriptObject getJSAdapterPrototype() {
1647 return ScriptFunction.getPrototype(getBuiltinJSAdapter());
1648 }
1649
1650 private synchronized ScriptFunction getBuiltinArrayBuffer() {
1651 if (this.builtinArrayBuffer == null) {
1652 this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
1653 }
1654 return this.builtinArrayBuffer;
1655 }
1656
1657 ScriptObject getArrayBufferPrototype() {
1658 return ScriptFunction.getPrototype(getBuiltinArrayBuffer());
1659 }
1660
1661 private synchronized ScriptFunction getBuiltinDataView() {
1662 if (this.builtinDataView == null) {
1663 this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
1664 }
1665 return this.builtinDataView;
1666 }
1667
1668 ScriptObject getDataViewPrototype() {
1669 return ScriptFunction.getPrototype(getBuiltinDataView());
1670 }
1671
1672 private synchronized ScriptFunction getBuiltinInt8Array() {
1673 if (this.builtinInt8Array == null) {
1674 this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
1675 }
1676 return this.builtinInt8Array;
1677 }
1678
1679 ScriptObject getInt8ArrayPrototype() {
1680 return ScriptFunction.getPrototype(getBuiltinInt8Array());
1681 }
1682
1683 private synchronized ScriptFunction getBuiltinUint8Array() {
1684 if (this.builtinUint8Array == null) {
1685 this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
1686 }
1687 return this.builtinUint8Array;
1688 }
1689
1690 ScriptObject getUint8ArrayPrototype() {
1691 return ScriptFunction.getPrototype(getBuiltinUint8Array());
1692 }
1693
1694 private synchronized ScriptFunction getBuiltinUint8ClampedArray() {
1695 if (this.builtinUint8ClampedArray == null) {
1696 this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
1697 }
1698 return this.builtinUint8ClampedArray;
1699 }
1700
1701 ScriptObject getUint8ClampedArrayPrototype() {
1702 return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray());
1703 }
1704
1705 private synchronized ScriptFunction getBuiltinInt16Array() {
1706 if (this.builtinInt16Array == null) {
1707 this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
1708 }
1709 return this.builtinInt16Array;
1710 }
1711
1712 ScriptObject getInt16ArrayPrototype() {
1713 return ScriptFunction.getPrototype(getBuiltinInt16Array());
1714 }
1715
1716 private synchronized ScriptFunction getBuiltinUint16Array() {
1717 if (this.builtinUint16Array == null) {
1718 this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
1719 }
1720 return this.builtinUint16Array;
1721 }
1722
1723 ScriptObject getUint16ArrayPrototype() {
1724 return ScriptFunction.getPrototype(getBuiltinUint16Array());
1725 }
1726
1727 private synchronized ScriptFunction getBuiltinInt32Array() {
1728 if (this.builtinInt32Array == null) {
1729 this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
1730 }
1731 return this.builtinInt32Array;
1732 }
1733
1734 ScriptObject getInt32ArrayPrototype() {
1735 return ScriptFunction.getPrototype(getBuiltinInt32Array());
1736 }
1737
1738 private synchronized ScriptFunction getBuiltinUint32Array() {
1739 if (this.builtinUint32Array == null) {
1740 this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
1741 }
1742 return this.builtinUint32Array;
1743 }
1744
1745 ScriptObject getUint32ArrayPrototype() {
1746 return ScriptFunction.getPrototype(getBuiltinUint32Array());
1747 }
1748
1749 private synchronized ScriptFunction getBuiltinFloat32Array() {
1750 if (this.builtinFloat32Array == null) {
1751 this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
1752 }
1753 return this.builtinFloat32Array;
1754 }
1755
1756 ScriptObject getFloat32ArrayPrototype() {
1757 return ScriptFunction.getPrototype(getBuiltinFloat32Array());
1758 }
1759
1760 private synchronized ScriptFunction getBuiltinFloat64Array() {
1761 if (this.builtinFloat64Array == null) {
1762 this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
1763 }
1764 return this.builtinFloat64Array;
1765 }
1766
1767 ScriptObject getFloat64ArrayPrototype() {
1768 return ScriptFunction.getPrototype(getBuiltinFloat64Array());
1769 }
1770
1771 private ScriptFunction getBuiltinArray() {
1772 return builtinArray;
1773 }
1774
1775 ScriptFunction getTypeErrorThrower() {
1776 return typeErrorThrower;
1777 }
1778
1779 /**
1780 * Called from compiled script code to test if builtin has been overridden
1781 *
1782 * @return true if builtin array has not been overridden
1783 */
1784 public static boolean isBuiltinArray() {
1785 final Global instance = Global.instance();
1786 return instance.array == instance.getBuiltinArray();
1787 }
1788
1789 private ScriptFunction getBuiltinBoolean() {
1790 return builtinBoolean;
1791 }
1792
1793 /**
1794 * Called from compiled script code to test if builtin has been overridden
1795 *
1796 * @return true if builtin boolean has not been overridden
1797 */
1798 public static boolean isBuiltinBoolean() {
1799 final Global instance = Global.instance();
1800 return instance._boolean == instance.getBuiltinBoolean();
1801 }
1802
1803 private synchronized ScriptFunction getBuiltinDate() {
1804 if (this.builtinDate == null) {
1805 this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
1806 final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate);
1807 // initialize default date
1808 this.DEFAULT_DATE = new NativeDate(NaN, dateProto);
1809 }
1810 return this.builtinDate;
1811 }
1812
1813 /**
1814 * Called from compiled script code to test if builtin has been overridden
1815 *
1816 * @return true if builtin date has not been overridden
1817 */
1818 public static boolean isBuiltinDate() {
1819 final Global instance = Global.instance();
1820 return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate();
1821 }
1822
1823 private ScriptFunction getBuiltinError() {
1824 return builtinError;
1825 }
1826
1827 /**
1828 * Called from compiled script code to test if builtin has been overridden
1829 *
1830 * @return true if builtin error has not been overridden
1831 */
1832 public static boolean isBuiltinError() {
1833 final Global instance = Global.instance();
1834 return instance.error == instance.getBuiltinError();
1835 }
1836
1837 private synchronized ScriptFunction getBuiltinEvalError() {
1838 if (this.builtinEvalError == null) {
1839 this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
1840 }
1841 return this.builtinEvalError;
1842 }
1843
1844 /**
1845 * Called from compiled script code to test if builtin has been overridden
1846 *
1847 * @return true if builtin eval error has not been overridden
1848 */
1849 public static boolean isBuiltinEvalError() {
1850 final Global instance = Global.instance();
1851 return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError();
1852 }
1853
1854 private ScriptFunction getBuiltinFunction() {
1855 return builtinFunction;
1856 }
1857
1858 /**
1859 * Called from compiled script code to test if builtin has been overridden
1860 *
1861 * @return true if builtin function has not been overridden
1862 */
1863 public static boolean isBuiltinFunction() {
1864 final Global instance = Global.instance();
1865 return instance.function == instance.getBuiltinFunction();
1866 }
1867
1868 /**
1869 * Get the switchpoint used to check property changes for Function.prototype.apply
1870 * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
1871 */
1872 public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
1873 return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
1874 }
1875
1876 private static boolean isBuiltinFunctionProperty(final String name) {
1877 final Global instance = Global.instance();
1878 final ScriptFunction builtinFunction = instance.getBuiltinFunction();
1879 if (builtinFunction == null) {
1880 return false; //conservative for compile-only mode
1881 }
1882 final boolean isBuiltinFunction = instance.function == builtinFunction;
1883 return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
1884 }
1885
1886 /**
1887 * Check if the Function.prototype.apply has not been replaced
1888 * @return true if Function.prototype.apply has been replaced
1889 */
1890 public static boolean isBuiltinFunctionPrototypeApply() {
1891 return isBuiltinFunctionProperty("apply");
1892 }
1893
1894 /**
1895 * Check if the Function.prototype.apply has not been replaced
1896 * @return true if Function.prototype.call has been replaced
1897 */
1898 public static boolean isBuiltinFunctionPrototypeCall() {
1899 return isBuiltinFunctionProperty("call");
1900 }
1901
1902 private synchronized ScriptFunction getBuiltinJSAdapter() {
1903 if (this.builtinJSAdapter == null) {
1904 this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
1905 }
1906 return builtinJSAdapter;
1907 }
1908
1909 /**
1910 * Called from compiled script code to test if builtin has been overridden
1911 *
1912 * @return true if builtin JSAdapter has not been overridden
1913 */
1914 public static boolean isBuiltinJSAdapter() {
1915 final Global instance = Global.instance();
1916 return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter();
1917 }
1918
1919 private synchronized ScriptObject getBuiltinJSON() {
1920 if (this.builtinJSON == null) {
1921 this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
1922 }
1923 return this.builtinJSON;
1924 }
1925
1926 /**
1927 * Called from compiled script code to test if builtin has been overridden
1928 *
1929 * @return true if builtin JSON has has not been overridden
1930 */
1931 public static boolean isBuiltinJSON() {
1932 final Global instance = Global.instance();
1933 return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON();
1934 }
1935
1936 private ScriptObject getBuiltinJava() {
1937 return builtinJava;
1938 }
1939
1940 /**
1941 * Called from compiled script code to test if builtin has been overridden
1942 *
1943 * @return true if builtin Java has not been overridden
1944 */
1945 public static boolean isBuiltinJava() {
1946 final Global instance = Global.instance();
1947 return instance.java == instance.getBuiltinJava();
1948 }
1949
1950 private ScriptObject getBuiltinJavax() {
1951 return builtinJavax;
1952 }
1953
1954 /**
1955 * Called from compiled script code to test if builtin has been overridden
1956 *
1957 * @return true if builtin Javax has not been overridden
1958 */
1959 public static boolean isBuiltinJavax() {
1960 final Global instance = Global.instance();
1961 return instance.javax == instance.getBuiltinJavax();
1962 }
1963
1964 private synchronized ScriptFunction getBuiltinJavaImporter() {
1965 if (this.builtinJavaImporter == null) {
1966 this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
1967 }
1968 return this.builtinJavaImporter;
1969 }
1970
1971 private synchronized ScriptObject getBuiltinJavaApi() {
1972 if (this.builtinJavaApi == null) {
1973 this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
1974 }
1975 return this.builtinJavaApi;
1976 }
1977
1978 /**
1979 * Called from compiled script code to test if builtin has been overridden
1980 *
1981 * @return true if builtin Java importer has not been overridden
1982 */
1983 public static boolean isBuiltinJavaImporter() {
1984 final Global instance = Global.instance();
1985 return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter();
1986 }
1987
1988 /**
1989 * Called from compiled script code to test if builtin has been overridden
1990 *
1991 * @return true if builtin math has not been overridden
1992 */
1993 public static boolean isBuiltinMath() {
1994 final Global instance = Global.instance();
1995 return instance.math == instance.builtinMath;
1996 }
1997
1998 private ScriptFunction getBuiltinNumber() {
1999 return builtinNumber;
2000 }
2001
2002 /**
2003 * Called from compiled script code to test if builtin has been overridden
2004 *
2005 * @return true if builtin number has not been overridden
2006 */
2007 public static boolean isBuiltinNumber() {
2008 final Global instance = Global.instance();
2009 return instance.number == instance.getBuiltinNumber();
2010 }
2011
2012 private ScriptFunction getBuiltinObject() {
2013 return builtinObject;
2014 }
2015
2016 /**
2017 * Called from compiled script code to test if builtin has been overridden
2018 *
2019 * @return true if builtin object has not been overridden
2020 */
2021 public static boolean isBuiltinObject() {
2022 final Global instance = Global.instance();
2023 return instance.object == instance.getBuiltinObject();
2024 }
2025
2026 private ScriptObject getBuiltinPackages() {
2027 return builtinPackages;
2028 }
2029
2030 /**
2031 * Called from compiled script code to test if builtin has been overridden
2032 *
2033 * @return true if builtin package has not been overridden
2034 */
2035 public static boolean isBuiltinPackages() {
2036 final Global instance = Global.instance();
2037 return instance.packages == instance.getBuiltinPackages();
2038 }
2039
2040 private synchronized ScriptFunction getBuiltinRangeError() {
2041 if (this.builtinRangeError == null) {
2042 this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
2043 }
2044 return builtinRangeError;
2045 }
2046
2047 /**
2048 * Called from compiled script code to test if builtin has been overridden
2049 *
2050 * @return true if builtin range error has not been overridden
2051 */
2052 public static boolean isBuiltinRangeError() {
2053 final Global instance = Global.instance();
2054 return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError();
2055 }
2056
2057 private synchronized ScriptFunction getBuiltinReferenceError() {
2058 return builtinReferenceError;
2059 }
2060
2061 /**
2062 * Called from compiled script code to test if builtin has been overridden
2063 *
2064 * @return true if builtin reference error has not been overridden
2065 */
2066 public static boolean isBuiltinReferenceError() {
2067 final Global instance = Global.instance();
2068 return instance.referenceError == instance.getBuiltinReferenceError();
2069 }
2070
2071 private synchronized ScriptFunction getBuiltinRegExp() {
2072 if (this.builtinRegExp == null) {
2073 this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
2074 final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
2075 // initialize default regexp object
2076 this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
2077 // RegExp.prototype should behave like a RegExp object. So copy the
2078 // properties.
2079 regExpProto.addBoundProperties(DEFAULT_REGEXP);
2080 }
2081 return builtinRegExp;
2082 }
2083
2084 /**
2085 * Called from compiled script code to test if builtin has been overridden
2086 *
2087 * @return true if builtin regexp has not been overridden
2088 */
2089 public static boolean isBuiltinRegExp() {
2090 final Global instance = Global.instance();
2091 return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp();
2092 }
2093
2094 private ScriptFunction getBuiltinString() {
2095 return builtinString;
2096 }
2097
2098 /**
2099 * Called from compiled script code to test if builtin has been overridden
2100 *
2101 * @return true if builtin Java has not been overridden
2102 */
2103 public static boolean isBuiltinString() {
2104 final Global instance = Global.instance();
2105 return instance.string == instance.getBuiltinString();
2106 }
2107
2108 private ScriptFunction getBuiltinSyntaxError() {
2109 return builtinSyntaxError;
2110 }
2111
2112 /**
2113 * Called from compiled script code to test if builtin has been overridden
2114 *
2115 * @return true if builtin syntax error has not been overridden
2116 */
2117 public static boolean isBuiltinSyntaxError() {
2118 final Global instance = Global.instance();
2119 return instance.syntaxError == instance.getBuiltinSyntaxError();
2120 }
2121
2122 private ScriptFunction getBuiltinTypeError() {
2123 return builtinTypeError;
2124 }
2125
2126 /**
2127 * Called from compiled script code to test if builtin has been overridden
2128 *
2129 * @return true if builtin type error has not been overridden
2130 */
2131 public static boolean isBuiltinTypeError() {
2132 final Global instance = Global.instance();
2133 return instance.typeError == instance.getBuiltinTypeError();
2134 }
2135
2136 private synchronized ScriptFunction getBuiltinURIError() {
2137 if (this.builtinURIError == null) {
2138 this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
2139 }
2140 return this.builtinURIError;
2141 }
2142
2143 /**
2144 * Called from compiled script code to test if builtin has been overridden
2145 *
2146 * @return true if builtin URI error has not been overridden
2147 */
2148 public static boolean isBuiltinURIError() {
2149 final Global instance = Global.instance();
2150 return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError();
2151 }
2152
2153 @Override
2154 public String getClassName() {
2155 return "global";
2156 }
2157
2158 /**
2159 * Copy function used to clone NativeRegExp objects.
2160 *
2161 * @param regexp a NativeRegExp to clone
2162 *
2163 * @return copy of the given regexp object
2164 */
2165 public static Object regExpCopy(final Object regexp) {
2166 return new NativeRegExp((NativeRegExp)regexp);
2167 }
2168
2169 /**
2170 * Convert given object to NativeRegExp type.
2171 *
2172 * @param obj object to be converted
2173 * @return NativeRegExp instance
2174 */
2175 public static NativeRegExp toRegExp(final Object obj) {
2176 if (obj instanceof NativeRegExp) {
2177 return (NativeRegExp)obj;
2178 }
2179 return new NativeRegExp(JSType.toString(obj));
2180 }
2181
2182 /**
2183 * ECMA 9.9 ToObject implementation
2184 *
2185 * @param obj an item for which to run ToObject
2186 * @return ToObject version of given item
2187 */
2188 public static Object toObject(final Object obj) {
2189 if (obj == null || obj == UNDEFINED) {
2190 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2191 }
2192
2193 if (obj instanceof ScriptObject) {
2194 return obj;
2195 }
2196
2197 return instance().wrapAsObject(obj);
2198 }
2199
2200 /**
2201 * Allocate a new object array.
2202 *
2203 * @param initial object values.
2204 * @return the new array
2205 */
2206 public static NativeArray allocate(final Object[] initial) {
2207 ArrayData arrayData = ArrayData.allocate(initial);
2208
2209 for (int index = 0; index < initial.length; index++) {
2210 final Object value = initial[index];
2211
2212 if (value == ScriptRuntime.EMPTY) {
2213 arrayData = arrayData.delete(index);
2214 }
2215 }
2216
2217 return new NativeArray(arrayData);
2218 }
2219
2220 /**
2221 * Allocate a new number array.
2222 *
2223 * @param initial number values.
2224 * @return the new array
2225 */
2226 public static NativeArray allocate(final double[] initial) {
2227 return new NativeArray(ArrayData.allocate(initial));
2228 }
2229
2230 /**
2231 * Allocate a new long array.
2232 *
2233 * @param initial number values.
2234 * @return the new array
2235 */
2236 public static NativeArray allocate(final long[] initial) {
2237 return new NativeArray(ArrayData.allocate(initial));
2238 }
2239
2240 /**
2241 * Allocate a new integer array.
2242 *
2243 * @param initial number values.
2244 * @return the new array
2245 */
2246 public static NativeArray allocate(final int[] initial) {
2247 return new NativeArray(ArrayData.allocate(initial));
2248 }
2249
2250 /**
2251 * Allocate a new object array for arguments.
2252 *
2253 * @param arguments initial arguments passed.
2254 * @param callee reference to the function that uses arguments object
2255 * @param numParams actual number of declared parameters
2256 *
2257 * @return the new array
2258 */
2259 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
2260 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
2261 }
2262
2263 /**
2264 * Called from generated to check if given function is the builtin 'eval'. If
2265 * eval is used in a script, a lot of optimizations and assumptions cannot be done.
2266 *
2267 * @param fn function object that is checked
2268 * @return true if fn is the builtin eval
2269 */
2270 public static boolean isEval(final Object fn) {
2271 return fn == Global.instance().builtinEval;
2272 }
2273
2274 /**
2275 * Called from generated to replace a location property placeholder with the actual location property value.
2276 *
2277 * @param placeholder the value tested for being a placeholder for a location property
2278 * @param locationProperty the actual value for the location property
2279 * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
2280 */
2281 public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
2282 return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
2283 }
2284
2285 /**
2286 * Called from runtime internals to check if the passed value is a location property placeholder.
2287 * @param placeholder the value tested for being a placeholder for a location property
2288 * @return true if the value is a placeholder, false otherwise.
2289 */
2290 public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
2291 return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
2292 }
2293
2294 /**
2295 * Create a new RegExp object.
2296 *
2297 * @param expression Regular expression.
2298 * @param options Search options.
2299 *
2300 * @return New RegExp object.
2301 */
2302 public static Object newRegExp(final String expression, final String options) {
2303 if (options == null) {
2304 return new NativeRegExp(expression);
2305 }
2306 return new NativeRegExp(expression, options);
2307 }
2308
2309 /**
2310 * Get the object prototype
2311 *
2312 * @return the object prototype
2313 */
2314 public static ScriptObject objectPrototype() {
2315 return Global.instance().getObjectPrototype();
2316 }
2317
2318 /**
2319 * Create a new empty object instance.
2320 *
2321 * @return New empty object.
2322 */
2323 public static ScriptObject newEmptyInstance() {
2324 return Global.instance().newObject();
2325 }
2326
2327 /**
2328 * Check if a given object is a ScriptObject, raises an exception if this is
2329 * not the case
2330 *
2331 * @param obj and object to check
2332 * @return the script object
2333 */
2334 public static ScriptObject checkObject(final Object obj) {
2335 if (!(obj instanceof ScriptObject)) {
2336 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2337 }
2338 return (ScriptObject)obj;
2339 }
2340
2341 /**
2342 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
2343 * if this object is null or undefined.
2344 *
2345 * @param obj an object to check
2346 */
2347 public static void checkObjectCoercible(final Object obj) {
2348 if (obj == null || obj == UNDEFINED) {
2349 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2350 }
2351 }
2352
2353 /**
2354 * Return the ES6 global scope for lexically declared bindings.
2355 * @return the ES6 lexical global scope.
2356 */
2357 public final ScriptObject getLexicalScope() {
2358 assert context.getEnv()._es6;
2359 return lexicalScope;
2360 }
2361
2362 @Override
2363 public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
2364 PropertyMap ownMap = getMap();
2365 LexicalScope lexScope = null;
2366 PropertyMap lexicalMap = null;
2367 boolean hasLexicalDefinitions = false;
2368
2369 if (context.getEnv()._es6) {
2370 lexScope = (LexicalScope) getLexicalScope();
2371 lexicalMap = lexScope.getMap();
2372
2373 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2374 if (property.isLexicalBinding()) {
2375 hasLexicalDefinitions = true;
2376 }
2377 // ES6 15.1.8 steps 6. and 7.
2378 final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
2379 if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
2380 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2381 }
2382 final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
2383 if (lexicalProperty != null && !property.isConfigurable()) {
2384 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2385 }
2386 }
2387 }
2388
2389 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2390 if (property.isLexicalBinding()) {
2391 assert lexScope != null;
2392 lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property);
2393
2394 if (ownMap.findProperty(property.getKey()) != null) {
2395 // If property exists in the global object invalidate any global constant call sites.
2396 invalidateGlobalConstant(property.getKey());
2397 }
2398 } else {
2399 ownMap = addBoundProperty(ownMap, source, property);
2400 }
2401 }
2402
2403 setMap(ownMap);
2404
2405 if (hasLexicalDefinitions) {
2406 assert lexScope != null;
2407 lexScope.setMap(lexicalMap);
2408 invalidateLexicalSwitchPoint();
2409 }
2410 }
2411
2412 @Override
2413 public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2414 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2415 final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2416
2417 if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
2418 if (lexicalScope.hasOwnProperty(name)) {
2419 return lexicalScope.findGetMethod(desc, request, operator);
2420 }
2421 }
2422
2423 final GuardedInvocation invocation = super.findGetMethod(desc, request, operator);
2424
2425 // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
2426 // because those are invalidated per-key in the addBoundProperties method above.
2427 // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
2428 // assuming this only applies to global constants. If other non-inherited properties will
2429 // start using switchpoints some time in the future we'll have to revisit this.
2430 if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
2431 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2432 }
2433
2434 return invocation;
2435 }
2436
2437 @Override
2438 protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
2439 if (lexicalScope != null && start != this && start.isScope()) {
2440 final FindProperty find = lexicalScope.findProperty(key, false);
2441 if (find != null) {
2442 return find;
2443 }
2444 }
2445 return super.findProperty(key, deep, start);
2446 }
2447
2448 @Override
2449 public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2450 final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2451
2452 if (lexicalScope != null && isScope) {
2453 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2454 if (lexicalScope.hasOwnProperty(name)) {
2455 return lexicalScope.findSetMethod(desc, request);
2456 }
2457 }
2458
2459 final GuardedInvocation invocation = super.findSetMethod(desc, request);
2460
2461 if (isScope && context.getEnv()._es6) {
2462 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2463 }
2464
2465 return invocation;
2466 }
2467
2468 /**
2469 * Adds jjs shell interactive mode builtin functions to global scope.
2470 */
2471 public void addShellBuiltins() {
2472 Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT);
2473 addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
2474
2475 value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT);
2476 addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
2477 }
2478
2479 private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
2480 SwitchPoint switchPoint = lexicalScopeSwitchPoint;
2481 if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
2482 switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
2483 }
2484 return switchPoint;
2485 }
2486
2487 private synchronized void invalidateLexicalSwitchPoint() {
2488 if (lexicalScopeSwitchPoint != null) {
2489 context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
2490 SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
2491 }
2492 }
2493
2494
2495 @SuppressWarnings("unused")
2496 private static Object lexicalScopeFilter(final Object self) {
2497 if (self instanceof Global) {
2498 return ((Global) self).getLexicalScope();
2499 }
2500 return self;
2501 }
2502
2503 private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
2504 final T func = initConstructor(name, clazz);
2505 tagBuiltinProperties(name, func);
2506 return func;
2507 }
2508
2509 private void init(final ScriptEngine eng) {
2510 assert Context.getGlobal() == this : "this global is not set as current";
2511
2512 final ScriptEnvironment env = getContext().getEnv();
2513
2514 // initialize Function and Object constructor
2515 initFunctionAndObject();
2516
2517 // Now fix Global's own proto.
2518 this.setInitialProto(getObjectPrototype());
2519
2520 // initialize global function properties
2521 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
2522
2523 this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT,
2524 new Specialization[] {
2525 new Specialization(GlobalFunctions.PARSEINT_Z),
2526 new Specialization(GlobalFunctions.PARSEINT_I),
2527 new Specialization(GlobalFunctions.PARSEINT_J),
2528 new Specialization(GlobalFunctions.PARSEINT_OI),
2529 new Specialization(GlobalFunctions.PARSEINT_O) });
2530 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2531 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN,
2532 new Specialization[] {
2533 new Specialization(GlobalFunctions.IS_NAN_I),
2534 new Specialization(GlobalFunctions.IS_NAN_J),
2535 new Specialization(GlobalFunctions.IS_NAN_D) });
2536 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2537 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN);
2538 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE);
2539 this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI);
2540 this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
2541 this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI);
2542 this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
2543 this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE);
2544 this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
2545 this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN);
2546 this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
2547 this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
2548 this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT);
2549 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
2550
2551 // built-in constructors
2552 this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
2553 this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
2554 this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
2555 this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class);
2556 this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class);
2557
2558 // initialize String.prototype.length to 0
2559 // add String.prototype.length
2560 final ScriptObject stringPrototype = getStringPrototype();
2561 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
2562
2563 // set isArray flag on Array.prototype
2564 final ScriptObject arrayPrototype = getArrayPrototype();
2565 arrayPrototype.setIsArray();
2566
2567 // Error stuff
2568 initErrorObjects();
2569
2570 // java access
2571 if (! env._no_java) {
2572 this.javaApi = LAZY_SENTINEL;
2573 this.javaImporter = LAZY_SENTINEL;
2574 initJavaAccess();
2575 }
2576
2577 if (! env._no_typed_arrays) {
2578 this.arrayBuffer = LAZY_SENTINEL;
2579 this.dataView = LAZY_SENTINEL;
2580 this.int8Array = LAZY_SENTINEL;
2581 this.uint8Array = LAZY_SENTINEL;
2582 this.uint8ClampedArray = LAZY_SENTINEL;
2583 this.int16Array = LAZY_SENTINEL;
2584 this.uint16Array = LAZY_SENTINEL;
2585 this.int32Array = LAZY_SENTINEL;
2586 this.uint32Array = LAZY_SENTINEL;
2587 this.float32Array = LAZY_SENTINEL;
2588 this.float64Array = LAZY_SENTINEL;
2589 }
2590
2591 if (env._scripting) {
2592 initScripting(env);
2593 }
2594
2595 if (Context.DEBUG) {
2596 boolean debugOkay;
2597 final SecurityManager sm = System.getSecurityManager();
2598 if (sm != null) {
2599 try {
2600 sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
2601 debugOkay = true;
2602 } catch (final SecurityException ignored) {
2603 // if no permission, don't initialize Debug object
2604 debugOkay = false;
2605 }
2606
2607 } else {
2608 debugOkay = true;
2609 }
2610
2611 if (debugOkay) {
2612 initDebug();
2613 }
2614 }
2615
2616 copyBuiltins();
2617
2618 // expose script (command line) arguments as "arguments" property of global
2619 arguments = wrapAsObject(env.getArguments().toArray());
2620 if (env._scripting) {
2621 // synonym for "arguments" in scripting mode
2622 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
2623 }
2624
2625 if (eng != null) {
2626 // default file name
2627 addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
2628 // __noSuchProperty__ hook for ScriptContext search of missing variables
2629 final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
2630 addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
2631 }
2632 }
2633
2634 private void initErrorObjects() {
2635 // Error objects
2636 this.builtinError = initConstructor("Error", ScriptFunction.class);
2637 final ScriptObject errorProto = getErrorPrototype();
2638
2639 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
2640 final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
2641 final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
2642 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
2643 final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
2644 final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
2645 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
2646 final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
2647 final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
2648 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
2649 final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
2650 final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
2651 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
2652
2653 // ECMA 15.11.4.2 Error.prototype.name
2654 // Error.prototype.name = "Error";
2655 errorProto.set(NativeError.NAME, "Error", 0);
2656 // ECMA 15.11.4.3 Error.prototype.message
2657 // Error.prototype.message = "";
2658 errorProto.set(NativeError.MESSAGE, "", 0);
2659
2660 tagBuiltinProperties("Error", builtinError);
2661
2662 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2663 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2664 this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
2665 }
2666
2667 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2668 final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2669 final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2670 prototype.set(NativeError.NAME, name, 0);
2671 prototype.set(NativeError.MESSAGE, "", 0);
2672 prototype.setInitialProto(errorProto);
2673 tagBuiltinProperties(name, cons);
2674 return cons;
2675 }
2676
2677 private void initJavaAccess() {
2678 final ScriptObject objectProto = getObjectPrototype();
2679 this.builtinPackages = new NativeJavaPackage("", objectProto);
2680 this.builtinCom = new NativeJavaPackage("com", objectProto);
2681 this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2682 this.builtinJava = new NativeJavaPackage("java", objectProto);
2683 this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2684 this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2685 this.builtinOrg = new NativeJavaPackage("org", objectProto);
2686 }
2687
2688 private void initScripting(final ScriptEnvironment scriptEnv) {
2689 Object value;
2690 value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
2691 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2692
2693 value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
2694 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2695
2696 final String execName = ScriptingFunctions.EXEC_NAME;
2697 value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
2698 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2699
2700 // Nashorn extension: global.echo (scripting-mode-only)
2701 // alias for "print"
2702 value = get("print");
2703 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2704
2705 // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2706 final ScriptObject options = newObject();
2707 copyOptions(options, scriptEnv);
2708 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2709
2710 // Nashorn extension: global.$ENV (scripting-mode-only)
2711 if (System.getSecurityManager() == null) {
2712 // do not fill $ENV if we have a security manager around
2713 // Retrieve current state of ENV variables.
2714 final ScriptObject env = newObject();
2715 env.putAll(System.getenv(), scriptEnv._strict);
2716
2717 // Some platforms, e.g., Windows, do not define the PWD environment
2718 // variable, so that the $ENV.PWD property needs to be explicitly
2719 // set.
2720 if (!env.containsKey(ScriptingFunctions.PWD_NAME)) {
2721 env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict);
2722 }
2723
2724 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2725 } else {
2726 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2727 }
2728
2729 // add other special properties for exec support
2730 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2731 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2732 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2733 }
2734
2735 private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2736 for (final Field f : scriptEnv.getClass().getFields()) {
2737 try {
2738 options.set(f.getName(), f.get(scriptEnv), 0);
2739 } catch (final IllegalArgumentException | IllegalAccessException exp) {
2740 throw new RuntimeException(exp);
2741 }
2742 }
2743 }
2744
2745 private void copyBuiltins() {
2746 this.array = this.builtinArray;
2747 this._boolean = this.builtinBoolean;
2748 this.error = this.builtinError;
2749 this.function = this.builtinFunction;
2750 this.com = this.builtinCom;
2751 this.edu = this.builtinEdu;
2752 this.java = this.builtinJava;
2753 this.javafx = this.builtinJavafx;
2754 this.javax = this.builtinJavax;
2755 this.org = this.builtinOrg;
2756 this.math = this.builtinMath;
2757 this.number = this.builtinNumber;
2758 this.object = this.builtinObject;
2759 this.packages = this.builtinPackages;
2760 this.referenceError = this.builtinReferenceError;
2761 this.string = this.builtinString;
2762 this.syntaxError = this.builtinSyntaxError;
2763 this.typeError = this.builtinTypeError;
2764 }
2765
2766 private void initDebug() {
2767 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2768 }
2769
2770 private Object printImpl(final boolean newLine, final Object... objects) {
2771 final ScriptContext sc = currentContext();
2772 @SuppressWarnings("resource")
2773 final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut();
2774 final StringBuilder sb = new StringBuilder();
2775
2776 for (final Object obj : objects) {
2777 if (sb.length() != 0) {
2778 sb.append(' ');
2779 }
2780
2781 sb.append(JSType.toString(obj));
2782 }
2783
2784 // Print all at once to ensure thread friendly result.
2785 if (newLine) {
2786 out.println(sb.toString());
2787 } else {
2788 out.print(sb.toString());
2789 }
2790
2791 out.flush();
2792
2793 return UNDEFINED;
2794 }
2795
2796 private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2797 try {
2798 // Assuming class name pattern for built-in JS constructors.
2799 final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2800
2801 sb.append("Native");
2802 sb.append(name);
2803 sb.append("$Constructor");
2804
2805 final Class<?> funcClass = Class.forName(sb.toString());
2806 final T res = clazz.cast(funcClass.newInstance());
2807
2808 if (res instanceof ScriptFunction) {
2809 // All global constructor prototypes are not-writable,
2810 // not-enumerable and not-configurable.
2811 final ScriptFunction func = (ScriptFunction)res;
2812 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2813 }
2814
2815 if (res.getProto() == null) {
2816 res.setInitialProto(getObjectPrototype());
2817 }
2818
2819 res.setIsBuiltin();
2820
2821 return res;
2822 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2823 throw new RuntimeException(e);
2824 }
2825 }
2826
2827 private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2828 final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2829
2830 list.addAll(Arrays.asList(func.getMap().getProperties()));
2831
2832 if (func instanceof ScriptFunction) {
2833 final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2834 if (proto != null) {
2835 list.addAll(Arrays.asList(proto.getMap().getProperties()));
2836 }
2837 }
2838
2839 final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2840 if (prop != null) {
2841 list.add(prop);
2842 }
2843
2844 return list;
2845 }
2846
2847 /**
2848 * Given a builtin object, traverse its properties recursively and associate them with a name that
2849 * will be a key to their invalidation switchpoint.
2850 * @param name name for key
2851 * @param func builtin script object
2852 */
2853 private void tagBuiltinProperties(final String name, final ScriptObject func) {
2854 SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2855 if (sp == null) {
2856 sp = context.newBuiltinSwitchPoint(name);
2857 }
2858
2859 //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2860 //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2861 for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2862 prop.setBuiltinSwitchPoint(sp);
2863 }
2864 }
2865
2866 // Function and Object constructors are inter-dependent. Also,
2867 // Function.prototype
2868 // functions are not properly initialized. We fix the references here.
2869 // NOTE: be careful if you want to re-order the operations here. You may
2870 // have
2871 // to play with object references carefully!!
2872 private void initFunctionAndObject() {
2873 // First-n-foremost is Function
2874
2875 this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2876
2877 // create global anonymous function
2878 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2879 // need to copy over members of Function.prototype to anon function
2880 anon.addBoundProperties(getFunctionPrototype());
2881
2882 // Function.prototype === Object.getPrototypeOf(Function) ===
2883 // <anon-function>
2884 builtinFunction.setInitialProto(anon);
2885 builtinFunction.setPrototype(anon);
2886 anon.set("constructor", builtinFunction, 0);
2887 anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2888
2889 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2890 this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2891 typeErrorThrower.setPrototype(UNDEFINED);
2892 // Non-constructor built-in functions do not have "prototype" property
2893 typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2894 typeErrorThrower.preventExtensions();
2895
2896 // now initialize Object
2897 this.builtinObject = initConstructor("Object", ScriptFunction.class);
2898 final ScriptObject ObjectPrototype = getObjectPrototype();
2899 // Object.getPrototypeOf(Function.prototype) === Object.prototype
2900 anon.setInitialProto(ObjectPrototype);
2901
2902 // ES6 draft compliant __proto__ property of Object.prototype
2903 // accessors on Object.prototype for "__proto__"
2904 final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2905 final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2906 ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2907
2908 // Function valued properties of Function.prototype were not properly
2909 // initialized. Because, these were created before global.function and
2910 // global.object were not initialized.
2911 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2912 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2913 final Object key = property.getKey();
2914 final Object value = builtinFunction.get(key);
2915
2916 if (value instanceof ScriptFunction && value != anon) {
2917 final ScriptFunction func = (ScriptFunction)value;
2918 func.setInitialProto(getFunctionPrototype());
2919 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2920 if (prototype != null) {
2921 prototype.setInitialProto(ObjectPrototype);
2922 }
2923 }
2924 }
2925
2926 // For function valued properties of Object and Object.prototype, make
2927 // sure prototype's proto chain ends with Object.prototype
2928 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2929 final Object key = property.getKey();
2930 final Object value = builtinObject.get(key);
2931
2932 if (value instanceof ScriptFunction) {
2933 final ScriptFunction func = (ScriptFunction)value;
2934 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2935 if (prototype != null) {
2936 prototype.setInitialProto(ObjectPrototype);
2937 }
2938 }
2939 }
2940
2941 properties = getObjectPrototype().getMap().getProperties();
2942
2943 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2944 final Object key = property.getKey();
2945 if (key.equals("constructor")) {
2946 continue;
2947 }
2948
2949 final Object value = ObjectPrototype.get(key);
2950 if (value instanceof ScriptFunction) {
2951 final ScriptFunction func = (ScriptFunction)value;
2952 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2953 if (prototype != null) {
2954 prototype.setInitialProto(ObjectPrototype);
2955 }
2956 }
2957 }
2958
2959 tagBuiltinProperties("Object", builtinObject);
2960 tagBuiltinProperties("Function", builtinFunction);
2961 tagBuiltinProperties("Function", anon);
2962 }
2963
2964 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2965 return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2966 }
2967
2968 RegExpResult getLastRegExpResult() {
2969 return lastRegExpResult;
2970 }
2971
2972 void setLastRegExpResult(final RegExpResult regExpResult) {
2973 this.lastRegExpResult = regExpResult;
2974 }
2975
2976 @Override
2977 protected boolean isGlobal() {
2978 return true;
2979 }
2980
2981 /**
2982 * A class representing the ES6 global lexical scope.
2983 */
2984 private static class LexicalScope extends ScriptObject {
2985
2986 LexicalScope(final Global global) {
2987 super(global, PropertyMap.newMap());
2988 }
2989
2990 @Override
2991 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2992 return filterInvocation(super.findGetMethod(desc, request, operator));
2993 }
2994
2995 @Override
2996 protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2997 return filterInvocation(super.findSetMethod(desc, request));
2998 }
2999
3000 @Override
3001 protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
3002 // We override this method just to make it callable by Global
3003 return super.addBoundProperty(propMap, source, property);
3004 }
3005
3006 private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
3007 final MethodType type = invocation.getInvocation().type();
3008 return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
3009 }
3010 }
3011
3012 }
--- EOF ---