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.typeError;
30 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
31
32 import java.io.IOException;
33 import java.io.PrintWriter;
34 import java.lang.invoke.MethodHandle;
35 import java.lang.invoke.MethodHandles;
36 import java.lang.ref.ReferenceQueue;
37 import java.lang.ref.SoftReference;
38 import java.lang.reflect.Field;
39 import java.util.Arrays;
40 import java.util.LinkedHashMap;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.concurrent.Callable;
44 import java.util.concurrent.ConcurrentHashMap;
45 import jdk.internal.dynalink.linker.GuardedInvocation;
46 import jdk.internal.dynalink.linker.LinkRequest;
47 import jdk.nashorn.internal.lookup.Lookup;
48 import jdk.nashorn.internal.objects.annotations.Attribute;
49 import jdk.nashorn.internal.objects.annotations.Property;
50 import jdk.nashorn.internal.objects.annotations.ScriptClass;
51 import jdk.nashorn.internal.runtime.ConsString;
52 import jdk.nashorn.internal.runtime.Context;
53 import jdk.nashorn.internal.runtime.GlobalFunctions;
54 import jdk.nashorn.internal.runtime.GlobalObject;
55 import jdk.nashorn.internal.runtime.JSType;
56 import jdk.nashorn.internal.runtime.NativeJavaPackage;
57 import jdk.nashorn.internal.runtime.PropertyDescriptor;
58 import jdk.nashorn.internal.runtime.PropertyMap;
59 import jdk.nashorn.internal.runtime.Scope;
60 import jdk.nashorn.internal.runtime.ScriptEnvironment;
61 import jdk.nashorn.internal.runtime.ScriptFunction;
62 import jdk.nashorn.internal.runtime.ScriptObject;
63 import jdk.nashorn.internal.runtime.ScriptRuntime;
64 import jdk.nashorn.internal.runtime.ScriptingFunctions;
65 import jdk.nashorn.internal.runtime.Source;
66 import jdk.nashorn.internal.runtime.arrays.ArrayData;
67 import jdk.nashorn.internal.runtime.linker.Bootstrap;
68 import jdk.nashorn.internal.runtime.linker.InvokeByName;
69 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
70 import jdk.nashorn.internal.scripts.JO;
71
72 /**
73 * Representation of global scope.
74 */
75 @ScriptClass("Global")
76 public final class Global extends ScriptObject implements GlobalObject, Scope {
77 private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
78 private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class);
79
80 /** ECMA 15.1.2.2 parseInt (string , radix) */
81 @Property(attributes = Attribute.NOT_ENUMERABLE)
82 public Object parseInt;
83
84 /** ECMA 15.1.2.3 parseFloat (string) */
85 @Property(attributes = Attribute.NOT_ENUMERABLE)
86 public Object parseFloat;
87
88 /** ECMA 15.1.2.4 isNaN (number) */
89 @Property(attributes = Attribute.NOT_ENUMERABLE)
90 public Object isNaN;
91
92 /** ECMA 15.1.2.5 isFinite (number) */
93 @Property(attributes = Attribute.NOT_ENUMERABLE)
94 public Object isFinite;
95
96 /** ECMA 15.1.3.3 encodeURI */
97 @Property(attributes = Attribute.NOT_ENUMERABLE)
98 public Object encodeURI;
99
100 /** ECMA 15.1.3.4 encodeURIComponent */
101 @Property(attributes = Attribute.NOT_ENUMERABLE)
102 public Object encodeURIComponent;
103
104 /** ECMA 15.1.3.1 decodeURI */
105 @Property(attributes = Attribute.NOT_ENUMERABLE)
106 public Object decodeURI;
107
108 /** ECMA 15.1.3.2 decodeURIComponent */
109 @Property(attributes = Attribute.NOT_ENUMERABLE)
110 public Object decodeURIComponent;
111
112 /** ECMA B.2.1 escape (string) */
113 @Property(attributes = Attribute.NOT_ENUMERABLE)
114 public Object escape;
115
116 /** ECMA B.2.2 unescape (string) */
117 @Property(attributes = Attribute.NOT_ENUMERABLE)
118 public Object unescape;
119
120 /** Nashorn extension: global.print */
121 @Property(attributes = Attribute.NOT_ENUMERABLE)
122 public Object print;
123
124 /** Nashorn extension: global.load */
125 @Property(attributes = Attribute.NOT_ENUMERABLE)
126 public Object load;
127
128 /** Nashorn extension: global.loadWithNewGlobal */
129 @Property(attributes = Attribute.NOT_ENUMERABLE)
130 public Object loadWithNewGlobal;
131
132 /** Nashorn extension: global.exit */
133 @Property(attributes = Attribute.NOT_ENUMERABLE)
134 public Object exit;
135
136 /** Nashorn extension: global.quit */
137 @Property(attributes = Attribute.NOT_ENUMERABLE)
138 public Object quit;
139
140 /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
141 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
142 public final Object NaN = Double.NaN;
143
144 /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
145 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
146 public final Object Infinity = Double.POSITIVE_INFINITY;
147
148 /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
149 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
150 public final Object undefined = UNDEFINED;
151
152 /** ECMA 15.1.2.1 eval(x) */
153 @Property(attributes = Attribute.NOT_ENUMERABLE)
154 public Object eval;
155
156 /** ECMA 15.1.4.1 Object constructor. */
157 @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
158 public volatile Object object;
159
160 /** ECMA 15.1.4.2 Function constructor. */
161 @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
162 public volatile Object function;
163
164 /** ECMA 15.1.4.3 Array constructor. */
165 @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
166 public volatile Object array;
167
168 /** ECMA 15.1.4.4 String constructor */
169 @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
170 public volatile Object string;
171
172 /** ECMA 15.1.4.5 Boolean constructor */
173 @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
174 public volatile Object _boolean;
175
176 /** ECMA 15.1.4.6 - Number constructor */
177 @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
178 public volatile Object number;
179
180 /** ECMA 15.1.4.7 Date constructor */
181 @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
182 public volatile Object date;
183
184 /** ECMA 15.1.4.8 RegExp constructor */
185 @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
186 public volatile Object regexp;
187
188 /** ECMA 15.12 - The JSON object */
189 @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
190 public volatile Object json;
191
192 /** Nashorn extension: global.JSAdapter */
193 @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
194 public volatile Object jsadapter;
195
196 /** ECMA 15.8 - The Math object */
197 @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
198 public volatile Object math;
199
200 /** Error object */
201 @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
202 public volatile Object error;
203
204 /** EvalError object */
205 @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
206 public volatile Object evalError;
207
208 /** RangeError object */
209 @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
210 public volatile Object rangeError;
211
212 /** ReferenceError object */
213 @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
214 public volatile Object referenceError;
215
216 /** SyntaxError object */
217 @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
218 public volatile Object syntaxError;
219
220 /** TypeError object */
221 @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
222 public volatile Object typeError;
223
224 /** URIError object */
225 @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
226 public volatile Object uriError;
227
228 /** ArrayBuffer object */
229 @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
230 public volatile Object arrayBuffer;
231
232 /** TypedArray (int8) */
233 @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
234 public volatile Object int8Array;
235
236 /** TypedArray (uint8) */
237 @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
238 public volatile Object uint8Array;
239
240 /** TypedArray (uint8) - Clamped */
241 @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
242 public volatile Object uint8ClampedArray;
243
244 /** TypedArray (int16) */
245 @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
246 public volatile Object int16Array;
247
248 /** TypedArray (uint16) */
249 @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
250 public volatile Object uint16Array;
251
252 /** TypedArray (int32) */
253 @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
254 public volatile Object int32Array;
255
256 /** TypedArray (uint32) */
257 @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
258 public volatile Object uint32Array;
259
260 /** TypedArray (float32) */
261 @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
262 public volatile Object float32Array;
263
264 /** TypedArray (float64) */
265 @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
266 public volatile Object float64Array;
267
268 /** Nashorn extension: Java access - global.Packages */
269 @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
270 public volatile Object packages;
271
272 /** Nashorn extension: Java access - global.com */
273 @Property(attributes = Attribute.NOT_ENUMERABLE)
274 public volatile Object com;
275
276 /** Nashorn extension: Java access - global.edu */
277 @Property(attributes = Attribute.NOT_ENUMERABLE)
278 public volatile Object edu;
279
280 /** Nashorn extension: Java access - global.java */
281 @Property(attributes = Attribute.NOT_ENUMERABLE)
282 public volatile Object java;
283
284 /** Nashorn extension: Java access - global.javafx */
285 @Property(attributes = Attribute.NOT_ENUMERABLE)
286 public volatile Object javafx;
287
288 /** Nashorn extension: Java access - global.javax */
289 @Property(attributes = Attribute.NOT_ENUMERABLE)
290 public volatile Object javax;
291
292 /** Nashorn extension: Java access - global.org */
293 @Property(attributes = Attribute.NOT_ENUMERABLE)
294 public volatile Object org;
295
296 /** Nashorn extension: Java access - global.javaImporter */
297 @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
298 public volatile Object javaImporter;
299
300 /** Nashorn extension: global.Java Object constructor. */
301 @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
302 public volatile Object javaApi;
303
304 /** Nashorn extension: current script's file name */
305 @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
306 public Object __FILE__;
307
308 /** Nashorn extension: current script's directory */
309 @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
310 public Object __DIR__;
311
312 /** Nashorn extension: current source line number being executed */
313 @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
314 public Object __LINE__;
315
316 /** Used as Date.prototype's default value */
317 public NativeDate DEFAULT_DATE;
318
319 /** Used as RegExp.prototype's default value */
320 public NativeRegExp DEFAULT_REGEXP;
321
322 /*
323 * Built-in constructor objects: Even if user changes dynamic values of
324 * "Object", "Array" etc., we still want to keep original values of these
325 * constructors here. For example, we need to be able to create array,
326 * regexp literals even after user overwrites global "Array" or "RegExp"
327 * constructor - see also ECMA 262 spec. Annex D.
328 */
329 private ScriptFunction builtinFunction;
330 private ScriptFunction builtinObject;
331 private ScriptFunction builtinArray;
332 private ScriptFunction builtinBoolean;
333 private ScriptFunction builtinDate;
334 private ScriptObject builtinJSON;
335 private ScriptFunction builtinJSAdapter;
336 private ScriptObject builtinMath;
337 private ScriptFunction builtinNumber;
338 private ScriptFunction builtinRegExp;
339 private ScriptFunction builtinString;
340 private ScriptFunction builtinError;
341 private ScriptFunction builtinEval;
342 private ScriptFunction builtinEvalError;
343 private ScriptFunction builtinRangeError;
344 private ScriptFunction builtinReferenceError;
345 private ScriptFunction builtinSyntaxError;
346 private ScriptFunction builtinTypeError;
347 private ScriptFunction builtinURIError;
348 private ScriptObject builtinPackages;
349 private ScriptObject builtinCom;
350 private ScriptObject builtinEdu;
351 private ScriptObject builtinJava;
352 private ScriptObject builtinJavafx;
353 private ScriptObject builtinJavax;
354 private ScriptObject builtinOrg;
355 private ScriptObject builtinJavaImporter;
356 private ScriptObject builtinJavaApi;
357 private ScriptObject builtinArrayBuffer;
358 private ScriptObject builtinInt8Array;
359 private ScriptObject builtinUint8Array;
360 private ScriptObject builtinUint8ClampedArray;
361 private ScriptObject builtinInt16Array;
362 private ScriptObject builtinUint16Array;
363 private ScriptObject builtinInt32Array;
364 private ScriptObject builtinUint32Array;
365 private ScriptObject builtinFloat32Array;
366 private ScriptObject builtinFloat64Array;
367
368 /*
369 * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
370 */
371 private ScriptFunction typeErrorThrower;
372
373 private PropertyMap accessorPropertyDescriptorMap;
374 private PropertyMap arrayBufferViewMap;
375 private PropertyMap dataPropertyDescriptorMap;
376 private PropertyMap genericPropertyDescriptorMap;
377 private PropertyMap nativeArgumentsMap;
378 private PropertyMap nativeArrayMap;
379 private PropertyMap nativeArrayBufferMap;
380 private PropertyMap nativeBooleanMap;
381 private PropertyMap nativeDateMap;
382 private PropertyMap nativeErrorMap;
383 private PropertyMap nativeEvalErrorMap;
384 private PropertyMap nativeJSAdapterMap;
385 private PropertyMap nativeJavaImporterMap;
386 private PropertyMap nativeNumberMap;
387 private PropertyMap nativeRangeErrorMap;
388 private PropertyMap nativeReferenceErrorMap;
389 private PropertyMap nativeRegExpMap;
390 private PropertyMap nativeRegExpExecResultMap;
391 private PropertyMap nativeStrictArgumentsMap;
392 private PropertyMap nativeStringMap;
393 private PropertyMap nativeSyntaxErrorMap;
394 private PropertyMap nativeTypeErrorMap;
395 private PropertyMap nativeURIErrorMap;
396 private PropertyMap prototypeObjectMap;
397 private PropertyMap objectMap;
398 private PropertyMap functionMap;
399 private PropertyMap anonymousFunctionMap;
400 private PropertyMap strictFunctionMap;
401 private PropertyMap boundFunctionMap;
402
403 // Flag to indicate that a split method issued a return statement
404 private int splitState = -1;
405
406 // class cache
407 private ClassCache classCache;
408
409 // Used to store the last RegExp result to support deprecated RegExp constructor properties
410 private RegExpResult lastRegExpResult;
411
412 private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class);
413 private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class);
414 private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
415 private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class);
416 private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
417 private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
418
419 // initialized by nasgen
420 private static PropertyMap $nasgenmap$;
421
422 // context to which this global belongs to
423 private final Context context;
424
425 @Override
426 protected Context getContext() {
427 return context;
428 }
429
430 // performs initialization checks for Global constructor and returns the
431 // PropertyMap, if everything is fine.
432 private static PropertyMap checkAndGetMap(final Context context) {
433 // security check first
434 final SecurityManager sm = System.getSecurityManager();
435 if (sm != null) {
436 sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
437 }
438
439 // null check on context
440 context.getClass();
441
442 /*
443 * Duplicate global's map and use it. This way the initial Map filled
444 * by nasgen (referenced from static field in this class) is retained
445 * 'as is' (as that one is process wide singleton.
446 */
447 return $nasgenmap$.duplicate();
448 }
449
450 /**
451 * Constructor
452 *
453 * @param context the context
454 */
455 public Global(final Context context) {
456 super(checkAndGetMap(context));
457 this.context = context;
458 this.setIsScope();
459
460 final int cacheSize = context.getEnv()._class_cache_size;
461 if (cacheSize > 0) {
462 classCache = new ClassCache(cacheSize);
463 }
464 }
465
466 /**
467 * Script access to "current" Global instance
468 *
469 * @return the global singleton
470 */
471 public static Global instance() {
472 ScriptObject global = Context.getGlobal();
473 if (! (global instanceof Global)) {
474 throw new IllegalStateException("no current global instance");
475 }
476 return (Global)global;
477 }
478
479 /**
480 * Script access to {@link ScriptEnvironment}
481 *
482 * @return the script environment
483 */
484 static ScriptEnvironment getEnv() {
485 return instance().getContext().getEnv();
486 }
487
488 /**
489 * Script access to {@link Context}
490 *
491 * @return the context
492 */
493 static Context getThisContext() {
494 return instance().getContext();
495 }
496
497 // GlobalObject interface implementation
498
499 @Override
500 public boolean isOfContext(final Context ctxt) {
501 return this.context == ctxt;
502 }
503
504 @Override
505 public boolean isStrictContext() {
506 return context.getEnv()._strict;
507 }
508
509 @Override
510 public void initBuiltinObjects() {
511 if (this.builtinObject != null) {
512 // already initialized, just return
513 return;
514 }
515
516 init();
517 }
518
519 @Override
520 public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
521 return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
522 }
523
524 @Override
525 public Object wrapAsObject(final Object obj) {
526 if (obj instanceof Boolean) {
527 return new NativeBoolean((Boolean)obj, this);
528 } else if (obj instanceof Number) {
529 return new NativeNumber(((Number)obj).doubleValue(), this);
530 } else if (obj instanceof String || obj instanceof ConsString) {
531 return new NativeString((CharSequence)obj, this);
532 } else if (obj instanceof Object[]) { // extension
533 return new NativeArray((Object[])obj);
534 } else if (obj instanceof double[]) { // extension
535 return new NativeArray((double[])obj);
536 } else if (obj instanceof long[]) {
537 return new NativeArray((long[])obj);
538 } else if (obj instanceof int[]) {
539 return new NativeArray((int[])obj);
540 } else {
541 // FIXME: more special cases? Map? List?
542 return obj;
543 }
544 }
545
546 @Override
547 public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
548 if (self instanceof String || self instanceof ConsString) {
549 return NativeString.lookupPrimitive(request, self);
550 } else if (self instanceof Number) {
551 return NativeNumber.lookupPrimitive(request, self);
552 } else if (self instanceof Boolean) {
553 return NativeBoolean.lookupPrimitive(request, self);
554 }
555 throw new IllegalArgumentException("Unsupported primitive: " + self);
556 }
557
558 @Override
559 public ScriptObject newObject() {
560 return new JO(getObjectPrototype(), getObjectMap());
561 }
562
563 @Override
564 public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
565 // When the [[DefaultValue]] internal method of O is called with no hint,
566 // then it behaves as if the hint were Number, unless O is a Date object
567 // in which case it behaves as if the hint were String.
568 Class<?> hint = typeHint;
569 if (hint == null) {
570 hint = Number.class;
571 }
572
573 try {
574 if (hint == String.class) {
575
576 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
577
578 if (Bootstrap.isCallable(toString)) {
579 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
580 if (JSType.isPrimitive(value)) {
581 return value;
582 }
583 }
584
585 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
586 if (Bootstrap.isCallable(valueOf)) {
587 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
588 if (JSType.isPrimitive(value)) {
589 return value;
590 }
591 }
592 throw typeError(this, "cannot.get.default.string");
593 }
594
595 if (hint == Number.class) {
596 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
597 if (Bootstrap.isCallable(valueOf)) {
598 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
599 if (JSType.isPrimitive(value)) {
600 return value;
601 }
602 }
603
604 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
605 if (Bootstrap.isCallable(toString)) {
606 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
607 if (JSType.isPrimitive(value)) {
608 return value;
609 }
610 }
611
612 throw typeError(this, "cannot.get.default.number");
613 }
614 } catch (final RuntimeException | Error e) {
615 throw e;
616 } catch (final Throwable t) {
617 throw new RuntimeException(t);
618 }
619
620 return UNDEFINED;
621 }
622
623 @Override
624 public boolean isError(final ScriptObject sobj) {
625 final ScriptObject errorProto = getErrorPrototype();
626 ScriptObject proto = sobj.getProto();
627 while (proto != null) {
628 if (proto == errorProto) {
629 return true;
630 }
631 proto = proto.getProto();
632 }
633 return false;
634 }
635
636 @Override
637 public ScriptObject newError(final String msg) {
638 return new NativeError(msg, this);
639 }
640
641 @Override
642 public ScriptObject newEvalError(final String msg) {
643 return new NativeEvalError(msg, this);
644 }
645
646 @Override
647 public ScriptObject newRangeError(final String msg) {
648 return new NativeRangeError(msg, this);
649 }
650
651 @Override
652 public ScriptObject newReferenceError(final String msg) {
653 return new NativeReferenceError(msg, this);
654 }
655
656 @Override
657 public ScriptObject newSyntaxError(final String msg) {
658 return new NativeSyntaxError(msg, this);
659 }
660
661 @Override
662 public ScriptObject newTypeError(final String msg) {
663 return new NativeTypeError(msg, this);
664 }
665
666 @Override
667 public ScriptObject newURIError(final String msg) {
668 return new NativeURIError(msg, this);
669 }
670
671 @Override
672 public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
673 return new GenericPropertyDescriptor(configurable, enumerable, this);
674 }
675
676 @Override
677 public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
678 return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
679 }
680
681 @Override
682 public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
683 final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
684
685 if (get == null) {
686 desc.delete(PropertyDescriptor.GET, false);
687 }
688
689 if (set == null) {
690 desc.delete(PropertyDescriptor.SET, false);
691 }
692
693 return desc;
694 }
695
696
697 /**
698 * Cache for compiled script classes.
699 */
700 @SuppressWarnings("serial")
701 private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
702 private final int size;
703 private final ReferenceQueue<Class<?>> queue;
704
705 ClassCache(int size) {
706 super(size, 0.75f, true);
707 this.size = size;
708 this.queue = new ReferenceQueue<>();
709 }
710
711 void cache(final Source source, final Class<?> clazz) {
712 put(source, new ClassReference(clazz, queue, source));
713 }
714
715 @Override
716 protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
717 return size() > size;
718 }
719
720 @Override
721 public ClassReference get(Object key) {
722 for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
723 remove(ref.source);
724 }
725 return super.get(key);
726 }
727
728 }
729
730 private static class ClassReference extends SoftReference<Class<?>> {
731 private final Source source;
732
733 ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
734 super(clazz, queue);
735 this.source = source;
736 }
737 }
738
739 // Class cache management
740 @Override
741 public Class<?> findCachedClass(final Source source) {
742 assert classCache != null : "Class cache used without being initialized";
743 ClassReference ref = classCache.get(source);
744 return ref != null ? ref.get() : null;
745 }
746
747 @Override
748 public void cacheClass(final Source source, final Class<?> clazz) {
749 assert classCache != null : "Class cache used without being initialized";
750 classCache.cache(source, clazz);
751 }
752
753 private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
754 final T obj = map.get(key);
755 if (obj != null) {
756 return obj;
757 }
758
759 try {
760 final T newObj = creator.call();
761 final T existingObj = map.putIfAbsent(key, newObj);
762 return existingObj != null ? existingObj : newObj;
763 } catch (final Exception exp) {
764 throw new RuntimeException(exp);
765 }
766 }
767
768 private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
769
770 @Override
771 public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
772 return getLazilyCreatedValue(key, creator, namedInvokers);
773 }
774
775 private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
776
777 @Override
778 public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
779 return getLazilyCreatedValue(key, creator, dynamicInvokers);
780 }
781
782 /**
783 * This is the eval used when 'indirect' eval call is made.
784 *
785 * var global = this;
786 * global.eval("print('hello')");
787 *
788 * @param self eval scope
789 * @param str eval string
790 *
791 * @return the result of eval
792 */
793 public static Object eval(final Object self, final Object str) {
794 return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
795 }
796
797 /**
798 * Direct eval
799 *
800 * @param self The scope of eval passed as 'self'
801 * @param str Evaluated code
802 * @param callThis "this" to be passed to the evaluated code
803 * @param location location of the eval call
804 * @param strict is eval called a strict mode code?
805 *
806 * @return the return value of the eval
807 *
808 * This is directly invoked from generated when eval(code) is called in user code
809 */
810 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
811 if (!(str instanceof String || str instanceof ConsString)) {
812 return str;
813 }
814 final Global global = Global.instance();
815 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
816
817 return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
818 }
819
820 /**
821 * Global print implementation - Nashorn extension
822 *
823 * @param self scope
824 * @param objects arguments to print
825 *
826 * @return result of print (undefined)
827 */
828 public static Object print(final Object self, final Object... objects) {
829 return printImpl(false, objects);
830 }
831
832 /**
833 * Global println implementation - Nashorn extension
834 *
835 * @param self scope
836 * @param objects arguments to print
837 *
838 * @return result of println (undefined)
839 */
840 public static Object println(final Object self, final Object... objects) {
841 return printImpl(true, objects);
842 }
843
844 /**
845 * Global load implementation - Nashorn extension
846 *
847 * @param self scope
848 * @param source source to load
849 *
850 * @return result of load (undefined)
851 *
852 * @throws IOException if source could not be read
853 */
854 public static Object load(final Object self, final Object source) throws IOException {
855 final Global global = Global.instance();
856 final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
857 return global.getContext().load(scope, source);
858 }
859
860 /**
861 * Global loadWithNewGlobal implementation - Nashorn extension
862 *
863 * @param self scope
864 * @param args from plus (optional) arguments to be passed to the loaded script
865 *
866 * @return result of load (may be undefined)
867 *
868 * @throws IOException if source could not be read
869 */
870 public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
871 final Global global = Global.instance();
872 final int length = args.length;
873 final boolean hasArgs = 0 < length;
874 final Object from = hasArgs ? args[0] : UNDEFINED;
875 final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
876
877 return global.getContext().loadWithNewGlobal(from, arguments);
878 }
879
880 /**
881 * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
882 *
883 * @param self self reference
884 * @param code exit code
885 *
886 * @return undefined (will never be reacheD)
887 */
888 public static Object exit(final Object self, final Object code) {
889 System.exit(JSType.toInt32(code));
890 return UNDEFINED;
891 }
892
893 // builtin prototype accessors
894 ScriptObject getFunctionPrototype() {
895 return ScriptFunction.getPrototype(builtinFunction);
896 }
897
898 ScriptObject getObjectPrototype() {
899 return ScriptFunction.getPrototype(builtinObject);
900 }
901
902 ScriptObject getArrayPrototype() {
903 return ScriptFunction.getPrototype(builtinArray);
904 }
905
906 ScriptObject getBooleanPrototype() {
907 return ScriptFunction.getPrototype(builtinBoolean);
908 }
909
910 ScriptObject getNumberPrototype() {
911 return ScriptFunction.getPrototype(builtinNumber);
912 }
913
914 ScriptObject getDatePrototype() {
915 return ScriptFunction.getPrototype(builtinDate);
916 }
917
918 ScriptObject getRegExpPrototype() {
919 return ScriptFunction.getPrototype(builtinRegExp);
920 }
921
922 ScriptObject getStringPrototype() {
923 return ScriptFunction.getPrototype(builtinString);
924 }
925
926 ScriptObject getErrorPrototype() {
927 return ScriptFunction.getPrototype(builtinError);
928 }
929
930 ScriptObject getEvalErrorPrototype() {
931 return ScriptFunction.getPrototype(builtinEvalError);
932 }
933
934 ScriptObject getRangeErrorPrototype() {
935 return ScriptFunction.getPrototype(builtinRangeError);
936 }
937
938 ScriptObject getReferenceErrorPrototype() {
939 return ScriptFunction.getPrototype(builtinReferenceError);
940 }
941
942 ScriptObject getSyntaxErrorPrototype() {
943 return ScriptFunction.getPrototype(builtinSyntaxError);
944 }
945
946 ScriptObject getTypeErrorPrototype() {
947 return ScriptFunction.getPrototype(builtinTypeError);
948 }
949
950 ScriptObject getURIErrorPrototype() {
951 return ScriptFunction.getPrototype(builtinURIError);
952 }
953
954 ScriptObject getJavaImporterPrototype() {
955 return ScriptFunction.getPrototype(builtinJavaImporter);
956 }
957
958 ScriptObject getJSAdapterPrototype() {
959 return ScriptFunction.getPrototype(builtinJSAdapter);
960 }
961
962 ScriptObject getArrayBufferPrototype() {
963 return ScriptFunction.getPrototype(builtinArrayBuffer);
964 }
965
966 ScriptObject getInt8ArrayPrototype() {
967 return ScriptFunction.getPrototype(builtinInt8Array);
968 }
969
970 ScriptObject getUint8ArrayPrototype() {
971 return ScriptFunction.getPrototype(builtinUint8Array);
972 }
973
974 ScriptObject getUint8ClampedArrayPrototype() {
975 return ScriptFunction.getPrototype(builtinUint8ClampedArray);
976 }
977
978 ScriptObject getInt16ArrayPrototype() {
979 return ScriptFunction.getPrototype(builtinInt16Array);
980 }
981
982 ScriptObject getUint16ArrayPrototype() {
983 return ScriptFunction.getPrototype(builtinUint16Array);
984 }
985
986 ScriptObject getInt32ArrayPrototype() {
987 return ScriptFunction.getPrototype(builtinInt32Array);
988 }
989
990 ScriptObject getUint32ArrayPrototype() {
991 return ScriptFunction.getPrototype(builtinUint32Array);
992 }
993
994 ScriptObject getFloat32ArrayPrototype() {
995 return ScriptFunction.getPrototype(builtinFloat32Array);
996 }
997
998 ScriptObject getFloat64ArrayPrototype() {
999 return ScriptFunction.getPrototype(builtinFloat64Array);
1000 }
1001
1002 // Builtin PropertyMap accessors
1003 PropertyMap getAccessorPropertyDescriptorMap() {
1004 return accessorPropertyDescriptorMap;
1005 }
1006
1007 PropertyMap getArrayBufferViewMap() {
1008 return arrayBufferViewMap;
1009 }
1010
1011 PropertyMap getDataPropertyDescriptorMap() {
1012 return dataPropertyDescriptorMap;
1013 }
1014
1015 PropertyMap getGenericPropertyDescriptorMap() {
1016 return genericPropertyDescriptorMap;
1017 }
1018
1019 PropertyMap getArgumentsMap() {
1020 return nativeArgumentsMap;
1021 }
1022
1023 PropertyMap getArrayMap() {
1024 return nativeArrayMap;
1025 }
1026
1027 PropertyMap getArrayBufferMap() {
1028 return nativeArrayBufferMap;
1029 }
1030
1031 PropertyMap getBooleanMap() {
1032 return nativeBooleanMap;
1033 }
1034
1035 PropertyMap getDateMap() {
1036 return nativeDateMap;
1037 }
1038
1039 PropertyMap getErrorMap() {
1040 return nativeErrorMap;
1041 }
1042
1043 PropertyMap getEvalErrorMap() {
1044 return nativeEvalErrorMap;
1045 }
1046
1047 PropertyMap getJSAdapterMap() {
1048 return nativeJSAdapterMap;
1049 }
1050
1051 PropertyMap getJavaImporterMap() {
1052 return nativeJavaImporterMap;
1053 }
1054
1055 PropertyMap getNumberMap() {
1056 return nativeNumberMap;
1057 }
1058
1059 PropertyMap getRangeErrorMap() {
1060 return nativeRangeErrorMap;
1061 }
1062
1063 PropertyMap getReferenceErrorMap() {
1064 return nativeReferenceErrorMap;
1065 }
1066
1067 PropertyMap getRegExpMap() {
1068 return nativeRegExpMap;
1069 }
1070
1071 PropertyMap getRegExpExecResultMap() {
1072 return nativeRegExpExecResultMap;
1073 }
1074
1075 PropertyMap getStrictArgumentsMap() {
1076 return nativeStrictArgumentsMap;
1077 }
1078
1079 PropertyMap getStringMap() {
1080 return nativeStringMap;
1081 }
1082
1083 PropertyMap getSyntaxErrorMap() {
1084 return nativeSyntaxErrorMap;
1085 }
1086
1087 PropertyMap getTypeErrorMap() {
1088 return nativeTypeErrorMap;
1089 }
1090
1091 PropertyMap getURIErrorMap() {
1092 return nativeURIErrorMap;
1093 }
1094
1095 PropertyMap getPrototypeObjectMap() {
1096 return prototypeObjectMap;
1097 }
1098
1099 PropertyMap getObjectMap() {
1100 return objectMap;
1101 }
1102
1103 PropertyMap getFunctionMap() {
1104 return functionMap;
1105 }
1106
1107 PropertyMap getAnonymousFunctionMap() {
1108 return anonymousFunctionMap;
1109 }
1110
1111 PropertyMap getStrictFunctionMap() {
1112 return strictFunctionMap;
1113 }
1114
1115 PropertyMap getBoundFunctionMap() {
1116 return boundFunctionMap;
1117 }
1118
1119 private ScriptFunction getBuiltinArray() {
1120 return builtinArray;
1121 }
1122
1123 ScriptFunction getTypeErrorThrower() {
1124 return typeErrorThrower;
1125 }
1126
1127 /**
1128 * Called from compiled script code to test if builtin has been overridden
1129 *
1130 * @return true if builtin array has not been overridden
1131 */
1132 public static boolean isBuiltinArray() {
1133 final Global instance = Global.instance();
1134 return instance.array == instance.getBuiltinArray();
1135 }
1136
1137 private ScriptFunction getBuiltinBoolean() {
1138 return builtinBoolean;
1139 }
1140
1141 /**
1142 * Called from compiled script code to test if builtin has been overridden
1143 *
1144 * @return true if builtin boolean has not been overridden
1145 */
1146 public static boolean isBuiltinBoolean() {
1147 final Global instance = Global.instance();
1148 return instance._boolean == instance.getBuiltinBoolean();
1149 }
1150
1151 private ScriptFunction getBuiltinDate() {
1152 return builtinDate;
1153 }
1154
1155 /**
1156 * Called from compiled script code to test if builtin has been overridden
1157 *
1158 * @return true if builtin date has not been overridden
1159 */
1160 public static boolean isBuiltinDate() {
1161 final Global instance = Global.instance();
1162 return instance.date == instance.getBuiltinDate();
1163 }
1164
1165 private ScriptFunction getBuiltinError() {
1166 return builtinError;
1167 }
1168
1169 /**
1170 * Called from compiled script code to test if builtin has been overridden
1171 *
1172 * @return true if builtin error has not been overridden
1173 */
1174 public static boolean isBuiltinError() {
1175 final Global instance = Global.instance();
1176 return instance.error == instance.getBuiltinError();
1177 }
1178
1179 private ScriptFunction getBuiltinEvalError() {
1180 return builtinEvalError;
1181 }
1182
1183 /**
1184 * Called from compiled script code to test if builtin has been overridden
1185 *
1186 * @return true if builtin eval error has not been overridden
1187 */
1188 public static boolean isBuiltinEvalError() {
1189 final Global instance = Global.instance();
1190 return instance.evalError == instance.getBuiltinEvalError();
1191 }
1192
1193 private ScriptFunction getBuiltinFunction() {
1194 return builtinFunction;
1195 }
1196
1197 /**
1198 * Called from compiled script code to test if builtin has been overridden
1199 *
1200 * @return true if builtin function has not been overridden
1201 */
1202 public static boolean isBuiltinFunction() {
1203 final Global instance = Global.instance();
1204 return instance.function == instance.getBuiltinFunction();
1205 }
1206
1207 private ScriptFunction getBuiltinJSAdapter() {
1208 return builtinJSAdapter;
1209 }
1210
1211 /**
1212 * Called from compiled script code to test if builtin has been overridden
1213 *
1214 * @return true if builtin JSAdapter has not been overridden
1215 */
1216 public static boolean isBuiltinJSAdapter() {
1217 final Global instance = Global.instance();
1218 return instance.jsadapter == instance.getBuiltinJSAdapter();
1219 }
1220
1221 private ScriptObject getBuiltinJSON() {
1222 return builtinJSON;
1223 }
1224
1225 /**
1226 * Called from compiled script code to test if builtin has been overridden
1227 *
1228 * @return true if builtin JSON has has not been overridden
1229 */
1230 public static boolean isBuiltinJSON() {
1231 final Global instance = Global.instance();
1232 return instance.json == instance.getBuiltinJSON();
1233 }
1234
1235 private ScriptObject getBuiltinJava() {
1236 return builtinJava;
1237 }
1238
1239 /**
1240 * Called from compiled script code to test if builtin has been overridden
1241 *
1242 * @return true if builtin Java has not been overridden
1243 */
1244 public static boolean isBuiltinJava() {
1245 final Global instance = Global.instance();
1246 return instance.java == instance.getBuiltinJava();
1247 }
1248
1249 private ScriptObject getBuiltinJavax() {
1250 return builtinJavax;
1251 }
1252
1253 /**
1254 * Called from compiled script code to test if builtin has been overridden
1255 *
1256 * @return true if builtin Javax has not been overridden
1257 */
1258 public static boolean isBuiltinJavax() {
1259 final Global instance = Global.instance();
1260 return instance.javax == instance.getBuiltinJavax();
1261 }
1262
1263 private ScriptObject getBuiltinJavaImporter() {
1264 return builtinJavaImporter;
1265 }
1266
1267 /**
1268 * Called from compiled script code to test if builtin has been overridden
1269 *
1270 * @return true if builtin Java importer has not been overridden
1271 */
1272 public static boolean isBuiltinJavaImporter() {
1273 final Global instance = Global.instance();
1274 return instance.javaImporter == instance.getBuiltinJavaImporter();
1275 }
1276
1277 private ScriptObject getBuiltinMath() {
1278 return builtinMath;
1279 }
1280
1281 /**
1282 * Called from compiled script code to test if builtin has been overridden
1283 *
1284 * @return true if builtin math has not been overridden
1285 */
1286 public static boolean isBuiltinMath() {
1287 final Global instance = Global.instance();
1288 return instance.math == instance.getBuiltinMath();
1289 }
1290
1291 private ScriptFunction getBuiltinNumber() {
1292 return builtinNumber;
1293 }
1294
1295 /**
1296 * Called from compiled script code to test if builtin has been overridden
1297 *
1298 * @return true if builtin number has not been overridden
1299 */
1300 public static boolean isBuiltinNumber() {
1301 final Global instance = Global.instance();
1302 return instance.number == instance.getBuiltinNumber();
1303 }
1304
1305 private ScriptFunction getBuiltinObject() {
1306 return builtinObject;
1307 }
1308
1309 /**
1310 * Called from compiled script code to test if builtin has been overridden
1311 *
1312 * @return true if builtin object has not been overridden
1313 */
1314 public static boolean isBuiltinObject() {
1315 final Global instance = Global.instance();
1316 return instance.object == instance.getBuiltinObject();
1317 }
1318
1319 private ScriptObject getBuiltinPackages() {
1320 return builtinPackages;
1321 }
1322
1323 /**
1324 * Called from compiled script code to test if builtin has been overridden
1325 *
1326 * @return true if builtin package has not been overridden
1327 */
1328 public static boolean isBuiltinPackages() {
1329 final Global instance = Global.instance();
1330 return instance.packages == instance.getBuiltinPackages();
1331 }
1332
1333 private ScriptFunction getBuiltinRangeError() {
1334 return builtinRangeError;
1335 }
1336
1337 /**
1338 * Called from compiled script code to test if builtin has been overridden
1339 *
1340 * @return true if builtin range error has not been overridden
1341 */
1342 public static boolean isBuiltinRangeError() {
1343 final Global instance = Global.instance();
1344 return instance.rangeError == instance.getBuiltinRangeError();
1345 }
1346
1347 private ScriptFunction getBuiltinReferenceError() {
1348 return builtinReferenceError;
1349 }
1350
1351 /**
1352 * Called from compiled script code to test if builtin has been overridden
1353 *
1354 * @return true if builtin reference error has not been overridden
1355 */
1356 public static boolean isBuiltinReferenceError() {
1357 final Global instance = Global.instance();
1358 return instance.referenceError == instance.getBuiltinReferenceError();
1359 }
1360
1361 private ScriptFunction getBuiltinRegExp() {
1362 return builtinRegExp;
1363 }
1364
1365 /**
1366 * Called from compiled script code to test if builtin has been overridden
1367 *
1368 * @return true if builtin regexp has not been overridden
1369 */
1370 public static boolean isBuiltinRegExp() {
1371 final Global instance = Global.instance();
1372 return instance.regexp == instance.getBuiltinRegExp();
1373 }
1374
1375 private ScriptFunction getBuiltinString() {
1376 return builtinString;
1377 }
1378
1379 /**
1380 * Called from compiled script code to test if builtin has been overridden
1381 *
1382 * @return true if builtin Java has not been overridden
1383 */
1384 public static boolean isBuiltinString() {
1385 final Global instance = Global.instance();
1386 return instance.string == instance.getBuiltinString();
1387 }
1388
1389 private ScriptFunction getBuiltinSyntaxError() {
1390 return builtinSyntaxError;
1391 }
1392
1393 /**
1394 * Called from compiled script code to test if builtin has been overridden
1395 *
1396 * @return true if builtin syntax error has not been overridden
1397 */
1398 public static boolean isBuiltinSyntaxError() {
1399 final Global instance = Global.instance();
1400 return instance.syntaxError == instance.getBuiltinSyntaxError();
1401 }
1402
1403 private ScriptFunction getBuiltinTypeError() {
1404 return builtinTypeError;
1405 }
1406
1407 /**
1408 * Called from compiled script code to test if builtin has been overridden
1409 *
1410 * @return true if builtin type error has not been overridden
1411 */
1412 public static boolean isBuiltinTypeError() {
1413 final Global instance = Global.instance();
1414 return instance.typeError == instance.getBuiltinTypeError();
1415 }
1416
1417 private ScriptFunction getBuiltinURIError() {
1418 return builtinURIError;
1419 }
1420
1421 /**
1422 * Called from compiled script code to test if builtin has been overridden
1423 *
1424 * @return true if builtin URI error has not been overridden
1425 */
1426 public static boolean isBuiltinURIError() {
1427 final Global instance = Global.instance();
1428 return instance.uriError == instance.getBuiltinURIError();
1429 }
1430
1431 @Override
1432 public String getClassName() {
1433 return "global";
1434 }
1435
1436 /**
1437 * Copy function used to clone NativeRegExp objects.
1438 *
1439 * @param regexp a NativeRegExp to clone
1440 *
1441 * @return copy of the given regexp object
1442 */
1443 public static Object regExpCopy(final Object regexp) {
1444 return new NativeRegExp((NativeRegExp)regexp);
1445 }
1446
1447 /**
1448 * Convert given object to NativeRegExp type.
1449 *
1450 * @param obj object to be converted
1451 * @return NativeRegExp instance
1452 */
1453 public static NativeRegExp toRegExp(final Object obj) {
1454 if (obj instanceof NativeRegExp) {
1455 return (NativeRegExp)obj;
1456 }
1457 return new NativeRegExp(JSType.toString(obj));
1458 }
1459
1460 /**
1461 * ECMA 9.9 ToObject implementation
1462 *
1463 * @param obj an item for which to run ToObject
1464 * @return ToObject version of given item
1465 */
1466 public static Object toObject(final Object obj) {
1467 if (obj == null || obj == UNDEFINED) {
1468 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1469 }
1470
1471 if (obj instanceof ScriptObject) {
1472 return obj;
1473 }
1474
1475 return instance().wrapAsObject(obj);
1476 }
1477
1478 /**
1479 * Allocate a new object array.
1480 *
1481 * @param initial object values.
1482 * @return the new array
1483 */
1484 public static NativeArray allocate(final Object[] initial) {
1485 ArrayData arrayData = ArrayData.allocate(initial);
1486
1487 for (int index = 0; index < initial.length; index++) {
1488 final Object value = initial[index];
1489
1490 if (value == ScriptRuntime.EMPTY) {
1491 arrayData = arrayData.delete(index);
1492 }
1493 }
1494
1495 return new NativeArray(arrayData);
1496 }
1497
1498 /**
1499 * Allocate a new number array.
1500 *
1501 * @param initial number values.
1502 * @return the new array
1503 */
1504 public static NativeArray allocate(final double[] initial) {
1505 return new NativeArray(ArrayData.allocate(initial));
1506 }
1507
1508 /**
1509 * Allocate a new long array.
1510 *
1511 * @param initial number values.
1512 * @return the new array
1513 */
1514 public static NativeArray allocate(final long[] initial) {
1515 return new NativeArray(ArrayData.allocate(initial));
1516 }
1517
1518 /**
1519 * Allocate a new integer array.
1520 *
1521 * @param initial number values.
1522 * @return the new array
1523 */
1524 public static NativeArray allocate(final int[] initial) {
1525 return new NativeArray(ArrayData.allocate(initial));
1526 }
1527
1528 /**
1529 * Allocate a new object array for arguments.
1530 *
1531 * @param arguments initial arguments passed.
1532 * @param callee reference to the function that uses arguments object
1533 * @param numParams actual number of declared parameters
1534 *
1535 * @return the new array
1536 */
1537 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1538 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1539 }
1540
1541 /**
1542 * Called from generated to check if given function is the builtin 'eval'. If
1543 * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1544 *
1545 * @param fn function object that is checked
1546 * @return true if fn is the builtin eval
1547 */
1548 public static boolean isEval(final Object fn) {
1549 return fn == Global.instance().builtinEval;
1550 }
1551
1552 /**
1553 * Create a new RegExp object.
1554 *
1555 * @param expression Regular expression.
1556 * @param options Search options.
1557 *
1558 * @return New RegExp object.
1559 */
1560 public static Object newRegExp(final String expression, final String options) {
1561 if (options == null) {
1562 return new NativeRegExp(expression);
1563 }
1564 return new NativeRegExp(expression, options);
1565 }
1566
1567 /**
1568 * Get the object prototype
1569 *
1570 * @return the object prototype
1571 */
1572 public static ScriptObject objectPrototype() {
1573 return Global.instance().getObjectPrototype();
1574 }
1575
1576 /**
1577 * Create a new empty object instance.
1578 *
1579 * @return New empty object.
1580 */
1581 public static ScriptObject newEmptyInstance() {
1582 return Global.instance().newObject();
1583 }
1584
1585 /**
1586 * Check if a given object is a ScriptObject, raises an exception if this is
1587 * not the case
1588 *
1589 * @param obj and object to check
1590 */
1591 public static void checkObject(final Object obj) {
1592 if (!(obj instanceof ScriptObject)) {
1593 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1594 }
1595 }
1596
1597 /**
1598 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1599 * if this object is null or undefined.
1600 *
1601 * @param obj an object to check
1602 */
1603 public static void checkObjectCoercible(final Object obj) {
1604 if (obj == null || obj == UNDEFINED) {
1605 throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1606 }
1607 }
1608
1609 /**
1610 * Get the current split state.
1611 *
1612 * @return current split state
1613 */
1614 @Override
1615 public int getSplitState() {
1616 return splitState;
1617 }
1618
1619 /**
1620 * Set the current split state.
1621 *
1622 * @param state current split state
1623 */
1624 @Override
1625 public void setSplitState(final int state) {
1626 splitState = state;
1627 }
1628
1629 private void init() {
1630 assert Context.getGlobal() == this : "this global is not set as current";
1631
1632 final ScriptEnvironment env = getContext().getEnv();
1633
1634 // duplicate PropertyMaps of Native* classes
1635 copyInitialMaps(env);
1636
1637 // initialize Function and Object constructor
1638 initFunctionAndObject();
1639
1640 // Now fix Global's own proto.
1641 this.setProto(getObjectPrototype());
1642
1643 // initialize global function properties
1644 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1645
1646 this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT);
1647 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1648 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN);
1649 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE);
1650 this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI);
1651 this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1652 this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI);
1653 this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1654 this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE);
1655 this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
1656 this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN);
1657 this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
1658 this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
1659 this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT);
1660 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
1661
1662 // built-in constructors
1663 this.builtinArray = (ScriptFunction)initConstructor("Array");
1664 this.builtinBoolean = (ScriptFunction)initConstructor("Boolean");
1665 this.builtinDate = (ScriptFunction)initConstructor("Date");
1666 this.builtinJSON = initConstructor("JSON");
1667 this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
1668 this.builtinMath = initConstructor("Math");
1669 this.builtinNumber = (ScriptFunction)initConstructor("Number");
1670 this.builtinRegExp = (ScriptFunction)initConstructor("RegExp");
1671 this.builtinString = (ScriptFunction)initConstructor("String");
1672
1673 // initialize String.prototype.length to 0
1674 // add String.prototype.length
1675 final ScriptObject stringPrototype = getStringPrototype();
1676 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1677
1678 // set isArray flag on Array.prototype
1679 final ScriptObject arrayPrototype = getArrayPrototype();
1680 arrayPrototype.setIsArray();
1681
1682 this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
1683
1684 // initialize default regexp object
1685 this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
1686
1687 // RegExp.prototype should behave like a RegExp object. So copy the
1688 // properties.
1689 final ScriptObject regExpProto = getRegExpPrototype();
1690 regExpProto.addBoundProperties(DEFAULT_REGEXP);
1691
1692 // Error stuff
1693 initErrorObjects();
1694
1695 // java access
1696 if (! env._no_java) {
1697 initJavaAccess();
1698 }
1699
1700 if (! env._no_typed_arrays) {
1701 initTypedArray();
1702 }
1703
1704 if (env._scripting) {
1705 initScripting(env);
1706 }
1707
1708 if (Context.DEBUG && System.getSecurityManager() == null) {
1709 initDebug();
1710 }
1711
1712 copyBuiltins();
1713
1714 // initialized with strings so that typeof will work as expected.
1715 this.__FILE__ = "";
1716 this.__DIR__ = "";
1717 this.__LINE__ = 0.0;
1718
1719 // expose script (command line) arguments as "arguments" property of global
1720 final List<String> arguments = env.getArguments();
1721 final Object argsObj = wrapAsObject(arguments.toArray());
1722
1723 addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
1724 if (env._scripting) {
1725 // synonym for "arguments" in scripting mode
1726 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
1727 }
1728 }
1729
1730 private void initErrorObjects() {
1731 // Error objects
1732 this.builtinError = (ScriptFunction)initConstructor("Error");
1733 final ScriptObject errorProto = getErrorPrototype();
1734
1735 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1736 final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1737 final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1738 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1739 final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1740 final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1741 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1742 final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1743 final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1744 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1745 final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1746 final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1747 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1748
1749 // ECMA 15.11.4.2 Error.prototype.name
1750 // Error.prototype.name = "Error";
1751 errorProto.set(NativeError.NAME, "Error", false);
1752 // ECMA 15.11.4.3 Error.prototype.message
1753 // Error.prototype.message = "";
1754 errorProto.set(NativeError.MESSAGE, "", false);
1755
1756 this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1757 this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1758 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1759 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1760 this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1761 this.builtinURIError = initErrorSubtype("URIError", errorProto);
1762 }
1763
1764 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1765 final ScriptObject cons = initConstructor(name);
1766 final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1767 prototype.set(NativeError.NAME, name, false);
1768 prototype.set(NativeError.MESSAGE, "", false);
1769 prototype.setProto(errorProto);
1770 return (ScriptFunction)cons;
1771 }
1772
1773 private void initJavaAccess() {
1774 final ScriptObject objectProto = getObjectPrototype();
1775 this.builtinPackages = new NativeJavaPackage("", objectProto);
1776 this.builtinCom = new NativeJavaPackage("com", objectProto);
1777 this.builtinEdu = new NativeJavaPackage("edu", objectProto);
1778 this.builtinJava = new NativeJavaPackage("java", objectProto);
1779 this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
1780 this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1781 this.builtinOrg = new NativeJavaPackage("org", objectProto);
1782 this.builtinJavaImporter = initConstructor("JavaImporter");
1783 this.builtinJavaApi = initConstructor("Java");
1784 }
1785
1786 private void initScripting(final ScriptEnvironment scriptEnv) {
1787 Object value;
1788 value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1789 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1790
1791 value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1792 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1793
1794 final String execName = ScriptingFunctions.EXEC_NAME;
1795 value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1796 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1797
1798 // Nashorn extension: global.echo (scripting-mode-only)
1799 // alias for "print"
1800 value = get("print");
1801 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1802
1803 // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1804 final ScriptObject options = newObject();
1805 copyOptions(options, scriptEnv);
1806 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1807
1808 // Nashorn extension: global.$ENV (scripting-mode-only)
1809 if (System.getSecurityManager() == null) {
1810 // do not fill $ENV if we have a security manager around
1811 // Retrieve current state of ENV variables.
1812 final ScriptObject env = newObject();
1813 env.putAll(System.getenv(), scriptEnv._strict);
1814 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1815 } else {
1816 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1817 }
1818
1819 // add other special properties for exec support
1820 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1821 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1822 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1823 }
1824
1825 private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1826 for (Field f : scriptEnv.getClass().getFields()) {
1827 try {
1828 options.set(f.getName(), f.get(scriptEnv), false);
1829 } catch (final IllegalArgumentException | IllegalAccessException exp) {
1830 throw new RuntimeException(exp);
1831 }
1832 }
1833 }
1834
1835 private void initTypedArray() {
1836 this.builtinArrayBuffer = initConstructor("ArrayBuffer");
1837 this.builtinInt8Array = initConstructor("Int8Array");
1838 this.builtinUint8Array = initConstructor("Uint8Array");
1839 this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
1840 this.builtinInt16Array = initConstructor("Int16Array");
1841 this.builtinUint16Array = initConstructor("Uint16Array");
1842 this.builtinInt32Array = initConstructor("Int32Array");
1843 this.builtinUint32Array = initConstructor("Uint32Array");
1844 this.builtinFloat32Array = initConstructor("Float32Array");
1845 this.builtinFloat64Array = initConstructor("Float64Array");
1846 }
1847
1848 private void copyBuiltins() {
1849 this.array = this.builtinArray;
1850 this._boolean = this.builtinBoolean;
1851 this.date = this.builtinDate;
1852 this.error = this.builtinError;
1853 this.evalError = this.builtinEvalError;
1854 this.function = this.builtinFunction;
1855 this.jsadapter = this.builtinJSAdapter;
1856 this.json = this.builtinJSON;
1857 this.com = this.builtinCom;
1858 this.edu = this.builtinEdu;
1859 this.java = this.builtinJava;
1860 this.javafx = this.builtinJavafx;
1861 this.javax = this.builtinJavax;
1862 this.org = this.builtinOrg;
1863 this.javaImporter = this.builtinJavaImporter;
1864 this.javaApi = this.builtinJavaApi;
1865 this.math = this.builtinMath;
1866 this.number = this.builtinNumber;
1867 this.object = this.builtinObject;
1868 this.packages = this.builtinPackages;
1869 this.rangeError = this.builtinRangeError;
1870 this.referenceError = this.builtinReferenceError;
1871 this.regexp = this.builtinRegExp;
1872 this.string = this.builtinString;
1873 this.syntaxError = this.builtinSyntaxError;
1874 this.typeError = this.builtinTypeError;
1875 this.uriError = this.builtinURIError;
1876 this.arrayBuffer = this.builtinArrayBuffer;
1877 this.int8Array = this.builtinInt8Array;
1878 this.uint8Array = this.builtinUint8Array;
1879 this.uint8ClampedArray = this.builtinUint8ClampedArray;
1880 this.int16Array = this.builtinInt16Array;
1881 this.uint16Array = this.builtinUint16Array;
1882 this.int32Array = this.builtinInt32Array;
1883 this.uint32Array = this.builtinUint32Array;
1884 this.float32Array = this.builtinFloat32Array;
1885 this.float64Array = this.builtinFloat64Array;
1886 }
1887
1888 private void initDebug() {
1889 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
1890 }
1891
1892 @SuppressWarnings("resource")
1893 private static Object printImpl(final boolean newLine, final Object... objects) {
1894 final PrintWriter out = Global.getEnv().getOut();
1895 final StringBuilder sb = new StringBuilder();
1896
1897 for (final Object object : objects) {
1898 if (sb.length() != 0) {
1899 sb.append(' ');
1900 }
1901
1902 sb.append(JSType.toString(object));
1903 }
1904
1905 // Print all at once to ensure thread friendly result.
1906 if (newLine) {
1907 out.println(sb.toString());
1908 } else {
1909 out.print(sb.toString());
1910 }
1911
1912 out.flush();
1913
1914 return UNDEFINED;
1915 }
1916
1917 /**
1918 * These classes are generated by nasgen tool and so we have to use
1919 * reflection to load and create new instance of these classes.
1920 */
1921 private ScriptObject initConstructor(final String name) {
1922 try {
1923 // Assuming class name pattern for built-in JS constructors.
1924 final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
1925
1926 sb.append("Native");
1927 sb.append(name);
1928 sb.append("$Constructor");
1929
1930 final Class<?> funcClass = Class.forName(sb.toString());
1931 final ScriptObject res = (ScriptObject)funcClass.newInstance();
1932
1933 if (res instanceof ScriptFunction) {
1934 // All global constructor prototypes are not-writable,
1935 // not-enumerable and not-configurable.
1936 final ScriptFunction func = (ScriptFunction)res;
1937 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
1938 }
1939
1940 if (res.getProto() == null) {
1941 res.setProto(getObjectPrototype());
1942 }
1943
1944 return res;
1945
1946 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
1947 throw new RuntimeException(e);
1948 }
1949 }
1950
1951 private void copyInitialMaps(final ScriptEnvironment env) {
1952 this.accessorPropertyDescriptorMap = AccessorPropertyDescriptor.getInitialMap().duplicate();
1953 this.dataPropertyDescriptorMap = DataPropertyDescriptor.getInitialMap().duplicate();
1954 this.genericPropertyDescriptorMap = GenericPropertyDescriptor.getInitialMap().duplicate();
1955 this.nativeArgumentsMap = NativeArguments.getInitialMap().duplicate();
1956 this.nativeArrayMap = NativeArray.getInitialMap().duplicate();
1957 this.nativeBooleanMap = NativeBoolean.getInitialMap().duplicate();
1958 this.nativeDateMap = NativeDate.getInitialMap().duplicate();
1959 this.nativeErrorMap = NativeError.getInitialMap().duplicate();
1960 this.nativeEvalErrorMap = NativeEvalError.getInitialMap().duplicate();
1961 this.nativeJSAdapterMap = NativeJSAdapter.getInitialMap().duplicate();
1962 this.nativeNumberMap = NativeNumber.getInitialMap().duplicate();
1963 this.nativeRangeErrorMap = NativeRangeError.getInitialMap().duplicate();
1964 this.nativeReferenceErrorMap = NativeReferenceError.getInitialMap().duplicate();
1965 this.nativeRegExpMap = NativeRegExp.getInitialMap().duplicate();
1966 this.nativeRegExpExecResultMap = NativeRegExpExecResult.getInitialMap().duplicate();
1967 this.nativeStrictArgumentsMap = NativeStrictArguments.getInitialMap().duplicate();
1968 this.nativeStringMap = NativeString.getInitialMap().duplicate();
1969 this.nativeSyntaxErrorMap = NativeSyntaxError.getInitialMap().duplicate();
1970 this.nativeTypeErrorMap = NativeTypeError.getInitialMap().duplicate();
1971 this.nativeURIErrorMap = NativeURIError.getInitialMap().duplicate();
1972 this.prototypeObjectMap = PrototypeObject.getInitialMap().duplicate();
1973 this.objectMap = JO.getInitialMap().duplicate();
1974 this.functionMap = ScriptFunctionImpl.getInitialMap().duplicate();
1975 this.anonymousFunctionMap = ScriptFunctionImpl.getInitialAnonymousMap().duplicate();
1976 this.strictFunctionMap = ScriptFunctionImpl.getInitialStrictMap().duplicate();
1977 this.boundFunctionMap = ScriptFunctionImpl.getInitialBoundMap().duplicate();
1978
1979 // java
1980 if (! env._no_java) {
1981 this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate();
1982 }
1983
1984 // typed arrays
1985 if (! env._no_typed_arrays) {
1986 this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate();
1987 this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate();
1988 }
1989 }
1990
1991 // Function and Object constructors are inter-dependent. Also,
1992 // Function.prototype
1993 // functions are not properly initialized. We fix the references here.
1994 // NOTE: be careful if you want to re-order the operations here. You may
1995 // have
1996 // to play with object references carefully!!
1997 private void initFunctionAndObject() {
1998 // First-n-foremost is Function
1999 this.builtinFunction = (ScriptFunction)initConstructor("Function");
2000
2001 // create global anonymous function
2002 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
2003 // need to copy over members of Function.prototype to anon function
2004 anon.addBoundProperties(getFunctionPrototype());
2005
2006 // Function.prototype === Object.getPrototypeOf(Function) ===
2007 // <anon-function>
2008 builtinFunction.setProto(anon);
2009 builtinFunction.setPrototype(anon);
2010 anon.set("constructor", builtinFunction, false);
2011 anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2012
2013 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2014 this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, false, false, false);
2015 typeErrorThrower.setPrototype(UNDEFINED);
2016 // Non-constructor built-in functions do not have "prototype" property
2017 typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2018 typeErrorThrower.preventExtensions();
2019
2020 // now initialize Object
2021 this.builtinObject = (ScriptFunction)initConstructor("Object");
2022 final ScriptObject ObjectPrototype = getObjectPrototype();
2023 // Object.getPrototypeOf(Function.prototype) === Object.prototype
2024 anon.setProto(ObjectPrototype);
2025
2026 // Function valued properties of Function.prototype were not properly
2027 // initialized. Because, these were created before global.function and
2028 // global.object were not initialized.
2029 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2030 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2031 final Object key = property.getKey();
2032 final Object value = builtinFunction.get(key);
2033
2034 if (value instanceof ScriptFunction && value != anon) {
2035 final ScriptFunction func = (ScriptFunction)value;
2036 func.setProto(getFunctionPrototype());
2037 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2038 if (prototype != null) {
2039 prototype.setProto(ObjectPrototype);
2040 }
2041 }
2042 }
2043
2044 // For function valued properties of Object and Object.prototype, make
2045 // sure prototype's proto chain ends with Object.prototype
2046 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2047 final Object key = property.getKey();
2048 final Object value = builtinObject.get(key);
2049
2050 if (value instanceof ScriptFunction) {
2051 final ScriptFunction func = (ScriptFunction)value;
2052 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2053 if (prototype != null) {
2054 prototype.setProto(ObjectPrototype);
2055 }
2056 }
2057 }
2058
2059 properties = getObjectPrototype().getMap().getProperties();
2060 for (final jdk.nashorn.internal.runtime.Property property : properties) {
2061 final Object key = property.getKey();
2062 final Object value = ObjectPrototype.get(key);
2063
2064 if (key.equals("constructor")) {
2065 continue;
2066 }
2067
2068 if (value instanceof ScriptFunction) {
2069 final ScriptFunction func = (ScriptFunction)value;
2070 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2071 if (prototype != null) {
2072 prototype.setProto(ObjectPrototype);
2073 }
2074 }
2075 }
2076 }
2077
2078 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
2079 return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2080 }
2081
2082 RegExpResult getLastRegExpResult() {
2083 return lastRegExpResult;
2084 }
2085
2086 void setLastRegExpResult(final RegExpResult regExpResult) {
2087 this.lastRegExpResult = regExpResult;
2088 }
2089
2090 }
--- EOF ---