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