diff --git a/src/main/java/com/caoccao/javet/swc4j/ast/expr/lit/Swc4jAstNumber.java b/src/main/java/com/caoccao/javet/swc4j/ast/expr/lit/Swc4jAstNumber.java index 9e37a01b..2f845c17 100644 --- a/src/main/java/com/caoccao/javet/swc4j/ast/expr/lit/Swc4jAstNumber.java +++ b/src/main/java/com/caoccao/javet/swc4j/ast/expr/lit/Swc4jAstNumber.java @@ -34,11 +34,11 @@ public class Swc4jAstNumber extends Swc4jAst implements ISwc4jAstLit, ISwc4jAstPropName, ISwc4jAstTsLit, ISwc4jAstCoercionPrimitive { - protected static final Pattern PATTERN_ALL_ZEROS = - Pattern.compile("^0+$", Pattern.CASE_INSENSITIVE); protected static final Pattern PATTERN_DECIMAL_ZEROS = Pattern.compile("^(\\d+)\\.0*$", Pattern.CASE_INSENSITIVE); - protected static final Pattern PATTERN_SCIENTIFIC_NOTATION = + protected static final Pattern PATTERN_SCIENTIFIC_NOTATION_WITHOUT_FRACTION = + Pattern.compile("^(\\d+)e([\\+\\-]?)(\\d+)$", Pattern.CASE_INSENSITIVE); + protected static final Pattern PATTERN_SCIENTIFIC_NOTATION_WITH_FRACTION = Pattern.compile("^(\\d+)\\.(\\d*)e([\\+\\-]?)(\\d+)$", Pattern.CASE_INSENSITIVE); @Jni2RustField(componentAtom = true) protected Optional raw; @@ -59,24 +59,57 @@ public static Swc4jAstNumber create(int value) { } public static Swc4jAstNumber create(double value) { - return new Swc4jAstNumber(value, getNormalizedNumberString(Double.toString(value)), Swc4jSpan.DUMMY); + return new Swc4jAstNumber(value, null, Swc4jSpan.DUMMY); } public static Swc4jAstNumber create(double value, String raw) { return new Swc4jAstNumber(value, raw, Swc4jSpan.DUMMY); } - protected static String getNormalizedNumberString(String raw) { - Matcher matcher = PATTERN_SCIENTIFIC_NOTATION.matcher(raw); + public static String getNormalizedNumberString(String raw) { + Matcher matcher = PATTERN_SCIENTIFIC_NOTATION_WITH_FRACTION.matcher(raw); if (matcher.matches()) { String sign = StringUtils.isEmpty(matcher.group(3)) ? "+" : matcher.group(3); - if (StringUtils.isEmpty(matcher.group(2))) { - return matcher.group(1) + "e" + sign + matcher.group(4); - } else if (PATTERN_ALL_ZEROS.matcher(matcher.group(2)).matches()) { - return matcher.group(1) + "e" + sign + matcher.group(4); - } else { - return matcher.group(1) + "." + matcher.group(2) + "e" + sign + matcher.group(4); + String integer = matcher.group(1); + String fraction = matcher.group(2); + int additionalExponent = 0; + while (fraction.endsWith("0")) { + fraction = fraction.substring(0, fraction.length() - 1); } + while (integer.startsWith("0")) { + integer = integer.substring(1); + } + if (integer.length() > 1) { + additionalExponent += integer.length() - 1; + fraction = integer.substring(1) + fraction; + integer = integer.substring(0, 1); + } + if (StringUtils.isNotEmpty(fraction)) { + fraction = "." + fraction; + } + long exponent = Long.parseLong(matcher.group(4)) + additionalExponent; + return integer + fraction + "e" + sign + exponent; + } + matcher = PATTERN_SCIENTIFIC_NOTATION_WITHOUT_FRACTION.matcher(raw); + if (matcher.matches()) { + String sign = StringUtils.isEmpty(matcher.group(2)) ? "+" : matcher.group(2); + String integer = matcher.group(1); + String fraction = ""; + int additionalExponent = 0; + while (integer.startsWith("0")) { + integer = integer.substring(1); + } + while (integer.endsWith("0")) { + ++additionalExponent; + integer = integer.substring(0, integer.length() - 1); + } + if (integer.length() > 1) { + additionalExponent += integer.length() - 1; + fraction = "." + integer.substring(1); + integer = integer.substring(0, 1); + } + long exponent = Long.parseLong(matcher.group(3)) + additionalExponent; + return integer + fraction + "e" + sign + exponent; } matcher = PATTERN_DECIMAL_ZEROS.matcher(raw); if (matcher.matches()) { @@ -122,7 +155,7 @@ public short asShort() { @Override public String asString() { - return getNormalizedNumberString(Double.toString(value)); + return toString(); } @Override @@ -162,7 +195,7 @@ public Swc4jAstNumber setValue(double value) { @Override public String toString() { - return raw.orElse(Double.toString(value)); + return getNormalizedNumberString(raw.orElse(Double.toString(value))); } @Override diff --git a/src/main/java/com/caoccao/javet/swc4j/plugins/jsfuck/Swc4jPluginVisitorJsFuckDecoder.java b/src/main/java/com/caoccao/javet/swc4j/plugins/jsfuck/Swc4jPluginVisitorJsFuckDecoder.java index c1c2fd21..98f8bfe5 100644 --- a/src/main/java/com/caoccao/javet/swc4j/plugins/jsfuck/Swc4jPluginVisitorJsFuckDecoder.java +++ b/src/main/java/com/caoccao/javet/swc4j/plugins/jsfuck/Swc4jPluginVisitorJsFuckDecoder.java @@ -135,17 +135,17 @@ public Swc4jAstVisitorResponse visitUnaryExpr(Swc4jAstUnaryExpr node) { break; case Number: { Swc4jAstNumber number = arg.as(Swc4jAstNumber.class); - newNode = Swc4jAstNumber.create(number.getValue()); + newNode = Swc4jAstNumber.create(number.getValue(), number.getRaw().orElse(null)); } break; case Str: { - Swc4jAstStr str = arg.as(Swc4jAstStr.class); + double value; try { - double value = Double.parseDouble(str.getValue()); - newNode = Swc4jAstNumber.create(value); + value = Double.parseDouble(arg.as(Swc4jAstStr.class).getValue()); } catch (Throwable t) { - newNode = Swc4jAstNumber.create(Double.NaN); + value = Double.NaN; } + newNode = Swc4jAstNumber.create(value); } break; default: diff --git a/src/test/java/com/caoccao/javet/swc4j/ast/expr/lit/TestSwc4jAstNumber.java b/src/test/java/com/caoccao/javet/swc4j/ast/expr/lit/TestSwc4jAstNumber.java index da70b8b7..43e817cc 100644 --- a/src/test/java/com/caoccao/javet/swc4j/ast/expr/lit/TestSwc4jAstNumber.java +++ b/src/test/java/com/caoccao/javet/swc4j/ast/expr/lit/TestSwc4jAstNumber.java @@ -31,9 +31,14 @@ public class TestSwc4jAstNumber extends BaseTestSuiteSwc4jAst { public void testCoercion() { assertEquals("0", Swc4jAstNumber.create(0).getRaw().get()); assertEquals("1", Swc4jAstNumber.create(1).getRaw().get()); - assertEquals("1.1", Swc4jAstNumber.create(1.1D).getRaw().get()); + assertEquals("1.1", Swc4jAstNumber.create(1.1D).toString()); + assertEquals("1.1e+20", Swc4jAstNumber.create(1.1e20D).toString()); + assertEquals("1.23e+21", Swc4jAstNumber.create(12.30e20D).toString()); + assertEquals("1.234e+21", Swc4jAstNumber.create(12.340e20D, "12.340e20").toString()); + assertEquals("1.234e+21", Swc4jAstNumber.create(12.340e20D, "012.34000e20").toString()); + assertEquals("1.1e-20", Swc4jAstNumber.create(1.1e-20D).toString()); assertEquals(1, Swc4jAstNumber.create(1.1D).asInt()); - assertEquals("NaN", Swc4jAstNumber.create(Double.NaN).getRaw().get()); + assertEquals("NaN", Swc4jAstNumber.create(Double.NaN).toString()); assertEquals(0, Swc4jAstNumber.create(Double.NaN).asInt()); }