diff --git a/src/org/mozilla/javascript/Context.java b/src/org/mozilla/javascript/Context.java index 383f98eec2..4a51f03c3c 100644 --- a/src/org/mozilla/javascript/Context.java +++ b/src/org/mozilla/javascript/Context.java @@ -327,6 +327,14 @@ public class Context */ public static final int FEATURE_THREAD_SAFE_OBJECTS = 17; + /** + * If set, then all integer numbers will be returned without decimal place. For instance + * assume there is a function like this: + * function foo() {return 5;} + * 5 will be returned if feature is set, 5.0 otherwise. + */ + public static final int FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE = 18; + public static final String languageVersionProperty = "language version"; public static final String errorReporterProperty = "error reporter"; diff --git a/src/org/mozilla/javascript/ContextFactory.java b/src/org/mozilla/javascript/ContextFactory.java index 97b4ed3097..9d9778d498 100644 --- a/src/org/mozilla/javascript/ContextFactory.java +++ b/src/org/mozilla/javascript/ContextFactory.java @@ -291,6 +291,9 @@ protected boolean hasFeature(Context cx, int featureIndex) case Context.FEATURE_THREAD_SAFE_OBJECTS: return false; + + case Context.FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE: + return false; } // It is a bug to call the method with unknown featureIndex throw new IllegalArgumentException(String.valueOf(featureIndex)); diff --git a/src/org/mozilla/javascript/NativeJavaObject.java b/src/org/mozilla/javascript/NativeJavaObject.java index 4432bd94fd..594d33eee1 100644 --- a/src/org/mozilla/javascript/NativeJavaObject.java +++ b/src/org/mozilla/javascript/NativeJavaObject.java @@ -516,6 +516,14 @@ else if (type == ScriptRuntime.StringClass) { return ScriptRuntime.toString(value); } else if (type == ScriptRuntime.ObjectClass) { + Context context = Context.getCurrentContext(); + if(context.hasFeature(Context.FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE)) { + //to process numbers like 2.0 as 2 without decimal place + long roundedValue = Math.round(toDouble(value)); + if(roundedValue == toDouble(value)) { + return coerceToNumber(Long.TYPE, value); + } + } return coerceToNumber(Double.TYPE, value); } else if ((type.isPrimitive() && type != Boolean.TYPE) || diff --git a/testsrc/doctests/feature18enabled.doctest b/testsrc/doctests/feature18enabled.doctest new file mode 100644 index 0000000000..50386d1c35 --- /dev/null +++ b/testsrc/doctests/feature18enabled.doctest @@ -0,0 +1,8 @@ +js> m = new java.util.LinkedHashMap(); m.put("a",1); m.put("b",2); m +{a=1, b=2} +js> for (i in Iterator(m.values())) print(i) +1 +2 +js> for (i in Iterator(m.values().iterator())) print(i) +1 +2 \ No newline at end of file diff --git a/testsrc/org/mozilla/javascript/tests/DoctestFeature18EnabledTest.java b/testsrc/org/mozilla/javascript/tests/DoctestFeature18EnabledTest.java new file mode 100644 index 0000000000..d71197d022 --- /dev/null +++ b/testsrc/org/mozilla/javascript/tests/DoctestFeature18EnabledTest.java @@ -0,0 +1,55 @@ +package org.mozilla.javascript.tests; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.ContextFactory; +import org.mozilla.javascript.tools.shell.Global; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.junit.Assert.assertTrue; + +@RunWith(Parameterized.class) +public class DoctestFeature18EnabledTest extends DoctestsTest { + public DoctestFeature18EnabledTest(String name, String source, int optimizationLevel) { + super(name, source, optimizationLevel); + } + + @Parameters(name = "{0}") + public static Collection singleDoctest() throws IOException { + List result = new ArrayList(); + File f = new File(DoctestsTest.baseDirectory, "feature18enabled.doctest"); + String contents = DoctestsTest.loadFile(f); + result.add(new Object[]{f.getName(), contents, -1}); + return result; + } + + @Test + public void runDoctest() { + ContextFactory contextFactory = new ContextFactory() { + @Override + protected boolean hasFeature(Context cx, int featureIndex) { + if (featureIndex == Context.FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE) { + return true; + } + return super.hasFeature(cx, featureIndex); + } + }; + Context context = contextFactory.enterContext(); + try { + context.setOptimizationLevel(optimizationLevel); + Global global = new Global(context); + int testsPassed = global.runDoctest(context, global, source, name, 1); + assertTrue(testsPassed > 0); + } finally { + Context.exit(); + } + } +} diff --git a/testsrc/org/mozilla/javascript/tests/DoctestsTest.java b/testsrc/org/mozilla/javascript/tests/DoctestsTest.java index a20ccb76a7..ecc7750659 100644 --- a/testsrc/org/mozilla/javascript/tests/DoctestsTest.java +++ b/testsrc/org/mozilla/javascript/tests/DoctestsTest.java @@ -48,7 +48,8 @@ public static File[] getDoctestFiles() { return TestUtils.recursiveListFiles(new File(baseDirectory), new FileFilter() { public boolean accept(File f) { - return f.getName().endsWith(doctestsExtension); + String name = f.getName(); + return !name.contains("feature18enabled") && name.endsWith(doctestsExtension); } }); }