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