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