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