Fix external issue 4772 (com.google.gwt.user.client.ui.UIObject.setHeight("1em") causes an assert error with rhino)
Tighten the regex defining a number (the old one could accept inputs such as '.' and 'e5')

Review at http://gwt-code-reviews.appspot.com/271801

Review by: scottb@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7791 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/UIObject.java b/user/src/com/google/gwt/user/client/ui/UIObject.java
index 9e29a3c..cfc93d0 100644
--- a/user/src/com/google/gwt/user/client/ui/UIObject.java
+++ b/user/src/com/google/gwt/user/client/ui/UIObject.java
@@ -16,6 +16,7 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.user.client.DOM;
 
@@ -123,6 +124,13 @@
  */
 public abstract class UIObject {
 
+  /**
+   * Stores a regular expression object to extract float values from the
+   * leading portion of an input string.
+   */
+  @SuppressWarnings("unused")
+  private static JavaScriptObject numberRegex;
+
   /*
    * WARNING: For historical reasons, there are two Element classes being used
    * in this code. The dom.Element (com.google.gwt.dom.client.Element) class is
@@ -817,8 +825,7 @@
   }
 
   /**
-   * Intended to be used to pull the value out of a CSS length. We rely on the
-   * behavior of parseFloat to ignore non-numeric chars in its input. If the
+   * Intended to be used to pull the value out of a CSS length. If the
    * value is "auto" or "inherit", 0 will be returned.
    * 
    * @param s The CSS length string to extract
@@ -829,6 +836,17 @@
     if (s == "auto" || s == "inherit" || s == "") {
       return 0;
     } else {
+      // numberRegex is similar to java.lang.Number.floatRegex, but divides
+      // the string into a leading numeric portion followed by an arbitrary
+      // portion.
+      var numberRegex = @com.google.gwt.user.client.ui.UIObject::numberRegex;
+      if (!numberRegex) {
+        numberRegex = @com.google.gwt.user.client.ui.UIObject::numberRegex =
+          /^(\s*[+-]?((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+)?)(.*)$/;
+      }
+
+      // Extract the leading numeric portion of s
+      s = s.replace(numberRegex, "$1");
       return parseFloat(s);
     }
   }-*/;
diff --git a/user/super/com/google/gwt/emul/java/lang/Number.java b/user/super/com/google/gwt/emul/java/lang/Number.java
index b96270b..810df15 100644
--- a/user/super/com/google/gwt/emul/java/lang/Number.java
+++ b/user/super/com/google/gwt/emul/java/lang/Number.java
@@ -164,7 +164,8 @@
   private static native double __parseDouble(String str) /*-{
     var floatRegex = @java.lang.Number::floatRegex;
     if (!floatRegex) {
-      floatRegex = @java.lang.Number::floatRegex = /^\s*[+-]?\d*\.?\d*([eE][+-]?\d+)?\s*$/i;
+      // Disallow '.' with no digits on either side
+      floatRegex = @java.lang.Number::floatRegex = /^\s*[+-]?((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+)?\s*$/i;
     }
     if (floatRegex.test(str)) {
       return parseFloat(str);
diff --git a/user/test/com/google/gwt/emultest/java/lang/DoubleTest.java b/user/test/com/google/gwt/emultest/java/lang/DoubleTest.java
index 4440997..d97f2fb 100644
--- a/user/test/com/google/gwt/emultest/java/lang/DoubleTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/DoubleTest.java
@@ -43,6 +43,34 @@
     }
 
     try {
+      Double.parseDouble(".");
+      fail("parse");
+    } catch (NumberFormatException e) {
+      // Expected behavior
+    }
+
+    try {
+      Double.parseDouble(".e");
+      fail("parse");
+    } catch (NumberFormatException e) {
+      // Expected behavior
+    }
+
+    try {
+      Double.parseDouble("e5");
+      fail("parse");
+    } catch (NumberFormatException e) {
+      // Expected behavior
+    }
+
+    try {
+      Double.parseDouble(".e5");
+      fail("parse");
+    } catch (NumberFormatException e) {
+      // Expected behavior
+    }
+
+    try {
       Double.valueOf("0x0e");
       fail("valueOf");
     } catch (NumberFormatException e) {
@@ -66,6 +94,8 @@
 
   public void testParse() {
     assertTrue(0 == Double.parseDouble("0"));
+    assertTrue(100 == Double.parseDouble("1e2"));
+    assertTrue(-100 == Double.parseDouble("-1e2"));
     assertTrue(-1.5 == Double.parseDouble("-1.5"));
     assertTrue(3.0 == Double.parseDouble("3."));
     assertTrue(0.5 == Double.parseDouble(".5"));