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