From 6a8717121261a39a966b6310c5935116609770e5 Mon Sep 17 00:00:00 2001 From: Gregory Brail Date: Wed, 27 Sep 2017 16:34:45 -0700 Subject: [PATCH] Do not treat all "Number"s as primitive types. Change WrapFactory so that the check for a "primitive type" only includes actual primitive Number subclasses and not other classes like BigInteger and BigDecimal. Include a test case for the same from @hatanaka-akihiro. --- src/org/mozilla/javascript/WrapFactory.java | 9 +- .../javascript/tests/WrapFactoryTest.java | 94 +++++++++++++++++++ 2 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 testsrc/org/mozilla/javascript/tests/WrapFactoryTest.java diff --git a/src/org/mozilla/javascript/WrapFactory.java b/src/org/mozilla/javascript/WrapFactory.java index c27be829e1..dba31ec569 100644 --- a/src/org/mozilla/javascript/WrapFactory.java +++ b/src/org/mozilla/javascript/WrapFactory.java @@ -57,8 +57,13 @@ public Object wrap(Context cx, Scriptable scope, return obj; } if (!isJavaPrimitiveWrap()) { - if (obj instanceof String || obj instanceof Number - || obj instanceof Boolean) + if (obj instanceof String || + obj instanceof Boolean || + obj instanceof Integer || + obj instanceof Short || + obj instanceof Long || + obj instanceof Float || + obj instanceof Double) { return obj; } else if (obj instanceof Character) { diff --git a/testsrc/org/mozilla/javascript/tests/WrapFactoryTest.java b/testsrc/org/mozilla/javascript/tests/WrapFactoryTest.java new file mode 100644 index 0000000000..e87c54f667 --- /dev/null +++ b/testsrc/org/mozilla/javascript/tests/WrapFactoryTest.java @@ -0,0 +1,94 @@ +package org.mozilla.javascript.tests; + +import static org.junit.Assert.assertEquals; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; + +import org.junit.Test; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.ImporterTopLevel; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; + +/** + * + * @author hatanaka + */ +public class WrapFactoryTest { + /** javascript code */ + private static String script = "var result = typeof test;" // + + "var mapResult = typeof map.get('test');" // + + "var getResult = typeof object.get();"; + + /** + * for your reference + * default setting (javaPrimitiveWrap = true) + */ + @Test + public void primitiveWrapTrue() { + test(true, "text", "string", "object", "object"); + test(true, Boolean.FALSE, "boolean", "object", "object"); + test(true, new Integer(1), "number", "object", "object"); + test(true, new Long(2L), "number", "object", "object"); + test(true, new BigInteger("3"), "number", "object", "object"); + test(true, new BigDecimal("4.0"), "number", "object", "object"); + } + + /** + * javaPrimitiveWrap = false + */ + @Test + public void primitiveWrapFalse() { + test(false, "text", "string", "string", "string"); // Great! I want to do this. + test(false, Boolean.FALSE, "boolean", "boolean", "boolean"); + test(false, new Integer(1), "number", "number", "number"); + test(false, new Long(2L), "number", "number", "number"); + + // I want to treat BigInteger / BigDecimal as BigInteger / BigDecimal. But fails. + test(false, new BigInteger("30"), "number", "object", "object"); + test(false, new BigDecimal("4.0"), "number", "object", "object"); + + // This is the best. I want not to convert to number. + //test(false, new BigInteger("30"), "object", "object", "object"); + //test(false, new BigDecimal("4.0"), "object", "object", "object"); + } + + /** + * @param javaPrimitiveWrap + * @param object + * @param result typeof value + * @param mapResult typeof map value + * @param getResult typeof getter value + */ + private void test(boolean javaPrimitiveWrap, Object object, String result, + String mapResult, String getResult) { + Context cx = Context.enter(); + try { + cx.getWrapFactory().setJavaPrimitiveWrap(javaPrimitiveWrap); + Scriptable scope = cx.initStandardObjects(new ImporterTopLevel(cx)); + + //register object + Map map = new LinkedHashMap<>(); + map.put("test", object); + ScriptableObject.putProperty(scope, "map", map); + ScriptableObject.putProperty(scope, "object", Optional.of(object)); + ScriptableObject.putProperty(scope, "test", object); + + //execute script + cx.evaluateString(scope, script, "", 1, null); + + //evaluate result + assertEquals(result, ScriptableObject.getProperty(scope, "result")); + assertEquals(mapResult, + ScriptableObject.getProperty(scope, "mapResult")); + assertEquals(getResult, + ScriptableObject.getProperty(scope, "getResult")); + } finally { + Context.exit(); + } + } +} \ No newline at end of file