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