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