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