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