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