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