Global.java revision 1805:7caf1f762f1d
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 // This also serves as placeholder value used in place of a location property 94 // (__FILE__, __DIR__, __LINE__) 95 private static final Object LAZY_SENTINEL = 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__ = LAZY_SENTINEL; 979 980 /** Nashorn extension: current script's directory */ 981 @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) 982 public static final Object __DIR__ = LAZY_SENTINEL; 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__ = LAZY_SENTINEL; 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 (this.builtinJavaImporter == null) { 2097 this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); 2098 } 2099 return this.builtinJavaImporter; 2100 } 2101 2102 private synchronized ScriptObject getBuiltinJavaApi() { 2103 if (this.builtinJavaApi == null) { 2104 this.builtinJavaApi = initConstructor("Java", ScriptObject.class); 2105 this.builtInJavaExtend = (ScriptFunction)builtinJavaApi.get("extend"); 2106 this.builtInJavaTo = (ScriptFunction)builtinJavaApi.get("to"); 2107 } 2108 return this.builtinJavaApi; 2109 } 2110 2111 /** 2112 * Returns true if the passed function is the built-in "Java.extend". 2113 * @param fn the function in question 2114 * @return true if the function is built-in "Java.extend" 2115 */ 2116 public static boolean isBuiltInJavaExtend(final ScriptFunction fn) { 2117 if(!"extend".equals(fn.getName())) { 2118 // Avoid hitting the thread local if the name doesn't match. 2119 return false; 2120 } 2121 return fn == Context.getGlobal().builtInJavaExtend; 2122 } 2123 2124 /** 2125 * Returns true if the passed function is the built-in "Java.to". 2126 * @param fn the function in question 2127 * @return true if the function is built-in "Java.to" 2128 */ 2129 public static boolean isBuiltInJavaTo(final ScriptFunction fn) { 2130 if(!"to".equals(fn.getName())) { 2131 // Avoid hitting the thread local if the name doesn't match. 2132 return false; 2133 } 2134 return fn == Context.getGlobal().builtInJavaTo; 2135 } 2136 2137 2138 private synchronized ScriptFunction getBuiltinRangeError() { 2139 if (this.builtinRangeError == null) { 2140 this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype()); 2141 } 2142 return builtinRangeError; 2143 } 2144 2145 private synchronized ScriptFunction getBuiltinRegExp() { 2146 if (this.builtinRegExp == null) { 2147 this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); 2148 final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp); 2149 // initialize default regexp object 2150 this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto); 2151 // RegExp.prototype should behave like a RegExp object. So copy the 2152 // properties. 2153 regExpProto.addBoundProperties(DEFAULT_REGEXP); 2154 } 2155 return builtinRegExp; 2156 } 2157 2158 private synchronized ScriptFunction getBuiltinURIError() { 2159 if (this.builtinURIError == null) { 2160 this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype()); 2161 } 2162 return this.builtinURIError; 2163 } 2164 2165 private synchronized ScriptFunction getBuiltinSymbol() { 2166 if (this.builtinSymbol == null) { 2167 this.builtinSymbol = initConstructorAndSwitchPoint("Symbol", ScriptFunction.class); 2168 } 2169 return this.builtinSymbol; 2170 } 2171 2172 private synchronized ScriptFunction getBuiltinMap() { 2173 if (this.builtinMap == null) { 2174 this.builtinMap = initConstructorAndSwitchPoint("Map", ScriptFunction.class); 2175 } 2176 return this.builtinMap; 2177 } 2178 2179 private synchronized ScriptFunction getBuiltinWeakMap() { 2180 if (this.builtinWeakMap == null) { 2181 this.builtinWeakMap = initConstructorAndSwitchPoint("WeakMap", ScriptFunction.class); 2182 } 2183 return this.builtinWeakMap; 2184 } 2185 2186 private synchronized ScriptFunction getBuiltinSet() { 2187 if (this.builtinSet == null) { 2188 this.builtinSet = initConstructorAndSwitchPoint("Set", ScriptFunction.class); 2189 } 2190 return this.builtinSet; 2191 } 2192 2193 private synchronized ScriptFunction getBuiltinWeakSet() { 2194 if (this.builtinWeakSet == null) { 2195 this.builtinWeakSet = initConstructorAndSwitchPoint("WeakSet", ScriptFunction.class); 2196 } 2197 return this.builtinWeakSet; 2198 } 2199 2200 @Override 2201 public String getClassName() { 2202 return "global"; 2203 } 2204 2205 /** 2206 * Copy function used to clone NativeRegExp objects. 2207 * 2208 * @param regexp a NativeRegExp to clone 2209 * 2210 * @return copy of the given regexp object 2211 */ 2212 public static Object regExpCopy(final Object regexp) { 2213 return new NativeRegExp((NativeRegExp)regexp); 2214 } 2215 2216 /** 2217 * Convert given object to NativeRegExp type. 2218 * 2219 * @param obj object to be converted 2220 * @return NativeRegExp instance 2221 */ 2222 public static NativeRegExp toRegExp(final Object obj) { 2223 if (obj instanceof NativeRegExp) { 2224 return (NativeRegExp)obj; 2225 } 2226 return new NativeRegExp(JSType.toString(obj)); 2227 } 2228 2229 /** 2230 * ECMA 9.9 ToObject implementation 2231 * 2232 * @param obj an item for which to run ToObject 2233 * @return ToObject version of given item 2234 */ 2235 public static Object toObject(final Object obj) { 2236 if (obj == null || obj == UNDEFINED) { 2237 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 2238 } 2239 2240 if (obj instanceof ScriptObject) { 2241 return obj; 2242 } 2243 2244 return instance().wrapAsObject(obj); 2245 } 2246 2247 /** 2248 * Allocate a new object array. 2249 * 2250 * @param initial object values. 2251 * @return the new array 2252 */ 2253 public static NativeArray allocate(final Object[] initial) { 2254 ArrayData arrayData = ArrayData.allocate(initial); 2255 2256 for (int index = 0; index < initial.length; index++) { 2257 final Object value = initial[index]; 2258 2259 if (value == ScriptRuntime.EMPTY) { 2260 arrayData = arrayData.delete(index); 2261 } 2262 } 2263 2264 return new NativeArray(arrayData); 2265 } 2266 2267 /** 2268 * Allocate a new number array. 2269 * 2270 * @param initial number values. 2271 * @return the new array 2272 */ 2273 public static NativeArray allocate(final double[] initial) { 2274 return new NativeArray(ArrayData.allocate(initial)); 2275 } 2276 2277 /** 2278 * Allocate a new integer array. 2279 * 2280 * @param initial number values. 2281 * @return the new array 2282 */ 2283 public static NativeArray allocate(final int[] initial) { 2284 return new NativeArray(ArrayData.allocate(initial)); 2285 } 2286 2287 /** 2288 * Allocate a new object array for arguments. 2289 * 2290 * @param arguments initial arguments passed. 2291 * @param callee reference to the function that uses arguments object 2292 * @param numParams actual number of declared parameters 2293 * 2294 * @return the new array 2295 */ 2296 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) { 2297 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams); 2298 } 2299 2300 /** 2301 * Called from generated to check if given function is the builtin 'eval'. If 2302 * eval is used in a script, a lot of optimizations and assumptions cannot be done. 2303 * 2304 * @param fn function object that is checked 2305 * @return true if fn is the builtin eval 2306 */ 2307 public static boolean isEval(final Object fn) { 2308 return fn == Global.instance().builtinEval; 2309 } 2310 2311 /** 2312 * Called from generated to replace a location property placeholder with the actual location property value. 2313 * 2314 * @param placeholder the value tested for being a placeholder for a location property 2315 * @param locationProperty the actual value for the location property 2316 * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise 2317 */ 2318 public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) { 2319 return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder; 2320 } 2321 2322 /** 2323 * Called from runtime internals to check if the passed value is a location property placeholder. 2324 * @param placeholder the value tested for being a placeholder for a location property 2325 * @return true if the value is a placeholder, false otherwise. 2326 */ 2327 public static boolean isLocationPropertyPlaceholder(final Object placeholder) { 2328 return placeholder == LAZY_SENTINEL; 2329 } 2330 2331 /** 2332 * Create a new RegExp object. 2333 * 2334 * @param expression Regular expression. 2335 * @param options Search options. 2336 * 2337 * @return New RegExp object. 2338 */ 2339 public static Object newRegExp(final String expression, final String options) { 2340 if (options == null) { 2341 return new NativeRegExp(expression); 2342 } 2343 return new NativeRegExp(expression, options); 2344 } 2345 2346 /** 2347 * Get the object prototype 2348 * 2349 * @return the object prototype 2350 */ 2351 public static ScriptObject objectPrototype() { 2352 return Global.instance().getObjectPrototype(); 2353 } 2354 2355 /** 2356 * Create a new empty object instance. 2357 * 2358 * @return New empty object. 2359 */ 2360 public static ScriptObject newEmptyInstance() { 2361 return Global.instance().newObject(); 2362 } 2363 2364 /** 2365 * Check if a given object is a ScriptObject, raises an exception if this is 2366 * not the case 2367 * 2368 * @param obj and object to check 2369 * @return the script object 2370 */ 2371 public static ScriptObject checkObject(final Object obj) { 2372 if (!(obj instanceof ScriptObject)) { 2373 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 2374 } 2375 return (ScriptObject)obj; 2376 } 2377 2378 /** 2379 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception 2380 * if this object is null or undefined. 2381 * 2382 * @param obj an object to check 2383 */ 2384 public static void checkObjectCoercible(final Object obj) { 2385 if (obj == null || obj == UNDEFINED) { 2386 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 2387 } 2388 } 2389 2390 /** 2391 * Return the ES6 global scope for lexically declared bindings. 2392 * @return the ES6 lexical global scope. 2393 */ 2394 public final ScriptObject getLexicalScope() { 2395 assert context.getEnv()._es6; 2396 return lexicalScope; 2397 } 2398 2399 @Override 2400 public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) { 2401 PropertyMap ownMap = getMap(); 2402 LexicalScope lexScope = null; 2403 PropertyMap lexicalMap = null; 2404 boolean hasLexicalDefinitions = false; 2405 2406 if (context.getEnv()._es6) { 2407 lexScope = (LexicalScope) getLexicalScope(); 2408 lexicalMap = lexScope.getMap(); 2409 2410 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2411 if (property.isLexicalBinding()) { 2412 hasLexicalDefinitions = true; 2413 } 2414 // ES6 15.1.8 steps 6. and 7. 2415 final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey()); 2416 if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) { 2417 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString()); 2418 } 2419 final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey()); 2420 if (lexicalProperty != null && !property.isConfigurable()) { 2421 throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString()); 2422 } 2423 } 2424 } 2425 2426 final boolean extensible = isExtensible(); 2427 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2428 if (property.isLexicalBinding()) { 2429 assert lexScope != null; 2430 lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property, true); 2431 2432 if (ownMap.findProperty(property.getKey()) != null) { 2433 // If property exists in the global object invalidate any global constant call sites. 2434 invalidateGlobalConstant(property.getKey()); 2435 } 2436 } else { 2437 ownMap = addBoundProperty(ownMap, source, property, extensible); 2438 } 2439 } 2440 2441 setMap(ownMap); 2442 2443 if (hasLexicalDefinitions) { 2444 assert lexScope != null; 2445 lexScope.setMap(lexicalMap); 2446 invalidateLexicalSwitchPoint(); 2447 } 2448 } 2449 2450 @Override 2451 public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 2452 final String name = NashornCallSiteDescriptor.getOperand(desc); 2453 final boolean isScope = NashornCallSiteDescriptor.isScope(desc); 2454 2455 if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) { 2456 if (lexicalScope.hasOwnProperty(name)) { 2457 return lexicalScope.findGetMethod(desc, request); 2458 } 2459 } 2460 2461 final GuardedInvocation invocation = super.findGetMethod(desc, request); 2462 2463 // We want to avoid adding our generic lexical scope switchpoint to global constant invocations, 2464 // because those are invalidated per-key in the addBoundProperties method above. 2465 // We therefore check if the invocation does already have a switchpoint and the property is non-inherited, 2466 // assuming this only applies to global constants. If other non-inherited properties will 2467 // start using switchpoints some time in the future we'll have to revisit this. 2468 if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) { 2469 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint()); 2470 } 2471 2472 return invocation; 2473 } 2474 2475 @Override 2476 protected FindProperty findProperty(final Object key, final boolean deep, final boolean isScope, final ScriptObject start) { 2477 if (lexicalScope != null && isScope) { 2478 final FindProperty find = lexicalScope.findProperty(key, false); 2479 if (find != null) { 2480 return find; 2481 } 2482 } 2483 return super.findProperty(key, deep, isScope, start); 2484 } 2485 2486 @Override 2487 public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 2488 final boolean isScope = NashornCallSiteDescriptor.isScope(desc); 2489 2490 if (lexicalScope != null && isScope) { 2491 final String name = NashornCallSiteDescriptor.getOperand(desc); 2492 if (lexicalScope.hasOwnProperty(name)) { 2493 return lexicalScope.findSetMethod(desc, request); 2494 } 2495 } 2496 2497 final GuardedInvocation invocation = super.findSetMethod(desc, request); 2498 2499 if (isScope && context.getEnv()._es6) { 2500 return invocation.addSwitchPoint(getLexicalScopeSwitchPoint()); 2501 } 2502 2503 return invocation; 2504 } 2505 2506 /** 2507 * Adds jjs shell interactive mode builtin functions to global scope. 2508 */ 2509 public void addShellBuiltins() { 2510 Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT); 2511 addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); 2512 2513 value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT); 2514 addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); 2515 } 2516 2517 private synchronized SwitchPoint getLexicalScopeSwitchPoint() { 2518 SwitchPoint switchPoint = lexicalScopeSwitchPoint; 2519 if (switchPoint == null || switchPoint.hasBeenInvalidated()) { 2520 switchPoint = lexicalScopeSwitchPoint = new SwitchPoint(); 2521 } 2522 return switchPoint; 2523 } 2524 2525 private synchronized void invalidateLexicalSwitchPoint() { 2526 if (lexicalScopeSwitchPoint != null) { 2527 context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update"); 2528 SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint }); 2529 } 2530 } 2531 2532 2533 @SuppressWarnings("unused") 2534 private static Object lexicalScopeFilter(final Object self) { 2535 if (self instanceof Global) { 2536 return ((Global) self).getLexicalScope(); 2537 } 2538 return self; 2539 } 2540 2541 private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) { 2542 final T func = initConstructor(name, clazz); 2543 tagBuiltinProperties(name, func); 2544 return func; 2545 } 2546 2547 private void init(final ScriptEngine eng) { 2548 assert Context.getGlobal() == this : "this global is not set as current"; 2549 2550 final ScriptEnvironment env = getContext().getEnv(); 2551 2552 // initialize Function and Object constructor 2553 initFunctionAndObject(); 2554 2555 // Now fix Global's own proto. 2556 this.setInitialProto(getObjectPrototype()); 2557 2558 // initialize global function properties 2559 this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL); 2560 2561 this.parseInt = ScriptFunction.createBuiltin("parseInt", GlobalFunctions.PARSEINT, 2562 new Specialization[] { 2563 new Specialization(GlobalFunctions.PARSEINT_Z), 2564 new Specialization(GlobalFunctions.PARSEINT_I), 2565 new Specialization(GlobalFunctions.PARSEINT_OI), 2566 new Specialization(GlobalFunctions.PARSEINT_O) }); 2567 this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); 2568 this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN, 2569 new Specialization[] { 2570 new Specialization(GlobalFunctions.IS_NAN_I), 2571 new Specialization(GlobalFunctions.IS_NAN_J), 2572 new Specialization(GlobalFunctions.IS_NAN_D) }); 2573 this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); 2574 this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN); 2575 this.isFinite = ScriptFunction.createBuiltin("isFinite", GlobalFunctions.IS_FINITE); 2576 this.encodeURI = ScriptFunction.createBuiltin("encodeURI", GlobalFunctions.ENCODE_URI); 2577 this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); 2578 this.decodeURI = ScriptFunction.createBuiltin("decodeURI", GlobalFunctions.DECODE_URI); 2579 this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); 2580 this.escape = ScriptFunction.createBuiltin("escape", GlobalFunctions.ESCAPE); 2581 this.unescape = ScriptFunction.createBuiltin("unescape", GlobalFunctions.UNESCAPE); 2582 this.print = ScriptFunction.createBuiltin("print", env._print_no_newline ? PRINT : PRINTLN); 2583 this.load = ScriptFunction.createBuiltin("load", LOAD); 2584 this.loadWithNewGlobal = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL); 2585 this.exit = ScriptFunction.createBuiltin("exit", EXIT); 2586 this.quit = ScriptFunction.createBuiltin("quit", EXIT); 2587 2588 // built-in constructors 2589 this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); 2590 this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class); 2591 this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); 2592 this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); 2593 this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class); 2594 2595 // initialize String.prototype.length to 0 2596 // add String.prototype.length 2597 final ScriptObject stringPrototype = getStringPrototype(); 2598 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0); 2599 2600 // set isArray flag on Array.prototype 2601 final ScriptObject arrayPrototype = getArrayPrototype(); 2602 arrayPrototype.setIsArray(); 2603 2604 if (env._es6) { 2605 this.symbol = LAZY_SENTINEL; 2606 this.map = LAZY_SENTINEL; 2607 this.weakMap = LAZY_SENTINEL; 2608 this.set = LAZY_SENTINEL; 2609 this.weakSet = LAZY_SENTINEL; 2610 } else { 2611 // We need to manually delete nasgen-generated properties we don't want 2612 this.delete("Symbol", false); 2613 this.delete("Map", false); 2614 this.delete("WeakMap", false); 2615 this.delete("Set", false); 2616 this.delete("WeakSet", false); 2617 builtinObject.delete("getOwnPropertySymbols", false); 2618 arrayPrototype.delete("entries", false); 2619 arrayPrototype.delete("keys", false); 2620 arrayPrototype.delete("values", false); 2621 } 2622 2623 // Error stuff 2624 initErrorObjects(); 2625 2626 // java access 2627 if (! env._no_java) { 2628 this.javaApi = LAZY_SENTINEL; 2629 this.javaImporter = LAZY_SENTINEL; 2630 initJavaAccess(); 2631 } 2632 2633 if (! env._no_typed_arrays) { 2634 this.arrayBuffer = LAZY_SENTINEL; 2635 this.dataView = LAZY_SENTINEL; 2636 this.int8Array = LAZY_SENTINEL; 2637 this.uint8Array = LAZY_SENTINEL; 2638 this.uint8ClampedArray = LAZY_SENTINEL; 2639 this.int16Array = LAZY_SENTINEL; 2640 this.uint16Array = LAZY_SENTINEL; 2641 this.int32Array = LAZY_SENTINEL; 2642 this.uint32Array = LAZY_SENTINEL; 2643 this.float32Array = LAZY_SENTINEL; 2644 this.float64Array = LAZY_SENTINEL; 2645 } 2646 2647 if (env._scripting) { 2648 initScripting(env); 2649 } 2650 2651 if (Context.DEBUG) { 2652 boolean debugOkay; 2653 final SecurityManager sm = System.getSecurityManager(); 2654 if (sm != null) { 2655 try { 2656 sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE)); 2657 debugOkay = true; 2658 } catch (final SecurityException ignored) { 2659 // if no permission, don't initialize Debug object 2660 debugOkay = false; 2661 } 2662 2663 } else { 2664 debugOkay = true; 2665 } 2666 2667 if (debugOkay) { 2668 initDebug(); 2669 } 2670 } 2671 2672 copyBuiltins(); 2673 2674 // expose script (command line) arguments as "arguments" property of global 2675 arguments = wrapAsObject(env.getArguments().toArray()); 2676 if (env._scripting) { 2677 // synonym for "arguments" in scripting mode 2678 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments); 2679 } 2680 2681 if (eng != null) { 2682 // default file name 2683 addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null); 2684 // __noSuchProperty__ hook for ScriptContext search of missing variables 2685 final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY); 2686 addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp); 2687 } 2688 } 2689 2690 private void initErrorObjects() { 2691 // Error objects 2692 this.builtinError = initConstructor("Error", ScriptFunction.class); 2693 final ScriptObject errorProto = getErrorPrototype(); 2694 2695 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName 2696 final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK); 2697 final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK); 2698 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); 2699 final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER); 2700 final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER); 2701 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber); 2702 final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER); 2703 final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER); 2704 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber); 2705 final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME); 2706 final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME); 2707 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName); 2708 2709 // ECMA 15.11.4.2 Error.prototype.name 2710 // Error.prototype.name = "Error"; 2711 errorProto.set(NativeError.NAME, "Error", 0); 2712 // ECMA 15.11.4.3 Error.prototype.message 2713 // Error.prototype.message = ""; 2714 errorProto.set(NativeError.MESSAGE, "", 0); 2715 2716 tagBuiltinProperties("Error", builtinError); 2717 2718 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); 2719 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto); 2720 this.builtinTypeError = initErrorSubtype("TypeError", errorProto); 2721 } 2722 2723 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) { 2724 final ScriptFunction cons = initConstructor(name, ScriptFunction.class); 2725 final ScriptObject prototype = ScriptFunction.getPrototype(cons); 2726 prototype.set(NativeError.NAME, name, 0); 2727 prototype.set(NativeError.MESSAGE, "", 0); 2728 prototype.setInitialProto(errorProto); 2729 tagBuiltinProperties(name, cons); 2730 return cons; 2731 } 2732 2733 private void initJavaAccess() { 2734 final ScriptObject objectProto = getObjectPrototype(); 2735 this.builtinPackages = new NativeJavaPackage("", objectProto); 2736 this.builtinCom = new NativeJavaPackage("com", objectProto); 2737 this.builtinEdu = new NativeJavaPackage("edu", objectProto); 2738 this.builtinJava = new NativeJavaPackage("java", objectProto); 2739 this.builtinJavafx = new NativeJavaPackage("javafx", objectProto); 2740 this.builtinJavax = new NativeJavaPackage("javax", objectProto); 2741 this.builtinOrg = new NativeJavaPackage("org", objectProto); 2742 } 2743 2744 private void initScripting(final ScriptEnvironment scriptEnv) { 2745 ScriptObject value; 2746 value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE); 2747 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value); 2748 2749 value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY); 2750 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value); 2751 2752 final String execName = ScriptingFunctions.EXEC_NAME; 2753 value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC); 2754 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value); 2755 2756 // Nashorn extension: global.echo (scripting-mode-only) 2757 // alias for "print" 2758 value = (ScriptObject)get("print"); 2759 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value); 2760 2761 // Nashorn extension: global.$OPTIONS (scripting-mode-only) 2762 final ScriptObject options = newObject(); 2763 copyOptions(options, scriptEnv); 2764 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options); 2765 2766 // Nashorn extension: global.$ENV (scripting-mode-only) 2767 final ScriptObject env = newObject(); 2768 if (System.getSecurityManager() == null) { 2769 // do not fill $ENV if we have a security manager around 2770 // Retrieve current state of ENV variables. 2771 env.putAll(System.getenv(), scriptEnv._strict); 2772 2773 // Set the PWD variable to a value that is guaranteed to be understood 2774 // by the underlying platform. 2775 env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); 2776 } 2777 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); 2778 2779 // add other special properties for exec support 2780 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2781 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2782 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 2783 } 2784 2785 private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) { 2786 for (final Field f : scriptEnv.getClass().getFields()) { 2787 try { 2788 options.set(f.getName(), f.get(scriptEnv), 0); 2789 } catch (final IllegalArgumentException | IllegalAccessException exp) { 2790 throw new RuntimeException(exp); 2791 } 2792 } 2793 } 2794 2795 private void copyBuiltins() { 2796 this.array = this.builtinArray; 2797 this._boolean = this.builtinBoolean; 2798 this.error = this.builtinError; 2799 this.function = this.builtinFunction; 2800 this.com = this.builtinCom; 2801 this.edu = this.builtinEdu; 2802 this.java = this.builtinJava; 2803 this.javafx = this.builtinJavafx; 2804 this.javax = this.builtinJavax; 2805 this.org = this.builtinOrg; 2806 this.math = this.builtinMath; 2807 this.number = this.builtinNumber; 2808 this.object = this.builtinObject; 2809 this.packages = this.builtinPackages; 2810 this.referenceError = this.builtinReferenceError; 2811 this.string = this.builtinString; 2812 this.syntaxError = this.builtinSyntaxError; 2813 this.typeError = this.builtinTypeError; 2814 } 2815 2816 private void initDebug() { 2817 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class)); 2818 } 2819 2820 private Object printImpl(final boolean newLine, final Object... objects) { 2821 final ScriptContext sc = currentContext(); 2822 @SuppressWarnings("resource") 2823 final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut(); 2824 final StringBuilder sb = new StringBuilder(); 2825 2826 for (final Object obj : objects) { 2827 if (sb.length() != 0) { 2828 sb.append(' '); 2829 } 2830 2831 sb.append(JSType.toString(obj)); 2832 } 2833 2834 // Print all at once to ensure thread friendly result. 2835 if (newLine) { 2836 out.println(sb.toString()); 2837 } else { 2838 out.print(sb.toString()); 2839 } 2840 2841 out.flush(); 2842 2843 return UNDEFINED; 2844 } 2845 2846 private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) { 2847 try { 2848 // Assuming class name pattern for built-in JS constructors. 2849 final StringBuilder sb = new StringBuilder(PACKAGE_PREFIX); 2850 2851 sb.append("Native"); 2852 sb.append(name); 2853 sb.append("$Constructor"); 2854 2855 final Class<?> funcClass = Class.forName(sb.toString()); 2856 final T res = clazz.cast(funcClass.getDeclaredConstructor().newInstance()); 2857 2858 if (res instanceof ScriptFunction) { 2859 // All global constructor prototypes are not-writable, 2860 // not-enumerable and not-configurable. 2861 final ScriptFunction func = (ScriptFunction)res; 2862 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT); 2863 } 2864 2865 if (res.getProto() == null) { 2866 res.setInitialProto(getObjectPrototype()); 2867 } 2868 2869 res.setIsBuiltin(); 2870 2871 return res; 2872 } catch (final Exception e) { 2873 if (e instanceof RuntimeException) { 2874 throw (RuntimeException)e; 2875 } else { 2876 throw new RuntimeException(e); 2877 } 2878 } 2879 } 2880 2881 private ScriptObject initPrototype(final String name, final ScriptObject prototype) { 2882 try { 2883 // Assuming class name pattern for JS prototypes 2884 final String className = PACKAGE_PREFIX + name + "$Prototype"; 2885 2886 final Class<?> funcClass = Class.forName(className); 2887 final ScriptObject res = (ScriptObject) funcClass.getDeclaredConstructor().newInstance(); 2888 2889 res.setIsBuiltin(); 2890 res.setInitialProto(prototype); 2891 return res; 2892 } catch (final Exception e) { 2893 if (e instanceof RuntimeException) { 2894 throw (RuntimeException)e; 2895 } else { 2896 throw new RuntimeException(e); 2897 } 2898 } 2899 } 2900 2901 private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) { 2902 final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>(); 2903 2904 list.addAll(Arrays.asList(func.getMap().getProperties())); 2905 2906 if (func instanceof ScriptFunction) { 2907 final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func); 2908 if (proto != null) { 2909 list.addAll(Arrays.asList(proto.getMap().getProperties())); 2910 } 2911 } 2912 2913 final jdk.nashorn.internal.runtime.Property prop = getProperty(name); 2914 if (prop != null) { 2915 list.add(prop); 2916 } 2917 2918 return list; 2919 } 2920 2921 /** 2922 * Given a builtin object, traverse its properties recursively and associate them with a name that 2923 * will be a key to their invalidation switchpoint. 2924 * @param name name for key 2925 * @param func builtin script object 2926 */ 2927 private void tagBuiltinProperties(final String name, final ScriptObject func) { 2928 SwitchPoint sp = context.getBuiltinSwitchPoint(name); 2929 if (sp == null) { 2930 sp = context.newBuiltinSwitchPoint(name); 2931 } 2932 2933 //get all builtin properties in this builtin object and register switchpoints keyed on the propery name, 2934 //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc 2935 for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) { 2936 prop.setBuiltinSwitchPoint(sp); 2937 } 2938 } 2939 2940 // Function and Object constructors are inter-dependent. Also, 2941 // Function.prototype 2942 // functions are not properly initialized. We fix the references here. 2943 // NOTE: be careful if you want to re-order the operations here. You may 2944 // have 2945 // to play with object references carefully!! 2946 private void initFunctionAndObject() { 2947 // First-n-foremost is Function 2948 2949 this.builtinFunction = initConstructor("Function", ScriptFunction.class); 2950 2951 // create global anonymous function 2952 final ScriptFunction anon = ScriptFunction.createAnonymous(); 2953 // need to copy over members of Function.prototype to anon function 2954 anon.addBoundProperties(getFunctionPrototype()); 2955 2956 // Function.prototype === Object.getPrototypeOf(Function) === 2957 // <anon-function> 2958 builtinFunction.setInitialProto(anon); 2959 builtinFunction.setPrototype(anon); 2960 anon.set("constructor", builtinFunction, 0); 2961 anon.deleteOwnProperty(anon.getMap().findProperty("prototype")); 2962 2963 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3 2964 this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER); 2965 typeErrorThrower.preventExtensions(); 2966 2967 // now initialize Object 2968 this.builtinObject = initConstructor("Object", ScriptFunction.class); 2969 final ScriptObject ObjectPrototype = getObjectPrototype(); 2970 // Object.getPrototypeOf(Function.prototype) === Object.prototype 2971 anon.setInitialProto(ObjectPrototype); 2972 2973 // ES6 draft compliant __proto__ property of Object.prototype 2974 // accessors on Object.prototype for "__proto__" 2975 final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__); 2976 final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__); 2977 ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto); 2978 2979 // Function valued properties of Function.prototype were not properly 2980 // initialized. Because, these were created before global.function and 2981 // global.object were not initialized. 2982 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties(); 2983 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2984 final Object key = property.getKey(); 2985 final Object value = builtinFunction.get(key); 2986 2987 if (value instanceof ScriptFunction && value != anon) { 2988 final ScriptFunction func = (ScriptFunction)value; 2989 func.setInitialProto(getFunctionPrototype()); 2990 final ScriptObject prototype = ScriptFunction.getPrototype(func); 2991 if (prototype != null) { 2992 prototype.setInitialProto(ObjectPrototype); 2993 } 2994 } 2995 } 2996 2997 // For function valued properties of Object and Object.prototype, make 2998 // sure prototype's proto chain ends with Object.prototype 2999 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) { 3000 final Object key = property.getKey(); 3001 final Object value = builtinObject.get(key); 3002 3003 if (value instanceof ScriptFunction) { 3004 final ScriptFunction func = (ScriptFunction)value; 3005 final ScriptObject prototype = ScriptFunction.getPrototype(func); 3006 if (prototype != null) { 3007 prototype.setInitialProto(ObjectPrototype); 3008 } 3009 } 3010 } 3011 3012 properties = getObjectPrototype().getMap().getProperties(); 3013 3014 for (final jdk.nashorn.internal.runtime.Property property : properties) { 3015 final Object key = property.getKey(); 3016 if (key.equals("constructor")) { 3017 continue; 3018 } 3019 3020 final Object value = ObjectPrototype.get(key); 3021 if (value instanceof ScriptFunction) { 3022 final ScriptFunction func = (ScriptFunction)value; 3023 final ScriptObject prototype = ScriptFunction.getPrototype(func); 3024 if (prototype != null) { 3025 prototype.setInitialProto(ObjectPrototype); 3026 } 3027 } 3028 } 3029 3030 tagBuiltinProperties("Object", builtinObject); 3031 tagBuiltinProperties("Function", builtinFunction); 3032 tagBuiltinProperties("Function", anon); 3033 } 3034 3035 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { 3036 return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types)); 3037 } 3038 3039 RegExpResult getLastRegExpResult() { 3040 return lastRegExpResult; 3041 } 3042 3043 void setLastRegExpResult(final RegExpResult regExpResult) { 3044 this.lastRegExpResult = regExpResult; 3045 } 3046 3047 @Override 3048 protected boolean isGlobal() { 3049 return true; 3050 } 3051 3052 /** 3053 * A class representing the ES6 global lexical scope. 3054 */ 3055 private static class LexicalScope extends ScriptObject { 3056 3057 LexicalScope(final Global global) { 3058 super(global, PropertyMap.newMap()); 3059 setIsInternal(); 3060 } 3061 3062 @Override 3063 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 3064 return filterInvocation(super.findGetMethod(desc, request)); 3065 } 3066 3067 @Override 3068 protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 3069 return filterInvocation(super.findSetMethod(desc, request)); 3070 } 3071 3072 @Override 3073 protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property, final boolean extensible) { 3074 // We override this method just to make it callable by Global 3075 return super.addBoundProperty(propMap, source, property, extensible); 3076 } 3077 3078 private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) { 3079 final MethodType type = invocation.getInvocation().type(); 3080 return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER); 3081 } 3082 } 3083 3084} 3085