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