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