1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.objects; 27 28 import static jdk.nashorn.internal.lookup.Lookup.MH; 29 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; 30 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 31 import static jdk.nashorn.internal.runtime.JSType.isString; 32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 33 34 import java.io.IOException; 35 import java.io.PrintWriter; 36 import java.lang.invoke.MethodHandle; 37 import java.lang.invoke.MethodHandles; 38 import java.lang.invoke.MethodType; 39 import java.lang.invoke.SwitchPoint; 40 import java.lang.reflect.Field; 41 import java.util.ArrayList; 42 import java.util.Arrays; 43 import java.util.List; 44 import java.util.Map; 45 import java.util.Objects; 46 import java.util.concurrent.Callable; 47 import java.util.concurrent.ConcurrentHashMap; 48 import javax.script.ScriptContext; 49 import javax.script.ScriptEngine; 50 import jdk.internal.dynalink.CallSiteDescriptor; 51 import jdk.internal.dynalink.linker.GuardedInvocation; 52 import jdk.internal.dynalink.linker.LinkRequest; 53 import jdk.nashorn.api.scripting.ClassFilter; 54 import jdk.nashorn.api.scripting.ScriptObjectMirror; 55 import jdk.nashorn.internal.lookup.Lookup; 56 import jdk.nashorn.internal.objects.annotations.Attribute; 57 import jdk.nashorn.internal.objects.annotations.Getter; 58 import jdk.nashorn.internal.objects.annotations.Property; 59 import jdk.nashorn.internal.objects.annotations.ScriptClass; 60 import jdk.nashorn.internal.objects.annotations.Setter; 61 import jdk.nashorn.internal.runtime.Context; 62 import jdk.nashorn.internal.runtime.ECMAErrors; 63 import jdk.nashorn.internal.runtime.FindProperty; 64 import jdk.nashorn.internal.runtime.GlobalConstants; 65 import jdk.nashorn.internal.runtime.GlobalFunctions; 66 import jdk.nashorn.internal.runtime.JSType; 67 import jdk.nashorn.internal.runtime.NativeJavaPackage; 68 import jdk.nashorn.internal.runtime.PropertyDescriptor; 69 import jdk.nashorn.internal.runtime.PropertyMap; 70 import jdk.nashorn.internal.runtime.Scope; 71 import jdk.nashorn.internal.runtime.ScriptEnvironment; 72 import jdk.nashorn.internal.runtime.ScriptFunction; 73 import jdk.nashorn.internal.runtime.ScriptObject; 74 import jdk.nashorn.internal.runtime.ScriptRuntime; 75 import jdk.nashorn.internal.runtime.ScriptingFunctions; 76 import jdk.nashorn.internal.runtime.Specialization; 77 import jdk.nashorn.internal.runtime.arrays.ArrayData; 78 import jdk.nashorn.internal.runtime.linker.Bootstrap; 79 import jdk.nashorn.internal.runtime.linker.InvokeByName; 80 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 81 import jdk.nashorn.internal.runtime.regexp.RegExpResult; 82 import jdk.nashorn.internal.scripts.JD; 83 import jdk.nashorn.internal.scripts.JO; 84 import jdk.nashorn.tools.ShellFunctions; 85 86 /** 87 * Representation of global scope. 88 */ 89 @ScriptClass("Global") 90 public final class Global extends ScriptObject implements Scope { 91 // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__) 92 private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object(); 93 private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); 94 private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class); 95 96 // placeholder value for lazily initialized global objects 97 private static final Object LAZY_SENTINEL = new Object(); 98 99 /** 100 * Optimistic builtin names that require switchpoint invalidation 101 * upon assignment. Overly conservative, but works for now, to avoid 102 * any complicated scope checks and especially heavy weight guards 103 * like 104 * 105 * <pre> 106 * public boolean setterGuard(final Object receiver) { 107 * final Global global = Global.instance(); 108 * final ScriptObject sobj = global.getFunctionPrototype(); 109 * final Object apply = sobj.get("apply"); 110 * return apply == receiver; 111 * } 112 * </pre> 113 * 114 * Naturally, checking for builtin classes like NativeFunction is cheaper, 115 * it's when you start adding property checks for said builtins you have 116 * problems with guard speed. 117 */ 118 119 /** Nashorn extension: arguments array */ 120 @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) 121 public Object arguments; 122 123 /** ECMA 15.1.2.2 parseInt (string , radix) */ 124 @Property(attributes = Attribute.NOT_ENUMERABLE) 125 public Object parseInt; 126 127 /** ECMA 15.1.2.3 parseFloat (string) */ 128 @Property(attributes = Attribute.NOT_ENUMERABLE) 129 public Object parseFloat; 130 131 /** ECMA 15.1.2.4 isNaN (number) */ 132 @Property(attributes = Attribute.NOT_ENUMERABLE) 133 public Object isNaN; 134 135 /** ECMA 15.1.2.5 isFinite (number) */ 136 @Property(attributes = Attribute.NOT_ENUMERABLE) 137 public Object isFinite; 138 139 /** ECMA 15.1.3.3 encodeURI */ 140 @Property(attributes = Attribute.NOT_ENUMERABLE) 141 public Object encodeURI; 142 143 /** ECMA 15.1.3.4 encodeURIComponent */ 144 @Property(attributes = Attribute.NOT_ENUMERABLE) 145 public Object encodeURIComponent; 146 147 /** ECMA 15.1.3.1 decodeURI */ 148 @Property(attributes = Attribute.NOT_ENUMERABLE) 149 public Object decodeURI; 150 151 /** ECMA 15.1.3.2 decodeURIComponent */ 152 @Property(attributes = Attribute.NOT_ENUMERABLE) 153 public Object decodeURIComponent; 154 155 /** ECMA B.2.1 escape (string) */ 156 @Property(attributes = Attribute.NOT_ENUMERABLE) 157 public Object escape; 158 159 /** ECMA B.2.2 unescape (string) */ 160 @Property(attributes = Attribute.NOT_ENUMERABLE) 161 public Object unescape; 162 163 /** Nashorn extension: global.print */ 164 @Property(attributes = Attribute.NOT_ENUMERABLE) 165 public Object print; 166 167 /** Nashorn extension: global.load */ 168 @Property(attributes = Attribute.NOT_ENUMERABLE) 169 public Object load; 170 171 /** Nashorn extension: global.loadWithNewGlobal */ 172 @Property(attributes = Attribute.NOT_ENUMERABLE) 173 public Object loadWithNewGlobal; 174 175 /** Nashorn extension: global.exit */ 176 @Property(attributes = Attribute.NOT_ENUMERABLE) 177 public Object exit; 178 179 /** Nashorn extension: global.quit */ 180 @Property(attributes = Attribute.NOT_ENUMERABLE) 181 public Object quit; 182 183 /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */ 184 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) 185 public final double NaN = Double.NaN; 186 187 /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */ 188 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) 189 public final double Infinity = Double.POSITIVE_INFINITY; 190 191 /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */ 192 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) 193 public final Object undefined = UNDEFINED; 194 195 /** ECMA 15.1.2.1 eval(x) */ 196 @Property(attributes = Attribute.NOT_ENUMERABLE) 197 public Object eval; 198 199 /** ECMA 15.1.4.1 Object constructor. */ 200 @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE) 201 public volatile Object object; 202 203 /** ECMA 15.1.4.2 Function constructor. */ 204 @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE) 205 public volatile Object function; 206 207 /** ECMA 15.1.4.3 Array constructor. */ 208 @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE) 209 public volatile Object array; 210 211 /** ECMA 15.1.4.4 String constructor */ 212 @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE) 213 public volatile Object string; 214 215 /** ECMA 15.1.4.5 Boolean constructor */ 216 @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE) 217 public volatile Object _boolean; 218 219 /** ECMA 15.1.4.6 - Number constructor */ 220 @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE) 221 public volatile Object number; 222 223 /** ECMA 15.1.4.7 Date constructor */ 224 @Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE) 225 public static Object getDate(final Object self) { 226 final Global global = Global.instanceFrom(self); 227 if (global.date == LAZY_SENTINEL) { 228 global.date = global.getBuiltinDate(); 229 } 230 return global.date; 231 } 232 233 @Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE) 234 public static void setDate(final Object self, final Object value) { 235 final Global global = Global.instanceFrom(self); 236 global.date = value; 237 } 238 239 private volatile Object date = LAZY_SENTINEL; 240 241 /** ECMA 15.1.4.8 RegExp constructor */ 242 @Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) 243 public static Object getRegExp(final Object self) { 244 final Global global = Global.instanceFrom(self); 245 if (global.regexp == LAZY_SENTINEL) { 246 global.regexp = global.getBuiltinRegExp(); 247 } 248 return global.regexp; 249 } 250 251 @Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) 252 public static void setRegExp(final Object self, final Object value) { 253 final Global global = Global.instanceFrom(self); 254 global.regexp = value; 255 } 256 257 private volatile Object regexp = LAZY_SENTINEL; 258 259 /** ECMA 15.12 - The JSON object */ 260 @Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) 261 public static Object getJSON(final Object self) { 262 final Global global = Global.instanceFrom(self); 263 if (global.json == LAZY_SENTINEL) { 264 global.json = global.getBuiltinJSON(); 265 } 266 return global.json; 267 } 268 269 @Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) 270 public static void setJSON(final Object self, final Object value) { 271 final Global global = Global.instanceFrom(self); 272 global.json = value; 273 } 274 275 private volatile Object json = LAZY_SENTINEL; 276 277 /** Nashorn extension: global.JSAdapter */ 278 @Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) 279 public static Object getJSAdapter(final Object self) { 280 final Global global = Global.instanceFrom(self); 281 if (global.jsadapter == LAZY_SENTINEL) { 282 global.jsadapter = global.getBuiltinJSAdapter(); 283 } 284 return global.jsadapter; 285 } 286 287 @Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) 288 public static void setJSAdapter(final Object self, final Object value) { 289 final Global global = Global.instanceFrom(self); 290 global.jsadapter = value; 291 } 292 293 private volatile Object jsadapter = LAZY_SENTINEL; 294 295 /** ECMA 15.8 - The Math object */ 296 @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE) 297 public volatile Object math; 298 299 /** Error object */ 300 @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE) 301 public volatile Object error; 302 303 /** EvalError object */ 304 @Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) 305 public static Object getEvalError(final Object self) { 306 final Global global = Global.instanceFrom(self); 307 if (global.evalError == LAZY_SENTINEL) { 308 global.evalError = global.getBuiltinEvalError(); 309 } 310 return global.evalError; 311 } 312 313 @Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) 314 public static void setEvalError(final Object self, final Object value) { 315 final Global global = Global.instanceFrom(self); 316 global.evalError = value; 317 } 318 319 private volatile Object evalError = LAZY_SENTINEL; 320 321 /** RangeError object */ 322 @Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) 323 public static Object getRangeError(final Object self) { 324 final Global global = Global.instanceFrom(self); 325 if (global.rangeError == LAZY_SENTINEL) { 326 global.rangeError = global.getBuiltinRangeError(); 327 } 328 return global.rangeError; 329 } 330 331 @Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) 332 public static void setRangeError(final Object self, final Object value) { 333 final Global global = Global.instanceFrom(self); 334 global.rangeError = value; 335 } 336 337 private volatile Object rangeError = LAZY_SENTINEL; 338 339 /** ReferenceError object */ 340 @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE) 341 public volatile Object referenceError; 342 343 /** SyntaxError object */ 344 @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE) 345 public volatile Object syntaxError; 346 347 /** TypeError object */ 348 @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE) 349 public volatile Object typeError; 350 351 /** URIError object */ 352 @Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) 353 public static Object getURIError(final Object self) { 354 final Global global = Global.instanceFrom(self); 355 if (global.uriError == LAZY_SENTINEL) { 356 global.uriError = global.getBuiltinURIError(); 357 } 358 return global.uriError; 359 } 360 361 @Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) 362 public static void setURIError(final Object self, final Object value) { 363 final Global global = Global.instanceFrom(self); 364 global.uriError = value; 365 } 366 367 private volatile Object uriError = LAZY_SENTINEL; 368 369 /** ArrayBuffer object */ 370 @Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) 371 public static Object getArrayBuffer(final Object self) { 372 final Global global = Global.instanceFrom(self); 373 if (global.arrayBuffer == LAZY_SENTINEL) { 374 global.arrayBuffer = global.getBuiltinArrayBuffer(); 375 } 376 return global.arrayBuffer; 377 } 378 379 @Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) 380 public static void setArrayBuffer(final Object self, final Object value) { 381 final Global global = Global.instanceFrom(self); 382 global.arrayBuffer = value; 383 } 384 385 private volatile Object arrayBuffer; 386 387 /** DataView object */ 388 @Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) 389 public static Object getDataView(final Object self) { 390 final Global global = Global.instanceFrom(self); 391 if (global.dataView == LAZY_SENTINEL) { 392 global.dataView = global.getBuiltinDataView(); 393 } 394 return global.dataView; 395 } 396 397 @Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) 398 public static void setDataView(final Object self, final Object value) { 399 final Global global = Global.instanceFrom(self); 400 global.dataView = value; 401 } 402 403 private volatile Object dataView; 404 405 /** TypedArray (int8) */ 406 @Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) 407 public static Object getInt8Array(final Object self) { 408 final Global global = Global.instanceFrom(self); 409 if (global.int8Array == LAZY_SENTINEL) { 410 global.int8Array = global.getBuiltinInt8Array(); 411 } 412 return global.int8Array; 413 } 414 415 @Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) 416 public static void setInt8Array(final Object self, final Object value) { 417 final Global global = Global.instanceFrom(self); 418 global.int8Array = value; 419 } 420 421 private volatile Object int8Array; 422 423 /** TypedArray (uint8) */ 424 @Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) 425 public static Object getUint8Array(final Object self) { 426 final Global global = Global.instanceFrom(self); 427 if (global.uint8Array == LAZY_SENTINEL) { 428 global.uint8Array = global.getBuiltinUint8Array(); 429 } 430 return global.uint8Array; 431 } 432 433 @Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) 434 public static void setUint8Array(final Object self, final Object value) { 435 final Global global = Global.instanceFrom(self); 436 global.uint8Array = value; 437 } 438 439 private volatile Object uint8Array; 440 441 /** TypedArray (uint8) - Clamped */ 442 @Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) 443 public static Object getUint8ClampedArray(final Object self) { 444 final Global global = Global.instanceFrom(self); 445 if (global.uint8ClampedArray == LAZY_SENTINEL) { 446 global.uint8ClampedArray = global.getBuiltinUint8ClampedArray(); 447 } 448 return global.uint8ClampedArray; 449 } 450 451 @Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) 452 public static void setUint8ClampedArray(final Object self, final Object value) { 453 final Global global = Global.instanceFrom(self); 454 global.uint8ClampedArray = value; 455 } 456 457 private volatile Object uint8ClampedArray; 458 459 /** TypedArray (int16) */ 460 @Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) 461 public static Object getInt16Array(final Object self) { 462 final Global global = Global.instanceFrom(self); 463 if (global.int16Array == LAZY_SENTINEL) { 464 global.int16Array = global.getBuiltinInt16Array(); 465 } 466 return global.int16Array; 467 } 468 469 @Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) 470 public static void setInt16Array(final Object self, final Object value) { 471 final Global global = Global.instanceFrom(self); 472 global.int16Array = value; 473 } 474 475 private volatile Object int16Array; 476 477 /** TypedArray (uint16) */ 478 @Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) 479 public static Object getUint16Array(final Object self) { 480 final Global global = Global.instanceFrom(self); 481 if (global.uint16Array == LAZY_SENTINEL) { 482 global.uint16Array = global.getBuiltinUint16Array(); 483 } 484 return global.uint16Array; 485 } 486 487 @Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) 488 public static void setUint16Array(final Object self, final Object value) { 489 final Global global = Global.instanceFrom(self); 490 global.uint16Array = value; 491 } 492 493 private volatile Object uint16Array; 494 495 /** TypedArray (int32) */ 496 @Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) 497 public static Object getInt32Array(final Object self) { 498 final Global global = Global.instanceFrom(self); 499 if (global.int32Array == LAZY_SENTINEL) { 500 global.int32Array = global.getBuiltinInt32Array(); 501 } 502 return global.int32Array; 503 } 504 505 @Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) 506 public static void setInt32Array(final Object self, final Object value) { 507 final Global global = Global.instanceFrom(self); 508 global.int32Array = value; 509 } 510 511 private volatile Object int32Array; 512 513 /** TypedArray (uint32) */ 514 @Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) 515 public static Object getUint32Array(final Object self) { 516 final Global global = Global.instanceFrom(self); 517 if (global.uint32Array == LAZY_SENTINEL) { 518 global.uint32Array = global.getBuiltinUint32Array(); 519 } 520 return global.uint32Array; 521 } 522 523 @Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) 524 public static void setUint32Array(final Object self, final Object value) { 525 final Global global = Global.instanceFrom(self); 526 global.uint32Array = value; 527 } 528 529 private volatile Object uint32Array; 530 531 /** TypedArray (float32) */ 532 @Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) 533 public static Object getFloat32Array(final Object self) { 534 final Global global = Global.instanceFrom(self); 535 if (global.float32Array == LAZY_SENTINEL) { 536 global.float32Array = global.getBuiltinFloat32Array(); 537 } 538 return global.float32Array; 539 } 540 541 @Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) 542 public static void setFloat32Array(final Object self, final Object value) { 543 final Global global = Global.instanceFrom(self); 544 global.float32Array = value; 545 } 546 547 private volatile Object float32Array; 548 549 /** TypedArray (float64) */ 550 @Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) 551 public static Object getFloat64Array(final Object self) { 552 final Global global = Global.instanceFrom(self); 553 if (global.float64Array == LAZY_SENTINEL) { 554 global.float64Array = global.getBuiltinFloat64Array(); 555 } 556 return global.float64Array; 557 } 558 559 @Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) 560 public static void setFloat64Array(final Object self, final Object value) { 561 final Global global = Global.instanceFrom(self); 562 global.float64Array = value; 563 } 564 565 private volatile Object float64Array; 566 567 /** Nashorn extension: Java access - global.Packages */ 568 @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE) 569 public volatile Object packages; 570 571 /** Nashorn extension: Java access - global.com */ 572 @Property(attributes = Attribute.NOT_ENUMERABLE) 573 public volatile Object com; 574 575 /** Nashorn extension: Java access - global.edu */ 576 @Property(attributes = Attribute.NOT_ENUMERABLE) 577 public volatile Object edu; 578 579 /** Nashorn extension: Java access - global.java */ 580 @Property(attributes = Attribute.NOT_ENUMERABLE) 581 public volatile Object java; 582 583 /** Nashorn extension: Java access - global.javafx */ 584 @Property(attributes = Attribute.NOT_ENUMERABLE) 585 public volatile Object javafx; 586 587 /** Nashorn extension: Java access - global.javax */ 588 @Property(attributes = Attribute.NOT_ENUMERABLE) 589 public volatile Object javax; 590 591 /** Nashorn extension: Java access - global.org */ 592 @Property(attributes = Attribute.NOT_ENUMERABLE) 593 public volatile Object org; 594 595 /** Nashorn extension: Java access - global.javaImporter */ 596 @Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) 597 public static Object getJavaImporter(final Object self) { 598 final Global global = Global.instanceFrom(self); 599 if (global.javaImporter == LAZY_SENTINEL) { 600 global.javaImporter = global.getBuiltinJavaImporter(); 601 } 602 return global.javaImporter; 603 } 604 605 @Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) 606 public static void setJavaImporter(final Object self, final Object value) { 607 final Global global = Global.instanceFrom(self); 608 global.javaImporter = value; 609 } 610 611 private volatile Object javaImporter; 612 613 /** Nashorn extension: global.Java Object constructor. */ 614 @Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE) 615 public static Object getJavaApi(final Object self) { 616 final Global global = Global.instanceFrom(self); 617 if (global.javaApi == LAZY_SENTINEL) { 618 global.javaApi = global.getBuiltinJavaApi(); 619 } 620 return global.javaApi; 621 } 622 623 @Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE) 624 public static void setJavaApi(final Object self, final Object value) { 625 final Global global = Global.instanceFrom(self); 626 global.javaApi = value; 627 } 628 629 private volatile Object javaApi; 630 631 /** Nashorn extension: current script's file name */ 632 @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) 633 public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER; 634 635 /** Nashorn extension: current script's directory */ 636 @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) 637 public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER; 638 639 /** Nashorn extension: current source line number being executed */ 640 @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) 641 public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER; 642 643 private volatile NativeDate DEFAULT_DATE; 644 645 /** Used as Date.prototype's default value */ 646 NativeDate getDefaultDate() { 647 return DEFAULT_DATE; 648 } 649 650 private volatile NativeRegExp DEFAULT_REGEXP; 651 652 /** Used as RegExp.prototype's default value */ 653 NativeRegExp getDefaultRegExp() { 654 return DEFAULT_REGEXP; 655 } 656 657 /* 658 * Built-in constructor objects: Even if user changes dynamic values of 659 * "Object", "Array" etc., we still want to keep original values of these 660 * constructors here. For example, we need to be able to create array, 661 * regexp literals even after user overwrites global "Array" or "RegExp" 662 * constructor - see also ECMA 262 spec. Annex D. 663 */ 664 private ScriptFunction builtinFunction; 665 private ScriptFunction builtinObject; 666 private ScriptFunction builtinArray; 667 private ScriptFunction builtinBoolean; 668 private ScriptFunction builtinDate; 669 private ScriptObject builtinJSON; 670 private ScriptFunction builtinJSAdapter; 671 private ScriptObject builtinMath; 672 private ScriptFunction builtinNumber; 673 private ScriptFunction builtinRegExp; 674 private ScriptFunction builtinString; 675 private ScriptFunction builtinError; 676 private ScriptFunction builtinEval; 677 private ScriptFunction builtinEvalError; 678 private ScriptFunction builtinRangeError; 679 private ScriptFunction builtinReferenceError; 680 private ScriptFunction builtinSyntaxError; 681 private ScriptFunction builtinTypeError; 682 private ScriptFunction builtinURIError; 683 private ScriptObject builtinPackages; 684 private ScriptObject builtinCom; 685 private ScriptObject builtinEdu; 686 private ScriptObject builtinJava; 687 private ScriptObject builtinJavafx; 688 private ScriptObject builtinJavax; 689 private ScriptObject builtinOrg; 690 private ScriptFunction builtinJavaImporter; 691 private ScriptObject builtinJavaApi; 692 private ScriptFunction builtinArrayBuffer; 693 private ScriptFunction builtinDataView; 694 private ScriptFunction builtinInt8Array; 695 private ScriptFunction builtinUint8Array; 696 private ScriptFunction builtinUint8ClampedArray; 697 private ScriptFunction builtinInt16Array; 698 private ScriptFunction builtinUint16Array; 699 private ScriptFunction builtinInt32Array; 700 private ScriptFunction builtinUint32Array; 701 private ScriptFunction builtinFloat32Array; 702 private ScriptFunction builtinFloat64Array; 703 704 /* 705 * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object 706 */ 707 private ScriptFunction typeErrorThrower; 708 709 // Flag to indicate that a split method issued a return statement 710 private int splitState = -1; 711 712 // Used to store the last RegExp result to support deprecated RegExp constructor properties 713 private RegExpResult lastRegExpResult; 714 715 private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class); 716 private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class); 717 private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class); 718 private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class); 719 private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class); 720 private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class); 721 private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class); 722 private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class); 723 724 // initialized by nasgen 725 private static PropertyMap $nasgenmap$; 726 727 // context to which this global belongs to 728 private final Context context; 729 730 // current ScriptContext to use - can be null. 731 private ScriptContext scontext; 732 // current ScriptEngine associated - can be null. 733 private ScriptEngine engine; 734 735 // ES6 global lexical scope. 736 private final LexicalScope lexicalScope; 737 738 // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope. 739 private SwitchPoint lexicalScopeSwitchPoint; 740 741 /** 742 * Set the current script context 743 * @param scontext script context 744 */ 745 public void setScriptContext(final ScriptContext scontext) { 746 this.scontext = scontext; 747 } 748 749 @Override 750 protected Context getContext() { 751 return context; 752 } 753 754 @Override 755 protected boolean useDualFields() { 756 return context.useDualFields(); 757 } 758 759 // performs initialization checks for Global constructor and returns the 760 // PropertyMap, if everything is fine. 761 private static PropertyMap checkAndGetMap(final Context context) { 762 // security check first 763 final SecurityManager sm = System.getSecurityManager(); 764 if (sm != null) { 765 sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL)); 766 } 767 768 Objects.requireNonNull(context); 769 770 return $nasgenmap$; 771 } 772 773 /** 774 * Constructor 775 * 776 * @param context the context 777 */ 778 public Global(final Context context) { 779 super(checkAndGetMap(context)); 780 this.context = context; 781 this.setIsScope(); 782 this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null; 783 } 784 785 /** 786 * Script access to "current" Global instance 787 * 788 * @return the global singleton 789 */ 790 public static Global instance() { 791 final Global global = Context.getGlobal(); 792 Objects.requireNonNull(global); 793 return global; 794 } 795 796 private static Global instanceFrom(final Object self) { 797 return self instanceof Global? (Global)self : instance(); 798 } 799 800 /** 801 * Check if we have a Global instance 802 * @return true if one exists 803 */ 804 public static boolean hasInstance() { 805 return Context.getGlobal() != null; 806 } 807 808 /** 809 * Script access to {@link ScriptEnvironment} 810 * 811 * @return the script environment 812 */ 813 static ScriptEnvironment getEnv() { 814 return instance().getContext().getEnv(); 815 } 816 817 /** 818 * Script access to {@link Context} 819 * 820 * @return the context 821 */ 822 static Context getThisContext() { 823 return instance().getContext(); 824 } 825 826 // Runtime interface to Global 827 828 /** 829 * Is there a class filter in the current Context? 830 * @return class filter 831 */ 832 public ClassFilter getClassFilter() { 833 return context.getClassFilter(); 834 } 835 836 /** 837 * Is this global of the given Context? 838 * @param ctxt the context 839 * @return true if this global belongs to the given Context 840 */ 841 public boolean isOfContext(final Context ctxt) { 842 return this.context == ctxt; 843 } 844 845 /** 846 * Does this global belong to a strict Context? 847 * @return true if this global belongs to a strict Context 848 */ 849 public boolean isStrictContext() { 850 return context.getEnv()._strict; 851 } 852 853 /** 854 * Initialize standard builtin objects like "Object", "Array", "Function" etc. 855 * as well as our extension builtin objects like "Java", "JSAdapter" as properties 856 * of the global scope object. 857 * 858 * @param engine ScriptEngine to initialize 859 */ 860 @SuppressWarnings("hiding") 861 public void initBuiltinObjects(final ScriptEngine engine) { 862 if (this.builtinObject != null) { 863 // already initialized, just return 864 return; 865 } 866 867 this.engine = engine; 868 init(engine); 869 } 870 871 /** 872 * Wrap a Java object as corresponding script object 873 * 874 * @param obj object to wrap 875 * @return wrapped object 876 */ 877 public Object wrapAsObject(final Object obj) { 878 if (obj instanceof Boolean) { 879 return new NativeBoolean((Boolean)obj, this); 880 } else if (obj instanceof Number) { 881 return new NativeNumber(((Number)obj).doubleValue(), this); 882 } else if (isString(obj)) { 883 return new NativeString((CharSequence)obj, this); 884 } else if (obj instanceof Object[]) { // extension 885 return new NativeArray(ArrayData.allocate((Object[])obj), this); 886 } else if (obj instanceof double[]) { // extension 887 return new NativeArray(ArrayData.allocate((double[])obj), this); 888 } else if (obj instanceof long[]) { 889 return new NativeArray(ArrayData.allocate((long[])obj), this); 890 } else if (obj instanceof int[]) { 891 return new NativeArray(ArrayData.allocate((int[]) obj), this); 892 } else if (obj instanceof ArrayData) { 893 return new NativeArray((ArrayData) obj, this); 894 } else { 895 // FIXME: more special cases? Map? List? 896 return obj; 897 } 898 } 899 900 /** 901 * Lookup helper for JS primitive types 902 * 903 * @param request the link request for the dynamic call site. 904 * @param self self reference 905 * 906 * @return guarded invocation 907 */ 908 public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) { 909 if (isString(self)) { 910 return NativeString.lookupPrimitive(request, self); 911 } else if (self instanceof Number) { 912 return NativeNumber.lookupPrimitive(request, self); 913 } else if (self instanceof Boolean) { 914 return NativeBoolean.lookupPrimitive(request, self); 915 } 916 throw new IllegalArgumentException("Unsupported primitive: " + self); 917 } 918 919 /** 920 * Returns a method handle that creates a wrapper object for a JS primitive value. 921 * 922 * @param self receiver object 923 * @return method handle to create wrapper objects for primitive receiver 924 */ 925 public static MethodHandle getPrimitiveWrapFilter(final Object self) { 926 if (isString(self)) { 927 return NativeString.WRAPFILTER; 928 } else if (self instanceof Number) { 929 return NativeNumber.WRAPFILTER; 930 } else if (self instanceof Boolean) { 931 return NativeBoolean.WRAPFILTER; 932 } 933 throw new IllegalArgumentException("Unsupported primitive: " + self); 934 } 935 936 937 /** 938 * Create a new empty script object 939 * 940 * @return the new ScriptObject 941 */ 942 public ScriptObject newObject() { 943 return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype()); 944 } 945 946 /** 947 * Default value of given type 948 * 949 * @param sobj script object 950 * @param typeHint type hint 951 * 952 * @return default value 953 */ 954 public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) { 955 // When the [[DefaultValue]] internal method of O is called with no hint, 956 // then it behaves as if the hint were Number, unless O is a Date object 957 // in which case it behaves as if the hint were String. 958 Class<?> hint = typeHint; 959 if (hint == null) { 960 hint = Number.class; 961 } 962 963 try { 964 if (hint == String.class) { 965 966 final Object toString = TO_STRING.getGetter().invokeExact(sobj); 967 968 if (Bootstrap.isCallable(toString)) { 969 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj); 970 if (JSType.isPrimitive(value)) { 971 return value; 972 } 973 } 974 975 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj); 976 if (Bootstrap.isCallable(valueOf)) { 977 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj); 978 if (JSType.isPrimitive(value)) { 979 return value; 980 } 981 } 982 throw typeError(this, "cannot.get.default.string"); 983 } 984 985 if (hint == Number.class) { 986 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj); 987 if (Bootstrap.isCallable(valueOf)) { 988 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj); 989 if (JSType.isPrimitive(value)) { 990 return value; 991 } 992 } 993 994 final Object toString = TO_STRING.getGetter().invokeExact(sobj); 995 if (Bootstrap.isCallable(toString)) { 996 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj); 997 if (JSType.isPrimitive(value)) { 998 return value; 999 } 1000 } 1001 1002 throw typeError(this, "cannot.get.default.number"); 1003 } 1004 } catch (final RuntimeException | Error e) { 1005 throw e; 1006 } catch (final Throwable t) { 1007 throw new RuntimeException(t); 1008 } 1009 1010 return UNDEFINED; 1011 } 1012 1013 /** 1014 * Is the given ScriptObject an ECMAScript Error object? 1015 * 1016 * @param sobj the object being checked 1017 * @return true if sobj is an Error object 1018 */ 1019 public boolean isError(final ScriptObject sobj) { 1020 final ScriptObject errorProto = getErrorPrototype(); 1021 ScriptObject proto = sobj.getProto(); 1022 while (proto != null) { 1023 if (proto == errorProto) { 1024 return true; 1025 } 1026 proto = proto.getProto(); 1027 } 1028 return false; 1029 } 1030 1031 /** 1032 * Create a new ECMAScript Error object. 1033 * 1034 * @param msg error message 1035 * @return newly created Error object 1036 */ 1037 public ScriptObject newError(final String msg) { 1038 return new NativeError(msg, this); 1039 } 1040 1041 /** 1042 * Create a new ECMAScript EvalError object. 1043 * 1044 * @param msg error message 1045 * @return newly created EvalError object 1046 */ 1047 public ScriptObject newEvalError(final String msg) { 1048 return new NativeEvalError(msg, this); 1049 } 1050 1051 /** 1052 * Create a new ECMAScript RangeError object. 1053 * 1054 * @param msg error message 1055 * @return newly created RangeError object 1056 */ 1057 public ScriptObject newRangeError(final String msg) { 1058 return new NativeRangeError(msg, this); 1059 } 1060 1061 /** 1062 * Create a new ECMAScript ReferenceError object. 1063 * 1064 * @param msg error message 1065 * @return newly created ReferenceError object 1066 */ 1067 public ScriptObject newReferenceError(final String msg) { 1068 return new NativeReferenceError(msg, this); 1069 } 1070 1071 /** 1072 * Create a new ECMAScript SyntaxError object. 1073 * 1074 * @param msg error message 1075 * @return newly created SyntaxError object 1076 */ 1077 public ScriptObject newSyntaxError(final String msg) { 1078 return new NativeSyntaxError(msg, this); 1079 } 1080 1081 /** 1082 * Create a new ECMAScript TypeError object. 1083 * 1084 * @param msg error message 1085 * @return newly created TypeError object 1086 */ 1087 public ScriptObject newTypeError(final String msg) { 1088 return new NativeTypeError(msg, this); 1089 } 1090 1091 /** 1092 * Create a new ECMAScript URIError object. 1093 * 1094 * @param msg error message 1095 * @return newly created URIError object 1096 */ 1097 public ScriptObject newURIError(final String msg) { 1098 return new NativeURIError(msg, this); 1099 } 1100 1101 /** 1102 * Create a new ECMAScript GenericDescriptor object. 1103 * 1104 * @param configurable is the property configurable? 1105 * @param enumerable is the property enumerable? 1106 * @return newly created GenericDescriptor object 1107 */ 1108 public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) { 1109 return new GenericPropertyDescriptor(configurable, enumerable, this); 1110 } 1111 1112 /** 1113 * Create a new ECMAScript DatePropertyDescriptor object. 1114 * 1115 * @param value of the data property 1116 * @param configurable is the property configurable? 1117 * @param enumerable is the property enumerable? 1118 * @param writable is the property writable? 1119 * @return newly created DataPropertyDescriptor object 1120 */ 1121 public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) { 1122 return new DataPropertyDescriptor(configurable, enumerable, writable, value, this); 1123 } 1124 1125 /** 1126 * Create a new ECMAScript AccessorPropertyDescriptor object. 1127 * 1128 * @param get getter function of the user accessor property 1129 * @param set setter function of the user accessor property 1130 * @param configurable is the property configurable? 1131 * @param enumerable is the property enumerable? 1132 * @return newly created AccessorPropertyDescriptor object 1133 */ 1134 public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) { 1135 final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this); 1136 1137 if (get == null) { 1138 desc.delete(PropertyDescriptor.GET, false); 1139 } 1140 1141 if (set == null) { 1142 desc.delete(PropertyDescriptor.SET, false); 1143 } 1144 1145 return desc; 1146 } 1147 1148 private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) { 1149 final T obj = map.get(key); 1150 if (obj != null) { 1151 return obj; 1152 } 1153 1154 try { 1155 final T newObj = creator.call(); 1156 final T existingObj = map.putIfAbsent(key, newObj); 1157 return existingObj != null ? existingObj : newObj; 1158 } catch (final Exception exp) { 1159 throw new RuntimeException(exp); 1160 } 1161 } 1162 1163 private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>(); 1164 1165 1166 /** 1167 * Get cached InvokeByName object for the given key 1168 * @param key key to be associated with InvokeByName object 1169 * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init) 1170 * @return InvokeByName object associated with the key. 1171 */ 1172 public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) { 1173 return getLazilyCreatedValue(key, creator, namedInvokers); 1174 } 1175 1176 private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>(); 1177 1178 /** 1179 * Get cached dynamic method handle for the given key 1180 * @param key key to be associated with dynamic method handle 1181 * @param creator if method handle is absent 'creator' is called to make one (lazy init) 1182 * @return dynamic method handle associated with the key. 1183 */ 1184 public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) { 1185 return getLazilyCreatedValue(key, creator, dynamicInvokers); 1186 } 1187 1188 /** 1189 * Hook to search missing variables in ScriptContext if available 1190 * @param self used to detect if scope call or not (this function is 'strict') 1191 * @param name name of the variable missing 1192 * @return value of the missing variable or undefined (or TypeError for scope search) 1193 */ 1194 public static Object __noSuchProperty__(final Object self, final Object name) { 1195 final Global global = Global.instance(); 1196 final ScriptContext sctxt = global.scontext; 1197 final String nameStr = name.toString(); 1198 1199 if (sctxt != null) { 1200 final int scope = sctxt.getAttributesScope(nameStr); 1201 if (scope != -1) { 1202 return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global); 1203 } 1204 } 1205 1206 switch (nameStr) { 1207 case "context": 1208 return sctxt; 1209 case "engine": 1210 return global.engine; 1211 default: 1212 break; 1213 } 1214 1215 if (self == UNDEFINED) { 1216 // scope access and so throw ReferenceError 1217 throw referenceError(global, "not.defined", nameStr); 1218 } 1219 1220 return UNDEFINED; 1221 } 1222 1223 /** 1224 * This is the eval used when 'indirect' eval call is made. 1225 * 1226 * var global = this; 1227 * global.eval("print('hello')"); 1228 * 1229 * @param self eval scope 1230 * @param str eval string 1231 * 1232 * @return the result of eval 1233 */ 1234 public static Object eval(final Object self, final Object str) { 1235 return directEval(self, str, UNDEFINED, UNDEFINED, false); 1236 } 1237 1238 /** 1239 * Direct eval 1240 * 1241 * @param self The scope of eval passed as 'self' 1242 * @param str Evaluated code 1243 * @param callThis "this" to be passed to the evaluated code 1244 * @param location location of the eval call 1245 * @param strict is eval called a strict mode code? 1246 * 1247 * @return the return value of the eval 1248 * 1249 * This is directly invoked from generated when eval(code) is called in user code 1250 */ 1251 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) { 1252 if (!isString(str)) { 1253 return str; 1254 } 1255 final Global global = Global.instanceFrom(self); 1256 final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global; 1257 1258 return global.getContext().eval(scope, str.toString(), callThis, location, strict, true); 1259 } 1260 1261 /** 1262 * Global print implementation - Nashorn extension 1263 * 1264 * @param self scope 1265 * @param objects arguments to print 1266 * 1267 * @return result of print (undefined) 1268 */ 1269 public static Object print(final Object self, final Object... objects) { 1270 return Global.instanceFrom(self).printImpl(false, objects); 1271 } 1272 1273 /** 1274 * Global println implementation - Nashorn extension 1275 * 1276 * @param self scope 1277 * @param objects arguments to print 1278 * 1279 * @return result of println (undefined) 1280 */ 1281 public static Object println(final Object self, final Object... objects) { 1282 return Global.instanceFrom(self).printImpl(true, objects); 1283 } 1284 1285 /** 1286 * Global load implementation - Nashorn extension 1287 * 1288 * @param self scope 1289 * @param source source to load 1290 * 1291 * @return result of load (undefined) 1292 * 1293 * @throws IOException if source could not be read 1294 */ 1295 public static Object load(final Object self, final Object source) throws IOException { 1296 final Global global = Global.instanceFrom(self); 1297 final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global; 1298 return global.getContext().load(scope, source); 1299 } 1300 1301 /** 1302 * Global loadWithNewGlobal implementation - Nashorn extension 1303 * 1304 * @param self scope 1305 * @param args from plus (optional) arguments to be passed to the loaded script 1306 * 1307 * @return result of load (may be undefined) 1308 * 1309 * @throws IOException if source could not be read 1310 */ 1311 public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException { 1312 final Global global = Global.instanceFrom(self); 1313 final int length = args.length; 1314 final boolean hasArgs = 0 < length; 1315 final Object from = hasArgs ? args[0] : UNDEFINED; 1316 final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args; 1317 1318 return global.getContext().loadWithNewGlobal(from, arguments); 1319 } 1320 1321 /** 1322 * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script 1323 * 1324 * @param self self reference 1325 * @param code exit code 1326 * 1327 * @return undefined (will never be reached) 1328 */ 1329 public static Object exit(final Object self, final Object code) { 1330 System.exit(JSType.toInt32(code)); 1331 return UNDEFINED; 1332 } 1333 1334 // builtin prototype accessors 1335 1336 /** 1337 * Get the builtin Object prototype. 1338 * @return the object prototype. 1339 */ 1340 public ScriptObject getObjectPrototype() { 1341 return ScriptFunction.getPrototype(builtinObject); 1342 } 1343 1344 ScriptObject getFunctionPrototype() { 1345 return ScriptFunction.getPrototype(builtinFunction); 1346 } 1347 1348 ScriptObject getArrayPrototype() { 1349 return ScriptFunction.getPrototype(builtinArray); 1350 } 1351 1352 ScriptObject getBooleanPrototype() { 1353 return ScriptFunction.getPrototype(builtinBoolean); 1354 } 1355 1356 ScriptObject getNumberPrototype() { 1357 return ScriptFunction.getPrototype(builtinNumber); 1358 } 1359 1360 ScriptObject getDatePrototype() { 1361 return ScriptFunction.getPrototype(getBuiltinDate()); 1362 } 1363 1364 ScriptObject getRegExpPrototype() { 1365 return ScriptFunction.getPrototype(getBuiltinRegExp()); 1366 } 1367 1368 ScriptObject getStringPrototype() { 1369 return ScriptFunction.getPrototype(builtinString); 1370 } 1371 1372 ScriptObject getErrorPrototype() { 1373 return ScriptFunction.getPrototype(builtinError); 1374 } 1375 1376 ScriptObject getEvalErrorPrototype() { 1377 return ScriptFunction.getPrototype(getBuiltinEvalError()); 1378 } 1379 1380 ScriptObject getRangeErrorPrototype() { 1381 return ScriptFunction.getPrototype(getBuiltinRangeError()); 1382 } 1383 1384 ScriptObject getReferenceErrorPrototype() { 1385 return ScriptFunction.getPrototype(builtinReferenceError); 1386 } 1387 1388 ScriptObject getSyntaxErrorPrototype() { 1389 return ScriptFunction.getPrototype(builtinSyntaxError); 1390 } 1391 1392 ScriptObject getTypeErrorPrototype() { 1393 return ScriptFunction.getPrototype(builtinTypeError); 1394 } 1395 1396 ScriptObject getURIErrorPrototype() { 1397 return ScriptFunction.getPrototype(getBuiltinURIError()); 1398 } 1399 1400 ScriptObject getJavaImporterPrototype() { 1401 return ScriptFunction.getPrototype(getBuiltinJavaImporter()); 1402 } 1403 1404 ScriptObject getJSAdapterPrototype() { 1405 return ScriptFunction.getPrototype(getBuiltinJSAdapter()); 1406 } 1407 1408 private synchronized ScriptFunction getBuiltinArrayBuffer() { 1409 if (this.builtinArrayBuffer == null) { 1410 this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); 1411 } 1412 return this.builtinArrayBuffer; 1413 } 1414 1415 ScriptObject getArrayBufferPrototype() { 1416 return ScriptFunction.getPrototype(getBuiltinArrayBuffer()); 1417 } 1418 1419 private synchronized ScriptFunction getBuiltinDataView() { 1420 if (this.builtinDataView == null) { 1421 this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); 1422 } 1423 return this.builtinDataView; 1424 } 1425 1426 ScriptObject getDataViewPrototype() { 1427 return ScriptFunction.getPrototype(getBuiltinDataView()); 1428 } 1429 1430 private synchronized ScriptFunction getBuiltinInt8Array() { 1431 if (this.builtinInt8Array == null) { 1432 this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); 1433 } 1434 return this.builtinInt8Array; 1435 } 1436 1437 ScriptObject getInt8ArrayPrototype() { 1438 return ScriptFunction.getPrototype(getBuiltinInt8Array()); 1439 } 1440 1441 private synchronized ScriptFunction getBuiltinUint8Array() { 1442 if (this.builtinUint8Array == null) { 1443 this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); 1444 } 1445 return this.builtinUint8Array; 1446 } 1447 1448 ScriptObject getUint8ArrayPrototype() { 1449 return ScriptFunction.getPrototype(getBuiltinUint8Array()); 1450 } 1451 1452 private synchronized ScriptFunction getBuiltinUint8ClampedArray() { 1453 if (this.builtinUint8ClampedArray == null) { 1454 this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); 1455 } 1456 return this.builtinUint8ClampedArray; 1457 } 1458 1459 ScriptObject getUint8ClampedArrayPrototype() { 1460 return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray()); 1461 } 1462 1463 private synchronized ScriptFunction getBuiltinInt16Array() { 1464 if (this.builtinInt16Array == null) { 1465 this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); 1466 } 1467 return this.builtinInt16Array; 1468 } 1469 1470 ScriptObject getInt16ArrayPrototype() { 1471 return ScriptFunction.getPrototype(getBuiltinInt16Array()); 1472 } 1473 1474 private synchronized ScriptFunction getBuiltinUint16Array() { 1475 if (this.builtinUint16Array == null) { 1476 this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); 1477 } 1478 return this.builtinUint16Array; 1479 } 1480 1481 ScriptObject getUint16ArrayPrototype() { 1482 return ScriptFunction.getPrototype(getBuiltinUint16Array()); 1483 } 1484 1485 private synchronized ScriptFunction getBuiltinInt32Array() { 1486 if (this.builtinInt32Array == null) { 1487 this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); 1488 } 1489 return this.builtinInt32Array; 1490 } 1491 1492 ScriptObject getInt32ArrayPrototype() { 1493 return ScriptFunction.getPrototype(getBuiltinInt32Array()); 1494 } 1495 1496 private synchronized ScriptFunction getBuiltinUint32Array() { 1497 if (this.builtinUint32Array == null) { 1498 this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); 1499 } 1500 return this.builtinUint32Array; 1501 } 1502 1503 ScriptObject getUint32ArrayPrototype() { 1504 return ScriptFunction.getPrototype(getBuiltinUint32Array()); 1505 } 1506 1507 private synchronized ScriptFunction getBuiltinFloat32Array() { 1508 if (this.builtinFloat32Array == null) { 1509 this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); 1510 } 1511 return this.builtinFloat32Array; 1512 } 1513 1514 ScriptObject getFloat32ArrayPrototype() { 1515 return ScriptFunction.getPrototype(getBuiltinFloat32Array()); 1516 } 1517 1518 private synchronized ScriptFunction getBuiltinFloat64Array() { 1519 if (this.builtinFloat64Array == null) { 1520 this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); 1521 } 1522 return this.builtinFloat64Array; 1523 } 1524 1525 ScriptObject getFloat64ArrayPrototype() { 1526 return ScriptFunction.getPrototype(getBuiltinFloat64Array()); 1527 } 1528 1529 private ScriptFunction getBuiltinArray() { 1530 return builtinArray; 1531 } 1532 1533 ScriptFunction getTypeErrorThrower() { 1534 return typeErrorThrower; 1535 } 1536 1537 /** 1538 * Called from compiled script code to test if builtin has been overridden 1539 * 1540 * @return true if builtin array has not been overridden 1541 */ 1542 public static boolean isBuiltinArray() { 1543 final Global instance = Global.instance(); 1544 return instance.array == instance.getBuiltinArray(); 1545 } 1546 1547 private ScriptFunction getBuiltinBoolean() { 1548 return builtinBoolean; 1549 } 1550 1551 /** 1552 * Called from compiled script code to test if builtin has been overridden 1553 * 1554 * @return true if builtin boolean has not been overridden 1555 */ 1556 public static boolean isBuiltinBoolean() { 1557 final Global instance = Global.instance(); 1558 return instance._boolean == instance.getBuiltinBoolean(); 1559 } 1560 1561 private synchronized ScriptFunction getBuiltinDate() { 1562 if (this.builtinDate == null) { 1563 this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); 1564 final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate); 1565 // initialize default date 1566 this.DEFAULT_DATE = new NativeDate(NaN, dateProto); 1567 } 1568 return this.builtinDate; 1569 } 1570 1571 /** 1572 * Called from compiled script code to test if builtin has been overridden 1573 * 1574 * @return true if builtin date has not been overridden 1575 */ 1576 public static boolean isBuiltinDate() { 1577 final Global instance = Global.instance(); 1578 return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate(); 1579 } 1580 1581 private ScriptFunction getBuiltinError() { 1582 return builtinError; 1583 } 1584 1585 /** 1586 * Called from compiled script code to test if builtin has been overridden 1587 * 1588 * @return true if builtin error has not been overridden 1589 */ 1590 public static boolean isBuiltinError() { 1591 final Global instance = Global.instance(); 1592 return instance.error == instance.getBuiltinError(); 1593 } 1594 1595 private synchronized ScriptFunction getBuiltinEvalError() { 1596 if (this.builtinEvalError == null) { 1597 this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype()); 1598 } 1599 return this.builtinEvalError; 1600 } 1601 1602 /** 1603 * Called from compiled script code to test if builtin has been overridden 1604 * 1605 * @return true if builtin eval error has not been overridden 1606 */ 1607 public static boolean isBuiltinEvalError() { 1608 final Global instance = Global.instance(); 1609 return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError(); 1610 } 1611 1612 private ScriptFunction getBuiltinFunction() { 1613 return builtinFunction; 1614 } 1615 1616 /** 1617 * Called from compiled script code to test if builtin has been overridden 1618 * 1619 * @return true if builtin function has not been overridden 1620 */ 1621 public static boolean isBuiltinFunction() { 1622 final Global instance = Global.instance(); 1623 return instance.function == instance.getBuiltinFunction(); 1624 } 1625 1626 /** 1627 * Get the switchpoint used to check property changes for Function.prototype.apply 1628 * @return the switchpoint guarding apply (same as guarding call, and everything else in function) 1629 */ 1630 public static SwitchPoint getBuiltinFunctionApplySwitchPoint() { 1631 return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint(); 1632 } 1633 1634 private static boolean isBuiltinFunctionProperty(final String name) { 1635 final Global instance = Global.instance(); 1636 final ScriptFunction builtinFunction = instance.getBuiltinFunction(); 1637 if (builtinFunction == null) { 1638 return false; //conservative for compile-only mode 1639 } 1640 final boolean isBuiltinFunction = instance.function == builtinFunction; 1641 return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin(); 1642 } 1643 1644 /** 1645 * Check if the Function.prototype.apply has not been replaced 1646 * @return true if Function.prototype.apply has been replaced 1647 */ 1648 public static boolean isBuiltinFunctionPrototypeApply() { 1649 return isBuiltinFunctionProperty("apply"); 1650 } 1651 1652 /** 1653 * Check if the Function.prototype.apply has not been replaced 1654 * @return true if Function.prototype.call has been replaced 1655 */ 1656 public static boolean isBuiltinFunctionPrototypeCall() { 1657 return isBuiltinFunctionProperty("call"); 1658 } 1659 1660 private synchronized ScriptFunction getBuiltinJSAdapter() { 1661 if (this.builtinJSAdapter == null) { 1662 this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class); 1663 } 1664 return builtinJSAdapter; 1665 } 1666 1667 /** 1668 * Called from compiled script code to test if builtin has been overridden 1669 * 1670 * @return true if builtin JSAdapter has not been overridden 1671 */ 1672 public static boolean isBuiltinJSAdapter() { 1673 final Global instance = Global.instance(); 1674 return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter(); 1675 } 1676 1677 private synchronized ScriptObject getBuiltinJSON() { 1678 if (this.builtinJSON == null) { 1679 this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); 1680 } 1681 return this.builtinJSON; 1682 } 1683 1684 /** 1685 * Called from compiled script code to test if builtin has been overridden 1686 * 1687 * @return true if builtin JSON has has not been overridden 1688 */ 1689 public static boolean isBuiltinJSON() { 1690 final Global instance = Global.instance(); 1691 return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON(); 1692 } 1693 1694 private ScriptObject getBuiltinJava() { 1695 return builtinJava; 1696 } 1697 1698 /** 1699 * Called from compiled script code to test if builtin has been overridden 1700 * 1701 * @return true if builtin Java has not been overridden 1702 */ 1703 public static boolean isBuiltinJava() { 1704 final Global instance = Global.instance(); 1705 return instance.java == instance.getBuiltinJava(); 1706 } 1707 1708 private ScriptObject getBuiltinJavax() { 1709 return builtinJavax; 1710 } 1711 1712 /** 1713 * Called from compiled script code to test if builtin has been overridden 1714 * 1715 * @return true if builtin Javax has not been overridden 1716 */ 1717 public static boolean isBuiltinJavax() { 1718 final Global instance = Global.instance(); 1719 return instance.javax == instance.getBuiltinJavax(); 1720 } 1721 1722 private synchronized ScriptFunction getBuiltinJavaImporter() { 1723 if (this.builtinJavaImporter == null) { 1724 this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); 1725 } 1726 return this.builtinJavaImporter; 1727 } 1728 1729 private synchronized ScriptObject getBuiltinJavaApi() { 1730 if (this.builtinJavaApi == null) { 1731 this.builtinJavaApi = initConstructor("Java", ScriptObject.class); 1732 } 1733 return this.builtinJavaApi; 1734 } 1735 1736 /** 1737 * Called from compiled script code to test if builtin has been overridden 1738 * 1739 * @return true if builtin Java importer has not been overridden 1740 */ 1741 public static boolean isBuiltinJavaImporter() { 1742 final Global instance = Global.instance(); 1743 return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter(); 1744 } 1745 1746 /** 1747 * Called from compiled script code to test if builtin has been overridden 1748 * 1749 * @return true if builtin math has not been overridden 1750 */ 1751 public static boolean isBuiltinMath() { 1752 final Global instance = Global.instance(); 1753 return instance.math == instance.builtinMath; 1754 } 1755 1756 private ScriptFunction getBuiltinNumber() { 1757 return builtinNumber; 1758 } 1759 1760 /** 1761 * Called from compiled script code to test if builtin has been overridden 1762 * 1763 * @return true if builtin number has not been overridden 1764 */ 1765 public static boolean isBuiltinNumber() { 1766 final Global instance = Global.instance(); 1767 return instance.number == instance.getBuiltinNumber(); 1768 } 1769 1770 private ScriptFunction getBuiltinObject() { 1771 return builtinObject; 1772 } 1773 1774 /** 1775 * Called from compiled script code to test if builtin has been overridden 1776 * 1777 * @return true if builtin object has not been overridden 1778 */ 1779 public static boolean isBuiltinObject() { 1780 final Global instance = Global.instance(); 1781 return instance.object == instance.getBuiltinObject(); 1782 } 1783 1784 private ScriptObject getBuiltinPackages() { 1785 return builtinPackages; 1786 } 1787 1788 /** 1789 * Called from compiled script code to test if builtin has been overridden 1790 * 1791 * @return true if builtin package has not been overridden 1792 */ 1793 public static boolean isBuiltinPackages() { 1794 final Global instance = Global.instance(); 1795 return instance.packages == instance.getBuiltinPackages(); 1796 } 1797 1798 private synchronized ScriptFunction getBuiltinRangeError() { 1799 if (this.builtinRangeError == null) { 1800 this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype()); 1801 } 1802 return builtinRangeError; 1803 } 1804 1805 /** 1806 * Called from compiled script code to test if builtin has been overridden 1807 * 1808 * @return true if builtin range error has not been overridden 1809 */ 1810 public static boolean isBuiltinRangeError() { 1811 final Global instance = Global.instance(); 1812 return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError(); 1813 } 1814 1815 private synchronized ScriptFunction getBuiltinReferenceError() { 1816 return builtinReferenceError; 1817 } 1818 1819 /** 1820 * Called from compiled script code to test if builtin has been overridden 1821 * 1822 * @return true if builtin reference error has not been overridden 1823 */ 1824 public static boolean isBuiltinReferenceError() { 1825 final Global instance = Global.instance(); 1826 return instance.referenceError == instance.getBuiltinReferenceError(); 1827 } 1828 1829 private synchronized ScriptFunction getBuiltinRegExp() { 1830 if (this.builtinRegExp == null) { 1831 this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); 1832 final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp); 1833 // initialize default regexp object 1834 this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto); 1835 // RegExp.prototype should behave like a RegExp object. So copy the 1836 // properties. 1837 regExpProto.addBoundProperties(DEFAULT_REGEXP); 1838 } 1839 return builtinRegExp; 1840 } 1841 1842 /** 1843 * Called from compiled script code to test if builtin has been overridden 1844 * 1845 * @return true if builtin regexp has not been overridden 1846 */ 1847 public static boolean isBuiltinRegExp() { 1848 final Global instance = Global.instance(); 1849 return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp(); 1850 } 1851 1852 private ScriptFunction getBuiltinString() { 1853 return builtinString; 1854 } 1855 1856 /** 1857 * Called from compiled script code to test if builtin has been overridden 1858 * 1859 * @return true if builtin Java has not been overridden 1860 */ 1861 public static boolean isBuiltinString() { 1862 final Global instance = Global.instance(); 1863 return instance.string == instance.getBuiltinString(); 1864 } 1865 1866 private ScriptFunction getBuiltinSyntaxError() { 1867 return builtinSyntaxError; 1868 } 1869 1870 /** 1871 * Called from compiled script code to test if builtin has been overridden 1872 * 1873 * @return true if builtin syntax error has not been overridden 1874 */ 1875 public static boolean isBuiltinSyntaxError() { 1876 final Global instance = Global.instance(); 1877 return instance.syntaxError == instance.getBuiltinSyntaxError(); 1878 } 1879 1880 private ScriptFunction getBuiltinTypeError() { 1881 return builtinTypeError; 1882 } 1883 1884 /** 1885 * Called from compiled script code to test if builtin has been overridden 1886 * 1887 * @return true if builtin type error has not been overridden 1888 */ 1889 public static boolean isBuiltinTypeError() { 1890 final Global instance = Global.instance(); 1891 return instance.typeError == instance.getBuiltinTypeError(); 1892 } 1893 1894 private synchronized ScriptFunction getBuiltinURIError() { 1895 if (this.builtinURIError == null) { 1896 this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype()); 1897 } 1898 return this.builtinURIError; 1899 } 1900 1901 /** 1902 * Called from compiled script code to test if builtin has been overridden 1903 * 1904 * @return true if builtin URI error has not been overridden 1905 */ 1906 public static boolean isBuiltinURIError() { 1907 final Global instance = Global.instance(); 1908 return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError(); 1909 } 1910 1911 @Override 1912 public String getClassName() { 1913 return "global"; 1914 } 1915 1916 /** 1917 * Copy function used to clone NativeRegExp objects. 1918 * 1919 * @param regexp a NativeRegExp to clone 1920 * 1921 * @return copy of the given regexp object 1922 */ 1923 public static Object regExpCopy(final Object regexp) { 1924 return new NativeRegExp((NativeRegExp)regexp); 1925 } 1926 1927 /** 1928 * Convert given object to NativeRegExp type. 1929 * 1930 * @param obj object to be converted 1931 * @return NativeRegExp instance 1932 */ 1933 public static NativeRegExp toRegExp(final Object obj) { 1934 if (obj instanceof NativeRegExp) { 1935 return (NativeRegExp)obj; 1936 } 1937 return new NativeRegExp(JSType.toString(obj)); 1938 } 1939 1940 /** 1941 * ECMA 9.9 ToObject implementation 1942 * 1943 * @param obj an item for which to run ToObject 1944 * @return ToObject version of given item 1945 */ 1946 public static Object toObject(final Object obj) { 1947 if (obj == null || obj == UNDEFINED) { 1948 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 1949 } 1950 1951 if (obj instanceof ScriptObject) { 1952 return obj; 1953 } 1954 1955 return instance().wrapAsObject(obj); 1956 } 1957 1958 /** 1959 * Allocate a new object array. 1960 * 1961 * @param initial object values. 1962 * @return the new array 1963 */ 1964 public static NativeArray allocate(final Object[] initial) { 1965 ArrayData arrayData = ArrayData.allocate(initial); 1966 1967 for (int index = 0; index < initial.length; index++) { 1968 final Object value = initial[index]; 1969 1970 if (value == ScriptRuntime.EMPTY) { 1971 arrayData = arrayData.delete(index); 1972 } 1973 } 1974 1975 return new NativeArray(arrayData); 1976 } 1977 1978 /** 1979 * Allocate a new number array. 1980 * 1981 * @param initial number values. 1982 * @return the new array 1983 */ 1984 public static NativeArray allocate(final double[] initial) { 1985 return new NativeArray(ArrayData.allocate(initial)); 1986 } 1987 1988 /** 1989 * Allocate a new long array. 1990 * 1991 * @param initial number values. 1992 * @return the new array 1993 */ 1994 public static NativeArray allocate(final long[] initial) { 1995 return new NativeArray(ArrayData.allocate(initial)); 1996 } 1997 1998 /** 1999 * Allocate a new integer array. 2000 * 2001 * @param initial number values. 2002 * @return the new array 2003 */ 2004 public static NativeArray allocate(final int[] initial) { 2005 return new NativeArray(ArrayData.allocate(initial)); 2006 } 2007 2008 /** 2009 * Allocate a new object array for arguments. 2010 * 2011 * @param arguments initial arguments passed. 2012 * @param callee reference to the function that uses arguments object 2013 * @param numParams actual number of declared parameters 2014 * 2015 * @return the new array 2016 */ 2017 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) { 2018 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams); 2019 } 2020 2021 /** 2022 * Called from generated to check if given function is the builtin 'eval'. If 2023 * eval is used in a script, a lot of optimizations and assumptions cannot be done. 2024 * 2025 * @param fn function object that is checked 2026 * @return true if fn is the builtin eval 2027 */ 2028 public static boolean isEval(final Object fn) { 2029 return fn == Global.instance().builtinEval; 2030 } 2031 2032 /** 2033 * Called from generated to replace a location property placeholder with the actual location property value. 2034 * 2035 * @param placeholder the value tested for being a placeholder for a location property 2036 * @param locationProperty the actual value for the location property 2037 * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise 2038 */ 2039 public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) { 2040 return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder; 2041 } 2042 2043 /** 2044 * Called from runtime internals to check if the passed value is a location property placeholder. 2045 * @param placeholder the value tested for being a placeholder for a location property 2046 * @return true if the value is a placeholder, false otherwise. 2047 */ 2048 public static boolean isLocationPropertyPlaceholder(final Object placeholder) { 2049 return placeholder == LOCATION_PROPERTY_PLACEHOLDER; 2050 } 2051 2052 /** 2053 * Create a new RegExp object. 2054 * 2055 * @param expression Regular expression. 2056 * @param options Search options. 2057 * 2058 * @return New RegExp object. 2059 */ 2060 public static Object newRegExp(final String expression, final String options) { 2061 if (options == null) { 2062 return new NativeRegExp(expression); 2063 } 2064 return new NativeRegExp(expression, options); 2065 } 2066 2067 /** 2068 * Get the object prototype 2069 * 2070 * @return the object prototype 2071 */ 2072 public static ScriptObject objectPrototype() { 2073 return Global.instance().getObjectPrototype(); 2074 } 2075 2076 /** 2077 * Create a new empty object instance. 2078 * 2079 * @return New empty object. 2080 */ 2081 public static ScriptObject newEmptyInstance() { 2082 return Global.instance().newObject(); 2083 } 2084 2085 /** 2086 * Check if a given object is a ScriptObject, raises an exception if this is 2087 * not the case 2088 * 2089 * @param obj and object to check 2090 * @return the script object 2091 */ 2092 public static ScriptObject checkObject(final Object obj) { 2093 if (!(obj instanceof ScriptObject)) { 2094 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 2095 } 2096 return (ScriptObject)obj; 2097 } 2098 2099 /** 2100 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception 2101 * if this object is null or undefined. 2102 * 2103 * @param obj an object to check 2104 */ 2105 public static void checkObjectCoercible(final Object obj) { 2106 if (obj == null || obj == UNDEFINED) { 2107 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 2108 } 2109 } 2110 2111 /** 2112 * Get the current split state. 2113 * 2114 * @return current split state 2115 */ 2116 @Override 2117 public int getSplitState() { 2118 return splitState; 2119 } 2120 2121 /** 2122 * Set the current split state. 2123 * 2124 * @param state current split state 2125 */ 2126 @Override 2127 public void setSplitState(final int state) { 2128 splitState = state; 2129 } 2130 2131 /** 2132 * Return the ES6 global scope for lexically declared bindings. 2133 * @return the ES6 lexical global scope. 2134 */ 2135 public final ScriptObject getLexicalScope() { 2136 assert context.getEnv()._es6; 2137 return lexicalScope; 2138 } 2139 2140 @Override 2141 public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) { 2142 PropertyMap ownMap = getMap(); 2143 LexicalScope lexicalScope = null; 2144 PropertyMap lexicalMap = null; 2145 boolean hasLexicalDefinitions = false; 2146 2147 if (context.getEnv()._es6) { 2148 lexicalScope = (LexicalScope) getLexicalScope(); 2149 lexicalMap = lexicalScope.getMap(); 2150 2151 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2152 if (property.isLexicalBinding()) { 2153 hasLexicalDefinitions = true; 2154 } 2155 // ES6 15.1.8 steps 6. and 7. 2156 final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey()); 2157 if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) { 2158 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey()); 2159 } 2160 final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey()); 2161 if (lexicalProperty != null && !property.isConfigurable()) { 2162 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey()); 2163 } 2164 } 2165 } 2166 2167 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2168 if (property.isLexicalBinding()) { 2169 assert lexicalScope != null; 2170 lexicalMap = lexicalScope.addBoundProperty(lexicalMap, source, property); 2171 2172 if (ownMap.findProperty(property.getKey()) != null) { 2173 // If property exists in the global object invalidate any global constant call sites. 2174 invalidateGlobalConstant(property.getKey()); 2175 } 2176 } else { 2177 ownMap = addBoundProperty(ownMap, source, property); 2178 } 2179 } 2180 2181 setMap(ownMap); 2182 2183 if (hasLexicalDefinitions) { 2184 lexicalScope.setMap(lexicalMap); 2185 invalidateLexicalSwitchPoint(); 2186 } 2187 } 2188 2189 @Override 2190 public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 2191 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 2192 final boolean isScope = NashornCallSiteDescriptor.isScope(desc); 2193 2194 if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) { 2195 if (lexicalScope.hasOwnProperty(name)) { 2196 return lexicalScope.findGetMethod(desc, request, operator); 2197 } 2198 } 2199 2200 final GuardedInvocation invocation = super.findGetMethod(desc, request, operator); 2201 2202 // We want to avoid adding our generic lexical scope switchpoint to global constant invocations, 2203 // because those are invalidated per-key in the addBoundProperties method above. 2204 // We therefor check if the invocation does already have a switchpoint and the property is non-inherited, 2205 // assuming this only applies to global constants. If other non-inherited properties will 2206 // start using switchpoints some time in the future we'll have to revisit this. 2207 if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) { 2208 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint()); 2209 } 2210 2211 return invocation; 2212 } 2213 2214 @Override 2215 protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) { 2216 if (lexicalScope != null && start != this && start.isScope()) { 2217 final FindProperty find = lexicalScope.findProperty(key, false); 2218 if (find != null) { 2219 return find; 2220 } 2221 } 2222 return super.findProperty(key, deep, start); 2223 } 2224 2225 @Override 2226 public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 2227 final boolean isScope = NashornCallSiteDescriptor.isScope(desc); 2228 2229 if (lexicalScope != null && isScope) { 2230 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 2231 if (lexicalScope.hasOwnProperty(name)) { 2232 return lexicalScope.findSetMethod(desc, request); 2233 } 2234 } 2235 2236 final GuardedInvocation invocation = super.findSetMethod(desc, request); 2237 2238 if (isScope && context.getEnv()._es6) { 2239 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint()); 2240 } 2241 2242 return invocation; 2243 } 2244 2245 /** 2246 * Adds jjs shell interactive mode builtin functions to global scope. 2247 */ 2248 public void addShellBuiltins() { 2249 Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT); 2250 addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); 2251 2252 value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT); 2253 addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); 2254 } 2255 2256 private synchronized SwitchPoint getLexicalScopeSwitchPoint() { 2257 SwitchPoint switchPoint = lexicalScopeSwitchPoint; 2258 if (switchPoint == null || switchPoint.hasBeenInvalidated()) { 2259 switchPoint = lexicalScopeSwitchPoint = new SwitchPoint(); 2260 } 2261 return switchPoint; 2262 } 2263 2264 private synchronized void invalidateLexicalSwitchPoint() { 2265 if (lexicalScopeSwitchPoint != null) { 2266 context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update"); 2267 SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint }); 2268 } 2269 } 2270 2271 2272 @SuppressWarnings("unused") 2273 private static Object lexicalScopeFilter(final Object self) { 2274 if (self instanceof Global) { 2275 return ((Global) self).getLexicalScope(); 2276 } 2277 return self; 2278 } 2279 2280 private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) { 2281 final T func = initConstructor(name, clazz); 2282 tagBuiltinProperties(name, func); 2283 return func; 2284 } 2285 2286 @SuppressWarnings("hiding") 2287 private void init(final ScriptEngine engine) { 2288 assert Context.getGlobal() == this : "this global is not set as current"; 2289 2290 final ScriptEnvironment env = getContext().getEnv(); 2291 2292 // initialize Function and Object constructor 2293 initFunctionAndObject(); 2294 2295 // Now fix Global's own proto. 2296 this.setInitialProto(getObjectPrototype()); 2297 2298 // initialize global function properties 2299 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL); 2300 2301 this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT, 2302 new Specialization[] { 2303 new Specialization(GlobalFunctions.PARSEINT_Z), 2304 new Specialization(GlobalFunctions.PARSEINT_I), 2305 new Specialization(GlobalFunctions.PARSEINT_J), 2306 new Specialization(GlobalFunctions.PARSEINT_OI), 2307 new Specialization(GlobalFunctions.PARSEINT_O) }); 2308 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); 2309 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN, 2310 new Specialization[] { 2311 new Specialization(GlobalFunctions.IS_NAN_I), 2312 new Specialization(GlobalFunctions.IS_NAN_J), 2313 new Specialization(GlobalFunctions.IS_NAN_D) }); 2314 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); 2315 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN); 2316 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE); 2317 this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI); 2318 this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); 2319 this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI); 2320 this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); 2321 this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE); 2322 this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE); 2323 this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN); 2324 this.load = ScriptFunctionImpl.makeFunction("load", LOAD); 2325 this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL); 2326 this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT); 2327 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT); 2328 2329 // built-in constructors 2330 this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); 2331 this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class); 2332 this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); 2333 this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); 2334 this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class); 2335 2336 // initialize String.prototype.length to 0 2337 // add String.prototype.length 2338 final ScriptObject stringPrototype = getStringPrototype(); 2339 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0); 2340 2341 // set isArray flag on Array.prototype 2342 final ScriptObject arrayPrototype = getArrayPrototype(); 2343 arrayPrototype.setIsArray(); 2344 2345 // Error stuff 2346 initErrorObjects(); 2347 2348 // java access 2349 if (! env._no_java) { 2350 this.javaApi = LAZY_SENTINEL; 2351 this.javaImporter = LAZY_SENTINEL; 2352 initJavaAccess(); 2353 } 2354 2355 if (! env._no_typed_arrays) { 2356 this.arrayBuffer = LAZY_SENTINEL; 2357 this.dataView = LAZY_SENTINEL; 2358 this.int8Array = LAZY_SENTINEL; 2359 this.uint8Array = LAZY_SENTINEL; 2360 this.uint8ClampedArray = LAZY_SENTINEL; 2361 this.int16Array = LAZY_SENTINEL; 2362 this.uint16Array = LAZY_SENTINEL; 2363 this.int32Array = LAZY_SENTINEL; 2364 this.uint32Array = LAZY_SENTINEL; 2365 this.float32Array = LAZY_SENTINEL; 2366 this.float64Array = LAZY_SENTINEL; 2367 } 2368 2369 if (env._scripting) { 2370 initScripting(env); 2371 } 2372 2373 if (Context.DEBUG) { 2374 boolean debugOkay; 2375 final SecurityManager sm = System.getSecurityManager(); 2376 if (sm != null) { 2377 try { 2378 sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE)); 2379 debugOkay = true; 2380 } catch (final SecurityException ignored) { 2381 // if no permission, don't initialize Debug object 2382 debugOkay = false; 2383 } 2384 2385 } else { 2386 debugOkay = true; 2387 } 2388 2389 if (debugOkay) { 2390 initDebug(); 2391 } 2392 } 2393 2394 copyBuiltins(); 2395 2396 // expose script (command line) arguments as "arguments" property of global 2397 arguments = wrapAsObject(env.getArguments().toArray()); 2398 if (env._scripting) { 2399 // synonym for "arguments" in scripting mode 2400 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments); 2401 } 2402 2403 if (engine != null) { 2404 // default file name 2405 addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null); 2406 // __noSuchProperty__ hook for ScriptContext search of missing variables 2407 final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY); 2408 addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp); 2409 } 2410 } 2411 2412 private void initErrorObjects() { 2413 // Error objects 2414 this.builtinError = initConstructor("Error", ScriptFunction.class); 2415 final ScriptObject errorProto = getErrorPrototype(); 2416 2417 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName 2418 final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK); 2419 final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK); 2420 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); 2421 final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER); 2422 final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER); 2423 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber); 2424 final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER); 2425 final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER); 2426 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber); 2427 final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME); 2428 final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME); 2429 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName); 2430 2431 // ECMA 15.11.4.2 Error.prototype.name 2432 // Error.prototype.name = "Error"; 2433 errorProto.set(NativeError.NAME, "Error", 0); 2434 // ECMA 15.11.4.3 Error.prototype.message 2435 // Error.prototype.message = ""; 2436 errorProto.set(NativeError.MESSAGE, "", 0); 2437 2438 tagBuiltinProperties("Error", builtinError); 2439 2440 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); 2441 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto); 2442 this.builtinTypeError = initErrorSubtype("TypeError", errorProto); 2443 } 2444 2445 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) { 2446 final ScriptFunction cons = initConstructor(name, ScriptFunction.class); 2447 final ScriptObject prototype = ScriptFunction.getPrototype(cons); 2448 prototype.set(NativeError.NAME, name, 0); 2449 prototype.set(NativeError.MESSAGE, "", 0); 2450 prototype.setInitialProto(errorProto); 2451 tagBuiltinProperties(name, cons); 2452 return cons; 2453 } 2454 2455 private void initJavaAccess() { 2456 final ScriptObject objectProto = getObjectPrototype(); 2457 this.builtinPackages = new NativeJavaPackage("", objectProto); 2458 this.builtinCom = new NativeJavaPackage("com", objectProto); 2459 this.builtinEdu = new NativeJavaPackage("edu", objectProto); 2460 this.builtinJava = new NativeJavaPackage("java", objectProto); 2461 this.builtinJavafx = new NativeJavaPackage("javafx", objectProto); 2462 this.builtinJavax = new NativeJavaPackage("javax", objectProto); 2463 this.builtinOrg = new NativeJavaPackage("org", objectProto); 2464 } 2465 2466 private void initScripting(final ScriptEnvironment scriptEnv) { 2467 Object value; 2468 value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE); 2469 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value); 2470 2471 value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY); 2472 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value); 2473 2474 final String execName = ScriptingFunctions.EXEC_NAME; 2475 value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC); 2476 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value); 2477 2478 // Nashorn extension: global.echo (scripting-mode-only) 2479 // alias for "print" 2480 value = get("print"); 2481 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value); 2482 2483 // Nashorn extension: global.$OPTIONS (scripting-mode-only) 2484 final ScriptObject options = newObject(); 2485 copyOptions(options, scriptEnv); 2486 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options); 2487 2488 // Nashorn extension: global.$ENV (scripting-mode-only) 2489 if (System.getSecurityManager() == null) { 2490 // do not fill $ENV if we have a security manager around 2491 // Retrieve current state of ENV variables. 2492 final ScriptObject env = newObject(); 2493 env.putAll(System.getenv(), scriptEnv._strict); 2494 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); 2495 } else { 2496 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2497 } 2498 2499 // add other special properties for exec support 2500 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2501 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2502 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2503 } 2504 2505 private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) { 2506 for (final Field f : scriptEnv.getClass().getFields()) { 2507 try { 2508 options.set(f.getName(), f.get(scriptEnv), 0); 2509 } catch (final IllegalArgumentException | IllegalAccessException exp) { 2510 throw new RuntimeException(exp); 2511 } 2512 } 2513 } 2514 2515 private void copyBuiltins() { 2516 this.array = this.builtinArray; 2517 this._boolean = this.builtinBoolean; 2518 this.error = this.builtinError; 2519 this.function = this.builtinFunction; 2520 this.com = this.builtinCom; 2521 this.edu = this.builtinEdu; 2522 this.java = this.builtinJava; 2523 this.javafx = this.builtinJavafx; 2524 this.javax = this.builtinJavax; 2525 this.org = this.builtinOrg; 2526 this.math = this.builtinMath; 2527 this.number = this.builtinNumber; 2528 this.object = this.builtinObject; 2529 this.packages = this.builtinPackages; 2530 this.referenceError = this.builtinReferenceError; 2531 this.string = this.builtinString; 2532 this.syntaxError = this.builtinSyntaxError; 2533 this.typeError = this.builtinTypeError; 2534 } 2535 2536 private void initDebug() { 2537 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class)); 2538 } 2539 2540 private Object printImpl(final boolean newLine, final Object... objects) { 2541 @SuppressWarnings("resource") 2542 final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut(); 2543 final StringBuilder sb = new StringBuilder(); 2544 2545 for (final Object obj : objects) { 2546 if (sb.length() != 0) { 2547 sb.append(' '); 2548 } 2549 2550 sb.append(JSType.toString(obj)); 2551 } 2552 2553 // Print all at once to ensure thread friendly result. 2554 if (newLine) { 2555 out.println(sb.toString()); 2556 } else { 2557 out.print(sb.toString()); 2558 } 2559 2560 out.flush(); 2561 2562 return UNDEFINED; 2563 } 2564 2565 private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) { 2566 try { 2567 // Assuming class name pattern for built-in JS constructors. 2568 final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects."); 2569 2570 sb.append("Native"); 2571 sb.append(name); 2572 sb.append("$Constructor"); 2573 2574 final Class<?> funcClass = Class.forName(sb.toString()); 2575 final T res = clazz.cast(funcClass.newInstance()); 2576 2577 if (res instanceof ScriptFunction) { 2578 // All global constructor prototypes are not-writable, 2579 // not-enumerable and not-configurable. 2580 final ScriptFunction func = (ScriptFunction)res; 2581 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT); 2582 } 2583 2584 if (res.getProto() == null) { 2585 res.setInitialProto(getObjectPrototype()); 2586 } 2587 2588 res.setIsBuiltin(); 2589 2590 return res; 2591 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) { 2592 throw new RuntimeException(e); 2593 } 2594 } 2595 2596 private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) { 2597 final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>(); 2598 2599 list.addAll(Arrays.asList(func.getMap().getProperties())); 2600 2601 if (func instanceof ScriptFunction) { 2602 final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func); 2603 if (proto != null) { 2604 list.addAll(Arrays.asList(proto.getMap().getProperties())); 2605 } 2606 } 2607 2608 final jdk.nashorn.internal.runtime.Property prop = getProperty(name); 2609 if (prop != null) { 2610 list.add(prop); 2611 } 2612 2613 return list; 2614 } 2615 2616 /** 2617 * Given a builtin object, traverse its properties recursively and associate them with a name that 2618 * will be a key to their invalidation switchpoint. 2619 * @param name name for key 2620 * @param func builtin script object 2621 */ 2622 private void tagBuiltinProperties(final String name, final ScriptObject func) { 2623 SwitchPoint sp = context.getBuiltinSwitchPoint(name); 2624 if (sp == null) { 2625 sp = context.newBuiltinSwitchPoint(name); 2626 } 2627 2628 //get all builtin properties in this builtin object and register switchpoints keyed on the propery name, 2629 //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc 2630 for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) { 2631 prop.setBuiltinSwitchPoint(sp); 2632 } 2633 } 2634 2635 // Function and Object constructors are inter-dependent. Also, 2636 // Function.prototype 2637 // functions are not properly initialized. We fix the references here. 2638 // NOTE: be careful if you want to re-order the operations here. You may 2639 // have 2640 // to play with object references carefully!! 2641 private void initFunctionAndObject() { 2642 // First-n-foremost is Function 2643 2644 this.builtinFunction = initConstructor("Function", ScriptFunction.class); 2645 2646 // create global anonymous function 2647 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(); 2648 // need to copy over members of Function.prototype to anon function 2649 anon.addBoundProperties(getFunctionPrototype()); 2650 2651 // Function.prototype === Object.getPrototypeOf(Function) === 2652 // <anon-function> 2653 builtinFunction.setInitialProto(anon); 2654 builtinFunction.setPrototype(anon); 2655 anon.set("constructor", builtinFunction, 0); 2656 anon.deleteOwnProperty(anon.getMap().findProperty("prototype")); 2657 2658 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3 2659 this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0); 2660 typeErrorThrower.setPrototype(UNDEFINED); 2661 // Non-constructor built-in functions do not have "prototype" property 2662 typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype")); 2663 typeErrorThrower.preventExtensions(); 2664 2665 // now initialize Object 2666 this.builtinObject = initConstructor("Object", ScriptFunction.class); 2667 final ScriptObject ObjectPrototype = getObjectPrototype(); 2668 // Object.getPrototypeOf(Function.prototype) === Object.prototype 2669 anon.setInitialProto(ObjectPrototype); 2670 2671 // ES6 draft compliant __proto__ property of Object.prototype 2672 // accessors on Object.prototype for "__proto__" 2673 final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__); 2674 final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__); 2675 ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto); 2676 2677 // Function valued properties of Function.prototype were not properly 2678 // initialized. Because, these were created before global.function and 2679 // global.object were not initialized. 2680 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties(); 2681 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2682 final Object key = property.getKey(); 2683 final Object value = builtinFunction.get(key); 2684 2685 if (value instanceof ScriptFunction && value != anon) { 2686 final ScriptFunction func = (ScriptFunction)value; 2687 func.setInitialProto(getFunctionPrototype()); 2688 final ScriptObject prototype = ScriptFunction.getPrototype(func); 2689 if (prototype != null) { 2690 prototype.setInitialProto(ObjectPrototype); 2691 } 2692 } 2693 } 2694 2695 // For function valued properties of Object and Object.prototype, make 2696 // sure prototype's proto chain ends with Object.prototype 2697 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) { 2698 final Object key = property.getKey(); 2699 final Object value = builtinObject.get(key); 2700 2701 if (value instanceof ScriptFunction) { 2702 final ScriptFunction func = (ScriptFunction)value; 2703 final ScriptObject prototype = ScriptFunction.getPrototype(func); 2704 if (prototype != null) { 2705 prototype.setInitialProto(ObjectPrototype); 2706 } 2707 } 2708 } 2709 2710 properties = getObjectPrototype().getMap().getProperties(); 2711 2712 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2713 final Object key = property.getKey(); 2714 if (key.equals("constructor")) { 2715 continue; 2716 } 2717 2718 final Object value = ObjectPrototype.get(key); 2719 if (value instanceof ScriptFunction) { 2720 final ScriptFunction func = (ScriptFunction)value; 2721 final ScriptObject prototype = ScriptFunction.getPrototype(func); 2722 if (prototype != null) { 2723 prototype.setInitialProto(ObjectPrototype); 2724 } 2725 } 2726 } 2727 2728 tagBuiltinProperties("Object", builtinObject); 2729 tagBuiltinProperties("Function", builtinFunction); 2730 tagBuiltinProperties("Function", anon); 2731 } 2732 2733 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { 2734 return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types)); 2735 } 2736 2737 RegExpResult getLastRegExpResult() { 2738 return lastRegExpResult; 2739 } 2740 2741 void setLastRegExpResult(final RegExpResult regExpResult) { 2742 this.lastRegExpResult = regExpResult; 2743 } 2744 2745 @Override 2746 protected boolean isGlobal() { 2747 return true; 2748 } 2749 2750 /** 2751 * A class representing the ES6 global lexical scope. 2752 */ 2753 private static class LexicalScope extends ScriptObject { 2754 2755 LexicalScope(final Global global) { 2756 super(global, PropertyMap.newMap()); 2757 } 2758 2759 @Override 2760 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 2761 return filterInvocation(super.findGetMethod(desc, request, operator)); 2762 } 2763 2764 @Override 2765 protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 2766 return filterInvocation(super.findSetMethod(desc, request)); 2767 } 2768 2769 @Override 2770 protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) { 2771 // We override this method just to make it callable by Global 2772 return super.addBoundProperty(propMap, source, property); 2773 } 2774 2775 private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) { 2776 final MethodType type = invocation.getInvocation().type(); 2777 return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER); 2778 } 2779 } 2780 2781 }