8143896: java.lang.Long is implicitly converted to double

Reviewed-by: mhaupt, jlaskey
This commit is contained in:
Hannes Wallnöfer 2016-01-12 16:30:10 +01:00
parent ff26874c25
commit dd9c62130f
17 changed files with 1236 additions and 1006 deletions

View File

@ -284,8 +284,8 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
// Step 3c and 3d - get new length and convert to long
final long newLen = NativeArray.validLength(newLenDesc.getValue());
// Step 3e
newLenDesc.setValue(newLen);
// Step 3e - note that we need to convert to int or double as long is not considered a JS number type anymore
newLenDesc.setValue(JSType.isRepresentableAsInt(newLen) ? Integer.valueOf((int) newLen) : Double.valueOf((double) newLen));
// Step 3f
// increasing array length - just need to set new length value (and attributes if any) and return
@ -908,21 +908,6 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
return getContinuousNonEmptyArrayDataCCE(self, IntElements.class).fastPopInt();
}
/**
* Specialization of pop for ContinuousArrayData
*
* Primitive specialization, {@link LinkLogic}
*
* @param self self reference
* @return element popped
* @throws ClassCastException if array is empty, facilitating Undefined return value
*/
@SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class)
public static long popLong(final Object self) {
//must be non empty Int or LongArrayData
return getContinuousNonEmptyArrayDataCCE(self, IntOrLongElements.class).fastPopLong();
}
/**
* Specialization of pop for ContinuousArrayData
*
@ -997,7 +982,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array length after push
*/
@SpecializedFunction(linkLogic=PushLinkLogic.class)
public static long push(final Object self, final int arg) {
public static double push(final Object self, final int arg) {
return getContinuousArrayDataCCE(self, Integer.class).fastPush(arg);
}
@ -1011,7 +996,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array length after push
*/
@SpecializedFunction(linkLogic=PushLinkLogic.class)
public static long push(final Object self, final long arg) {
public static double push(final Object self, final long arg) {
return getContinuousArrayDataCCE(self, Long.class).fastPush(arg);
}
@ -1025,7 +1010,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array length after push
*/
@SpecializedFunction(linkLogic=PushLinkLogic.class)
public static long push(final Object self, final double arg) {
public static double push(final Object self, final double arg) {
return getContinuousArrayDataCCE(self, Double.class).fastPush(arg);
}
@ -1039,7 +1024,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array length after push
*/
@SpecializedFunction(name="push", linkLogic=PushLinkLogic.class)
public static long pushObject(final Object self, final Object arg) {
public static double pushObject(final Object self, final Object arg) {
return getContinuousArrayDataCCE(self, Object.class).fastPush(arg);
}
@ -1081,7 +1066,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array after pushes
*/
@SpecializedFunction
public static long push(final Object self, final Object arg) {
public static double push(final Object self, final Object arg) {
try {
final ScriptObject sobj = (ScriptObject)self;
final ArrayData arrayData = sobj.getArray();
@ -1498,7 +1483,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return index of element, or -1 if not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static long indexOf(final Object self, final Object searchElement, final Object fromIndex) {
public static double indexOf(final Object self, final Object searchElement, final Object fromIndex) {
try {
final ScriptObject sobj = (ScriptObject)Global.toObject(self);
final long len = JSType.toUint32(sobj.getLength());
@ -1534,7 +1519,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return index of element, or -1 if not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static long lastIndexOf(final Object self, final Object... args) {
public static double lastIndexOf(final Object self, final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)Global.toObject(self);
final long len = JSType.toUint32(sobj.getLength());

View File

@ -256,8 +256,9 @@ public final class NativeDate extends ScriptObject {
* @return a Date that points to the current moment in time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static long now(final Object self) {
return System.currentTimeMillis();
public static double now(final Object self) {
// convert to double as long does not represent the primitive JS number type
return (double) System.currentTimeMillis();
}
/**

View File

@ -48,6 +48,7 @@ import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.doubleconv.DoubleConversion;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
/**
@ -315,7 +316,7 @@ public final class NativeNumber extends ScriptObject {
* @return Link to be invoked at call site.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER, PROTOFILTER);
return PrimitiveLookup.lookupPrimitive(request, NashornGuards.getNumberGuard(), new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER, PROTOFILTER);
}
@SuppressWarnings("unused")

View File

@ -74,7 +74,7 @@ public final class NativeRegExpExecResult extends ScriptObject {
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
public static Object length(final Object self) {
if (self instanceof ScriptObject) {
return JSType.toUint32(((ScriptObject)self).getArray().length());
return (double) JSType.toUint32(((ScriptObject)self).getArray().length());
}
return 0;

View File

@ -146,7 +146,7 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti
if (returnType == Object.class && JSType.isString(self)) {
try {
return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getStringGuard());
} catch (final LookupException e) {
//empty. Shouldn't happen. Fall back to super
}
@ -1235,8 +1235,8 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti
* @return Link to be invoked at call site.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
final MethodHandle guard = NashornGuards.getInstanceOf2Guard(String.class, ConsString.class);
return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER, PROTOFILTER);
return PrimitiveLookup.lookupPrimitive(request, NashornGuards.getStringGuard(),
new NativeString((CharSequence)receiver), WRAPFILTER, PROTOFILTER);
}
@SuppressWarnings("unused")

View File

@ -178,6 +178,12 @@ public enum JSType {
/** Method handle for void returns. */
public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class);
/** Method handle for isString method */
public static final Call IS_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "isString", boolean.class, Object.class);
/** Method handle for isNumber method */
public static final Call IS_NUMBER = staticCall(JSTYPE_LOOKUP, JSType.class, "isNumber", boolean.class, Object.class);
/**
* The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide
* in the dual--fields world
@ -280,7 +286,7 @@ public enum JSType {
return JSType.STRING;
}
if (obj instanceof Number) {
if (isNumber(obj)) {
return JSType.NUMBER;
}
@ -322,7 +328,7 @@ public enum JSType {
return JSType.STRING;
}
if (obj instanceof Number) {
if (isNumber(obj)) {
return JSType.NUMBER;
}
@ -434,7 +440,7 @@ public enum JSType {
return obj == null ||
obj == ScriptRuntime.UNDEFINED ||
isString(obj) ||
obj instanceof Number ||
isNumber(obj) ||
obj instanceof Boolean ||
obj instanceof Symbol;
}
@ -609,6 +615,24 @@ public enum JSType {
return obj instanceof String || obj instanceof ConsString;
}
/**
* Returns true if object represents a primitive JavaScript number value. Note that we only
* treat wrapper objects of Java primitive number types as objects that can be fully represented
* as JavaScript numbers (doubles). This means we exclude {@code long} and special purpose Number
* instances such as {@link java.util.concurrent.atomic.AtomicInteger}, as well as arbitrary precision
* numbers such as {@link java.math.BigInteger}.
*
* @param obj the object
* @return true if the object represents a primitive JavaScript number value.
*/
public static boolean isNumber(final Object obj) {
if (obj != null) {
final Class<?> c = obj.getClass();
return c == Integer.class || c == Double.class || c == Float.class || c == Short.class || c == Byte.class;
}
return false;
}
/**
* JavaScript compliant conversion of integer to String
*
@ -761,7 +785,7 @@ public enum JSType {
if (obj instanceof Double) {
return (Double)obj;
}
if (obj instanceof Number) {
if (isNumber(obj)) {
return ((Number)obj).doubleValue();
}
return Double.NaN;
@ -1337,7 +1361,7 @@ public enum JSType {
return obj.toString();
}
if (obj instanceof Number) {
if (isNumber(obj)) {
return toString(((Number)obj).doubleValue());
}

View File

@ -287,7 +287,7 @@ public abstract class ContinuousArrayData extends ArrayData {
* @param arg argument
* @return new array length
*/
public long fastPush(final int arg) {
public double fastPush(final int arg) {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
@ -296,7 +296,7 @@ public abstract class ContinuousArrayData extends ArrayData {
* @param arg argument
* @return new array length
*/
public long fastPush(final long arg) {
public double fastPush(final long arg) {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
@ -305,7 +305,7 @@ public abstract class ContinuousArrayData extends ArrayData {
* @param arg argument
* @return new array length
*/
public long fastPush(final double arg) {
public double fastPush(final double arg) {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
@ -314,7 +314,7 @@ public abstract class ContinuousArrayData extends ArrayData {
* @param arg argument
* @return new array length
*/
public long fastPush(final Object arg) {
public double fastPush(final Object arg) {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
@ -326,14 +326,6 @@ public abstract class ContinuousArrayData extends ArrayData {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
/**
* Specialization - fast pop implementation
* @return element value
*/
public long fastPopLong() {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
/**
* Specialization - fast pop implementation
* @return element value

View File

@ -340,7 +340,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
}
@Override
public long fastPush(final int arg) {
public double fastPush(final int arg) {
final int len = (int)length();
if (len == array.length) {
array = Arrays.copyOf(array, nextSize(len));
@ -361,11 +361,6 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
return elem;
}
@Override
public long fastPopLong() {
return fastPopInt();
}
@Override
public double fastPopDouble() {
return fastPopInt();

View File

@ -303,17 +303,17 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
}
@Override
public long fastPush(final int arg) {
public double fastPush(final int arg) {
return fastPush((double)arg);
}
@Override
public long fastPush(final long arg) {
public double fastPush(final long arg) {
return fastPush((double)arg);
}
@Override
public long fastPush(final double arg) {
public double fastPush(final double arg) {
final int len = (int)length();
if (len == array.length) {
//note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory

View File

@ -236,22 +236,22 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
}
@Override
public long fastPush(final int arg) {
public double fastPush(final int arg) {
return fastPush((Object)arg);
}
@Override
public long fastPush(final long arg) {
public double fastPush(final long arg) {
return fastPush((Object)arg);
}
@Override
public long fastPush(final double arg) {
public double fastPush(final double arg) {
return fastPush((Object)arg);
}
@Override
public long fastPush(final Object arg) {
public double fastPush(final Object arg) {
final int len = (int)length();
if (len == array.length) {
array = Arrays.copyOf(array, nextSize(len));

View File

@ -34,6 +34,7 @@ import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.linker.LinkRequest;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
@ -46,10 +47,9 @@ import jdk.nashorn.internal.runtime.options.Options;
public final class NashornGuards {
private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, ScriptObject.class, PropertyMap.class);
private static final MethodHandle IS_MAP_SCRIPTOBJECT = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class);
private static final MethodHandle IS_NOT_JSOBJECT = findOwnMH("isNotJSObject", boolean.class, Object.class);
private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class);
private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class);
//TODO - maybe put this back in ScriptFunction instead of the ClassCastException.class relinkage
//private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
@ -165,14 +165,21 @@ public final class NashornGuards {
}
/**
* Get a guard that checks if in item is an instance of either of two classes.
* Get a guard that checks if in item is a JS string.
*
* @param class1 the first class
* @param class2 the second class
* @return method handle for guard
*/
public static MethodHandle getInstanceOf2Guard(final Class<?> class1, final Class<?> class2) {
return MH.insertArguments(IS_INSTANCEOF_2, 1, class1, class2);
public static MethodHandle getStringGuard() {
return JSType.IS_STRING.methodHandle();
}
/**
* Get a guard that checks if in item is a JS number.
*
* @return method handle for guard
*/
public static MethodHandle getNumberGuard() {
return JSType.IS_NUMBER.methodHandle();
}
/**
@ -223,11 +230,6 @@ public final class NashornGuards {
return self == ref.get();
}
@SuppressWarnings("unused")
private static boolean isInstanceOf2(final Object self, final Class<?> class1, final Class<?> class2) {
return class1.isInstance(self) || class2.isInstance(self);
}
@SuppressWarnings("unused")
private static boolean isScriptFunction(final Object self) {
return self instanceof ScriptFunction;

View File

@ -57,7 +57,8 @@ final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, Gu
}
private static boolean canLinkTypeStatic(final Class<?> type) {
return type == String.class || type == Boolean.class || type == ConsString.class || Number.class.isAssignableFrom(type);
return type == String.class || type == Boolean.class || type == ConsString.class || type == Integer.class
|| type == Double.class || type == Float.class || type == Short.class || type == Byte.class;
}
@Override
@ -167,7 +168,7 @@ final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, Gu
@SuppressWarnings("unused")
private static boolean isJavaScriptPrimitive(final Object o) {
return JSType.isString(o) || o instanceof Boolean || o instanceof Number || o == null;
return JSType.isString(o) || o instanceof Boolean || JSType.isNumber(o) || o == null;
}
private static final MethodHandle GUARD_PRIMITIVE = findOwnMH("isJavaScriptPrimitive", boolean.class, Object.class);

View File

@ -33,4 +33,4 @@ print(n);
var s = n.toString(5);
var m = parseInt(s, 5);
print(m === n);
print(n);
print(m);

View File

@ -5,8 +5,8 @@ int array: check widen for false [class java.lang.Boolean]
int array: check widen for true [class java.lang.Boolean]
int array: check widen for 34 [class java.lang.Byte]
int array: check widen for 344454 [class java.lang.Integer]
int array: check widen for 454545 [class java.lang.Long]
int array: check widen for 2147483648 [class java.lang.Long]
int array: check widen for 454545
int array: check widen for 2147483648
int array: check widen for 34.29999923706055 [class java.lang.Float]
int array: check widen for 3.141592653589793 [class java.lang.Double]
int array: check widen for s
@ -17,8 +17,8 @@ long array: check widen for false [class java.lang.Boolean]
long array: check widen for true [class java.lang.Boolean]
long array: check widen for 34 [class java.lang.Byte]
long array: check widen for 344454 [class java.lang.Integer]
long array: check widen for 454545 [class java.lang.Long]
long array: check widen for 2147483648 [class java.lang.Long]
long array: check widen for 454545
long array: check widen for 2147483648
long array: check widen for 34.29999923706055 [class java.lang.Float]
long array: check widen for 3.141592653589793 [class java.lang.Double]
long array: check widen for s
@ -29,8 +29,8 @@ number array: check widen for false [class java.lang.Boolean]
number array: check widen for true [class java.lang.Boolean]
number array: check widen for 34 [class java.lang.Byte]
number array: check widen for 344454 [class java.lang.Integer]
number array: check widen for 454545 [class java.lang.Long]
number array: check widen for 2147483648 [class java.lang.Long]
number array: check widen for 454545
number array: check widen for 2147483648
number array: check widen for 34.29999923706055 [class java.lang.Float]
number array: check widen for 3.141592653589793 [class java.lang.Double]
number array: check widen for s
@ -41,8 +41,8 @@ object array: check widen for false [class java.lang.Boolean]
object array: check widen for true [class java.lang.Boolean]
object array: check widen for 34 [class java.lang.Byte]
object array: check widen for 344454 [class java.lang.Integer]
object array: check widen for 454545 [class java.lang.Long]
object array: check widen for 2147483648 [class java.lang.Long]
object array: check widen for 454545
object array: check widen for 2147483648
object array: check widen for 34.29999923706055 [class java.lang.Float]
object array: check widen for 3.141592653589793 [class java.lang.Double]
object array: check widen for s

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2016, 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-8143896: java.lang.Long is implicitly converted to double
*
* @test
* @run
*/
Assert.assertTrue(java.lang.Long.valueOf("301077366599181567").toString() === "301077366599181567");
Assert.assertTrue(java.lang.Long.valueOf("-301077366599181567").toString() === "-301077366599181567");
Assert.assertTrue(java.lang.Long.valueOf("301077366599181567") == 301077366599181567);
Assert.assertFalse(java.lang.Long.valueOf("301077366599181567") === 301077366599181567);
Assert.assertTrue(new java.math.BigInteger("301077366599181567").toString() === "301077366599181567");
Assert.assertTrue(new java.math.BigInteger("-301077366599181567").toString() === "-301077366599181567");
Assert.assertTrue(new java.math.BigInteger("301077366599181567") == 301077366599181567);
Assert.assertFalse(new java.math.BigInteger("301077366599181567") === 301077366599181567);
var n = new java.lang.Byte("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Short("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Integer("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Float("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Double("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Long("123");
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.util.concurrent.atomic.DoubleAdder();
n.add("123");
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.util.concurrent.atomic.AtomicInteger(123);
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.util.concurrent.atomic.AtomicLong(123);
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.math.BigInteger("123");
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.math.BigDecimal("123");
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);

View File

@ -30,8 +30,8 @@
*/
function Parser() {
// create nashorn parser
this._parser = Parser.create();
// create nashorn parser
this._parser = Parser.create();
}
// Java types used
@ -54,59 +54,60 @@ Parser.create = function() {
// convert Nashorn parser Tree, Diagnostic as a script friendly object
Parser.prototype.convert = function(tree) {
if (!tree || typeof tree != 'object') {
if (!tree || typeof tree != 'object' || tree instanceof java.lang.Long) {
return tree;
}
var obj = Object.bindProperties({}, tree);
var result = {};
for (var i in obj) {
var val = obj[i];
if (val instanceof Parser.Tree) {
result[i] = this.convert(val);
} else if (val instanceof Parser.List) {
var arr = new Array(val.size());
for (var j in val) {
arr[j] = this.convert(val[j]);
}
result[i] = arr;
} else {
switch (typeof val) {
case 'number':
case 'string':
case 'boolean':
result[i] = String(val);
default:
if (val instanceof Parser.Enum) {
result[i] = String(val);
}
}
}
}
return result;
var val = obj[i];
if (val instanceof Parser.Tree) {
result[i] = this.convert(val);
} else if (val instanceof Parser.List) {
var arr = new Array(val.size());
for (var j in val) {
arr[j] = this.convert(val[j]);
}
result[i] = arr;
} else {
switch (typeof val) {
case 'number':
case 'string':
case 'boolean':
result[i] = String(val);
break;
default:
if (val instanceof java.lang.Long || val instanceof Parser.Enum) {
result[i] = String(val);
}
}
}
}
return result;
}
function processFiles(subdir) {
var File = Java.type("java.io.File");
var files = new File(__DIR__ + subdir).listFiles();
java.util.Arrays.sort(files);
for each (var file in files) {
if (file.name.endsWith(".js")) {
var script = readFully(file);
var parser = new Parser();
var tree = parser.parse(subdir + "/" + file.name, script,
function(diagnostic) {
print(JSON.stringify(parser.convert(diagnostic), null, 2).replace(/\\r/g, ''));
print(",");
});
var File = Java.type("java.io.File");
var files = new File(__DIR__ + subdir).listFiles();
java.util.Arrays.sort(files);
for each (var file in files) {
if (file.name.endsWith(".js")) {
var script = readFully(file);
var parser = new Parser();
var tree = parser.parse(subdir + "/" + file.name, script,
function(diagnostic) {
print(JSON.stringify(parser.convert(diagnostic), null, 2).replace(/\\r/g, ''));
print(",");
});
if (tree != null) {
print(JSON.stringify(tree, null, 2));
print(",");
}
}
}
if (tree != null) {
print(JSON.stringify(tree, null, 2));
print(",");
}
}
}
}
// parse files in parsertests directory

File diff suppressed because it is too large Load Diff