1/* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.nashorn.internal.objects; 27 28import static jdk.nashorn.internal.lookup.Lookup.MH; 29import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; 30import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 31import static jdk.nashorn.internal.runtime.JSType.isString; 32import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 33 34import java.io.IOException; 35import java.io.PrintWriter; 36import java.lang.invoke.MethodHandle; 37import java.lang.invoke.MethodHandles; 38import java.lang.invoke.MethodType; 39import java.lang.invoke.SwitchPoint; 40import java.lang.reflect.Field; 41import java.util.ArrayList; 42import java.util.Arrays; 43import java.util.List; 44import java.util.Map; 45import java.util.Objects; 46import java.util.concurrent.Callable; 47import java.util.concurrent.ConcurrentHashMap; 48import javax.script.ScriptContext; 49import javax.script.ScriptEngine; 50import jdk.dynalink.CallSiteDescriptor; 51import jdk.dynalink.linker.GuardedInvocation; 52import jdk.dynalink.linker.LinkRequest; 53import jdk.nashorn.api.scripting.ClassFilter; 54import jdk.nashorn.api.scripting.ScriptObjectMirror; 55import jdk.nashorn.internal.lookup.Lookup; 56import jdk.nashorn.internal.objects.annotations.Attribute; 57import jdk.nashorn.internal.objects.annotations.Getter; 58import jdk.nashorn.internal.objects.annotations.Property; 59import jdk.nashorn.internal.objects.annotations.ScriptClass; 60import jdk.nashorn.internal.objects.annotations.Setter; 61import jdk.nashorn.internal.runtime.Context; 62import jdk.nashorn.internal.runtime.ECMAErrors; 63import jdk.nashorn.internal.runtime.FindProperty; 64import jdk.nashorn.internal.runtime.GlobalConstants; 65import jdk.nashorn.internal.runtime.GlobalFunctions; 66import jdk.nashorn.internal.runtime.JSType; 67import jdk.nashorn.internal.runtime.NativeJavaPackage; 68import jdk.nashorn.internal.runtime.PropertyDescriptor; 69import jdk.nashorn.internal.runtime.PropertyMap; 70import jdk.nashorn.internal.runtime.Scope; 71import jdk.nashorn.internal.runtime.ScriptEnvironment; 72import jdk.nashorn.internal.runtime.ScriptFunction; 73import jdk.nashorn.internal.runtime.ScriptObject; 74import jdk.nashorn.internal.runtime.ScriptRuntime; 75import jdk.nashorn.internal.runtime.ScriptingFunctions; 76import jdk.nashorn.internal.runtime.Specialization; 77import jdk.nashorn.internal.runtime.Symbol; 78import jdk.nashorn.internal.runtime.arrays.ArrayData; 79import jdk.nashorn.internal.runtime.linker.Bootstrap; 80import jdk.nashorn.internal.runtime.linker.InvokeByName; 81import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 82import jdk.nashorn.internal.runtime.regexp.RegExpResult; 83import jdk.nashorn.internal.scripts.JD; 84import jdk.nashorn.internal.scripts.JO; 85import jdk.nashorn.tools.ShellFunctions; 86 87/** 88 * Representation of global scope. 89 */ 90@ScriptClass("Global") 91public 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 switch (nameStr) { 1605 case "context": 1606 return sctxt; 1607 case "engine": 1608 return global.engine; 1609 default: 1610 break; 1611 } 1612 1613 if (self == UNDEFINED) { 1614 // scope access and so throw ReferenceError 1615 throw referenceError(global, "not.defined", nameStr); 1616 } 1617 1618 return UNDEFINED; 1619 } 1620 1621 /** 1622 * This is the eval used when 'indirect' eval call is made. 1623 * 1624 * var global = this; 1625 * global.eval("print('hello')"); 1626 * 1627 * @param self eval scope 1628 * @param str eval string 1629 * 1630 * @return the result of eval 1631 */ 1632 public static Object eval(final Object self, final Object str) { 1633 return directEval(self, str, Global.instanceFrom(self), UNDEFINED, false); 1634 } 1635 1636 /** 1637 * Direct eval 1638 * 1639 * @param self The scope of eval passed as 'self' 1640 * @param str Evaluated code 1641 * @param callThis "this" to be passed to the evaluated code 1642 * @param location location of the eval call 1643 * @param strict is eval called from a strict mode code? 1644 * 1645 * @return the return value of the eval 1646 * 1647 * This is directly invoked from generated when eval(code) is called in user code 1648 */ 1649 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) { 1650 if (!isString(str)) { 1651 return str; 1652 } 1653 final Global global = Global.instanceFrom(self); 1654 final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global; 1655 1656 return global.getContext().eval(scope, str.toString(), callThis, location, strict, true); 1657 } 1658 1659 /** 1660 * Global print implementation - Nashorn extension 1661 * 1662 * @param self scope 1663 * @param objects arguments to print 1664 * 1665 * @return result of print (undefined) 1666 */ 1667 public static Object print(final Object self, final Object... objects) { 1668 return Global.instanceFrom(self).printImpl(false, objects); 1669 } 1670 1671 /** 1672 * Global println implementation - Nashorn extension 1673 * 1674 * @param self scope 1675 * @param objects arguments to print 1676 * 1677 * @return result of println (undefined) 1678 */ 1679 public static Object println(final Object self, final Object... objects) { 1680 return Global.instanceFrom(self).printImpl(true, objects); 1681 } 1682 1683 /** 1684 * Global load implementation - Nashorn extension. 1685 * 1686 * <p> 1687 * load builtin loads the given script. Script source can be a URL or a File 1688 * or a script object with name and script properties. Evaluated code gets 1689 * global object "this" and uses global object as scope for evaluation. 1690 * </p> 1691 * <p> 1692 * If self is undefined or null or global, then global object is used 1693 * as scope as well as "this" for the evaluated code. If self is any other 1694 * object, then it is indirect load call. With indirect load call, the 1695 * properties of scope are available to evaluated script as variables. Also, 1696 * global scope properties are accessible. Any var, function definition in 1697 * evaluated script goes into an object that is not accessible to user scripts. 1698 * </p> 1699 * Thus the indirect load call is equivalent to the following: 1700 * <pre> 1701 * <code> 1702 * (function (scope, source) { 1703 * with(scope) { 1704 * eval(<script_from_source>); 1705 * } 1706 * })(self, source); 1707 * </code> 1708 * </pre> 1709 * 1710 * @param self scope to use for the script evaluation 1711 * @param source script source 1712 * 1713 * @return result of load (may be undefined) 1714 * 1715 * @throws IOException if source could not be read 1716 */ 1717 public static Object load(final Object self, final Object source) throws IOException { 1718 final Global global = Global.instanceFrom(self); 1719 return global.getContext().load(self, source); 1720 } 1721 1722 /** 1723 * Global loadWithNewGlobal implementation - Nashorn extension. 1724 * 1725 * loadWithNewGlobal builtin loads the given script from a URL or a File 1726 * or a script object with name and script properties. Evaluated code gets 1727 * new global object "this" and uses that new global object as scope for evaluation. 1728 * 1729 * @param self self This value is ignored by this function 1730 * @param args optional arguments to be passed to the loaded script 1731 * 1732 * @return result of load (may be undefined) 1733 * 1734 * @throws IOException if source could not be read 1735 */ 1736 public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException { 1737 final Global global = Global.instanceFrom(self); 1738 final int length = args.length; 1739 final boolean hasArgs = 0 < length; 1740 final Object from = hasArgs ? args[0] : UNDEFINED; 1741 final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args; 1742 1743 return global.getContext().loadWithNewGlobal(from, arguments); 1744 } 1745 1746 /** 1747 * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script 1748 * 1749 * @param self self reference 1750 * @param code exit code 1751 * 1752 * @return undefined (will never be reached) 1753 */ 1754 public static Object exit(final Object self, final Object code) { 1755 System.exit(JSType.toInt32(code)); 1756 return UNDEFINED; 1757 } 1758 1759 // builtin prototype accessors 1760 1761 /** 1762 * Get the builtin Object prototype. 1763 * @return the Object prototype. 1764 */ 1765 public ScriptObject getObjectPrototype() { 1766 return ScriptFunction.getPrototype(builtinObject); 1767 } 1768 1769 /** 1770 * Get the builtin Function prototype. 1771 * @return the Function prototype. 1772 */ 1773 public ScriptObject getFunctionPrototype() { 1774 return ScriptFunction.getPrototype(builtinFunction); 1775 } 1776 1777 /** 1778 * Get the builtin Array prototype. 1779 * @return the Array prototype 1780 */ 1781 public ScriptObject getArrayPrototype() { 1782 return ScriptFunction.getPrototype(builtinArray); 1783 } 1784 1785 ScriptObject getBooleanPrototype() { 1786 return ScriptFunction.getPrototype(builtinBoolean); 1787 } 1788 1789 ScriptObject getNumberPrototype() { 1790 return ScriptFunction.getPrototype(builtinNumber); 1791 } 1792 1793 ScriptObject getDatePrototype() { 1794 return ScriptFunction.getPrototype(getBuiltinDate()); 1795 } 1796 1797 ScriptObject getRegExpPrototype() { 1798 return ScriptFunction.getPrototype(getBuiltinRegExp()); 1799 } 1800 1801 ScriptObject getStringPrototype() { 1802 return ScriptFunction.getPrototype(builtinString); 1803 } 1804 1805 ScriptObject getErrorPrototype() { 1806 return ScriptFunction.getPrototype(builtinError); 1807 } 1808 1809 ScriptObject getEvalErrorPrototype() { 1810 return ScriptFunction.getPrototype(getBuiltinEvalError()); 1811 } 1812 1813 ScriptObject getRangeErrorPrototype() { 1814 return ScriptFunction.getPrototype(getBuiltinRangeError()); 1815 } 1816 1817 ScriptObject getReferenceErrorPrototype() { 1818 return ScriptFunction.getPrototype(builtinReferenceError); 1819 } 1820 1821 ScriptObject getSyntaxErrorPrototype() { 1822 return ScriptFunction.getPrototype(builtinSyntaxError); 1823 } 1824 1825 ScriptObject getTypeErrorPrototype() { 1826 return ScriptFunction.getPrototype(builtinTypeError); 1827 } 1828 1829 ScriptObject getURIErrorPrototype() { 1830 return ScriptFunction.getPrototype(getBuiltinURIError()); 1831 } 1832 1833 ScriptObject getJavaImporterPrototype() { 1834 return ScriptFunction.getPrototype(getBuiltinJavaImporter()); 1835 } 1836 1837 ScriptObject getJSAdapterPrototype() { 1838 return ScriptFunction.getPrototype(getBuiltinJSAdapter()); 1839 } 1840 1841 ScriptObject getSymbolPrototype() { 1842 return ScriptFunction.getPrototype(getBuiltinSymbol()); 1843 } 1844 1845 ScriptObject getMapPrototype() { 1846 return ScriptFunction.getPrototype(getBuiltinMap()); 1847 } 1848 1849 ScriptObject getWeakMapPrototype() { 1850 return ScriptFunction.getPrototype(getBuiltinWeakMap()); 1851 } 1852 1853 ScriptObject getSetPrototype() { 1854 return ScriptFunction.getPrototype(getBuiltinSet()); 1855 } 1856 1857 ScriptObject getWeakSetPrototype() { 1858 return ScriptFunction.getPrototype(getBuiltinWeakSet()); 1859 } 1860 1861 ScriptObject getIteratorPrototype() { 1862 if (builtinIteratorPrototype == null) { 1863 builtinIteratorPrototype = initPrototype("AbstractIterator", getObjectPrototype()); 1864 } 1865 return builtinIteratorPrototype; 1866 } 1867 1868 ScriptObject getMapIteratorPrototype() { 1869 if (builtinMapIteratorPrototype == null) { 1870 builtinMapIteratorPrototype = initPrototype("MapIterator", getIteratorPrototype()); 1871 } 1872 return builtinMapIteratorPrototype; 1873 } 1874 1875 ScriptObject getSetIteratorPrototype() { 1876 if (builtinSetIteratorPrototype == null) { 1877 builtinSetIteratorPrototype = initPrototype("SetIterator", getIteratorPrototype()); 1878 } 1879 return builtinSetIteratorPrototype; 1880 } 1881 1882 ScriptObject getArrayIteratorPrototype() { 1883 if (builtinArrayIteratorPrototype == null) { 1884 builtinArrayIteratorPrototype = initPrototype("ArrayIterator", getIteratorPrototype()); 1885 } 1886 return builtinArrayIteratorPrototype; 1887 } 1888 1889 ScriptObject getStringIteratorPrototype() { 1890 if (builtinStringIteratorPrototype == null) { 1891 builtinStringIteratorPrototype = initPrototype("StringIterator", getIteratorPrototype()); 1892 } 1893 return builtinStringIteratorPrototype; 1894 } 1895 1896 private synchronized ScriptFunction getBuiltinArrayBuffer() { 1897 if (this.builtinArrayBuffer == null) { 1898 this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); 1899 } 1900 return this.builtinArrayBuffer; 1901 } 1902 1903 ScriptObject getArrayBufferPrototype() { 1904 return ScriptFunction.getPrototype(getBuiltinArrayBuffer()); 1905 } 1906 1907 private synchronized ScriptFunction getBuiltinDataView() { 1908 if (this.builtinDataView == null) { 1909 this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); 1910 } 1911 return this.builtinDataView; 1912 } 1913 1914 ScriptObject getDataViewPrototype() { 1915 return ScriptFunction.getPrototype(getBuiltinDataView()); 1916 } 1917 1918 private synchronized ScriptFunction getBuiltinInt8Array() { 1919 if (this.builtinInt8Array == null) { 1920 this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); 1921 } 1922 return this.builtinInt8Array; 1923 } 1924 1925 ScriptObject getInt8ArrayPrototype() { 1926 return ScriptFunction.getPrototype(getBuiltinInt8Array()); 1927 } 1928 1929 private synchronized ScriptFunction getBuiltinUint8Array() { 1930 if (this.builtinUint8Array == null) { 1931 this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); 1932 } 1933 return this.builtinUint8Array; 1934 } 1935 1936 ScriptObject getUint8ArrayPrototype() { 1937 return ScriptFunction.getPrototype(getBuiltinUint8Array()); 1938 } 1939 1940 private synchronized ScriptFunction getBuiltinUint8ClampedArray() { 1941 if (this.builtinUint8ClampedArray == null) { 1942 this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); 1943 } 1944 return this.builtinUint8ClampedArray; 1945 } 1946 1947 ScriptObject getUint8ClampedArrayPrototype() { 1948 return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray()); 1949 } 1950 1951 private synchronized ScriptFunction getBuiltinInt16Array() { 1952 if (this.builtinInt16Array == null) { 1953 this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); 1954 } 1955 return this.builtinInt16Array; 1956 } 1957 1958 ScriptObject getInt16ArrayPrototype() { 1959 return ScriptFunction.getPrototype(getBuiltinInt16Array()); 1960 } 1961 1962 private synchronized ScriptFunction getBuiltinUint16Array() { 1963 if (this.builtinUint16Array == null) { 1964 this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); 1965 } 1966 return this.builtinUint16Array; 1967 } 1968 1969 ScriptObject getUint16ArrayPrototype() { 1970 return ScriptFunction.getPrototype(getBuiltinUint16Array()); 1971 } 1972 1973 private synchronized ScriptFunction getBuiltinInt32Array() { 1974 if (this.builtinInt32Array == null) { 1975 this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); 1976 } 1977 return this.builtinInt32Array; 1978 } 1979 1980 ScriptObject getInt32ArrayPrototype() { 1981 return ScriptFunction.getPrototype(getBuiltinInt32Array()); 1982 } 1983 1984 private synchronized ScriptFunction getBuiltinUint32Array() { 1985 if (this.builtinUint32Array == null) { 1986 this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); 1987 } 1988 return this.builtinUint32Array; 1989 } 1990 1991 ScriptObject getUint32ArrayPrototype() { 1992 return ScriptFunction.getPrototype(getBuiltinUint32Array()); 1993 } 1994 1995 private synchronized ScriptFunction getBuiltinFloat32Array() { 1996 if (this.builtinFloat32Array == null) { 1997 this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); 1998 } 1999 return this.builtinFloat32Array; 2000 } 2001 2002 ScriptObject getFloat32ArrayPrototype() { 2003 return ScriptFunction.getPrototype(getBuiltinFloat32Array()); 2004 } 2005 2006 private synchronized ScriptFunction getBuiltinFloat64Array() { 2007 if (this.builtinFloat64Array == null) { 2008 this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); 2009 } 2010 return this.builtinFloat64Array; 2011 } 2012 2013 ScriptObject getFloat64ArrayPrototype() { 2014 return ScriptFunction.getPrototype(getBuiltinFloat64Array()); 2015 } 2016 2017 /** 2018 * Return the function that throws TypeError unconditionally. Used as "poison" methods for certain Function properties. 2019 * 2020 * @return the TypeError throwing function 2021 */ 2022 public ScriptFunction getTypeErrorThrower() { 2023 return typeErrorThrower; 2024 } 2025 2026 private synchronized ScriptFunction getBuiltinDate() { 2027 if (this.builtinDate == null) { 2028 this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); 2029 final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate); 2030 // initialize default date 2031 this.DEFAULT_DATE = new NativeDate(NaN, dateProto); 2032 } 2033 return this.builtinDate; 2034 } 2035 2036 private synchronized ScriptFunction getBuiltinEvalError() { 2037 if (this.builtinEvalError == null) { 2038 this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype()); 2039 } 2040 return this.builtinEvalError; 2041 } 2042 2043 private ScriptFunction getBuiltinFunction() { 2044 return builtinFunction; 2045 } 2046 2047 /** 2048 * Get the switchpoint used to check property changes for Function.prototype.apply 2049 * @return the switchpoint guarding apply (same as guarding call, and everything else in function) 2050 */ 2051 public static SwitchPoint getBuiltinFunctionApplySwitchPoint() { 2052 return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint(); 2053 } 2054 2055 private static boolean isBuiltinFunctionProperty(final String name) { 2056 final Global instance = Global.instance(); 2057 final ScriptFunction builtinFunction = instance.getBuiltinFunction(); 2058 if (builtinFunction == null) { 2059 return false; //conservative for compile-only mode 2060 } 2061 final boolean isBuiltinFunction = instance.function == builtinFunction; 2062 return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin(); 2063 } 2064 2065 /** 2066 * Check if the Function.prototype.apply has not been replaced 2067 * @return true if Function.prototype.apply has been replaced 2068 */ 2069 public static boolean isBuiltinFunctionPrototypeApply() { 2070 return isBuiltinFunctionProperty("apply"); 2071 } 2072 2073 /** 2074 * Check if the Function.prototype.apply has not been replaced 2075 * @return true if Function.prototype.call has been replaced 2076 */ 2077 public static boolean isBuiltinFunctionPrototypeCall() { 2078 return isBuiltinFunctionProperty("call"); 2079 } 2080 2081 private synchronized ScriptFunction getBuiltinJSAdapter() { 2082 if (this.builtinJSAdapter == null) { 2083 this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class); 2084 } 2085 return builtinJSAdapter; 2086 } 2087 2088 private synchronized ScriptObject getBuiltinJSON() { 2089 if (this.builtinJSON == null) { 2090 this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); 2091 } 2092 return this.builtinJSON; 2093 } 2094 2095 private synchronized ScriptFunction getBuiltinJavaImporter() { 2096 if (getContext().getEnv()._no_java) { 2097 throw new IllegalStateException(); 2098 } 2099 if (this.builtinJavaImporter == null) { 2100 this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); 2101 } 2102 return this.builtinJavaImporter; 2103 } 2104 2105 private synchronized ScriptObject getBuiltinJavaApi() { 2106 if (getContext().getEnv()._no_java) { 2107 throw new IllegalStateException(); 2108 } 2109 if (this.builtinJavaApi == null) { 2110 this.builtinJavaApi = initConstructor("Java", ScriptObject.class); 2111 this.builtInJavaExtend = (ScriptFunction)builtinJavaApi.get("extend"); 2112 this.builtInJavaTo = (ScriptFunction)builtinJavaApi.get("to"); 2113 } 2114 return this.builtinJavaApi; 2115 } 2116 2117 /** 2118 * Returns true if the passed function is the built-in "Java.extend". 2119 * @param fn the function in question 2120 * @return true if the function is built-in "Java.extend" 2121 */ 2122 public static boolean isBuiltInJavaExtend(final ScriptFunction fn) { 2123 if(!"extend".equals(fn.getName())) { 2124 // Avoid hitting the thread local if the name doesn't match. 2125 return false; 2126 } 2127 return fn == Context.getGlobal().builtInJavaExtend; 2128 } 2129 2130 /** 2131 * Returns true if the passed function is the built-in "Java.to". 2132 * @param fn the function in question 2133 * @return true if the function is built-in "Java.to" 2134 */ 2135 public static boolean isBuiltInJavaTo(final ScriptFunction fn) { 2136 if(!"to".equals(fn.getName())) { 2137 // Avoid hitting the thread local if the name doesn't match. 2138 return false; 2139 } 2140 return fn == Context.getGlobal().builtInJavaTo; 2141 } 2142 2143 2144 private synchronized ScriptFunction getBuiltinRangeError() { 2145 if (this.builtinRangeError == null) { 2146 this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype()); 2147 } 2148 return builtinRangeError; 2149 } 2150 2151 private synchronized ScriptFunction getBuiltinRegExp() { 2152 if (this.builtinRegExp == null) { 2153 this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); 2154 final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp); 2155 // initialize default regexp object 2156 this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto); 2157 // RegExp.prototype should behave like a RegExp object. So copy the 2158 // properties. 2159 regExpProto.addBoundProperties(DEFAULT_REGEXP); 2160 } 2161 return builtinRegExp; 2162 } 2163 2164 private synchronized ScriptFunction getBuiltinURIError() { 2165 if (this.builtinURIError == null) { 2166 this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype()); 2167 } 2168 return this.builtinURIError; 2169 } 2170 2171 private synchronized ScriptFunction getBuiltinSymbol() { 2172 if (this.builtinSymbol == null) { 2173 this.builtinSymbol = initConstructorAndSwitchPoint("Symbol", ScriptFunction.class); 2174 } 2175 return this.builtinSymbol; 2176 } 2177 2178 private synchronized ScriptFunction getBuiltinMap() { 2179 if (this.builtinMap == null) { 2180 this.builtinMap = initConstructorAndSwitchPoint("Map", ScriptFunction.class); 2181 } 2182 return this.builtinMap; 2183 } 2184 2185 private synchronized ScriptFunction getBuiltinWeakMap() { 2186 if (this.builtinWeakMap == null) { 2187 this.builtinWeakMap = initConstructorAndSwitchPoint("WeakMap", ScriptFunction.class); 2188 } 2189 return this.builtinWeakMap; 2190 } 2191 2192 private synchronized ScriptFunction getBuiltinSet() { 2193 if (this.builtinSet == null) { 2194 this.builtinSet = initConstructorAndSwitchPoint("Set", ScriptFunction.class); 2195 } 2196 return this.builtinSet; 2197 } 2198 2199 private synchronized ScriptFunction getBuiltinWeakSet() { 2200 if (this.builtinWeakSet == null) { 2201 this.builtinWeakSet = initConstructorAndSwitchPoint("WeakSet", ScriptFunction.class); 2202 } 2203 return this.builtinWeakSet; 2204 } 2205 2206 @Override 2207 public String getClassName() { 2208 return "global"; 2209 } 2210 2211 /** 2212 * Copy function used to clone NativeRegExp objects. 2213 * 2214 * @param regexp a NativeRegExp to clone 2215 * 2216 * @return copy of the given regexp object 2217 */ 2218 public static Object regExpCopy(final Object regexp) { 2219 return new NativeRegExp((NativeRegExp)regexp); 2220 } 2221 2222 /** 2223 * Convert given object to NativeRegExp type. 2224 * 2225 * @param obj object to be converted 2226 * @return NativeRegExp instance 2227 */ 2228 public static NativeRegExp toRegExp(final Object obj) { 2229 if (obj instanceof NativeRegExp) { 2230 return (NativeRegExp)obj; 2231 } 2232 return new NativeRegExp(JSType.toString(obj)); 2233 } 2234 2235 /** 2236 * ECMA 9.9 ToObject implementation 2237 * 2238 * @param obj an item for which to run ToObject 2239 * @return ToObject version of given item 2240 */ 2241 public static Object toObject(final Object obj) { 2242 if (obj == null || obj == UNDEFINED) { 2243 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 2244 } 2245 2246 if (obj instanceof ScriptObject) { 2247 return obj; 2248 } 2249 2250 return instance().wrapAsObject(obj); 2251 } 2252 2253 /** 2254 * Allocate a new object array. 2255 * 2256 * @param initial object values. 2257 * @return the new array 2258 */ 2259 public static NativeArray allocate(final Object[] initial) { 2260 ArrayData arrayData = ArrayData.allocate(initial); 2261 2262 for (int index = 0; index < initial.length; index++) { 2263 final Object value = initial[index]; 2264 2265 if (value == ScriptRuntime.EMPTY) { 2266 arrayData = arrayData.delete(index); 2267 } 2268 } 2269 2270 return new NativeArray(arrayData); 2271 } 2272 2273 /** 2274 * Allocate a new number array. 2275 * 2276 * @param initial number values. 2277 * @return the new array 2278 */ 2279 public static NativeArray allocate(final double[] initial) { 2280 return new NativeArray(ArrayData.allocate(initial)); 2281 } 2282 2283 /** 2284 * Allocate a new integer array. 2285 * 2286 * @param initial number values. 2287 * @return the new array 2288 */ 2289 public static NativeArray allocate(final int[] initial) { 2290 return new NativeArray(ArrayData.allocate(initial)); 2291 } 2292 2293 /** 2294 * Allocate a new object array for arguments. 2295 * 2296 * @param arguments initial arguments passed. 2297 * @param callee reference to the function that uses arguments object 2298 * @param numParams actual number of declared parameters 2299 * 2300 * @return the new array 2301 */ 2302 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) { 2303 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams); 2304 } 2305 2306 /** 2307 * Called from generated to check if given function is the builtin 'eval'. If 2308 * eval is used in a script, a lot of optimizations and assumptions cannot be done. 2309 * 2310 * @param fn function object that is checked 2311 * @return true if fn is the builtin eval 2312 */ 2313 public static boolean isEval(final Object fn) { 2314 return fn == Global.instance().builtinEval; 2315 } 2316 2317 /** 2318 * Called from generated to replace a location property placeholder with the actual location property value. 2319 * 2320 * @param placeholder the value tested for being a placeholder for a location property 2321 * @param locationProperty the actual value for the location property 2322 * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise 2323 */ 2324 public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) { 2325 return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder; 2326 } 2327 2328 /** 2329 * Called from runtime internals to check if the passed value is a location property placeholder. 2330 * @param placeholder the value tested for being a placeholder for a location property 2331 * @return true if the value is a placeholder, false otherwise. 2332 */ 2333 public static boolean isLocationPropertyPlaceholder(final Object placeholder) { 2334 return placeholder == LOCATION_PLACEHOLDER; 2335 } 2336 2337 /** 2338 * Create a new RegExp object. 2339 * 2340 * @param expression Regular expression. 2341 * @param options Search options. 2342 * 2343 * @return New RegExp object. 2344 */ 2345 public static Object newRegExp(final String expression, final String options) { 2346 if (options == null) { 2347 return new NativeRegExp(expression); 2348 } 2349 return new NativeRegExp(expression, options); 2350 } 2351 2352 /** 2353 * Get the object prototype 2354 * 2355 * @return the object prototype 2356 */ 2357 public static ScriptObject objectPrototype() { 2358 return Global.instance().getObjectPrototype(); 2359 } 2360 2361 /** 2362 * Create a new empty object instance. 2363 * 2364 * @return New empty object. 2365 */ 2366 public static ScriptObject newEmptyInstance() { 2367 return Global.instance().newObject(); 2368 } 2369 2370 /** 2371 * Check if a given object is a ScriptObject, raises an exception if this is 2372 * not the case 2373 * 2374 * @param obj and object to check 2375 * @return the script object 2376 */ 2377 public static ScriptObject checkObject(final Object obj) { 2378 if (!(obj instanceof ScriptObject)) { 2379 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 2380 } 2381 return (ScriptObject)obj; 2382 } 2383 2384 /** 2385 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception 2386 * if this object is null or undefined. 2387 * 2388 * @param obj an object to check 2389 */ 2390 public static void checkObjectCoercible(final Object obj) { 2391 if (obj == null || obj == UNDEFINED) { 2392 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 2393 } 2394 } 2395 2396 /** 2397 * Return the ES6 global scope for lexically declared bindings. 2398 * @return the ES6 lexical global scope. 2399 */ 2400 public final ScriptObject getLexicalScope() { 2401 assert context.getEnv()._es6; 2402 return lexicalScope; 2403 } 2404 2405 @Override 2406 public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) { 2407 PropertyMap ownMap = getMap(); 2408 LexicalScope lexScope = null; 2409 PropertyMap lexicalMap = null; 2410 boolean hasLexicalDefinitions = false; 2411 2412 if (context.getEnv()._es6) { 2413 lexScope = (LexicalScope) getLexicalScope(); 2414 lexicalMap = lexScope.getMap(); 2415 2416 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2417 if (property.isLexicalBinding()) { 2418 hasLexicalDefinitions = true; 2419 } 2420 // ES6 15.1.8 steps 6. and 7. 2421 final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey()); 2422 if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) { 2423 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString()); 2424 } 2425 final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey()); 2426 if (lexicalProperty != null && !property.isConfigurable()) { 2427 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString()); 2428 } 2429 } 2430 } 2431 2432 final boolean extensible = isExtensible(); 2433 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2434 if (property.isLexicalBinding()) { 2435 assert lexScope != null; 2436 lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property, true); 2437 2438 if (ownMap.findProperty(property.getKey()) != null) { 2439 // If property exists in the global object invalidate any global constant call sites. 2440 invalidateGlobalConstant(property.getKey()); 2441 } 2442 } else { 2443 ownMap = addBoundProperty(ownMap, source, property, extensible); 2444 } 2445 } 2446 2447 setMap(ownMap); 2448 2449 if (hasLexicalDefinitions) { 2450 assert lexScope != null; 2451 lexScope.setMap(lexicalMap); 2452 invalidateLexicalSwitchPoint(); 2453 } 2454 } 2455 2456 @Override 2457 public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 2458 final String name = NashornCallSiteDescriptor.getOperand(desc); 2459 final boolean isScope = NashornCallSiteDescriptor.isScope(desc); 2460 2461 if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) { 2462 if (lexicalScope.hasOwnProperty(name)) { 2463 return lexicalScope.findGetMethod(desc, request); 2464 } 2465 } 2466 2467 final GuardedInvocation invocation = super.findGetMethod(desc, request); 2468 2469 // We want to avoid adding our generic lexical scope switchpoint to global constant invocations, 2470 // because those are invalidated per-key in the addBoundProperties method above. 2471 // We therefore check if the invocation does already have a switchpoint and the property is non-inherited, 2472 // assuming this only applies to global constants. If other non-inherited properties will 2473 // start using switchpoints some time in the future we'll have to revisit this. 2474 if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) { 2475 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint()); 2476 } 2477 2478 return invocation; 2479 } 2480 2481 @Override 2482 protected FindProperty findProperty(final Object key, final boolean deep, final boolean isScope, final ScriptObject start) { 2483 if (lexicalScope != null && isScope) { 2484 final FindProperty find = lexicalScope.findProperty(key, false); 2485 if (find != null) { 2486 return find; 2487 } 2488 } 2489 return super.findProperty(key, deep, isScope, start); 2490 } 2491 2492 @Override 2493 public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 2494 final boolean isScope = NashornCallSiteDescriptor.isScope(desc); 2495 2496 if (lexicalScope != null && isScope) { 2497 final String name = NashornCallSiteDescriptor.getOperand(desc); 2498 if (lexicalScope.hasOwnProperty(name)) { 2499 return lexicalScope.findSetMethod(desc, request); 2500 } 2501 } 2502 2503 final GuardedInvocation invocation = super.findSetMethod(desc, request); 2504 2505 if (isScope && context.getEnv()._es6) { 2506 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint()); 2507 } 2508 2509 return invocation; 2510 } 2511 2512 /** 2513 * Adds jjs shell interactive mode builtin functions to global scope. 2514 */ 2515 public void addShellBuiltins() { 2516 Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT); 2517 addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); 2518 2519 value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT); 2520 addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); 2521 } 2522 2523 private synchronized SwitchPoint getLexicalScopeSwitchPoint() { 2524 SwitchPoint switchPoint = lexicalScopeSwitchPoint; 2525 if (switchPoint == null || switchPoint.hasBeenInvalidated()) { 2526 switchPoint = lexicalScopeSwitchPoint = new SwitchPoint(); 2527 } 2528 return switchPoint; 2529 } 2530 2531 private synchronized void invalidateLexicalSwitchPoint() { 2532 if (lexicalScopeSwitchPoint != null) { 2533 context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update"); 2534 SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint }); 2535 } 2536 } 2537 2538 2539 @SuppressWarnings("unused") 2540 private static Object lexicalScopeFilter(final Object self) { 2541 if (self instanceof Global) { 2542 return ((Global) self).getLexicalScope(); 2543 } 2544 return self; 2545 } 2546 2547 private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) { 2548 final T func = initConstructor(name, clazz); 2549 tagBuiltinProperties(name, func); 2550 return func; 2551 } 2552 2553 private void init(final ScriptEngine eng) { 2554 assert Context.getGlobal() == this : "this global is not set as current"; 2555 2556 final ScriptEnvironment env = getContext().getEnv(); 2557 2558 // initialize Function and Object constructor 2559 initFunctionAndObject(); 2560 2561 // Now fix Global's own proto. 2562 this.setInitialProto(getObjectPrototype()); 2563 2564 // initialize global function properties 2565 this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL); 2566 2567 this.parseInt = ScriptFunction.createBuiltin("parseInt", GlobalFunctions.PARSEINT, 2568 new Specialization[] { 2569 new Specialization(GlobalFunctions.PARSEINT_Z), 2570 new Specialization(GlobalFunctions.PARSEINT_I), 2571 new Specialization(GlobalFunctions.PARSEINT_OI), 2572 new Specialization(GlobalFunctions.PARSEINT_O) }); 2573 this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); 2574 this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN, 2575 new Specialization[] { 2576 new Specialization(GlobalFunctions.IS_NAN_I), 2577 new Specialization(GlobalFunctions.IS_NAN_J), 2578 new Specialization(GlobalFunctions.IS_NAN_D) }); 2579 this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); 2580 this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN); 2581 this.isFinite = ScriptFunction.createBuiltin("isFinite", GlobalFunctions.IS_FINITE); 2582 this.encodeURI = ScriptFunction.createBuiltin("encodeURI", GlobalFunctions.ENCODE_URI); 2583 this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); 2584 this.decodeURI = ScriptFunction.createBuiltin("decodeURI", GlobalFunctions.DECODE_URI); 2585 this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); 2586 this.escape = ScriptFunction.createBuiltin("escape", GlobalFunctions.ESCAPE); 2587 this.unescape = ScriptFunction.createBuiltin("unescape", GlobalFunctions.UNESCAPE); 2588 this.print = ScriptFunction.createBuiltin("print", env._print_no_newline ? PRINT : PRINTLN); 2589 this.load = ScriptFunction.createBuiltin("load", LOAD); 2590 this.loadWithNewGlobal = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL); 2591 this.exit = ScriptFunction.createBuiltin("exit", EXIT); 2592 this.quit = ScriptFunction.createBuiltin("quit", EXIT); 2593 2594 // built-in constructors 2595 this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); 2596 this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class); 2597 this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); 2598 this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); 2599 this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class); 2600 2601 // initialize String.prototype.length to 0 2602 // add String.prototype.length 2603 final ScriptObject stringPrototype = getStringPrototype(); 2604 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0); 2605 2606 // set isArray flag on Array.prototype 2607 final ScriptObject arrayPrototype = getArrayPrototype(); 2608 arrayPrototype.setIsArray(); 2609 2610 if (env._es6) { 2611 this.symbol = LAZY_SENTINEL; 2612 this.map = LAZY_SENTINEL; 2613 this.weakMap = LAZY_SENTINEL; 2614 this.set = LAZY_SENTINEL; 2615 this.weakSet = LAZY_SENTINEL; 2616 } else { 2617 // We need to manually delete nasgen-generated properties we don't want 2618 this.delete("Symbol", false); 2619 this.delete("Map", false); 2620 this.delete("WeakMap", false); 2621 this.delete("Set", false); 2622 this.delete("WeakSet", false); 2623 builtinObject.delete("getOwnPropertySymbols", false); 2624 arrayPrototype.delete("entries", false); 2625 arrayPrototype.delete("keys", false); 2626 arrayPrototype.delete("values", false); 2627 } 2628 2629 // Error stuff 2630 initErrorObjects(); 2631 2632 // java access 2633 if (! env._no_java) { 2634 this.javaApi = LAZY_SENTINEL; 2635 this.javaImporter = LAZY_SENTINEL; 2636 initJavaAccess(); 2637 } else { 2638 // delete nasgen-created global properties related to java access 2639 this.delete("Java", false); 2640 this.delete("JavaImporter", false); 2641 this.delete("Packages", false); 2642 this.delete("com", false); 2643 this.delete("edu", false); 2644 this.delete("java", false); 2645 this.delete("javafx", false); 2646 this.delete("javax", false); 2647 this.delete("org", false); 2648 } 2649 2650 if (! env._no_typed_arrays) { 2651 this.arrayBuffer = LAZY_SENTINEL; 2652 this.dataView = LAZY_SENTINEL; 2653 this.int8Array = LAZY_SENTINEL; 2654 this.uint8Array = LAZY_SENTINEL; 2655 this.uint8ClampedArray = LAZY_SENTINEL; 2656 this.int16Array = LAZY_SENTINEL; 2657 this.uint16Array = LAZY_SENTINEL; 2658 this.int32Array = LAZY_SENTINEL; 2659 this.uint32Array = LAZY_SENTINEL; 2660 this.float32Array = LAZY_SENTINEL; 2661 this.float64Array = LAZY_SENTINEL; 2662 } 2663 2664 if (env._scripting) { 2665 initScripting(env); 2666 } 2667 2668 if (Context.DEBUG) { 2669 boolean debugOkay; 2670 final SecurityManager sm = System.getSecurityManager(); 2671 if (sm != null) { 2672 try { 2673 sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE)); 2674 debugOkay = true; 2675 } catch (final SecurityException ignored) { 2676 // if no permission, don't initialize Debug object 2677 debugOkay = false; 2678 } 2679 2680 } else { 2681 debugOkay = true; 2682 } 2683 2684 if (debugOkay) { 2685 initDebug(); 2686 } 2687 } 2688 2689 copyBuiltins(); 2690 2691 // expose script (command line) arguments as "arguments" property of global 2692 arguments = wrapAsObject(env.getArguments().toArray()); 2693 if (env._scripting) { 2694 // synonym for "arguments" in scripting mode 2695 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments); 2696 } 2697 2698 if (eng != null) { 2699 // default file name 2700 addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null); 2701 // __noSuchProperty__ hook for ScriptContext search of missing variables 2702 final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY); 2703 addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp); 2704 } 2705 } 2706 2707 private void initErrorObjects() { 2708 // Error objects 2709 this.builtinError = initConstructor("Error", ScriptFunction.class); 2710 final ScriptObject errorProto = getErrorPrototype(); 2711 2712 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName 2713 final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK); 2714 final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK); 2715 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); 2716 final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER); 2717 final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER); 2718 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber); 2719 final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER); 2720 final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER); 2721 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber); 2722 final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME); 2723 final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME); 2724 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName); 2725 2726 // ECMA 15.11.4.2 Error.prototype.name 2727 // Error.prototype.name = "Error"; 2728 errorProto.set(NativeError.NAME, "Error", 0); 2729 // ECMA 15.11.4.3 Error.prototype.message 2730 // Error.prototype.message = ""; 2731 errorProto.set(NativeError.MESSAGE, "", 0); 2732 2733 tagBuiltinProperties("Error", builtinError); 2734 2735 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); 2736 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto); 2737 this.builtinTypeError = initErrorSubtype("TypeError", errorProto); 2738 } 2739 2740 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) { 2741 final ScriptFunction cons = initConstructor(name, ScriptFunction.class); 2742 final ScriptObject prototype = ScriptFunction.getPrototype(cons); 2743 prototype.set(NativeError.NAME, name, 0); 2744 prototype.set(NativeError.MESSAGE, "", 0); 2745 prototype.setInitialProto(errorProto); 2746 tagBuiltinProperties(name, cons); 2747 return cons; 2748 } 2749 2750 private void initJavaAccess() { 2751 final ScriptObject objectProto = getObjectPrototype(); 2752 this.builtinPackages = new NativeJavaPackage("", objectProto); 2753 this.builtinCom = new NativeJavaPackage("com", objectProto); 2754 this.builtinEdu = new NativeJavaPackage("edu", objectProto); 2755 this.builtinJava = new NativeJavaPackage("java", objectProto); 2756 this.builtinJavafx = new NativeJavaPackage("javafx", objectProto); 2757 this.builtinJavax = new NativeJavaPackage("javax", objectProto); 2758 this.builtinOrg = new NativeJavaPackage("org", objectProto); 2759 } 2760 2761 private void initScripting(final ScriptEnvironment scriptEnv) { 2762 ScriptObject value; 2763 value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE); 2764 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value); 2765 2766 value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY); 2767 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value); 2768 2769 final String execName = ScriptingFunctions.EXEC_NAME; 2770 value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC); 2771 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value); 2772 2773 // Nashorn extension: global.echo (scripting-mode-only) 2774 // alias for "print" 2775 value = (ScriptObject)get("print"); 2776 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value); 2777 2778 // Nashorn extension: global.$OPTIONS (scripting-mode-only) 2779 final ScriptObject options = newObject(); 2780 copyOptions(options, scriptEnv); 2781 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options); 2782 2783 // Nashorn extension: global.$ENV (scripting-mode-only) 2784 final ScriptObject env = newObject(); 2785 if (System.getSecurityManager() == null) { 2786 // do not fill $ENV if we have a security manager around 2787 // Retrieve current state of ENV variables. 2788 env.putAll(System.getenv(), scriptEnv._strict); 2789 2790 // Set the PWD variable to a value that is guaranteed to be understood 2791 // by the underlying platform. 2792 env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); 2793 } 2794 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); 2795 2796 // add other special properties for exec support 2797 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2798 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2799 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2800 } 2801 2802 private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) { 2803 for (final Field f : scriptEnv.getClass().getFields()) { 2804 try { 2805 options.set(f.getName(), f.get(scriptEnv), 0); 2806 } catch (final IllegalArgumentException | IllegalAccessException exp) { 2807 throw new RuntimeException(exp); 2808 } 2809 } 2810 } 2811 2812 private void copyBuiltins() { 2813 this.array = this.builtinArray; 2814 this._boolean = this.builtinBoolean; 2815 this.error = this.builtinError; 2816 this.function = this.builtinFunction; 2817 this.com = this.builtinCom; 2818 this.edu = this.builtinEdu; 2819 this.java = this.builtinJava; 2820 this.javafx = this.builtinJavafx; 2821 this.javax = this.builtinJavax; 2822 this.org = this.builtinOrg; 2823 this.math = this.builtinMath; 2824 this.number = this.builtinNumber; 2825 this.object = this.builtinObject; 2826 this.packages = this.builtinPackages; 2827 this.referenceError = this.builtinReferenceError; 2828 this.string = this.builtinString; 2829 this.syntaxError = this.builtinSyntaxError; 2830 this.typeError = this.builtinTypeError; 2831 } 2832 2833 private void initDebug() { 2834 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class)); 2835 } 2836 2837 private Object printImpl(final boolean newLine, final Object... objects) { 2838 final ScriptContext sc = currentContext(); 2839 @SuppressWarnings("resource") 2840 final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut(); 2841 final StringBuilder sb = new StringBuilder(); 2842 2843 for (final Object obj : objects) { 2844 if (sb.length() != 0) { 2845 sb.append(' '); 2846 } 2847 2848 sb.append(JSType.toString(obj)); 2849 } 2850 2851 // Print all at once to ensure thread friendly result. 2852 if (newLine) { 2853 out.println(sb.toString()); 2854 } else { 2855 out.print(sb.toString()); 2856 } 2857 2858 out.flush(); 2859 2860 return UNDEFINED; 2861 } 2862 2863 private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) { 2864 try { 2865 // Assuming class name pattern for built-in JS constructors. 2866 final StringBuilder sb = new StringBuilder(PACKAGE_PREFIX); 2867 2868 sb.append("Native"); 2869 sb.append(name); 2870 sb.append("$Constructor"); 2871 2872 final Class<?> funcClass = Class.forName(sb.toString()); 2873 final T res = clazz.cast(funcClass.getDeclaredConstructor().newInstance()); 2874 2875 if (res instanceof ScriptFunction) { 2876 // All global constructor prototypes are not-writable, 2877 // not-enumerable and not-configurable. 2878 final ScriptFunction func = (ScriptFunction)res; 2879 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT); 2880 } 2881 2882 if (res.getProto() == null) { 2883 res.setInitialProto(getObjectPrototype()); 2884 } 2885 2886 res.setIsBuiltin(); 2887 2888 return res; 2889 } catch (final Exception e) { 2890 if (e instanceof RuntimeException) { 2891 throw (RuntimeException)e; 2892 } else { 2893 throw new RuntimeException(e); 2894 } 2895 } 2896 } 2897 2898 private ScriptObject initPrototype(final String name, final ScriptObject prototype) { 2899 try { 2900 // Assuming class name pattern for JS prototypes 2901 final String className = PACKAGE_PREFIX + name + "$Prototype"; 2902 2903 final Class<?> funcClass = Class.forName(className); 2904 final ScriptObject res = (ScriptObject) funcClass.getDeclaredConstructor().newInstance(); 2905 2906 res.setIsBuiltin(); 2907 res.setInitialProto(prototype); 2908 return res; 2909 } catch (final Exception e) { 2910 if (e instanceof RuntimeException) { 2911 throw (RuntimeException)e; 2912 } else { 2913 throw new RuntimeException(e); 2914 } 2915 } 2916 } 2917 2918 private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) { 2919 final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>(); 2920 2921 list.addAll(Arrays.asList(func.getMap().getProperties())); 2922 2923 if (func instanceof ScriptFunction) { 2924 final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func); 2925 if (proto != null) { 2926 list.addAll(Arrays.asList(proto.getMap().getProperties())); 2927 } 2928 } 2929 2930 final jdk.nashorn.internal.runtime.Property prop = getProperty(name); 2931 if (prop != null) { 2932 list.add(prop); 2933 } 2934 2935 return list; 2936 } 2937 2938 /** 2939 * Given a builtin object, traverse its properties recursively and associate them with a name that 2940 * will be a key to their invalidation switchpoint. 2941 * @param name name for key 2942 * @param func builtin script object 2943 */ 2944 private void tagBuiltinProperties(final String name, final ScriptObject func) { 2945 SwitchPoint sp = context.getBuiltinSwitchPoint(name); 2946 if (sp == null) { 2947 sp = context.newBuiltinSwitchPoint(name); 2948 } 2949 2950 //get all builtin properties in this builtin object and register switchpoints keyed on the propery name, 2951 //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc 2952 for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) { 2953 prop.setBuiltinSwitchPoint(sp); 2954 } 2955 } 2956 2957 // Function and Object constructors are inter-dependent. Also, 2958 // Function.prototype 2959 // functions are not properly initialized. We fix the references here. 2960 // NOTE: be careful if you want to re-order the operations here. You may 2961 // have 2962 // to play with object references carefully!! 2963 private void initFunctionAndObject() { 2964 // First-n-foremost is Function 2965 2966 this.builtinFunction = initConstructor("Function", ScriptFunction.class); 2967 2968 // create global anonymous function 2969 final ScriptFunction anon = ScriptFunction.createAnonymous(); 2970 // need to copy over members of Function.prototype to anon function 2971 anon.addBoundProperties(getFunctionPrototype()); 2972 2973 // Function.prototype === Object.getPrototypeOf(Function) === 2974 // <anon-function> 2975 builtinFunction.setInitialProto(anon); 2976 builtinFunction.setPrototype(anon); 2977 anon.set("constructor", builtinFunction, 0); 2978 anon.deleteOwnProperty(anon.getMap().findProperty("prototype")); 2979 2980 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3 2981 this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER); 2982 typeErrorThrower.preventExtensions(); 2983 2984 // now initialize Object 2985 this.builtinObject = initConstructor("Object", ScriptFunction.class); 2986 final ScriptObject ObjectPrototype = getObjectPrototype(); 2987 // Object.getPrototypeOf(Function.prototype) === Object.prototype 2988 anon.setInitialProto(ObjectPrototype); 2989 2990 // ES6 draft compliant __proto__ property of Object.prototype 2991 // accessors on Object.prototype for "__proto__" 2992 final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__); 2993 final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__); 2994 ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto); 2995 2996 // Function valued properties of Function.prototype were not properly 2997 // initialized. Because, these were created before global.function and 2998 // global.object were not initialized. 2999 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties(); 3000 for (final jdk.nashorn.internal.runtime.Property property : properties) { 3001 final Object key = property.getKey(); 3002 final Object value = builtinFunction.get(key); 3003 3004 if (value instanceof ScriptFunction && value != anon) { 3005 final ScriptFunction func = (ScriptFunction)value; 3006 func.setInitialProto(getFunctionPrototype()); 3007 final ScriptObject prototype = ScriptFunction.getPrototype(func); 3008 if (prototype != null) { 3009 prototype.setInitialProto(ObjectPrototype); 3010 } 3011 } 3012 } 3013 3014 // For function valued properties of Object and Object.prototype, make 3015 // sure prototype's proto chain ends with Object.prototype 3016 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) { 3017 final Object key = property.getKey(); 3018 final Object value = builtinObject.get(key); 3019 3020 if (value instanceof ScriptFunction) { 3021 final ScriptFunction func = (ScriptFunction)value; 3022 final ScriptObject prototype = ScriptFunction.getPrototype(func); 3023 if (prototype != null) { 3024 prototype.setInitialProto(ObjectPrototype); 3025 } 3026 } 3027 } 3028 3029 properties = getObjectPrototype().getMap().getProperties(); 3030 3031 for (final jdk.nashorn.internal.runtime.Property property : properties) { 3032 final Object key = property.getKey(); 3033 if (key.equals("constructor")) { 3034 continue; 3035 } 3036 3037 final Object value = ObjectPrototype.get(key); 3038 if (value instanceof ScriptFunction) { 3039 final ScriptFunction func = (ScriptFunction)value; 3040 final ScriptObject prototype = ScriptFunction.getPrototype(func); 3041 if (prototype != null) { 3042 prototype.setInitialProto(ObjectPrototype); 3043 } 3044 } 3045 } 3046 3047 tagBuiltinProperties("Object", builtinObject); 3048 tagBuiltinProperties("Function", builtinFunction); 3049 tagBuiltinProperties("Function", anon); 3050 } 3051 3052 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { 3053 return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types)); 3054 } 3055 3056 RegExpResult getLastRegExpResult() { 3057 return lastRegExpResult; 3058 } 3059 3060 void setLastRegExpResult(final RegExpResult regExpResult) { 3061 this.lastRegExpResult = regExpResult; 3062 } 3063 3064 @Override 3065 protected boolean isGlobal() { 3066 return true; 3067 } 3068 3069 /** 3070 * A class representing the ES6 global lexical scope. 3071 */ 3072 private static class LexicalScope extends ScriptObject { 3073 3074 LexicalScope(final Global global) { 3075 super(global, PropertyMap.newMap()); 3076 setIsInternal(); 3077 } 3078 3079 @Override 3080 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 3081 return filterInvocation(super.findGetMethod(desc, request)); 3082 } 3083 3084 @Override 3085 protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 3086 return filterInvocation(super.findSetMethod(desc, request)); 3087 } 3088 3089 @Override 3090 protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property, final boolean extensible) { 3091 // We override this method just to make it callable by Global 3092 return super.addBoundProperty(propMap, source, property, extensible); 3093 } 3094 3095 private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) { 3096 final MethodType type = invocation.getInvocation().type(); 3097 return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER); 3098 } 3099 } 3100 3101} 3102