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