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