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