# HG changeset patch # User asaha # Date 1428645568 25200 # Node ID e790c138759476625cc765ded0726c7a6ee372a6 # Parent 4d85dc2a37119e34c21bab8f0e38634b0124234f# Parent 3668fbc46e2ab8d2f5639109c563db1a0832c0e0 Merge diff -r 4d85dc2a3711 -r e790c1387594 .hgtags --- a/.hgtags Wed Apr 01 11:35:19 2015 -0700 +++ b/.hgtags Thu Apr 09 22:59:28 2015 -0700 @@ -392,3 +392,4 @@ 80966e5cc384fb8c67938c0e05e2b990116d3f4c jdk8u60-b07 e024db176497a3655f7c9d1d86571df74707ba62 jdk8u60-b08 1f73439a45bf9cdb73ece75b2c935980657b10d4 jdk8u60-b09 +7aaa64363e1a632ab113b459c46a8ce0c32e4738 jdk8u60-b10 diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/Global.java --- a/src/jdk/nashorn/internal/objects/Global.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/Global.java Thu Apr 09 22:59:28 2015 -0700 @@ -54,10 +54,13 @@ import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.lookup.Lookup; import jdk.nashorn.internal.objects.annotations.Attribute; +import jdk.nashorn.internal.objects.annotations.Getter; import jdk.nashorn.internal.objects.annotations.Property; import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.objects.annotations.Setter; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ECMAErrors; +import jdk.nashorn.internal.runtime.FindProperty; import jdk.nashorn.internal.runtime.GlobalConstants; import jdk.nashorn.internal.runtime.GlobalFunctions; import jdk.nashorn.internal.runtime.JSType; @@ -77,6 +80,7 @@ import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.regexp.RegExpResult; import jdk.nashorn.internal.scripts.JO; +import jdk.nashorn.tools.ShellFunctions; /** * Representation of global scope. @@ -88,6 +92,9 @@ private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class); + // placeholder value for lazily initialized global objects + private static final Object LAZY_SENTINEL = new Object(); + /** * Optimistic builtin names that require switchpoint invalidation * upon assignment. Overly conservative, but works for now, to avoid @@ -213,20 +220,76 @@ public volatile Object number; /** ECMA 15.1.4.7 Date constructor */ - @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object date; + @Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE) + public static Object getDate(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.date == LAZY_SENTINEL) { + global.date = global.getBuiltinDate(); + } + return global.date; + } + + @Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE) + public static void setDate(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.date = value; + } + + private volatile Object date = LAZY_SENTINEL; /** ECMA 15.1.4.8 RegExp constructor */ - @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object regexp; + @Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) + public static Object getRegExp(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.regexp == LAZY_SENTINEL) { + global.regexp = global.getBuiltinRegExp(); + } + return global.regexp; + } + + @Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) + public static void setRegExp(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.regexp = value; + } + + private volatile Object regexp = LAZY_SENTINEL; /** ECMA 15.12 - The JSON object */ - @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object json; + @Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) + public static Object getJSON(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.json == LAZY_SENTINEL) { + global.json = global.getBuiltinJSON(); + } + return global.json; + } + + @Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) + public static void setJSON(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.json = value; + } + + private volatile Object json = LAZY_SENTINEL; /** Nashorn extension: global.JSAdapter */ - @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object jsadapter; + @Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) + public static Object getJSAdapter(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.jsadapter == LAZY_SENTINEL) { + global.jsadapter = global.getBuiltinJSAdapter(); + } + return global.jsadapter; + } + + @Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) + public static void setJSAdapter(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.jsadapter = value; + } + + private volatile Object jsadapter = LAZY_SENTINEL; /** ECMA 15.8 - The Math object */ @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE) @@ -237,12 +300,40 @@ public volatile Object error; /** EvalError object */ - @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object evalError; + @Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) + public static Object getEvalError(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.evalError == LAZY_SENTINEL) { + global.evalError = global.getBuiltinEvalError(); + } + return global.evalError; + } + + @Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) + public static void setEvalError(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.evalError = value; + } + + private volatile Object evalError = LAZY_SENTINEL; /** RangeError object */ - @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object rangeError; + @Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) + public static Object getRangeError(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.rangeError == LAZY_SENTINEL) { + global.rangeError = global.getBuiltinRangeError(); + } + return global.rangeError; + } + + @Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) + public static void setRangeError(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.rangeError = value; + } + + private volatile Object rangeError = LAZY_SENTINEL; /** ReferenceError object */ @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE) @@ -257,52 +348,220 @@ public volatile Object typeError; /** URIError object */ - @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uriError; + @Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) + public static Object getURIError(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uriError == LAZY_SENTINEL) { + global.uriError = global.getBuiltinURIError(); + } + return global.uriError; + } + + @Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) + public static void setURIError(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uriError = value; + } + + private volatile Object uriError = LAZY_SENTINEL; /** ArrayBuffer object */ - @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object arrayBuffer; + @Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) + public static Object getArrayBuffer(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.arrayBuffer == LAZY_SENTINEL) { + global.arrayBuffer = global.getBuiltinArrayBuffer(); + } + return global.arrayBuffer; + } + + @Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) + public static void setArrayBuffer(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.arrayBuffer = value; + } + + private volatile Object arrayBuffer; /** DataView object */ - @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object dataView; + @Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) + public static Object getDataView(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.dataView == LAZY_SENTINEL) { + global.dataView = global.getBuiltinDataView(); + } + return global.dataView; + } + + @Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) + public static void setDataView(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.dataView = value; + } + + private volatile Object dataView; /** TypedArray (int8) */ - @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object int8Array; + @Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getInt8Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.int8Array == LAZY_SENTINEL) { + global.int8Array = global.getBuiltinInt8Array(); + } + return global.int8Array; + } + + @Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setInt8Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.int8Array = value; + } + + private volatile Object int8Array; /** TypedArray (uint8) */ - @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uint8Array; + @Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getUint8Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uint8Array == LAZY_SENTINEL) { + global.uint8Array = global.getBuiltinUint8Array(); + } + return global.uint8Array; + } + + @Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setUint8Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uint8Array = value; + } + + private volatile Object uint8Array; /** TypedArray (uint8) - Clamped */ - @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uint8ClampedArray; + @Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) + public static Object getUint8ClampedArray(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uint8ClampedArray == LAZY_SENTINEL) { + global.uint8ClampedArray = global.getBuiltinUint8ClampedArray(); + } + return global.uint8ClampedArray; + } + + @Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) + public static void setUint8ClampedArray(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uint8ClampedArray = value; + } + + private volatile Object uint8ClampedArray; /** TypedArray (int16) */ - @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object int16Array; + @Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getInt16Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.int16Array == LAZY_SENTINEL) { + global.int16Array = global.getBuiltinInt16Array(); + } + return global.int16Array; + } + + @Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setInt16Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.int16Array = value; + } + + private volatile Object int16Array; /** TypedArray (uint16) */ - @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uint16Array; + @Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getUint16Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uint16Array == LAZY_SENTINEL) { + global.uint16Array = global.getBuiltinUint16Array(); + } + return global.uint16Array; + } + + @Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setUint16Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uint16Array = value; + } + + private volatile Object uint16Array; /** TypedArray (int32) */ - @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object int32Array; + @Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getInt32Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.int32Array == LAZY_SENTINEL) { + global.int32Array = global.getBuiltinInt32Array(); + } + return global.int32Array; + } + + @Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setInt32Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.int32Array = value; + } + + private volatile Object int32Array; /** TypedArray (uint32) */ - @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object uint32Array; + @Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getUint32Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.uint32Array == LAZY_SENTINEL) { + global.uint32Array = global.getBuiltinUint32Array(); + } + return global.uint32Array; + } + + @Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setUint32Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.uint32Array = value; + } + + private volatile Object uint32Array; /** TypedArray (float32) */ - @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object float32Array; + @Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getFloat32Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.float32Array == LAZY_SENTINEL) { + global.float32Array = global.getBuiltinFloat32Array(); + } + return global.float32Array; + } + + @Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setFloat32Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.float32Array = value; + } + + private volatile Object float32Array; /** TypedArray (float64) */ - @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object float64Array; + @Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) + public static Object getFloat64Array(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.float64Array == LAZY_SENTINEL) { + global.float64Array = global.getBuiltinFloat64Array(); + } + return global.float64Array; + } + + @Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) + public static void setFloat64Array(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.float64Array = value; + } + + private volatile Object float64Array; /** Nashorn extension: Java access - global.Packages */ @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE) @@ -333,12 +592,40 @@ public volatile Object org; /** Nashorn extension: Java access - global.javaImporter */ - @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object javaImporter; + @Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) + public static Object getJavaImporter(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.javaImporter == LAZY_SENTINEL) { + global.javaImporter = global.getBuiltinJavaImporter(); + } + return global.javaImporter; + } + + @Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) + public static void setJavaImporter(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.javaImporter = value; + } + + private volatile Object javaImporter; /** Nashorn extension: global.Java Object constructor. */ - @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object javaApi; + @Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE) + public static Object getJavaApi(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.javaApi == LAZY_SENTINEL) { + global.javaApi = global.getBuiltinJavaApi(); + } + return global.javaApi; + } + + @Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE) + public static void setJavaApi(final Object self, final Object value) { + final Global global = Global.instanceFrom(self); + global.javaApi = value; + } + + private volatile Object javaApi; /** Nashorn extension: current script's file name */ @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) @@ -352,11 +639,19 @@ @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER; + private volatile NativeDate DEFAULT_DATE; + /** Used as Date.prototype's default value */ - public NativeDate DEFAULT_DATE; + NativeDate getDefaultDate() { + return DEFAULT_DATE; + } + + private volatile NativeRegExp DEFAULT_REGEXP; /** Used as RegExp.prototype's default value */ - public NativeRegExp DEFAULT_REGEXP; + NativeRegExp getDefaultRegExp() { + return DEFAULT_REGEXP; + } /* * Built-in constructor objects: Even if user changes dynamic values of @@ -1034,7 +1329,7 @@ /** * Get the builtin Object prototype. - * @return the object prototype. + * @return the object prototype. */ public ScriptObject getObjectPrototype() { return ScriptFunction.getPrototype(builtinObject); @@ -1057,11 +1352,11 @@ } ScriptObject getDatePrototype() { - return ScriptFunction.getPrototype(builtinDate); + return ScriptFunction.getPrototype(getBuiltinDate()); } ScriptObject getRegExpPrototype() { - return ScriptFunction.getPrototype(builtinRegExp); + return ScriptFunction.getPrototype(getBuiltinRegExp()); } ScriptObject getStringPrototype() { @@ -1073,11 +1368,11 @@ } ScriptObject getEvalErrorPrototype() { - return ScriptFunction.getPrototype(builtinEvalError); + return ScriptFunction.getPrototype(getBuiltinEvalError()); } ScriptObject getRangeErrorPrototype() { - return ScriptFunction.getPrototype(builtinRangeError); + return ScriptFunction.getPrototype(getBuiltinRangeError()); } ScriptObject getReferenceErrorPrototype() { @@ -1093,59 +1388,136 @@ } ScriptObject getURIErrorPrototype() { - return ScriptFunction.getPrototype(builtinURIError); + return ScriptFunction.getPrototype(getBuiltinURIError()); } ScriptObject getJavaImporterPrototype() { - return ScriptFunction.getPrototype(builtinJavaImporter); + return ScriptFunction.getPrototype(getBuiltinJavaImporter()); } ScriptObject getJSAdapterPrototype() { - return ScriptFunction.getPrototype(builtinJSAdapter); + return ScriptFunction.getPrototype(getBuiltinJSAdapter()); } + private synchronized ScriptFunction getBuiltinArrayBuffer() { + if (this.builtinArrayBuffer == null) { + this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); + } + return this.builtinArrayBuffer; + } + ScriptObject getArrayBufferPrototype() { - return ScriptFunction.getPrototype(builtinArrayBuffer); + return ScriptFunction.getPrototype(getBuiltinArrayBuffer()); } + private synchronized ScriptFunction getBuiltinDataView() { + if (this.builtinDataView == null) { + this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); + } + return this.builtinDataView; + } + ScriptObject getDataViewPrototype() { - return ScriptFunction.getPrototype(builtinDataView); + return ScriptFunction.getPrototype(getBuiltinDataView()); } + private synchronized ScriptFunction getBuiltinInt8Array() { + if (this.builtinInt8Array == null) { + this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); + } + return this.builtinInt8Array; + } + ScriptObject getInt8ArrayPrototype() { - return ScriptFunction.getPrototype(builtinInt8Array); + return ScriptFunction.getPrototype(getBuiltinInt8Array()); } + private synchronized ScriptFunction getBuiltinUint8Array() { + if (this.builtinUint8Array == null) { + this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); + } + return this.builtinUint8Array; + } + ScriptObject getUint8ArrayPrototype() { - return ScriptFunction.getPrototype(builtinUint8Array); + return ScriptFunction.getPrototype(getBuiltinUint8Array()); } + private synchronized ScriptFunction getBuiltinUint8ClampedArray() { + if (this.builtinUint8ClampedArray == null) { + this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); + } + return this.builtinUint8ClampedArray; + } + ScriptObject getUint8ClampedArrayPrototype() { - return ScriptFunction.getPrototype(builtinUint8ClampedArray); + return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray()); } + private synchronized ScriptFunction getBuiltinInt16Array() { + if (this.builtinInt16Array == null) { + this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); + } + return this.builtinInt16Array; + } + ScriptObject getInt16ArrayPrototype() { - return ScriptFunction.getPrototype(builtinInt16Array); + return ScriptFunction.getPrototype(getBuiltinInt16Array()); } + private synchronized ScriptFunction getBuiltinUint16Array() { + if (this.builtinUint16Array == null) { + this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); + } + return this.builtinUint16Array; + } + ScriptObject getUint16ArrayPrototype() { - return ScriptFunction.getPrototype(builtinUint16Array); + return ScriptFunction.getPrototype(getBuiltinUint16Array()); } + private synchronized ScriptFunction getBuiltinInt32Array() { + if (this.builtinInt32Array == null) { + this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); + } + return this.builtinInt32Array; + } + ScriptObject getInt32ArrayPrototype() { - return ScriptFunction.getPrototype(builtinInt32Array); + return ScriptFunction.getPrototype(getBuiltinInt32Array()); } + private synchronized ScriptFunction getBuiltinUint32Array() { + if (this.builtinUint32Array == null) { + this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); + } + return this.builtinUint32Array; + } + ScriptObject getUint32ArrayPrototype() { - return ScriptFunction.getPrototype(builtinUint32Array); + return ScriptFunction.getPrototype(getBuiltinUint32Array()); } + private synchronized ScriptFunction getBuiltinFloat32Array() { + if (this.builtinFloat32Array == null) { + this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); + } + return this.builtinFloat32Array; + } + ScriptObject getFloat32ArrayPrototype() { - return ScriptFunction.getPrototype(builtinFloat32Array); + return ScriptFunction.getPrototype(getBuiltinFloat32Array()); } + private synchronized ScriptFunction getBuiltinFloat64Array() { + if (this.builtinFloat64Array == null) { + this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); + } + return this.builtinFloat64Array; + } + ScriptObject getFloat64ArrayPrototype() { - return ScriptFunction.getPrototype(builtinFloat64Array); + return ScriptFunction.getPrototype(getBuiltinFloat64Array()); } private ScriptFunction getBuiltinArray() { @@ -1180,8 +1552,14 @@ return instance._boolean == instance.getBuiltinBoolean(); } - private ScriptFunction getBuiltinDate() { - return builtinDate; + private synchronized ScriptFunction getBuiltinDate() { + if (this.builtinDate == null) { + this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); + final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate); + // initialize default date + this.DEFAULT_DATE = new NativeDate(NaN, dateProto); + } + return this.builtinDate; } /** @@ -1191,7 +1569,7 @@ */ public static boolean isBuiltinDate() { final Global instance = Global.instance(); - return instance.date == instance.getBuiltinDate(); + return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate(); } private ScriptFunction getBuiltinError() { @@ -1208,8 +1586,11 @@ return instance.error == instance.getBuiltinError(); } - private ScriptFunction getBuiltinEvalError() { - return builtinEvalError; + private synchronized ScriptFunction getBuiltinEvalError() { + if (this.builtinEvalError == null) { + this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype()); + } + return this.builtinEvalError; } /** @@ -1219,7 +1600,7 @@ */ public static boolean isBuiltinEvalError() { final Global instance = Global.instance(); - return instance.evalError == instance.getBuiltinEvalError(); + return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError(); } private ScriptFunction getBuiltinFunction() { @@ -1270,7 +1651,10 @@ return isBuiltinFunctionProperty("call"); } - private ScriptFunction getBuiltinJSAdapter() { + private synchronized ScriptFunction getBuiltinJSAdapter() { + if (this.builtinJSAdapter == null) { + this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class); + } return builtinJSAdapter; } @@ -1281,11 +1665,14 @@ */ public static boolean isBuiltinJSAdapter() { final Global instance = Global.instance(); - return instance.jsadapter == instance.getBuiltinJSAdapter(); + return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter(); } - private ScriptObject getBuiltinJSON() { - return builtinJSON; + private synchronized ScriptObject getBuiltinJSON() { + if (this.builtinJSON == null) { + this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); + } + return this.builtinJSON; } /** @@ -1295,7 +1682,7 @@ */ public static boolean isBuiltinJSON() { final Global instance = Global.instance(); - return instance.json == instance.getBuiltinJSON(); + return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON(); } private ScriptObject getBuiltinJava() { @@ -1326,8 +1713,18 @@ return instance.javax == instance.getBuiltinJavax(); } - private ScriptObject getBuiltinJavaImporter() { - return builtinJavaImporter; + private synchronized ScriptFunction getBuiltinJavaImporter() { + if (this.builtinJavaImporter == null) { + this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); + } + return this.builtinJavaImporter; + } + + private synchronized ScriptObject getBuiltinJavaApi() { + if (this.builtinJavaApi == null) { + this.builtinJavaApi = initConstructor("Java", ScriptObject.class); + } + return this.builtinJavaApi; } /** @@ -1337,11 +1734,7 @@ */ public static boolean isBuiltinJavaImporter() { final Global instance = Global.instance(); - return instance.javaImporter == instance.getBuiltinJavaImporter(); - } - - private ScriptObject getBuiltinMath() { - return builtinMath; + return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter(); } /** @@ -1351,7 +1744,7 @@ */ public static boolean isBuiltinMath() { final Global instance = Global.instance(); - return instance.math == instance.getBuiltinMath(); + return instance.math == instance.builtinMath; } private ScriptFunction getBuiltinNumber() { @@ -1396,7 +1789,10 @@ return instance.packages == instance.getBuiltinPackages(); } - private ScriptFunction getBuiltinRangeError() { + private synchronized ScriptFunction getBuiltinRangeError() { + if (this.builtinRangeError == null) { + this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype()); + } return builtinRangeError; } @@ -1407,10 +1803,10 @@ */ public static boolean isBuiltinRangeError() { final Global instance = Global.instance(); - return instance.rangeError == instance.getBuiltinRangeError(); + return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError(); } - private ScriptFunction getBuiltinReferenceError() { + private synchronized ScriptFunction getBuiltinReferenceError() { return builtinReferenceError; } @@ -1424,7 +1820,16 @@ return instance.referenceError == instance.getBuiltinReferenceError(); } - private ScriptFunction getBuiltinRegExp() { + private synchronized ScriptFunction getBuiltinRegExp() { + if (this.builtinRegExp == null) { + this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); + final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp); + // initialize default regexp object + this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto); + // RegExp.prototype should behave like a RegExp object. So copy the + // properties. + regExpProto.addBoundProperties(DEFAULT_REGEXP); + } return builtinRegExp; } @@ -1435,7 +1840,7 @@ */ public static boolean isBuiltinRegExp() { final Global instance = Global.instance(); - return instance.regexp == instance.getBuiltinRegExp(); + return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp(); } private ScriptFunction getBuiltinString() { @@ -1480,8 +1885,11 @@ return instance.typeError == instance.getBuiltinTypeError(); } - private ScriptFunction getBuiltinURIError() { - return builtinURIError; + private synchronized ScriptFunction getBuiltinURIError() { + if (this.builtinURIError == null) { + this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype()); + } + return this.builtinURIError; } /** @@ -1491,7 +1899,7 @@ */ public static boolean isBuiltinURIError() { final Global instance = Global.instance(); - return instance.uriError == instance.getBuiltinURIError(); + return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError(); } @Override @@ -1798,6 +2206,17 @@ } @Override + protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) { + if (lexicalScope != null && start != this && start.isScope()) { + final FindProperty find = lexicalScope.findProperty(key, false); + if (find != null) { + return find; + } + } + return super.findProperty(key, deep, start); + } + + @Override public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { final boolean isScope = NashornCallSiteDescriptor.isScope(desc); @@ -1817,6 +2236,17 @@ return invocation; } + /** + * Adds jjs shell interactive mode builtin functions to global scope. + */ + public void addShellBuiltins() { + Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT); + addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); + + value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT); + addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); + } + private synchronized SwitchPoint getLexicalScopeSwitchPoint() { SwitchPoint switchPoint = lexicalScopeSwitchPoint; if (switchPoint == null || switchPoint.hasBeenInvalidated()) { @@ -1893,13 +2323,9 @@ // built-in constructors this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class); - this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); - this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); - this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class); + this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); + this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class); - this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); - this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); - this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); // initialize String.prototype.length to 0 // add String.prototype.length @@ -1910,26 +2336,28 @@ final ScriptObject arrayPrototype = getArrayPrototype(); arrayPrototype.setIsArray(); - this.DEFAULT_DATE = new NativeDate(Double.NaN, this); - - // initialize default regexp object - this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this); - - // RegExp.prototype should behave like a RegExp object. So copy the - // properties. - final ScriptObject regExpProto = getRegExpPrototype(); - regExpProto.addBoundProperties(DEFAULT_REGEXP); - // Error stuff initErrorObjects(); // java access if (! env._no_java) { + this.javaApi = LAZY_SENTINEL; + this.javaImporter = LAZY_SENTINEL; initJavaAccess(); } if (! env._no_typed_arrays) { - initTypedArray(); + this.arrayBuffer = LAZY_SENTINEL; + this.dataView = LAZY_SENTINEL; + this.int8Array = LAZY_SENTINEL; + this.uint8Array = LAZY_SENTINEL; + this.uint8ClampedArray = LAZY_SENTINEL; + this.int16Array = LAZY_SENTINEL; + this.uint16Array = LAZY_SENTINEL; + this.int32Array = LAZY_SENTINEL; + this.uint32Array = LAZY_SENTINEL; + this.float32Array = LAZY_SENTINEL; + this.float64Array = LAZY_SENTINEL; } if (env._scripting) { @@ -2003,12 +2431,9 @@ tagBuiltinProperties("Error", builtinError); - this.builtinEvalError = initErrorSubtype("EvalError", errorProto); - this.builtinRangeError = initErrorSubtype("RangeError", errorProto); this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto); this.builtinTypeError = initErrorSubtype("TypeError", errorProto); - this.builtinURIError = initErrorSubtype("URIError", errorProto); } private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) { @@ -2030,8 +2455,6 @@ this.builtinJavafx = new NativeJavaPackage("javafx", objectProto); this.builtinJavax = new NativeJavaPackage("javax", objectProto); this.builtinOrg = new NativeJavaPackage("org", objectProto); - this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); - this.builtinJavaApi = initConstructor("Java", ScriptObject.class); } private void initScripting(final ScriptEnvironment scriptEnv) { @@ -2083,60 +2506,25 @@ } } - private void initTypedArray() { - this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); - this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); - this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); - this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); - this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); - this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); - this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); - this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); - this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); - this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); - this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); - - } - private void copyBuiltins() { this.array = this.builtinArray; this._boolean = this.builtinBoolean; - this.date = this.builtinDate; this.error = this.builtinError; - this.evalError = this.builtinEvalError; this.function = this.builtinFunction; - this.jsadapter = this.builtinJSAdapter; - this.json = this.builtinJSON; this.com = this.builtinCom; this.edu = this.builtinEdu; this.java = this.builtinJava; this.javafx = this.builtinJavafx; this.javax = this.builtinJavax; this.org = this.builtinOrg; - this.javaImporter = this.builtinJavaImporter; - this.javaApi = this.builtinJavaApi; this.math = this.builtinMath; this.number = this.builtinNumber; this.object = this.builtinObject; this.packages = this.builtinPackages; - this.rangeError = this.builtinRangeError; this.referenceError = this.builtinReferenceError; - this.regexp = this.builtinRegExp; this.string = this.builtinString; this.syntaxError = this.builtinSyntaxError; this.typeError = this.builtinTypeError; - this.uriError = this.builtinURIError; - this.arrayBuffer = this.builtinArrayBuffer; - this.dataView = this.builtinDataView; - this.int8Array = this.builtinInt8Array; - this.uint8Array = this.builtinUint8Array; - this.uint8ClampedArray = this.builtinUint8ClampedArray; - this.int16Array = this.builtinInt16Array; - this.uint16Array = this.builtinUint16Array; - this.int32Array = this.builtinInt32Array; - this.uint32Array = this.builtinUint32Array; - this.float32Array = this.builtinFloat32Array; - this.float64Array = this.builtinFloat64Array; } private void initDebug() { diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeDate.java --- a/src/jdk/nashorn/internal/objects/NativeDate.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java Thu Apr 09 22:59:28 2015 -0700 @@ -121,6 +121,10 @@ this.timezone = env._timezone; } + NativeDate(final double time, final ScriptObject proto) { + this(time, proto, $nasgenmap$); + } + NativeDate(final double time, final Global global) { this(time, global.getDatePrototype(), $nasgenmap$); } @@ -1276,7 +1280,7 @@ if (self instanceof NativeDate) { return (NativeDate)self; } else if (self != null && self == Global.instance().getDatePrototype()) { - return Global.instance().DEFAULT_DATE; + return Global.instance().getDefaultDate(); } else { throw typeError("not.a.date", ScriptRuntime.safeToString(self)); } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeFloat32Array.java --- a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java Thu Apr 09 22:59:28 2015 -0700 @@ -114,12 +114,11 @@ private void setElem(final int index, final double elem) { try { - nb.put(index, (float)elem); + if (index < nb.limit()) { + nb.put(index, (float) elem); + } } catch (final IndexOutOfBoundsException e) { - //swallow valid array indexes. it's ok. - if (index < 0) { - throw new ClassCastException(); - } + throw new ClassCastException(); } } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeFloat64Array.java --- a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java Thu Apr 09 22:59:28 2015 -0700 @@ -114,12 +114,11 @@ private void setElem(final int index, final double elem) { try { - nb.put(index, elem); + if (index < nb.limit()) { + nb.put(index, elem); + } } catch (final IndexOutOfBoundsException e) { - //swallow valid array indexes. it's ok. - if (index < 0) { - throw new ClassCastException(); - } + throw new ClassCastException(); } } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeInt16Array.java --- a/src/jdk/nashorn/internal/objects/NativeInt16Array.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeInt16Array.java Thu Apr 09 22:59:28 2015 -0700 @@ -115,12 +115,11 @@ private void setElem(final int index, final int elem) { try { - nb.put(index, (short)elem); + if (index < nb.limit()) { + nb.put(index, (short) elem); + } } catch (final IndexOutOfBoundsException e) { - //swallow valid array indexes. it's ok. - if (index < 0) { - throw new ClassCastException(); - } + throw new ClassCastException(); } } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeInt32Array.java --- a/src/jdk/nashorn/internal/objects/NativeInt32Array.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeInt32Array.java Thu Apr 09 22:59:28 2015 -0700 @@ -104,11 +104,11 @@ private void setElem(final int index, final int elem) { try { - nb.put(index, elem); - } catch (final IndexOutOfBoundsException e) { - if (index < 0) { - throw new ClassCastException(); - } + if (index < nb.limit()) { + nb.put(index, elem); + } + } catch (final IndexOutOfBoundsException e) { + throw new ClassCastException(); } } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeInt8Array.java --- a/src/jdk/nashorn/internal/objects/NativeInt8Array.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeInt8Array.java Thu Apr 09 22:59:28 2015 -0700 @@ -113,12 +113,11 @@ private void setElem(final int index, final int elem) { try { - nb.put(index, (byte)elem); + if (index < nb.limit()) { + nb.put(index, (byte) elem); + } } catch (final IndexOutOfBoundsException e) { - //swallow valid array indexes. it's ok. - if (index < 0) { - throw new ClassCastException(); - } + throw new ClassCastException(); } } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeRegExp.java --- a/src/jdk/nashorn/internal/objects/NativeRegExp.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java Thu Apr 09 22:59:28 2015 -0700 @@ -78,8 +78,8 @@ this.globalObject = global; } - NativeRegExp(final String input, final String flagString, final Global global) { - this(global); + NativeRegExp(final String input, final String flagString, final Global global, final ScriptObject proto) { + super(proto, $nasgenmap$); try { this.regexp = RegExpFactory.create(input, flagString); } catch (final ParserException e) { @@ -87,8 +87,12 @@ e.throwAsEcmaException(); throw new AssertionError(); //guard against null warnings below } + this.globalObject = global; + this.setLastIndex(0); + } - this.setLastIndex(0); + NativeRegExp(final String input, final String flagString, final Global global) { + this(input, flagString, global, global.getRegExpPrototype()); } NativeRegExp(final String input, final String flagString) { @@ -928,7 +932,7 @@ if (self instanceof NativeRegExp) { return (NativeRegExp)self; } else if (self != null && self == Global.instance().getRegExpPrototype()) { - return Global.instance().DEFAULT_REGEXP; + return Global.instance().getDefaultRegExp(); } else { throw typeError("not.a.regexp", ScriptRuntime.safeToString(self)); } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeUint16Array.java --- a/src/jdk/nashorn/internal/objects/NativeUint16Array.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeUint16Array.java Thu Apr 09 22:59:28 2015 -0700 @@ -104,12 +104,11 @@ private void setElem(final int index, final int elem) { try { - nb.put(index, (char)elem); + if (index < nb.limit()) { + nb.put(index, (char) elem); + } } catch (final IndexOutOfBoundsException e) { - //swallow valid array indexes. it's ok. - if (index < 0) { - throw new ClassCastException(); - } + throw new ClassCastException(); } } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeUint32Array.java --- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java Thu Apr 09 22:59:28 2015 -0700 @@ -113,12 +113,11 @@ private void setElem(final int index, final int elem) { try { - nb.put(index, elem); + if (index < nb.limit()) { + nb.put(index, elem); + } } catch (final IndexOutOfBoundsException e) { - //swallow valid array indexes. it's ok. - if (index < 0) { - throw new ClassCastException(); - } + throw new ClassCastException(); } } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeUint8Array.java --- a/src/jdk/nashorn/internal/objects/NativeUint8Array.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeUint8Array.java Thu Apr 09 22:59:28 2015 -0700 @@ -104,12 +104,11 @@ private void setElem(final int index, final int elem) { try { - nb.put(index, (byte)elem); + if (index < nb.limit()) { + nb.put(index, (byte) elem); + } } catch (final IndexOutOfBoundsException e) { - //swallow valid array indexes. it's ok. - if (index < 0) { - throw new ClassCastException(); - } + throw new ClassCastException(); } } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java --- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Thu Apr 09 22:59:28 2015 -0700 @@ -133,18 +133,17 @@ private void setElem(final int index, final int elem) { try { - final byte clamped; - if ((elem & 0xffff_ff00) == 0) { - clamped = (byte)elem; - } else { - clamped = elem < 0 ? 0 : (byte)0xff; + if (index < nb.limit()) { + final byte clamped; + if ((elem & 0xffff_ff00) == 0) { + clamped = (byte) elem; + } else { + clamped = elem < 0 ? 0 : (byte) 0xff; + } + nb.put(index, clamped); } - nb.put(index, clamped); } catch (final IndexOutOfBoundsException e) { - //swallow valid array indexes. it's ok. - if (index < 0) { - throw new ClassCastException(); - } + throw new ClassCastException(); } } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/runtime/JSType.java --- a/src/jdk/nashorn/internal/runtime/JSType.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Thu Apr 09 22:59:28 2015 -0700 @@ -934,11 +934,15 @@ if (start + 1 < end && f == '0' && Character.toLowerCase(str.charAt(start + 1)) == 'x') { //decode hex string value = parseRadix(str.toCharArray(), start + 2, end, 16); + } else if (f == 'I' && end - start == 8 && str.regionMatches(start, "Infinity", 0, 8)) { + return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; } else { - // Fast (no NumberFormatException) path to NaN for non-numeric strings. We allow those starting with "I" or - // "N" to allow for parsing "NaN" and "Infinity" correctly. - if ((f < '0' || f > '9') && f != '.' && f != 'I' && f != 'N') { - return Double.NaN; + // Fast (no NumberFormatException) path to NaN for non-numeric strings. + for (int i = start; i < end; i++) { + f = str.charAt(i); + if ((f < '0' || f > '9') && f != '.' && f != 'e' && f != 'E' && f != '+' && f != '-') { + return Double.NaN; + } } try { value = Double.parseDouble(str.substring(start, end)); diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/runtime/PropertyMap.java --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java Thu Apr 09 22:59:28 2015 -0700 @@ -330,12 +330,15 @@ * Indicate that proto itself has changed in hierarchy somewhere. */ synchronized void invalidateAllProtoGetSwitchPoints() { - if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) { - if (Context.DEBUG) { - protoInvalidations += protoGetSwitches.size(); + if (protoGetSwitches != null) { + final int size = protoGetSwitches.size(); + if (size > 0) { + if (Context.DEBUG) { + protoInvalidations += size; + } + SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[size])); + protoGetSwitches.clear(); } - SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()])); - protoGetSwitches.clear(); } } @@ -375,7 +378,8 @@ } } - // Update the free slots bitmap for a property that has been deleted and/or added. + // Update the free slots bitmap for a property that has been deleted and/or added. This method is not synchronized + // as it is always invoked on a newly created instance. private void updateFreeSlots(final Property oldProperty, final Property newProperty) { // Free slots bitset is possibly shared with parent map, so we must clone it before making modifications. boolean freeSlotsCloned = false; @@ -425,7 +429,7 @@ * * @return New {@link PropertyMap} with {@link Property} added. */ - public PropertyMap addProperty(final Property property) { + public synchronized PropertyMap addProperty(final Property property) { if (listeners != null) { listeners.propertyAdded(property); } @@ -434,9 +438,9 @@ if (newMap == null) { final PropertyHashMap newProperties = properties.immutableAdd(property); newMap = new PropertyMap(this, newProperties); - addToHistory(property, newMap); newMap.updateFlagsAndBoundaries(property); newMap.updateFreeSlots(null, property); + addToHistory(property, newMap); } return newMap; @@ -449,7 +453,7 @@ * * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found. */ - public PropertyMap deleteProperty(final Property property) { + public synchronized PropertyMap deleteProperty(final Property property) { if (listeners != null) { listeners.propertyDeleted(property); } @@ -881,8 +885,7 @@ * @param newProto New prototype object to replace oldProto. * @return New {@link PropertyMap} with prototype changed. */ - public PropertyMap changeProto(final ScriptObject newProto) { - + public synchronized PropertyMap changeProto(final ScriptObject newProto) { final PropertyMap nextMap = checkProtoHistory(newProto); if (nextMap != null) { return nextMap; diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/runtime/ScriptObject.java --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Apr 09 22:59:28 2015 -0700 @@ -812,7 +812,7 @@ * * @return FindPropertyData or null if not found. */ - FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) { + protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) { final PropertyMap selfMap = getMap(); final Property property = selfMap.findProperty(key); diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/runtime/WithObject.java --- a/src/jdk/nashorn/internal/runtime/WithObject.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java Thu Apr 09 22:59:28 2015 -0700 @@ -198,7 +198,7 @@ * @return FindPropertyData or null if not found. */ @Override - FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) { + protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) { // We call findProperty on 'expression' with 'expression' itself as start parameter. // This way in ScriptObject.setObject we can tell the property is from a 'with' expression // (as opposed from another non-scope object in the proto chain such as Object.prototype). diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java Thu Apr 09 22:59:28 2015 -0700 @@ -145,9 +145,6 @@ case TargetInfo.IS_EMPTY_MEM: addOpcode(OPCode.NULL_CHECK_END_MEMST); break; - case TargetInfo.IS_EMPTY_REC: - addOpcode(OPCode.NULL_CHECK_END_MEMST_PUSH); - break; default: break; } // switch diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java Thu Apr 09 22:59:28 2015 -0700 @@ -183,7 +183,6 @@ case OPCode.NULL_CHECK_START: opNullCheckStart(); continue; case OPCode.NULL_CHECK_END: opNullCheckEnd(); continue; case OPCode.NULL_CHECK_END_MEMST: opNullCheckEndMemST(); continue; - case OPCode.NULL_CHECK_END_MEMST_PUSH: opNullCheckEndMemSTPush(); continue; case OPCode.JUMP: opJump(); continue; case OPCode.PUSH: opPush(); continue; @@ -1025,29 +1024,6 @@ } } - // USE_SUBEXP_CALL - private void opNullCheckEndMemSTPush() { - final int mem = code[ip++]; /* mem: null check id */ - - int isNull; - if (Config.USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT) { - isNull = nullCheckMemStRec(mem, s); - } else { - isNull = nullCheckRec(mem, s); - } - - if (isNull != 0) { - if (Config.DEBUG_MATCH) { - Config.log.println("NULL_CHECK_END_MEMST_PUSH: skip id:" + mem + ", s:" + s); - } - - if (isNull == -1) {opFail(); return;} - nullCheckFound(); - } else { - pushNullCheckEnd(mem); - } - } - private void opJump() { ip += code[ip] + 1; } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java Thu Apr 09 22:59:28 2015 -0700 @@ -19,7 +19,6 @@ */ package jdk.nashorn.internal.runtime.regexp.joni; -import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt; import java.lang.ref.WeakReference; import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel; import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType; @@ -369,118 +368,9 @@ } } - protected final int nullCheckRec(final int id, final int s) { - int level = 0; - int k = stk; - while (true) { - k--; - final StackEntry e = stack[k]; - - if (e.type == NULL_CHECK_START) { - if (e.getNullCheckNum() == id) { - if (level == 0) { - return e.getNullCheckPStr() == s ? 1 : 0; - } - level--; - } - } else if (e.type == NULL_CHECK_END) { - level++; - } - } - } - protected final int nullCheckMemSt(final int id, final int s) { - int k = stk; - int isNull; - while (true) { - k--; - StackEntry e = stack[k]; - - if (e.type == NULL_CHECK_START) { - if (e.getNullCheckNum() == id) { - if (e.getNullCheckPStr() != s) { - isNull = 0; - break; - } - int endp; - isNull = 1; - while (k < stk) { - if (e.type == MEM_START) { - if (e.getMemEnd() == INVALID_INDEX) { - isNull = 0; - break; - } - if (bsAt(regex.btMemEnd, e.getMemNum())) { - endp = stack[e.getMemEnd()].getMemPStr(); - } else { - endp = e.getMemEnd(); - } - if (stack[e.getMemStart()].getMemPStr() != endp) { - isNull = 0; - break; - } else if (endp != s) { - isNull = -1; /* empty, but position changed */ - } - } - k++; - e = stack[k]; // !! - } - break; - } - } - } - return isNull; - } - - protected final int nullCheckMemStRec(final int id, final int s) { - int level = 0; - int k = stk; - int isNull; - while (true) { - k--; - StackEntry e = stack[k]; - - if (e.type == NULL_CHECK_START) { - if (e.getNullCheckNum() == id) { - if (level == 0) { - if (e.getNullCheckPStr() != s) { - isNull = 0; - break; - } - int endp; - isNull = 1; - while (k < stk) { - if (e.type == MEM_START) { - if (e.getMemEnd() == INVALID_INDEX) { - isNull = 0; - break; - } - if (bsAt(regex.btMemEnd, e.getMemNum())) { - endp = stack[e.getMemEnd()].getMemPStr(); - } else { - endp = e.getMemEnd(); - } - if (stack[e.getMemStart()].getMemPStr() != endp) { - isNull = 0; - break; - } else if (endp != s) { - isNull = -1; /* empty, but position changed */ - } - } - k++; - e = stack[k]; - } - break; - } - level--; - } - } else if (e.type == NULL_CHECK_END) { - if (e.getNullCheckNum() == id) { - level++; - } - } - } - return isNull; + // Return -1 here to cause operation to fail + return -nullCheck(id, s); } protected final int getRepeat(final int id) { diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java Thu Apr 09 22:59:28 2015 -0700 @@ -24,5 +24,4 @@ final int ISNOT_EMPTY = 0; final int IS_EMPTY = 1; final int IS_EMPTY_MEM = 2; - final int IS_EMPTY_REC = 3; } diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/tools/Shell.java --- a/src/jdk/nashorn/tools/Shell.java Wed Apr 01 11:35:19 2015 -0700 +++ b/src/jdk/nashorn/tools/Shell.java Thu Apr 09 22:59:28 2015 -0700 @@ -109,7 +109,10 @@ */ public static void main(final String[] args) { try { - System.exit(main(System.in, System.out, System.err, args)); + final int exitCode = main(System.in, System.out, System.err, args); + if (exitCode != SUCCESS) { + System.exit(exitCode); + } } catch (final IOException e) { System.err.println(e); //bootstrapping, Context.err may not exist System.exit(IO_ERROR); @@ -414,18 +417,7 @@ Context.setGlobal(global); } - // initialize with "shell.js" script - try { - final Source source = sourceFor("", Shell.class.getResource("resources/shell.js")); - context.eval(global, source.getString(), global, "", false); - } catch (final Exception e) { - err.println(e); - if (env._dump_on_error) { - e.printStackTrace(err); - } - - return INTERNAL_ERROR; - } + global.addShellBuiltins(); while (true) { err.print(prompt); diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/tools/ShellFunctions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/tools/ShellFunctions.java Thu Apr 09 22:59:28 2015 -0700 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.tools; + +import static jdk.nashorn.internal.lookup.Lookup.MH; +import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.objects.Global; + +/** + * Global functions supported only in shell interactive mode. + */ +public final class ShellFunctions { + + /** Handle to implementation of {@link ShellFunctions#input} - Nashorn extension */ + public static final MethodHandle INPUT = findOwnMH("input", Object.class, Object.class, Object.class, Object.class); + + /** Handle to implementation of {@link ShellFunctions#evalinput} - Nashorn extension */ + public static final MethodHandle EVALINPUT = findOwnMH("evalinput", Object.class, Object.class, Object.class, Object.class); + + private ShellFunctions() { + } + + /** + * Nashorn extension: global.input (shell-interactive-mode-only) + * Read one or more lines of input from the standard input till the + * given end marker is seen in standard input. + * + * @param self self reference + * @param endMarker String used as end marker for input + * @param prompt String used as input prompt + * + * @return line that was read + * + * @throws IOException if an exception occurs + */ + public static Object input(final Object self, final Object endMarker, final Object prompt) throws IOException { + final String endMarkerStr = (endMarker != UNDEFINED)? JSType.toString(endMarker) : ""; + final String promptStr = (prompt != UNDEFINED)? JSType.toString(prompt) : ">> "; + final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + final StringBuilder buf = new StringBuilder(); + while (true) { + System.out.print(promptStr); + final String line = reader.readLine(); + if (line == null || line.equals(endMarkerStr)) { + break; + } + buf.append(line); + buf.append('\n'); + } + return buf.toString(); + } + + /** + * Nashorn extension: Reads zero or more lines from standard input and + * evaluates the concatenated string as code + * + * @param self self reference + * @param endMarker String used as end marker for input + * @param prompt String used as input prompt + * + * @return output from evaluating the script + * + * @throws IOException if an exception occurs + */ + public static Object evalinput(final Object self, final Object endMarker, final Object prompt) throws IOException { + return Global.eval(self, input(self, endMarker, prompt)); + } + + private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { + return MH.findStatic(MethodHandles.lookup(), ShellFunctions.class, name, MH.type(rtype, types)); + } +} diff -r 4d85dc2a3711 -r e790c1387594 src/jdk/nashorn/tools/resources/shell.js --- a/src/jdk/nashorn/tools/resources/shell.js Wed Apr 01 11:35:19 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Initialization script for shell when running in interactive mode. - */ - -/** - * Reads zero or more lines from standard input and returns concatenated string - * - * @param endMarker marker string that signals end of input - * @param prompt prompt printed for each line - */ -Object.defineProperty(this, "input", { - value: function input(endMarker, prompt) { - if (!endMarker) { - endMarker = ""; - } - - if (!prompt) { - prompt = " >> "; - } - - var imports = new JavaImporter(java.io, java.lang); - var str = ""; - with (imports) { - var reader = new BufferedReader(new InputStreamReader(System['in'])); - var line; - while (true) { - System.out.print(prompt); - line = reader.readLine(); - if (line == null || line == endMarker) { - break; - } - str += line + "\n"; - } - } - - return str; - }, - enumerable: false, - writable: true, - configurable: true -}); - - -/** - * Reads zero or more lines from standard input and evaluates the concatenated - * string as code - * - * @param endMarker marker string that signals end of input - * @param prompt prompt printed for each line - */ -Object.defineProperty(this, "evalinput", { - value: function evalinput(endMarker, prompt) { - var code = input(endMarker, prompt); - // make sure everything is evaluated in global scope! - return this.eval(code); - }, - enumerable: false, - writable: true, - configurable: true -}); diff -r 4d85dc2a3711 -r e790c1387594 test/script/basic/JDK-8073868.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8073868.js Thu Apr 09 22:59:28 2015 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8073868: Regex matching causes java.lang.ArrayIndexOutOfBoundsException: 64 + * + * @test + * @run + */ + +function test(input) { + var comma = input.indexOf(","); + Assert.assertEquals(/([^\s]+),(.*)+/.exec(input)[0], input.trimLeft()); + Assert.assertEquals(/([^\s]+),(.*)+/.exec(input)[1], input.substring(0, comma).trimLeft()); + Assert.assertEquals(/([^\s]+),(.*)+/.exec(input)[2], input.substring(comma + 1)); + Assert.assertEquals(/(.*)+/.exec(input)[0], input); + Assert.assertEquals(/(.*)+/.exec(input)[1], input); +} + +test(" xxxx, xxx xxxxxx xxxxxxxxx xxxxxxx, xxxx xxxxx xxxxx "); +test(" xxxx, xxx xxxxxx xxxxxxxxx xxxxxxx, xxxx xxxxx xxxxx "); +test("x, xxxxxxxxxx xxxxxxxxx xxxxxxx, xxxx xxxxx xxxxx "); + +Assert.assertEquals(/(?:\1a|())*/.exec("a")[0], "a"); +Assert.assertEquals(/(?:\1a|())*/.exec("a")[1], undefined); diff -r 4d85dc2a3711 -r e790c1387594 test/script/basic/JDK-8075927.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8075927.js Thu Apr 09 22:59:28 2015 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8075927: toNumber(String) accepts illegal characters + * + * @test + * @run + */ + +Assert.assertTrue(isNaN(Number("-123d"))); +Assert.assertTrue(isNaN(Number("-123f"))); +Assert.assertTrue(Number(" 123 ") === 123); +Assert.assertTrue(Number(" -123 ") === -123); +Assert.assertEquals(Number(" Infinity "), Infinity); +Assert.assertEquals(Number(" +Infinity "), Infinity); +Assert.assertEquals(Number(" -Infinity "), -Infinity); + diff -r 4d85dc2a3711 -r e790c1387594 test/script/basic/es6/let-eval.js --- a/test/script/basic/es6/let-eval.js Wed Apr 01 11:35:19 2015 -0700 +++ b/test/script/basic/es6/let-eval.js Thu Apr 09 22:59:28 2015 -0700 @@ -96,3 +96,9 @@ f(); print(typeof a, typeof b, typeof c, typeof x, typeof z); + +let v = 1; +eval("print('v: ' + v); v = 2; print ('v: ' + v);"); +print("this.v: " + this.v); +print("v: " + v); + diff -r 4d85dc2a3711 -r e790c1387594 test/script/basic/es6/let-eval.js.EXPECTED --- a/test/script/basic/es6/let-eval.js.EXPECTED Wed Apr 01 11:35:19 2015 -0700 +++ b/test/script/basic/es6/let-eval.js.EXPECTED Thu Apr 09 22:59:28 2015 -0700 @@ -14,3 +14,7 @@ 2 1 0 2 1 0 undefined undefined undefined undefined undefined undefined +v: 1 +v: 2 +this.v: undefined +v: 2