diff --git a/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip b/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip index cc920f480..52b640a03 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip and b/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/differences.txt b/sources/net.sf.j2s.core/dist/swingjs/differences.txt index 46e49ec1a..60f5fcc74 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/differences.txt +++ b/sources/net.sf.j2s.core/dist/swingjs/differences.txt @@ -31,6 +31,7 @@ ever be shadowed or overridden by subclasses. For example, we see in java.lang.T ---------------------------------- +updated 12/6/2020 -- note about restrictions on long, including BitSet and Scanner updated 3/21/2020 -- adds note about HashMap, Hashtable, and HashSet iterator ordering updated 3/20/2020 -- adds note about interning, new String("xxx"), and "xxx" updated 2/26/2020 -- adds Graphics.setClip issue @@ -480,6 +481,8 @@ MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS See below for a full discussion. +Restrictions on long +Restriction on BitSet and Scanner HashMap, Hashtable, and HashSet iterator ordering interning, new String("xxx") vs "xxx" Names with "$" and "_" @@ -586,6 +589,60 @@ changed to JSToolkit.isDispatchThread() MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS ===================================================================== +restrictions on long +-------------------- + +Java's 64-bit long type is not supported in JavaScript. There is no Int64Array in JavaScript, +and 0x20000000000000 + 1 evaluates to 0x20000000000000, not 0x20000000000001. +(Likewise, -0x20000000000000 - 1 is left unchanged.) + +The largest "integer" value in JavaScript is 9007199254740991 (9.007199254740991E13, or 0x1FFFFFFFFFFFFFF). +Effectively, you get to use only 53 bits of the long, not 64. Trying to set a long larger than +0x1FFFFFFFFFFFFFF or smaller than -0x1FFFFFFFFFFFFFF will result in a NumberFormatException. + +The transpiler handles conversion to long the same as Java for all cases other than from double. + +For small double values, there is no problem, and, in fact, this is a known trick used to round +doubles and floats toward zero: + +double d; +d = (long) 3.8; +assert(d == 3); +d = (long) -3.8; +assert(d == -3); + +SwingJS will evaluate (long) d as 0 for d > 9007199254740991 +or d < -9007199254740991, same as Java returns for Double.NaN. +So, in Java we have: + + assert(((long) Double.NaN) == 0); + assert(((int) Double.NaN) == 0); + assert(((long) Float.NaN) == 0); + assert(((int) Float.NaN) == 0); + +and also, in JavaScript only, we also have: + + double d = 0x2000000000000L; + assert(((long) d) == 0); + + +restrictions on BitSet and Scanner +---------------------------------- + +Because of the issue of long being only 53 bits, any time a method returns a long value, considerations must +be made as to whether this will work in JavaScript. In particular, BitSet and Scanner have issues. + +In SwingJS, java.util.BitSet has been implemented as a 32-bit integer-based bitset. This was no problem in +Java 6, but starting with Java 7, a method was added to BitSet that allows for the extraction of the +underlying long[] word data. This is not work in JavaScript. Instead, SwingJS java.util.Bitset.toLongArray() will deliver +32-bit int[] data. + +SwingJS Scanner has hasNextLong() and nextLong(), and although it will scan through long numbers, +Scanner will choke on long numbers greater than the JavaScript 53-bit limit. hasNextLong() will +return false, and nextLong() will throw an InputMismatchException triggered by the NumberFormatException +thrown by Long.parseLong(). + + HashMap, Hashtable, and HashSet iterator ordering ------------------------------------------------- diff --git a/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core.jar b/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core.jar index 8ad963c23..ab277a94c 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core.jar and b/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core.jar differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/timestamp b/sources/net.sf.j2s.core/dist/swingjs/timestamp index 85b1cd109..2672f785d 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/timestamp +++ b/sources/net.sf.j2s.core/dist/swingjs/timestamp @@ -1 +1 @@ -20201205151557 +20201206115202 diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/SwingJS-site.zip b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/SwingJS-site.zip index cc920f480..52b640a03 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/SwingJS-site.zip and b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/differences.txt b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/differences.txt index 46e49ec1a..60f5fcc74 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/differences.txt +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/differences.txt @@ -31,6 +31,7 @@ ever be shadowed or overridden by subclasses. For example, we see in java.lang.T ---------------------------------- +updated 12/6/2020 -- note about restrictions on long, including BitSet and Scanner updated 3/21/2020 -- adds note about HashMap, Hashtable, and HashSet iterator ordering updated 3/20/2020 -- adds note about interning, new String("xxx"), and "xxx" updated 2/26/2020 -- adds Graphics.setClip issue @@ -480,6 +481,8 @@ MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS See below for a full discussion. +Restrictions on long +Restriction on BitSet and Scanner HashMap, Hashtable, and HashSet iterator ordering interning, new String("xxx") vs "xxx" Names with "$" and "_" @@ -586,6 +589,60 @@ changed to JSToolkit.isDispatchThread() MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS ===================================================================== +restrictions on long +-------------------- + +Java's 64-bit long type is not supported in JavaScript. There is no Int64Array in JavaScript, +and 0x20000000000000 + 1 evaluates to 0x20000000000000, not 0x20000000000001. +(Likewise, -0x20000000000000 - 1 is left unchanged.) + +The largest "integer" value in JavaScript is 9007199254740991 (9.007199254740991E13, or 0x1FFFFFFFFFFFFFF). +Effectively, you get to use only 53 bits of the long, not 64. Trying to set a long larger than +0x1FFFFFFFFFFFFFF or smaller than -0x1FFFFFFFFFFFFFF will result in a NumberFormatException. + +The transpiler handles conversion to long the same as Java for all cases other than from double. + +For small double values, there is no problem, and, in fact, this is a known trick used to round +doubles and floats toward zero: + +double d; +d = (long) 3.8; +assert(d == 3); +d = (long) -3.8; +assert(d == -3); + +SwingJS will evaluate (long) d as 0 for d > 9007199254740991 +or d < -9007199254740991, same as Java returns for Double.NaN. +So, in Java we have: + + assert(((long) Double.NaN) == 0); + assert(((int) Double.NaN) == 0); + assert(((long) Float.NaN) == 0); + assert(((int) Float.NaN) == 0); + +and also, in JavaScript only, we also have: + + double d = 0x2000000000000L; + assert(((long) d) == 0); + + +restrictions on BitSet and Scanner +---------------------------------- + +Because of the issue of long being only 53 bits, any time a method returns a long value, considerations must +be made as to whether this will work in JavaScript. In particular, BitSet and Scanner have issues. + +In SwingJS, java.util.BitSet has been implemented as a 32-bit integer-based bitset. This was no problem in +Java 6, but starting with Java 7, a method was added to BitSet that allows for the extraction of the +underlying long[] word data. This is not work in JavaScript. Instead, SwingJS java.util.Bitset.toLongArray() will deliver +32-bit int[] data. + +SwingJS Scanner has hasNextLong() and nextLong(), and although it will scan through long numbers, +Scanner will choke on long numbers greater than the JavaScript 53-bit limit. hasNextLong() will +return false, and nextLong() will throw an InputMismatchException triggered by the NumberFormatException +thrown by Long.parseLong(). + + HashMap, Hashtable, and HashSet iterator ordering ------------------------------------------------- diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core.jar b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core.jar index 8ad963c23..ab277a94c 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core.jar and b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core.jar differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/timestamp b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/timestamp index 85b1cd109..2672f785d 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/timestamp +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/timestamp @@ -1 +1 @@ -20201205151557 +20201206115202 diff --git a/sources/net.sf.j2s.core/src/net/sf/j2s/core/CorePlugin.java b/sources/net.sf.j2s.core/src/net/sf/j2s/core/CorePlugin.java index bcaa66c06..4303fe37f 100644 --- a/sources/net.sf.j2s.core/src/net/sf/j2s/core/CorePlugin.java +++ b/sources/net.sf.j2s.core/src/net/sf/j2s/core/CorePlugin.java @@ -30,7 +30,7 @@ public class CorePlugin extends Plugin { // if you change the x.x.x number, be sure to also indicate that in // j2sApplet.js and also (Bob only) update.bat, update-clean.bat - + // BH 2020.12.06 -- 3.2.9-v1r fix for (long) double using |0 // BH 2020.11.20 -- 3.2.9-v1q fix for new ImmutableCollections.ListN<>(E...) should use Object[] // BH 2020.08.03 -- 3.2.9-v1p fix for boxing boolean should be Boolean.valueOf$, not new Boolean // BH 2020.08.01 -- 3.2.9-v1o fix for lambda expressions too static diff --git a/sources/net.sf.j2s.core/src/net/sf/j2s/core/Java2ScriptVisitor.java b/sources/net.sf.j2s.core/src/net/sf/j2s/core/Java2ScriptVisitor.java index 27cd7084c..e6945dca1 100644 --- a/sources/net.sf.j2s.core/src/net/sf/j2s/core/Java2ScriptVisitor.java +++ b/sources/net.sf.j2s.core/src/net/sf/j2s/core/Java2ScriptVisitor.java @@ -135,6 +135,7 @@ // TODO: superclass inheritance for JAXB XmlAccessorType +//BH 2020.12.06 -- 3.2.9-v1r fix for (long) double using |0 //BH 2020.11.20 -- 3.2.9-v1q fix for new ImmutableCollections.ListN<>(E...) should use Object[] //BH 2020.08.03 -- 3.2.9-v1p fix for boxing boolean should be Boolean.valueOf$, not new Boolean //BH 2020.08.01 -- 3.2.9-v1o fix for lambda expressions too static @@ -4589,7 +4590,7 @@ private boolean addPrimitiveTypedExpression(Expression left, IVariableBinding as // a = ($b$[0] = a | right, $b$[0]) String classIntArray = null; - String more = null; + String more = null, less = null; String prefix = (isAssignment ? "=" : ""); boolean fromChar = ("char".equals(rightName)); @@ -4611,7 +4612,8 @@ private boolean addPrimitiveTypedExpression(Expression left, IVariableBinding as break; case "long": if (isDiv || !fromIntType) { - more = "|0)"; + less = "Clazz.toLong("; + more = ")"; addParens = true; } else { left = null; @@ -4662,6 +4664,8 @@ private boolean addPrimitiveTypedExpression(Expression left, IVariableBinding as buffer.append("("); buffer.append(classIntArray).append(" = "); temp_processingArrayIndex = true; + } else if (less != null) { + buffer.append(less); } else if (more == "|0)") { buffer.append("("); } diff --git a/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip b/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip index cc920f480..52b640a03 100644 Binary files a/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip and b/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.java.core/dist/differences.txt b/sources/net.sf.j2s.java.core/dist/differences.txt index 46e49ec1a..60f5fcc74 100644 --- a/sources/net.sf.j2s.java.core/dist/differences.txt +++ b/sources/net.sf.j2s.java.core/dist/differences.txt @@ -31,6 +31,7 @@ ever be shadowed or overridden by subclasses. For example, we see in java.lang.T ---------------------------------- +updated 12/6/2020 -- note about restrictions on long, including BitSet and Scanner updated 3/21/2020 -- adds note about HashMap, Hashtable, and HashSet iterator ordering updated 3/20/2020 -- adds note about interning, new String("xxx"), and "xxx" updated 2/26/2020 -- adds Graphics.setClip issue @@ -480,6 +481,8 @@ MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS See below for a full discussion. +Restrictions on long +Restriction on BitSet and Scanner HashMap, Hashtable, and HashSet iterator ordering interning, new String("xxx") vs "xxx" Names with "$" and "_" @@ -586,6 +589,60 @@ changed to JSToolkit.isDispatchThread() MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS ===================================================================== +restrictions on long +-------------------- + +Java's 64-bit long type is not supported in JavaScript. There is no Int64Array in JavaScript, +and 0x20000000000000 + 1 evaluates to 0x20000000000000, not 0x20000000000001. +(Likewise, -0x20000000000000 - 1 is left unchanged.) + +The largest "integer" value in JavaScript is 9007199254740991 (9.007199254740991E13, or 0x1FFFFFFFFFFFFFF). +Effectively, you get to use only 53 bits of the long, not 64. Trying to set a long larger than +0x1FFFFFFFFFFFFFF or smaller than -0x1FFFFFFFFFFFFFF will result in a NumberFormatException. + +The transpiler handles conversion to long the same as Java for all cases other than from double. + +For small double values, there is no problem, and, in fact, this is a known trick used to round +doubles and floats toward zero: + +double d; +d = (long) 3.8; +assert(d == 3); +d = (long) -3.8; +assert(d == -3); + +SwingJS will evaluate (long) d as 0 for d > 9007199254740991 +or d < -9007199254740991, same as Java returns for Double.NaN. +So, in Java we have: + + assert(((long) Double.NaN) == 0); + assert(((int) Double.NaN) == 0); + assert(((long) Float.NaN) == 0); + assert(((int) Float.NaN) == 0); + +and also, in JavaScript only, we also have: + + double d = 0x2000000000000L; + assert(((long) d) == 0); + + +restrictions on BitSet and Scanner +---------------------------------- + +Because of the issue of long being only 53 bits, any time a method returns a long value, considerations must +be made as to whether this will work in JavaScript. In particular, BitSet and Scanner have issues. + +In SwingJS, java.util.BitSet has been implemented as a 32-bit integer-based bitset. This was no problem in +Java 6, but starting with Java 7, a method was added to BitSet that allows for the extraction of the +underlying long[] word data. This is not work in JavaScript. Instead, SwingJS java.util.Bitset.toLongArray() will deliver +32-bit int[] data. + +SwingJS Scanner has hasNextLong() and nextLong(), and although it will scan through long numbers, +Scanner will choke on long numbers greater than the JavaScript 53-bit limit. hasNextLong() will +return false, and nextLong() will throw an InputMismatchException triggered by the NumberFormatException +thrown by Long.parseLong(). + + HashMap, Hashtable, and HashSet iterator ordering ------------------------------------------------- diff --git a/sources/net.sf.j2s.java.core/doc/Differences.txt b/sources/net.sf.j2s.java.core/doc/Differences.txt index 46e49ec1a..60f5fcc74 100644 --- a/sources/net.sf.j2s.java.core/doc/Differences.txt +++ b/sources/net.sf.j2s.java.core/doc/Differences.txt @@ -31,6 +31,7 @@ ever be shadowed or overridden by subclasses. For example, we see in java.lang.T ---------------------------------- +updated 12/6/2020 -- note about restrictions on long, including BitSet and Scanner updated 3/21/2020 -- adds note about HashMap, Hashtable, and HashSet iterator ordering updated 3/20/2020 -- adds note about interning, new String("xxx"), and "xxx" updated 2/26/2020 -- adds Graphics.setClip issue @@ -480,6 +481,8 @@ MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS See below for a full discussion. +Restrictions on long +Restriction on BitSet and Scanner HashMap, Hashtable, and HashSet iterator ordering interning, new String("xxx") vs "xxx" Names with "$" and "_" @@ -586,6 +589,60 @@ changed to JSToolkit.isDispatchThread() MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS ===================================================================== +restrictions on long +-------------------- + +Java's 64-bit long type is not supported in JavaScript. There is no Int64Array in JavaScript, +and 0x20000000000000 + 1 evaluates to 0x20000000000000, not 0x20000000000001. +(Likewise, -0x20000000000000 - 1 is left unchanged.) + +The largest "integer" value in JavaScript is 9007199254740991 (9.007199254740991E13, or 0x1FFFFFFFFFFFFFF). +Effectively, you get to use only 53 bits of the long, not 64. Trying to set a long larger than +0x1FFFFFFFFFFFFFF or smaller than -0x1FFFFFFFFFFFFFF will result in a NumberFormatException. + +The transpiler handles conversion to long the same as Java for all cases other than from double. + +For small double values, there is no problem, and, in fact, this is a known trick used to round +doubles and floats toward zero: + +double d; +d = (long) 3.8; +assert(d == 3); +d = (long) -3.8; +assert(d == -3); + +SwingJS will evaluate (long) d as 0 for d > 9007199254740991 +or d < -9007199254740991, same as Java returns for Double.NaN. +So, in Java we have: + + assert(((long) Double.NaN) == 0); + assert(((int) Double.NaN) == 0); + assert(((long) Float.NaN) == 0); + assert(((int) Float.NaN) == 0); + +and also, in JavaScript only, we also have: + + double d = 0x2000000000000L; + assert(((long) d) == 0); + + +restrictions on BitSet and Scanner +---------------------------------- + +Because of the issue of long being only 53 bits, any time a method returns a long value, considerations must +be made as to whether this will work in JavaScript. In particular, BitSet and Scanner have issues. + +In SwingJS, java.util.BitSet has been implemented as a 32-bit integer-based bitset. This was no problem in +Java 6, but starting with Java 7, a method was added to BitSet that allows for the extraction of the +underlying long[] word data. This is not work in JavaScript. Instead, SwingJS java.util.Bitset.toLongArray() will deliver +32-bit int[] data. + +SwingJS Scanner has hasNextLong() and nextLong(), and although it will scan through long numbers, +Scanner will choke on long numbers greater than the JavaScript 53-bit limit. hasNextLong() will +return false, and nextLong() will throw an InputMismatchException triggered by the NumberFormatException +thrown by Long.parseLong(). + + HashMap, Hashtable, and HashSet iterator ordering ------------------------------------------------- diff --git a/sources/net.sf.j2s.java.core/src/java/util/BitSet.java b/sources/net.sf.j2s.java.core/src/java/util/BitSet.java index d3ce2fb0d..1bcb7baad 100644 --- a/sources/net.sf.j2s.java.core/src/java/util/BitSet.java +++ b/sources/net.sf.j2s.java.core/src/java/util/BitSet.java @@ -20,12 +20,12 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; -import java.nio.LongBuffer; import java.util.stream.IntStream; import java.util.stream.StreamSupport; import javajs.api.JSONEncodable; import javajs.util.SB; +import swingjs.JSUtil; /** @@ -1028,6 +1028,7 @@ public BitSet get(int fromIndex, int toIndex) { * @return */ public long[] toLongArray() { + JSUtil.notImplemented("BitSet.toLongArray returns a 32-bit array"); long[] a = new long[words.length]; for (int i = a.length; --i >= 0;) a[i] = words[i]; diff --git a/sources/net.sf.j2s.java.core/src/java/util/Scanner.java b/sources/net.sf.j2s.java.core/src/java/util/Scanner.java index a8e7a22b0..f80119ad9 100644 --- a/sources/net.sf.j2s.java.core/src/java/util/Scanner.java +++ b/sources/net.sf.j2s.java.core/src/java/util/Scanner.java @@ -52,6 +52,7 @@ import java.util.regex.Pattern; import sun.misc.LRUCache; +import swingjs.JSUtil; /** * A simple text scanner which can parse primitive types and strings using @@ -447,12 +448,12 @@ private static Pattern boolPattern() { private String non0Digit = "[1-9]";//"[\\p{javaDigit}&&[^0]]"; private int SIMPLE_GROUP_INDEX = 12; // SwingJS - moved simple to later private String buildIntegerPatternString() { - String radixDigits = (radix == 10 ? "0-9" : digits.substring(0, radix) + digits.substring(10, radix).toUpperCase()); + String radixDigits = (radix == 10 ? "\\d" : radix < 10 ? "[" + digits.substring(0, radix) + "]" : "[0-9a-" + digits.charAt(radix - 1) + "A-" + digits.substring(radix-1, radix).toUpperCase() + "]"); // \\p{javaDigit} is not guaranteed to be appropriate // here but what can we do? The final authority will be // whatever parse method is invoked, so ultimately the // Scanner will do the right thing - String digit = "(["+radixDigits+"])";//\\p{javaDigit})"; + String digit = "("+radixDigits+")";//\\p{javaDigit})"; String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+ groupSeparator+digit+digit+digit+")+)"; // digit++ is the possessive form which is necessary for reducing @@ -2194,12 +2195,22 @@ public boolean hasNextLong(int radix) { boolean result = hasNext(integerPattern()); if (result) { // Cache it try { - String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? - processIntegerToken(hasNextResult) : - hasNextResult; + String s = (matcher.group(SIMPLE_GROUP_INDEX) == null ? + processIntegerToken(hasNextResult) : hasNextResult); + // SwingJS may choke here typeCache = Long.parseLong(s, radix); } catch (NumberFormatException nfe) { - result = false; + /** @j2sNative + var l = parseInt(s, radix); + result = (l < -0x1FFFFFFFFFFFFF || l > 0x1FFFFFFFFFFFFF); + */ + { + result = false; + } + if (result) { + JSUtil.notImplemented("Scanner found long value with > 53 bits"); + result = false; + } } } return result; diff --git a/sources/net.sf.j2s.java.core/src/java/util/regex/Pattern.java b/sources/net.sf.j2s.java.core/src/java/util/regex/Pattern.java index 59ec08a64..3f52fb032 100644 --- a/sources/net.sf.j2s.java.core/src/java/util/regex/Pattern.java +++ b/sources/net.sf.j2s.java.core/src/java/util/regex/Pattern.java @@ -1794,8 +1794,8 @@ private Pattern(String p, int f) { } private final static String[] posixes = { - "\\p{javaWhitespace}","\\W", - "\\p{javaDigit}","[0-9]", + "\\p{javaWhitespace}","\\s", + "\\p{javaDigit}","\\d", "\\p{Lower}", "[a-z]", "\\p{Upper}", "[A-Z]", "\\p{ASCII}", "[\u0000-\u007F]", @@ -1811,7 +1811,6 @@ private Pattern(String p, int f) { "\\p{Space}", "[ \t\n\u000B\f\r]", "\\p{javaLowerCase}", "[a-z]", "\\p{javaUpperCase}", "[A-Z]", - "\\p{javaWhitespace}", "\\W", "\\p{Sc}", "[\u0024\u00A2\u00A3\u00A4\u00A5\u058F\u060B\u07FE\u07FF\u09F2\u09F3\u09FB\u0AF1\u0BF9\u0E3F\u20A0\u20A1\u20A2\u20A3\u20A4\u20A5\u20A6\u20A7\u20A8\u20A9\u20AA\u20AB\u20AC\u20AD\u20AE\u20AF\u20B0\u20B1\u20B2\u20B3\u20B4\u20B5\u20B6\u20B7\u20B8\u20B9\u20BA\u20BB\u20BC\u20BD\u20BE\u20BF\uA838\uFDFC\uFE69\uFF04\uFFE0\uFFE1\uFFE5\uFFE6]" // more currency: \u11FDD\u11FDE\u11FDF\u11FE0\u17DB\u1E2FF\u1ECB0 diff --git a/sources/net.sf.j2s.java.core/src/test/ScanTest.java b/sources/net.sf.j2s.java.core/src/test/ScanTest.java index 88a05d415..3e3040540 100644 --- a/sources/net.sf.j2s.java.core/src/test/ScanTest.java +++ b/sources/net.sf.j2s.java.core/src/test/ScanTest.java @@ -75,7 +75,7 @@ public static void main(String[] args) throws Exception { closeTest(); cacheTest(); cacheTest2(); - System.err.println("Skipping Tibetan number test nonASCIITest()"); + System.err.println("!!!!!!!!!Skipping Tibetan number test nonASCIITest()"); resetTest(); for (int j = 0; j < NUM_SOURCE_TYPES; j++) { @@ -87,8 +87,8 @@ public static void main(String[] args) throws Exception { byteTest(j); shortTest(j); intTest(j); - System.err.println("Skipping longTest(j)"); - //SwingJS does not support high-bit long numbers longTest(j); + System.err.println("!!!!!!!!!!56-bit longTest(j)"); + longTest(j); floatTest(j); doubleTest(j); integerPatternTest(j); @@ -1292,7 +1292,7 @@ private static void shortTest(int sourceType) throws Exception { } private static void intTest(int sourceType) throws Exception { - Scanner s = scannerFor("22 022 C -34 0x80000000 -2147483649 dog ", sourceType); + Scanner s = scannerFor("22 022 C -34 80 0x80 -2147483649 dog ", sourceType); if (!s.hasNextInt()) failed(); if (s.nextInt() != 22) @@ -1309,6 +1309,10 @@ private static void intTest(int sourceType) throws Exception { failed(); if (s.nextInt() != -34) failed(); + if (!s.hasNextInt(16)) + failed(); + if (s.nextInt(16) != 0x80) + failed(); for (int i = 0; i < 3; i++) { if (s.hasNextInt()) failed(); @@ -1331,17 +1335,51 @@ private static void intTest(int sourceType) throws Exception { report("Scan ints"); } + @SuppressWarnings("unused") private static void longTest(int sourceType) throws Exception { - Scanner s = scannerFor("022 9223372036854775807 0x8000000000000000 9223372036854775808 dog ", sourceType); +// Scanner s = scannerFor("022 9223372036854775807 0x8000000000000000 9223372036854775808 dog ", sourceType); + Scanner s = scannerFor( + "022 9007199254740991 -9007199254740991 1FFFFFFFFFFFFF -1FFFFFFFFFFFFF 9007199254740992 9223372036854775808 dog ", + sourceType); if (!s.hasNextLong()) failed(); if (s.nextLong() != (long) 22) failed(); if (!s.hasNextLong()) failed(); - if (s.nextLong() != 9223372036854775807L) + + if (s.nextLong() != 0x1FFFFFFFFFFFFFL) failed(); - for (int i = 0; i < 3; i++) { + if (!s.hasNextLong()) + failed(); + if (s.nextLong() != -0x1FFFFFFFFFFFFFL) + failed(); + + if (!s.hasNextLong(16)) + failed(); + if (s.nextLong(16) != 0x1FFFFFFFFFFFFFL) + failed(); + if (!s.hasNextLong(16)) + failed(); + if (s.nextLong(16) != -0x1FFFFFFFFFFFFFL) + failed(); + + try { + // SwingJS will fail here because the long value is too large for JavaScript. + if (!s.hasNextLong()) { + if (/** @j2sNative false && */ + true) + failed(); + } + long l = s.nextLong(); + if (l != 0x20000000000000L) + failed(); + } catch (InputMismatchException e) { + // SwingJS will throw this, because the number is too large + System.err.println("!!!!!!!!!! SwingJS cannot read 0x20000000000000 as a long: " + s.next()); + } + + for (int i = 0; i < 2; i++) { if (s.hasNextLong()) failed(); try { @@ -1351,6 +1389,7 @@ private static void longTest(int sourceType) throws Exception { // Correct result } s.next(); + System.err.flush(); } try { s.next(); diff --git a/sources/net.sf.j2s.java.core/src/test/Test_.java b/sources/net.sf.j2s.java.core/src/test/Test_.java index 9a9fdc308..b440ab396 100644 --- a/sources/net.sf.j2s.java.core/src/test/Test_.java +++ b/sources/net.sf.j2s.java.core/src/test/Test_.java @@ -178,6 +178,7 @@ private static void _test1(String[] args) { Test_JAXB_Obj.main(args); //failing on unicode char in "somewhatComplex" Test_JAXB_ORDERED.main(args); // Test_Map.main(args); + // this is just a test for long += huge decimal Test_Long.main(args), which does fail; Test_Math.main(args); Test_Native.main(args); Test_NoAssert.main(args); diff --git a/sources/net.sf.j2s.java.core/src/test/Test_Long.java b/sources/net.sf.j2s.java.core/src/test/Test_Long.java new file mode 100644 index 000000000..20dc04e09 --- /dev/null +++ b/sources/net.sf.j2s.java.core/src/test/Test_Long.java @@ -0,0 +1,77 @@ +package test; + +/** + * demonstrates that + * + * @author hansonr + * + */ +public abstract class Test_Long extends Test_ { + + public static void main(String[] args) { + + long l; + double d; + int ii = (int) Float.MAX_VALUE; + assert (ii == Integer.MAX_VALUE); + assert (Long.parseLong("1FFFFFFFFFFFFF", 16) == 0x1FFFFFFFFFFFFFL); + d = 0x1FFFFFFFFFFFFFL; + System.out.println((long) d); + // note that long literals are NOT caught + System.out.println(0x1FFFFFFFFFFFFFL); + assert (((long) d) == /** @j2sNative 1 ? 0 : */ + 0x1FFFFFFFFFFFFFL); + + // Can't do this in Java: + try { + l = Long.valueOf("0xFFFFF"); + assert (false); + } catch (NumberFormatException e) { + } + + try { + l = Long.parseLong("0xFFFFF", 16); + assert (false); + } catch (NumberFormatException e) { + } + + try { + l = Long.parseLong("0xFFFFF"); + assert (false); + } catch (NumberFormatException e) { + } + + // Eclipse compilation checker is incorrect! + assert (((long) Double.NaN) == 0); + assert (((int) Double.NaN) == 0); + assert (((long) Float.NaN) == 0); + assert (((int) Float.NaN) == 0); + d = (long) 3.8; + assert (d == 3); + d = (long) -3.8; + assert (d == -3); + + long m; + for (double i = -20; i < 20; i++) { + l = 0; + m = (long) (l + i / 10); + l += i / 10; + System.out.println(l + " " + (i / 10) + " " + m); + assert (l == m); + } + for (double i = -20; i < 20; i++) { + l = 0; + m = (long) (l - i / 10); + l -= i / 10; + System.out.println(l + " " + (-i / 10) + " " + m); + assert (l == m); + } + l = 0; + l += 9E13; + System.out.println("9E13=" + l); + + assert (l == 9e13); + System.out.println("Test_Long OK"); + } + +} \ No newline at end of file diff --git a/sources/net.sf.j2s.java.core/srcjs/js/core/corebottom2.js b/sources/net.sf.j2s.java.core/srcjs/js/core/corebottom2.js index 0cc9410bf..301f13063 100644 --- a/sources/net.sf.j2s.java.core/srcjs/js/core/corebottom2.js +++ b/sources/net.sf.j2s.java.core/srcjs/js/core/corebottom2.js @@ -1 +1 @@ -})(Clazz,Clazz.setTVer,Clazz.array,Clazz.assert,Clazz.clone,Clazz.exceptionOf,Clazz.forName,Clazz.getClass,Clazz.instanceOf,Clazz.load,Clazz.new_,Clazz.newClass,Clazz.newEnumConst,Clazz.newInstance,Clazz.newInterface,Clazz.newMeth,Clazz.newPackage,Clazz.super_); +})(Clazz,Clazz.setTVer,Clazz.toLong,Clazz.array,Clazz.assert,Clazz.clone,Clazz.exceptionOf,Clazz.forName,Clazz.getClass,Clazz.instanceOf,Clazz.load,Clazz.new_,Clazz.newClass,Clazz.newEnumConst,Clazz.newInstance,Clazz.newInterface,Clazz.newMeth,Clazz.newPackage,Clazz.super_); diff --git a/sources/net.sf.j2s.java.core/srcjs/js/core/coretop2.js b/sources/net.sf.j2s.java.core/srcjs/js/core/coretop2.js index 526dfd83e..3670a9724 100644 --- a/sources/net.sf.j2s.java.core/srcjs/js/core/coretop2.js +++ b/sources/net.sf.j2s.java.core/srcjs/js/core/coretop2.js @@ -1 +1 @@ -(function(Clazz,Clazz_setTVer,Clazz_array,Clazz_assert,Clazz_clone,Clazz_exceptionOf,Clazz_forName,Clazz_getClass,Clazz_instanceOf,Clazz_load,Clazz_new_,Clazz_newClass,Clazz_newEnumConst,Clazz_newInstance,Clazz_newInterface,Clazz_newMeth,Clazz_newPackage,Clazz_super_){ \ No newline at end of file +(function(Clazz,Clazz_setTVer,Clazz_toLong,Clazz_array,Clazz_assert,Clazz_clone,Clazz_exceptionOf,Clazz_forName,Clazz_getClass,Clazz_instanceOf,Clazz_load,Clazz_new_,Clazz_newClass,Clazz_newEnumConst,Clazz_newInstance,Clazz_newInterface,Clazz_newMeth,Clazz_newPackage,Clazz_super_){ \ No newline at end of file diff --git a/sources/net.sf.j2s.java.core/srcjs/js/j2sClazz.js b/sources/net.sf.j2s.java.core/srcjs/js/j2sClazz.js index 8e5b433b8..3f1aa1ec7 100644 --- a/sources/net.sf.j2s.java.core/srcjs/js/j2sClazz.js +++ b/sources/net.sf.j2s.java.core/srcjs/js/j2sClazz.js @@ -7,6 +7,8 @@ // Google closure compiler cannot handle Clazz.new or Clazz.super +// BH 2020.12.06 changing Long maxval to 0x1FFFFFFFFFFFFF from 0x20000000000000 +// BH 2020.12.06 better error checking for TYPE.parseTYPE(string) // BH 2020.07.27 fix for inner class array names // BH 2020.06.18 better test for instanceof Object[] // BH 2020.06.03 sets user.home and user.dir to /TEMP/swingjs, and user.name to "swingjs" @@ -3696,6 +3698,24 @@ var decorateAsNumber = function (clazz, qClazzName, type, PARAMCODE, hcOffset) { return clazz; }; +Clazz.toLong = function(v) { + return (isNaN(v = parseInt(v)) || v < minLong || v > maxLong ? 0 : v); +} + +var parseIntLimit = function(s,radix, min, max) { + var v = (s == null || s.indexOf(".") >= 0 || s.startsWith("0x") ? NaN : radix === false ? parseInt(s) : parseInt(s, radix)); + if (!isNaN(v)) { + // check for trailing garbage + var v1 = parseInt(s + "1", radix); + if (v1 == v) + v = NaN; + } + if (isNaN(v) || v < min || v > max){ + throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); + } + return v; +} + decorateAsNumber(Integer, "Integer", "int", "I", iHCOffset); Integer.toString=Integer.toString$I=Integer.toString$I$I=Integer.prototype.toString=function(i,radix){ @@ -3766,29 +3786,14 @@ function(i){ return (v ? v : Clazz.new_(Integer.c$$I, [i])); }, 1); +m$(Integer,"parseInt$S", +function(s){ + return parseIntLimit(s, false, minInt, maxInt); +}, 1); m$(Integer,"parseInt$S$I", function(s,radix){ - var v = (s == null || s.indexOf(".") >= 0 ? NaN : parseInt(s, radix)); - if (!isNaN(v)) { - // check for trailing garbage - var v1 = parseInt(s + "1", radix); - if (v1 == v) - v = NaN; - } - - if (isNaN(v) || v < minInt || v > maxInt){ - throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); - } -return v; -}, 1); - -m$(Integer,"parseInt$S", -function(s){ - var v = (s == null ? NaN : +s); - if (isNaN(v)) - s= "?" + s; // just to ensure it gets trapped -return Integer.parseInt$S$I(s, 10); + return parseIntLimit(s, radix, minInt, maxInt); }, 1); m$(Integer,"highestOneBit$I", @@ -3923,20 +3928,23 @@ Long.toString=Long.toString$J=Long.toString$J$I = Long.prototype.toString=functi }; -//Long.MIN_VALUE=Long.prototype.MIN_VALUE=-0x8000000000000000; -//Long.MAX_VALUE=Long.prototype.MAX_VALUE=0x7fffffffffffffff; //Long.TYPE=Long.prototype.TYPE=Long; //Note that the largest usable "Long" in JavaScript is 53 digits: -var maxLong = 0x20000000000000; // 53 digits, plus 1 -var minLong = -0x20000000000000; -Long.SIZE=Long.prototype.SIZE=64; +Long.MIN_VALUE=Long.prototype.MIN_VALUE=-0x1fffffffffffff; +Long.MAX_VALUE=Long.prototype.MAX_VALUE=0x1fffffffffffff; + +var maxLong = Long.MAX_VALUE; +var minLong = -maxLong; +Long.SIZE=Long.prototype.SIZE=64;// REALLY 53 Long.sum$J$J = Integer.sum$I$I; Long.toHexString$J=Integer.toHexString$I; Long.toOctalString$J=Integer.toOctalString$I; Long.toBinaryString$J=Integer.toBinaryString$I; +m$(Long,["longValue","longValue$"],function(){return this.valueOf();}); + m$(Long,"c$", function(v){ v || v == null || (v = 0); @@ -3975,16 +3983,12 @@ function(i){ m$(Long,"parseLong$S", function(s){ - return Long.parseLong$S$I(s, 10); + return parseIntLimit(s, false, minLong, maxLong); }, 1); m$(Long,"parseLong$S$I", function(s,radix){ - var v = parseInt(s, radix); - if (isNaN(v) || v < minLong || v > maxLong) { - throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); - } - return v; + return parseIntLimit(s, radix, minLong, maxLong); }, 1); m$(Long,"equals$O", @@ -4081,16 +4085,12 @@ function(i){ m$(Short,"parseShort$S", function(s){ - return Short.parseShort$S$I(s, 10); + return parseIntLimit(s, false, minShort, maxShort); }, 1); m$(Short,"parseShort$S$I", function(s,radix){ - var v = parseInt(s, radix); - if (isNaN(v) || v < minShort || v > maxShort) { - throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); - } - return v; + return parseIntLimit(s, radix, minShort, maxShort); }, 1); @@ -4174,18 +4174,14 @@ Byte.toString=Byte.toString$B=Byte.toString$B$I=Byte.prototype.toString=function }; m$(Byte,"parseByte$S", - function(s){ - return Byte.parseByte$S$I(s, 10); - }, 1); + function(s){ + return parseIntLimit(s, false, minByte, maxByte); + }, 1); m$(Byte,"parseByte$S$I", function(s,radix){ - var v = parseInt(s, radix); - if (isNaN(v) || v < minByte || v > maxByte) { - throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); - } - return v; -}, 1); + return parseIntLimit(s, radix, minByte, maxByte); + }, 1); Byte.toString=Byte.toString$B=Byte.toString$B$I=Byte.prototype.toString=function(i,radix){ switch(arguments.length) { @@ -4315,6 +4311,9 @@ function(s){ return Clazz.new_(Float.c$$S, [s]); }, 1); + +m$(Float,["longValue$","longValue"],function(){return Math.floor(this.valueOf());}); + m$(Float,"valueOf$D", function(i){ return Clazz.new_(Float.c$$F, [i < minFloat ? -Infinity : i > maxFloat ? Infinity : i]); @@ -4412,6 +4411,9 @@ throw Clazz.new_(NumberFormatException.c$$S, ["Not a Number : "+s]); return v; }, 1); +m$(Double,["longValue","longValue$"],function(){return Math.floor(this.valueOf());}); + + m$(Double,"valueOf$S", function(v){ return Clazz.new_(Double.c$$S, [v]); diff --git a/sources/net.sf.j2s.java.core/srcjs/swingjs2.js b/sources/net.sf.j2s.java.core/srcjs/swingjs2.js index f41f2170d..dcdcb8e1d 100644 --- a/sources/net.sf.j2s.java.core/srcjs/swingjs2.js +++ b/sources/net.sf.j2s.java.core/srcjs/swingjs2.js @@ -14019,6 +14019,8 @@ if (ev.keyCode == 9 && ev.target["data-focuscomponent"]) { // Google closure compiler cannot handle Clazz.new or Clazz.super +// BH 2020.12.06 changing Long maxval to 0x1FFFFFFFFFFFFF from 0x20000000000000 +// BH 2020.12.06 better error checking for TYPE.parseTYPE(string) // BH 2020.07.27 fix for inner class array names // BH 2020.06.18 better test for instanceof Object[] // BH 2020.06.03 sets user.home and user.dir to /TEMP/swingjs, and user.name to "swingjs" @@ -17708,6 +17710,24 @@ var decorateAsNumber = function (clazz, qClazzName, type, PARAMCODE, hcOffset) { return clazz; }; +Clazz.toLong = function(v) { + return (isNaN(v = parseInt(v)) || v < minLong || v > maxLong ? 0 : v); +} + +var parseIntLimit = function(s,radix, min, max) { + var v = (s == null || s.indexOf(".") >= 0 || s.startsWith("0x") ? NaN : radix === false ? parseInt(s) : parseInt(s, radix)); + if (!isNaN(v)) { + // check for trailing garbage + var v1 = parseInt(s + "1", radix); + if (v1 == v) + v = NaN; + } + if (isNaN(v) || v < min || v > max){ + throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); + } + return v; +} + decorateAsNumber(Integer, "Integer", "int", "I", iHCOffset); Integer.toString=Integer.toString$I=Integer.toString$I$I=Integer.prototype.toString=function(i,radix){ @@ -17778,29 +17798,14 @@ function(i){ return (v ? v : Clazz.new_(Integer.c$$I, [i])); }, 1); +m$(Integer,"parseInt$S", +function(s){ + return parseIntLimit(s, false, minInt, maxInt); +}, 1); m$(Integer,"parseInt$S$I", function(s,radix){ - var v = (s == null || s.indexOf(".") >= 0 ? NaN : parseInt(s, radix)); - if (!isNaN(v)) { - // check for trailing garbage - var v1 = parseInt(s + "1", radix); - if (v1 == v) - v = NaN; - } - - if (isNaN(v) || v < minInt || v > maxInt){ - throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); - } -return v; -}, 1); - -m$(Integer,"parseInt$S", -function(s){ - var v = (s == null ? NaN : +s); - if (isNaN(v)) - s= "?" + s; // just to ensure it gets trapped -return Integer.parseInt$S$I(s, 10); + return parseIntLimit(s, radix, minInt, maxInt); }, 1); m$(Integer,"highestOneBit$I", @@ -17935,20 +17940,23 @@ Long.toString=Long.toString$J=Long.toString$J$I = Long.prototype.toString=functi }; -//Long.MIN_VALUE=Long.prototype.MIN_VALUE=-0x8000000000000000; -//Long.MAX_VALUE=Long.prototype.MAX_VALUE=0x7fffffffffffffff; //Long.TYPE=Long.prototype.TYPE=Long; //Note that the largest usable "Long" in JavaScript is 53 digits: -var maxLong = 0x20000000000000; // 53 digits, plus 1 -var minLong = -0x20000000000000; -Long.SIZE=Long.prototype.SIZE=64; +Long.MIN_VALUE=Long.prototype.MIN_VALUE=-0x1fffffffffffff; +Long.MAX_VALUE=Long.prototype.MAX_VALUE=0x1fffffffffffff; + +var maxLong = Long.MAX_VALUE; +var minLong = -maxLong; +Long.SIZE=Long.prototype.SIZE=64;// REALLY 53 Long.sum$J$J = Integer.sum$I$I; Long.toHexString$J=Integer.toHexString$I; Long.toOctalString$J=Integer.toOctalString$I; Long.toBinaryString$J=Integer.toBinaryString$I; +m$(Long,["longValue","longValue$"],function(){return this.valueOf();}); + m$(Long,"c$", function(v){ v || v == null || (v = 0); @@ -17987,16 +17995,12 @@ function(i){ m$(Long,"parseLong$S", function(s){ - return Long.parseLong$S$I(s, 10); + return parseIntLimit(s, false, minLong, maxLong); }, 1); m$(Long,"parseLong$S$I", function(s,radix){ - var v = parseInt(s, radix); - if (isNaN(v) || v < minLong || v > maxLong) { - throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); - } - return v; + return parseIntLimit(s, radix, minLong, maxLong); }, 1); m$(Long,"equals$O", @@ -18093,16 +18097,12 @@ function(i){ m$(Short,"parseShort$S", function(s){ - return Short.parseShort$S$I(s, 10); + return parseIntLimit(s, false, minShort, maxShort); }, 1); m$(Short,"parseShort$S$I", function(s,radix){ - var v = parseInt(s, radix); - if (isNaN(v) || v < minShort || v > maxShort) { - throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); - } - return v; + return parseIntLimit(s, radix, minShort, maxShort); }, 1); @@ -18186,18 +18186,14 @@ Byte.toString=Byte.toString$B=Byte.toString$B$I=Byte.prototype.toString=function }; m$(Byte,"parseByte$S", - function(s){ - return Byte.parseByte$S$I(s, 10); - }, 1); + function(s){ + return parseIntLimit(s, false, minByte, maxByte); + }, 1); m$(Byte,"parseByte$S$I", function(s,radix){ - var v = parseInt(s, radix); - if (isNaN(v) || v < minByte || v > maxByte) { - throw Clazz.new_(NumberFormatException.c$$S, ["parsing " + s + " radix " + radix]); - } - return v; -}, 1); + return parseIntLimit(s, radix, minByte, maxByte); + }, 1); Byte.toString=Byte.toString$B=Byte.toString$B$I=Byte.prototype.toString=function(i,radix){ switch(arguments.length) { @@ -18327,6 +18323,9 @@ function(s){ return Clazz.new_(Float.c$$S, [s]); }, 1); + +m$(Float,["longValue$","longValue"],function(){return Math.floor(this.valueOf());}); + m$(Float,"valueOf$D", function(i){ return Clazz.new_(Float.c$$F, [i < minFloat ? -Infinity : i > maxFloat ? Infinity : i]); @@ -18424,6 +18423,9 @@ throw Clazz.new_(NumberFormatException.c$$S, ["Not a Number : "+s]); return v; }, 1); +m$(Double,["longValue","longValue$"],function(){return Math.floor(this.valueOf());}); + + m$(Double,"valueOf$S", function(v){ return Clazz.new_(Double.c$$S, [v]);