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 }