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