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