Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions user/super/com/google/gwt/emul/java/lang/Double.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,23 @@ public static Double valueOf(String s) throws NumberFormatException {
return new Double(s);
}

public static String toHexString(double d) {
if (!Double.isFinite(d)) {
return Double.toString(d);
}
int exp = Math.abs(d) == 0 ? -1 : Math.getExponent(d);
long allBits = Double.doubleToLongBits(d);
String sign = allBits < 0 ? "-" : "";
long significantBits = allBits & 0xfffffffffffffL;
String unsignedPrefix = "0x1.";
if (Math.abs(d) < Double.MIN_NORMAL) {
unsignedPrefix = "0x0.";
exp++;
}
return sign + unsignedPrefix + Long.toString(significantBits,16)
.replaceFirst("(.)0+$", "$1") + "p" + exp;
}

public Double(double value) {
/*
* Call to $create(value) must be here so that the method is referenced and not
Expand Down
17 changes: 17 additions & 0 deletions user/super/com/google/gwt/emul/java/lang/Float.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,23 @@ public static Float valueOf(String s) throws NumberFormatException {
return new Float(s);
}

public static String toHexString(float f) {
if (!Float.isFinite(f)) {
return Float.toString(f);
}
int exp = Math.abs(f) == 0 ? -1 : Math.getExponent(f);
int allBits = Float.floatToIntBits(f);
String sign = allBits < 0 ? "-" : "";
int significantBits = allBits << 1 & 0xffffff;
String unsignedPrefix = "0x1.";
if (Math.abs(f) < Float.MIN_NORMAL) {
unsignedPrefix = "0x0.";
exp++;
}
return sign + unsignedPrefix + Long.toString(significantBits,16)
.replaceFirst("(.)0+$", "$1") + "p" + exp;
}

private final transient float value;

public Float(double value) {
Expand Down
5 changes: 5 additions & 0 deletions user/super/com/google/gwt/emul/java/lang/Integer.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ public static int parseInt(String s, int radix) throws NumberFormatException {
return __parseAndValidateInt(s, radix, MIN_VALUE, MAX_VALUE);
}

public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix)
throws NumberFormatException {
return parseInt(s.subSequence(beginIndex, endIndex).toString(), radix);
}

public static int reverse(int i) {
int[] nibbles = ReverseNibbles.reverseNibbles;
return (nibbles[i >>> 28]) | (nibbles[(i >> 24) & 0xf] << 4)
Expand Down
4 changes: 4 additions & 0 deletions user/super/com/google/gwt/emul/java/lang/System.java
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ public static void setOut(PrintStream out) {
System.out = out;
}

public static String lineSeparator() {
return "\n";
}

private static boolean arrayTypeMatch(Class<?> srcComp, Class<?> destComp) {
if (srcComp.isPrimitive()) {
return srcComp.equals(destComp);
Expand Down
40 changes: 35 additions & 5 deletions user/super/com/google/gwt/emul/java/util/Objects.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,24 +139,44 @@ public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)

public static int checkIndex(int index, int length) {
if (index < 0 || index >= length) {
throw new IndexOutOfBoundsException("Index " + index + " out of bounds for length " + length);
throw getIndexError(index, length);
}
return index;
}

public static int checkFromToIndex(int fromIndex, int toIndex, int length) {
if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) {
throw new IndexOutOfBoundsException("Range [" + fromIndex + ", " + toIndex
+ ") out of bounds for length " + length);
throw getFromIndexError(fromIndex, toIndex, length);
}
return fromIndex;
}

public static int checkFromIndexSize(int fromIndex, int size, int length) {
// in JS fromIndex + size cannot overflow because int is not limited to 32 bits
if (fromIndex < 0 || size < 0 || fromIndex + size > length) {
throw new IndexOutOfBoundsException("Range [" + fromIndex + ", " + (fromIndex + size)
+ ") out of bounds for length " + length);
throw getFromIndexError(fromIndex, fromIndex + size, length);
}
return fromIndex;
}

public static long checkIndex(long index, long length) {
if (index < 0 || index >= length) {
throw getIndexError(index, length);
}
return index;
}

public static long checkFromToIndex(long fromIndex, long toIndex, long length) {
if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) {
throw getFromIndexError(fromIndex, toIndex, length);
}
return fromIndex;
}

public static long checkFromIndexSize(long fromIndex, long size, long length) {
// in JS fromIndex + size cannot overflow because int is not limited to 64 bits
if (fromIndex < 0 || size < 0 || fromIndex + size > length) {
throw getFromIndexError(fromIndex, fromIndex + size, length);
}
return fromIndex;
}
Expand All @@ -168,4 +188,14 @@ public static String toString(Object o) {
public static String toString(Object o, String nullDefault) {
return o != null ? o.toString() : nullDefault;
}

private static IndexOutOfBoundsException getIndexError(long index, long length) {
return new IndexOutOfBoundsException("Index " + index + " out of bounds for length " + length);
}

private static IndexOutOfBoundsException getFromIndexError(long fromIndex,
long toIndex, long length) {
return new IndexOutOfBoundsException("Range [" + fromIndex + ", " + toIndex
+ ") out of bounds for length " + length);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2025 GWT Project Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.emultest.java17.util;

import com.google.gwt.emultest.java.util.EmulTestBase;

import java.util.Objects;

/**
* Tests {@link Objects} additions up to Java 17 (checkIndex* is part of Java 16).
*/
public class ObjectsTest extends EmulTestBase {

public void testCheckIndex() {
assertEquals(50000000000L, Objects.checkIndex(50000000000L, 100000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkIndex(-50000000000L, 50000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkIndex(100000000000L, 50000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkIndex(50000000000L, 50000000000L));
}

public void testCheckFromToIndex() {
assertEquals(50000000000L,
Objects.checkFromToIndex(50000000000L, 70000000000L, 100000000000L));
assertEquals(0L, Objects.checkFromToIndex(0, 100000000000L, 100000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkFromToIndex(-50000000000L, 10000000000L, 50000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkFromToIndex(100000000000L, 10000000000L, 50000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkFromToIndex(10000000000L, 100000000000L, 50000000000L));
}

public void testCheckFromIndexSize() {
assertEquals(50000000000L,
Objects.checkFromIndexSize(50000000000L, 20000000000L, 100000000000L));
assertEquals(0L, Objects.checkFromIndexSize(0, 100000000000L, 100000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkFromIndexSize(-50000000000L, 10000000000L, 50000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkFromIndexSize(100000000000L, 10000000000L, 50000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkFromIndexSize(10000000000L, 100000000000L, 50000000000L));
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkFromIndexSize(10000000000L, -50000000000L, 50000000000L));
}

}
4 changes: 3 additions & 1 deletion user/test/com/google/gwt/emultest/EmulJava17Suite.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.gwt.emultest.java17.lang.MathTest;
import com.google.gwt.emultest.java17.lang.StringTest;
import com.google.gwt.emultest.java17.util.MapEntryTest;
import com.google.gwt.emultest.java17.util.ObjectsTest;
import com.google.gwt.emultest.java17.util.stream.CollectorsTest;
import com.google.gwt.emultest.java17.util.stream.DoubleStreamTest;
import com.google.gwt.emultest.java17.util.stream.IntStreamTest;
Expand All @@ -39,7 +40,8 @@
DoubleStreamTest.class,
IntStreamTest.class,
LongStreamTest.class,
MapEntryTest.class
MapEntryTest.class,
ObjectsTest.class
})
public class EmulJava17Suite {
}
19 changes: 19 additions & 0 deletions user/test/com/google/gwt/emultest/java/lang/DoubleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,25 @@ public void testParse() {
}
}

public void testToHexString() {
assertEquals("-0x1.0p0", Double.toHexString(-1.0));
assertEquals("0x1.0p0", Double.toHexString(1.0));
assertEquals("0x1.0p1", Double.toHexString(2.0));
assertEquals("0x1.8p1", Double.toHexString(3.0));
Comment thread
zbynek marked this conversation as resolved.
assertEquals("0x1.81c8p13", Double.toHexString(12345.0));
assertEquals("0x1.0p-1022", Double.toHexString(Double.MIN_NORMAL));
assertEquals("0x0.8p-1022", Double.toHexString(Double.MIN_NORMAL / 2));
assertEquals("0x0.cp-1022", Double.toHexString(Double.MIN_NORMAL / 4 * 3));
assertEquals("0x1.7e43c8800759cp996", Double.toHexString(1.0E300));
assertEquals("-0x1.7e43c8800759cp996", Double.toHexString(-1.0E300));
assertEquals("0x1.0p-1021", Double.toHexString(4.450147717014403E-308));
assertEquals("0x0.0p0", Double.toHexString(0.0));
assertEquals("-0x0.0p0", Double.toHexString(-0.0));
assertEquals("Infinity", Double.toHexString(Double.POSITIVE_INFINITY));
assertEquals("-Infinity", Double.toHexString(Double.NEGATIVE_INFINITY));
assertEquals("NaN", Double.toHexString(Double.NaN));
}

public void testDoubleBits() {
// special values
compareDoubleBits(0x0000000000000000L, 0.0);
Expand Down
16 changes: 16 additions & 0 deletions user/test/com/google/gwt/emultest/java/lang/FloatTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,22 @@ public void testParse() {
}
}

public void testToHexString() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Float.html#toHexString(float) for the other tests, but floats can get a little dicey in GWT (since we emulate them with JS number, which is basically just Double already)

assertEquals("-0x1.0p0", Float.toHexString(-1.0f));
assertEquals("0x1.0p0", Float.toHexString(1.0f));
assertEquals("0x1.0p1", Float.toHexString(2.0f));
assertEquals("0x1.8p1", Float.toHexString(3.0f));
assertEquals("0x1.5p5", Float.toHexString(42.0f));
assertEquals("0x1.81c8p13", Float.toHexString(12345.0f));
assertEquals("0x0.0p0", Float.toHexString(0.0f));
assertEquals("-0x0.0p0", Float.toHexString(-0.0f));
assertEquals("Infinity", Float.toHexString(Float.POSITIVE_INFINITY));
assertEquals("-Infinity", Float.toHexString(Float.NEGATIVE_INFINITY));
assertEquals("NaN", Float.toHexString(Float.NaN));
assertEquals("0x1.0p-126", Float.toHexString(Float.MIN_NORMAL));
assertEquals("0x0.8p-126", Float.toHexString(Float.MIN_NORMAL / 2));
}

public void testFloatBits() {
compareFloatBits(0x1, 1.401298464324817E-45F);
compareFloatBits(0x2, 1.401298464324817E-45F * 2.0F);
Expand Down
12 changes: 12 additions & 0 deletions user/test/com/google/gwt/emultest/java/lang/IntegerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package com.google.gwt.emultest.java.lang;

import static com.google.gwt.emultest.java.util.EmulTestBase.assertThrows;

import com.google.gwt.junit.client.GWTTestCase;

/**
Expand Down Expand Up @@ -100,6 +102,16 @@ public void testBadStrings() {
}
}

public void testParseIntWithIndex() {
assertEquals(42, Integer.parseInt("a42", 1, 3, 10));
assertThrows(NumberFormatException.class, () ->
assertEquals(42, Integer.parseInt("bad", 1, 3, 10)));
assertThrows(StringIndexOutOfBoundsException.class, () ->
assertEquals(42, Integer.parseInt("bad", 1, 30, 10)));
assertThrows(StringIndexOutOfBoundsException.class, () ->
assertEquals(42, Integer.parseInt("bad", -1, 3, 10)));
}

public void testBinaryString() {
assertEquals("11000000111001", Integer.toBinaryString(12345));
assertEquals("0", Integer.toBinaryString(0));
Expand Down
4 changes: 4 additions & 0 deletions user/test/com/google/gwt/emultest/java/lang/SystemTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -332,5 +332,9 @@ public void testNanoTime() {
public void testCurrentTimeMillis() {
assertTrue(System.currentTimeMillis() > Date.parse("1/1/2021"));
}

public void testLineSeparator() {
assertEquals("\n", System.lineSeparator());
}
}

9 changes: 9 additions & 0 deletions user/test/com/google/gwt/emultest/java/util/EmulTestBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ public static void assertIAE(String methodName, Runnable runnable) {
}
}

public static void assertThrows(Class<? extends Exception> thrownCheck, Runnable toTest) {
try {
toTest.run();
fail("Should have failed");
} catch (Exception ex) {
assertEquals(thrownCheck, ex.getClass());
}
}

@Override
public String getModuleName() {
return "com.google.gwt.emultest.EmulSuite";
Expand Down
18 changes: 1 addition & 17 deletions user/test/com/google/gwt/emultest/java/util/ObjectsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,13 @@
*/
package com.google.gwt.emultest.java.util;

import com.google.gwt.junit.client.GWTTestCase;

import java.util.Comparator;
import java.util.Objects;

/**
* Tests {@link Objects}.
*/
public class ObjectsTest extends GWTTestCase {

@Override
public String getModuleName() {
return "com.google.gwt.emultest.EmulSuite";
}
public class ObjectsTest extends EmulTestBase {

public void testCompare() {
Comparator<Integer> intComparator = new Comparator<Integer>() {
Expand Down Expand Up @@ -167,13 +160,4 @@ public void testCheckFromIndexSize() {
assertThrows(IndexOutOfBoundsException.class,
() -> Objects.checkFromIndexSize(1, -5, 5));
}

private void assertThrows(Class<? extends Exception> thrownCheck, Runnable toTest) {
try {
toTest.run();
fail("Should have failed");
} catch (Exception ex) {
assertEquals(thrownCheck, ex.getClass());
}
}
}
40 changes: 40 additions & 0 deletions user/test/com/google/gwt/emultest/java17/util/ObjectsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2025 GWT Project Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.emultest.java17.util;

import com.google.gwt.dev.util.arg.SourceLevel;
import com.google.gwt.emultest.java.util.EmulTestBase;
import com.google.gwt.junit.JUnitShell;

public class ObjectsTest extends EmulTestBase {

public void testCheckIndex() {
assertFalse(isGwtSourceLevel17());
}

public void testCheckFromIndexSize() {
assertFalse(isGwtSourceLevel17());
}

public void testCheckFromToIndex() {
assertFalse(isGwtSourceLevel17());
}

private boolean isGwtSourceLevel17() {
return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0;
}

}
Loading