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