Rolling back r8329 because it hands in IE8.

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


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8335 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/core/client/JsonUtils.java b/user/src/com/google/gwt/core/client/JsonUtils.java
index 4fd9942..c205ece 100644
--- a/user/src/com/google/gwt/core/client/JsonUtils.java
+++ b/user/src/com/google/gwt/core/client/JsonUtils.java
@@ -22,117 +22,38 @@
   @SuppressWarnings("unused")
   private static JavaScriptObject escapeTable = initEscapeTable();
 
-  @SuppressWarnings("unused")
-  private static final boolean hasJsonParse = hasJsonParse();
-
-  /**
-   * Escapes characters within a JSON string than cannot be passed directly to
-   * eval(). Control characters, quotes and backslashes are not affected.
-   */
-  public static native String escapeJsonForEval(String toEscape) /*-{
-    var s = toEscape.replace(/[\xad\u0600-\u0603\u06dd\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202e\u2060-\u2063\u206a-\u206f\ufeff\ufff9-\ufffb]/g, function(x) {
-      return @com.google.gwt.core.client.JsonUtils::escapeChar(Ljava/lang/String;)(x);
-    });
-    return s;
-  }-*/;
-
   /**
    * Returns a quoted, escaped JSON String.
    */
   public static native String escapeValue(String toEscape) /*-{
-    var s = toEscape.replace(/[\x00-\x1f\xad\u0600-\u0603\u06dd\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202e\u2060-\u2063\u206a-\u206f\ufeff\ufff9-\ufffb"\\]/g, function(x) {
+    var s = toEscape.replace(/[\x00-\x1F\u2028\u2029"\\]/g, function(x) {
       return @com.google.gwt.core.client.JsonUtils::escapeChar(Ljava/lang/String;)(x);
     });
     return "\"" + s + "\"";
   }-*/;
 
-  /**
-   * Evaluates a JSON expression safely. The payload must evaluate to an Object
-   * or an Array (not a primitive or a String).
-   * 
-   * @param <T> The type of JavaScriptObject that should be returned
-   * @param json The source JSON text
-   * @return The evaluated object
-   * 
-   * @throws IllegalArgumentException if the input is not valid JSON
+  /*
+   * TODO: Implement safeEval using a proper parser.
    */
-  public static native <T extends JavaScriptObject> T safeEval(String json) /*-{
-    var v;
-    if (@com.google.gwt.core.client.JsonUtils::hasJsonParse) {
-      try {
-        return JSON.parse(json);
-      } catch (e) {
-        return @com.google.gwt.core.client.JsonUtils::throwIllegalArgumentException(Ljava/lang/String;)("Error parsing JSON: " + e);
-      }
-    } else {
-      if (!@com.google.gwt.core.client.JsonUtils::safeToEval(Ljava/lang/String;)(json)) {
-        return @com.google.gwt.core.client.JsonUtils::throwIllegalArgumentException(Ljava/lang/String;)("Illegal character in JSON string");
-      }
-      json = @com.google.gwt.core.client.JsonUtils::escapeJsonForEval(Ljava/lang/String;)(json);
-      try {
-        return eval('(' + json + ')');
-      } catch (e) {
-        return @com.google.gwt.core.client.JsonUtils::throwIllegalArgumentException(Ljava/lang/String;)("Error parsing JSON: " + e);
-      }
-    }
-  }-*/;
-  
+
   /**
-   * Returns true if the given JSON string may be safely evaluated by {@code
-   * eval()} without undersired side effects or security risks. Note that a true
-   * result from this method does not guarantee that the input string is valid
-   * JSON.  This method does not consider the contents of quoted strings; it
-   * may still be necessary to perform escaping prior to evaluation for correct
-   * results.
-   * 
-   * <p> The technique used is taken from <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>.
-   */
-  public static native boolean safeToEval(String text) /*-{
-    // Remove quoted strings and disallow anything except:
-    //
-    // 1) symbols and brackets ,:{}[]
-    // 2) numbers: digits 0-9, ., -, +, e, and E
-    // 3) literal values: 'null', 'true' and 'false' = [aeflnr-u]
-    // 4) whitespace: ' ', '\n', '\r', and '\t'
-    return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(text.replace(/"(\\.|[^"\\])*"/g, '')));
-  }-*/;
-  
-  /**
-   * Evaluates a JSON expression using {@code eval()}. This method does not
-   * validate the JSON text and should only be used on JSON from trusted
-   * sources. The payload must evaluate to an Object or an Array (not a
-   * primitive or a String).
+   * Evaluates a JSON expression. This method does not validate the JSON text
+   * and should only be used on JSON from trusted sources.
    * 
    * @param <T> The type of JavaScriptObject that should be returned
    * @param json The source JSON text
    * @return The evaluated object
    */
   public static native <T extends JavaScriptObject> T unsafeEval(String json) /*-{
-    var escaped = @com.google.gwt.core.client.JsonUtils::escapeJsonForEval(Ljava/lang/String;)(json);
-    try {
-      return eval('(' + escaped + ')');
-    } catch (e) {
-      return @com.google.gwt.core.client.JsonUtils::throwIllegalArgumentException(Ljava/lang/String;)("Error parsing JSON: " + e);
-    }
+    return eval('(' + json + ')');
   }-*/;
 
-  static void throwIllegalArgumentException(String message) {
-    throw new IllegalArgumentException(message);
-  }
-
   @SuppressWarnings("unused")
   private static native String escapeChar(String c) /*-{
     var lookedUp = @com.google.gwt.core.client.JsonUtils::escapeTable[c.charCodeAt(0)];
     return (lookedUp == null) ? c : lookedUp;
   }-*/;
 
-  /**
-   * Returns true if the JSON.parse function is present, false otherwise.
-   */
-  private static native boolean hasJsonParse() /*-{
-    return typeof JSON == "object" && typeof JSON.parse == "function";
-  }-*/;
-
   private static native JavaScriptObject initEscapeTable() /*-{
     var out = [
       "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005",
@@ -143,40 +64,10 @@
       "\\u001E", "\\u001F"];
     out[34] = '\\"';
     out[92] = '\\\\';
-    out[0xad] = '\\u00ad'; // Soft hyphen
-    out[0x600] = '\\u0600'; // Arabic number sign
-    out[0x601] = '\\u0601'; // Arabic sign sanah
-    out[0x602] = '\\u0602'; // Arabic footnote marker
-    out[0x603] = '\\u0603'; // Arabic sign safha
-    out[0x6dd] = '\\u06dd'; // Arabic and of ayah
-    out[0x70f] = '\\u070f'; // Syriac abbreviation mark
-    out[0x17b4] = '\\u17b4'; // Khmer vowel inherent aq
-    out[0x17b5] = '\\u17b5'; // Khmer vowel inherent aa
-    out[0x200c] = '\\u200c'; // Zero width non-joiner
-    out[0x200d] = '\\u200d'; // Zero width joiner
-    out[0x200e] = '\\u200e'; // Left-to-right mark
-    out[0x200f] = '\\u200f'; // Right-to-left mark
-    out[0x2028] = '\\u2028'; // Line separator
-    out[0x2029] = '\\u2029'; // Paragraph separator
-    out[0x202a] = '\\u202a'; // Left-to-right embedding
-    out[0x202b] = '\\u202b'; // Right-to-left embedding
-    out[0x202c] = '\\u202c'; // Pop directional formatting
-    out[0x202d] = '\\u202d'; // Left-to-right override
-    out[0x202e] = '\\u202e'; // Right-to-left override
-    out[0x2060] = '\\u2060'; // Word joiner
-    out[0x2061] = '\\u2061'; // Function application
-    out[0x2062] = '\\u2062'; // Invisible times
-    out[0x2063] = '\\u2063'; // Invisible separator
-    out[0x206a] = '\\u206a'; // Inhibit symmetric swapping
-    out[0x206b] = '\\u206b'; // Activate symmetric swapping
-    out[0x206c] = '\\u206c'; // Inherent Arabic form shaping
-    out[0x206d] = '\\u206d'; // Activate Arabic form shaping
-    out[0x206e] = '\\u206e'; // National digit shapes
-    out[0x206f] = '\\u206f'; // Nominal digit shapes
-    out[0xfeff] = '\\ufeff'; // Zero width no-break space
-    out[0xfff9] = '\\ufff9'; // Intralinear annotation anchor
-    out[0xfffa] = '\\ufffa'; // Intralinear annotation separator
-    out[0xfffb] = '\\ufffb'; // Intralinear annotation terminator
+
+    // Unicode line separator chars
+    out[0x2028] = '\\u2028';
+    out[0x2029] = '\\u2029';
     return out;
   }-*/;
 
diff --git a/user/src/com/google/gwt/json/client/JSONParser.java b/user/src/com/google/gwt/json/client/JSONParser.java
index 20320dd..7b5ccd9 100644
--- a/user/src/com/google/gwt/json/client/JSONParser.java
+++ b/user/src/com/google/gwt/json/client/JSONParser.java
@@ -30,65 +30,28 @@
 
   /**
    * Evaluates a trusted JSON string and returns its JSONValue representation.
-   * CAUTION! This method calls the JavaScript <code>eval()</code> function,
-   * which can execute arbitrary script. DO NOT pass an untrusted string into
-   * this method.
-   * 
-   * <p>
-   * This method has been deprecated. Please call either
-   * {@link #parseStrict(String)} (for inputs that strictly follow the JSON
-   * specification) or {@link #parseLenient(String)}. The implementation of this
-   * method calls parseLenient.
+   * CAUTION! For efficiency, this method is implemented using the JavaScript
+   * <code>eval()</code> function, which can execute arbitrary script. DO NOT
+   * pass an untrusted string into this method.
    * 
    * @param jsonString a JSON object to parse
    * @return a JSONValue that has been built by parsing the JSON string
    * @throws NullPointerException if <code>jsonString</code> is
    *           <code>null</code>
    * @throws IllegalArgumentException if <code>jsonString</code> is empty
-   * 
-   * @deprecated use {@link #parseStrict(String)} or
-   *             {@link #parseLenient(String)}
    */
-  @Deprecated
   public static JSONValue parse(String jsonString) {
-    return parseLenient(jsonString);
-  }
-
-  /**
-   * Evaluates a trusted JSON string and returns its JSONValue representation.
-   * CAUTION! This method calls the JavaScript {@code eval()} function, which
-   * can execute arbitrary script. DO NOT pass an untrusted string into this
-   * method.
-   * 
-   * @param jsonString a JSON object to parse
-   * @return a JSONValue that has been built by parsing the JSON string
-   * @throws NullPointerException if <code>jsonString</code> is
-   *           <code>null</code>
-   * @throws IllegalArgumentException if <code>jsonString</code> is empty
-   */
-  public static JSONValue parseLenient(String jsonString) {
-    return parse(jsonString, false);
-  }
-
-  /**
-   * Evaluates a JSON string and returns its JSONValue representation. Where
-   * possible, the browser's {@code JSON.parse function} is used. For older
-   * browsers including IE6 and IE7 that lack a {@code JSON.parse} function, the
-   * input is validated as described in RFC 4627 for safety and passed to
-   * {@code eval()}.
-   * 
-   * @param jsonString a JSON object to parse
-   * @return a JSONValue that has been built by parsing the JSON string
-   * @throws NullPointerException if <code>jsonString</code> is
-   *           <code>null</code>
-   * @throws IllegalArgumentException if <code>jsonString</code> is empty
-   */
-  public static JSONValue parseStrict(String jsonString) {
-    return parse(jsonString, true);
-  }
-  
-  static void throwJSONException(String message) {
-    throw new JSONException(message);
+    if (jsonString == null) {
+      throw new NullPointerException();
+    }
+    if (jsonString.length() == 0) {
+      throw new IllegalArgumentException("empty argument");
+    }
+    try {
+      return evaluate(jsonString);
+    } catch (JavaScriptException ex) {
+      throw new JSONException(ex);
+    }
   }
 
   static void throwUnknownTypeException(String typeString) {
@@ -149,8 +112,8 @@
   }
 
   /**
-   * Called from {@link #initTypeMap()}. This method returns a <code>null</code>
-   * pointer, representing JavaScript <code>undefined</code>.
+   * Called from {@link #initTypeMap()}. This method returns a
+   * <code>null</code> pointer, representing JavaScript <code>undefined</code>.
    */
   @SuppressWarnings("unused")
   private static JSONValue createUndefined() {
@@ -159,39 +122,9 @@
 
   /**
    * This method converts <code>jsonString</code> into a JSONValue.
-   * In strict mode (strict == true), one of two code paths is taken:
-   * 1) Call JSON.parse if available, or
-   * 2) Validate the input and call eval()
-   * 
-   * In lenient mode (strict == false), eval() is called without validation.
-   * 
-   * @param strict if true, parse in strict mode. 
    */
-  private static native JSONValue evaluate(String json, boolean strict) /*-{
-    // Note: we cannot simply call JsonUtils.unsafeEval because it is unable
-    // to return a result for inputs whose outermost type is 'string' in
-    // dev mode.
-    var v;
-    if (strict && @com.google.gwt.core.client.JsonUtils::hasJsonParse) {
-      try {
-        v = JSON.parse(json);
-      } catch (e) {
-        return @com.google.gwt.json.client.JSONParser::throwJSONException(Ljava/lang/String;)("Error parsing JSON: " + e);
-      }
-    } else {
-      if (strict) {
-        // Validate the input according to RFC 4627.
-        if (!@com.google.gwt.core.client.JsonUtils::safeToEval(Ljava/lang/String;)(json)) {
-          return @com.google.gwt.json.client.JSONParser::throwJSONException(Ljava/lang/String;)("Illegal character in JSON string");
-        }
-      }
-      json = @com.google.gwt.core.client.JsonUtils::escapeJsonForEval(Ljava/lang/String;)(json);
-      try {
-        v = eval('(' + json + ')');
-      } catch (e) { 
-        return @com.google.gwt.json.client.JSONParser::throwJSONException(Ljava/lang/String;)("Error parsing JSON: " + e);
-      }
-    }
+  private static native JSONValue evaluate(String jsonString) /*-{
+    var v = eval('(' + jsonString + ')');
     var func = @com.google.gwt.json.client.JSONParser::typeMap[typeof v];
     return func ? func(v) : @com.google.gwt.json.client.JSONParser::throwUnknownTypeException(Ljava/lang/String;)(typeof v);
   }-*/;
@@ -207,20 +140,6 @@
     }
   }-*/;
 
-  private static JSONValue parse(String jsonString, boolean strict) {
-    if (jsonString == null) {
-      throw new NullPointerException();
-    }
-    if (jsonString.length() == 0) {
-      throw new IllegalArgumentException("empty argument");
-    }
-    try {
-      return evaluate(jsonString, strict);
-    } catch (JavaScriptException ex) {
-      throw new JSONException(ex);
-    }
-  }
-
   /**
    * Not instantiable.
    */
diff --git a/user/test/com/google/gwt/json/client/JSONTest.java b/user/test/com/google/gwt/json/client/JSONTest.java
index 340c362..ba639cd 100644
--- a/user/test/com/google/gwt/json/client/JSONTest.java
+++ b/user/test/com/google/gwt/json/client/JSONTest.java
@@ -15,7 +15,6 @@
  */
 package com.google.gwt.json.client;
 
-import com.google.gwt.core.client.JsonUtils;
 import com.google.gwt.junit.client.GWTTestCase;
 
 import java.util.Set;
@@ -141,7 +140,7 @@
       arr.set(i, new JSONNumber(i));
     }
     String s = arr.toString();
-    JSONValue v = parseStrictVsLenient(s);
+    JSONValue v = JSONParser.parse(s);
     JSONArray array = v.isArray();
     assertTrue("v must be an array", array != null);
     assertEquals("Array size must be 10", 10, array.size());
@@ -155,17 +154,17 @@
     assertTrue(JSONBoolean.getInstance(true).booleanValue());
     assertFalse(JSONBoolean.getInstance(false).booleanValue());
 
-    JSONValue trueVal = parseStrictVsLenient("true");
+    JSONValue trueVal = JSONParser.parse("true");
     assertEquals(trueVal, trueVal.isBoolean());
     assertTrue(trueVal.isBoolean().booleanValue());
 
-    JSONValue falseVal = parseStrictVsLenient("false");
+    JSONValue falseVal = JSONParser.parse("false");
     assertEquals(falseVal, falseVal.isBoolean());
     assertFalse(falseVal.isBoolean().booleanValue());
   }
 
   public void testEquals() {
-    JSONArray array = parseStrictVsLenient("[]").isArray();
+    JSONArray array = JSONParser.parse("[]").isArray();
     assertEquals(array, new JSONArray(array.getJavaScriptObject()));
 
     assertEquals(JSONBoolean.getInstance(false), JSONBoolean.getInstance(false));
@@ -175,11 +174,33 @@
 
     assertEquals(new JSONNumber(3.1), new JSONNumber(3.1));
 
-    JSONObject object = parseStrictVsLenient("{}").isObject();
+    JSONObject object = JSONParser.parse("{}").isObject();
     assertEquals(object, new JSONObject(object.getJavaScriptObject()));
 
     assertEquals(new JSONString("foo"), new JSONString("foo"));
   }
+  
+  public void testHashCode() {
+    JSONArray array = JSONParser.parse("[]").isArray();
+    assertHashCodeEquals(array, new JSONArray(array.getJavaScriptObject()));
+
+    assertHashCodeEquals(JSONBoolean.getInstance(false), JSONBoolean.getInstance(false));
+    assertHashCodeEquals(JSONBoolean.getInstance(true), JSONBoolean.getInstance(true));
+
+    assertHashCodeEquals(JSONNull.getInstance(), JSONNull.getInstance());
+
+    assertHashCodeEquals(new JSONNumber(3.1), new JSONNumber(3.1));
+
+    JSONObject object = JSONParser.parse("{}").isObject();
+    assertHashCodeEquals(object, new JSONObject(object.getJavaScriptObject()));
+
+    assertHashCodeEquals(new JSONString("foo"), new JSONString("foo"));
+  }
+
+  private void assertHashCodeEquals(Object expected, Object actual) {
+    assertEquals("hashCodes are not equal", expected.hashCode(),
+        actual.hashCode());
+  }
 
   // Null characters do not work in hosted mode
   public void testEscaping() {
@@ -217,23 +238,6 @@
         + "\"c39\":\"/\", \"c40\":\"\\u2028\", \"c41\":\"\\u2029\"}", o.toString());
   }
 
-  public void testHashCode() {
-    JSONArray array = parseStrictVsLenient("[]").isArray();
-    assertHashCodeEquals(array, new JSONArray(array.getJavaScriptObject()));
-
-    assertHashCodeEquals(JSONBoolean.getInstance(false), JSONBoolean.getInstance(false));
-    assertHashCodeEquals(JSONBoolean.getInstance(true), JSONBoolean.getInstance(true));
-
-    assertHashCodeEquals(JSONNull.getInstance(), JSONNull.getInstance());
-
-    assertHashCodeEquals(new JSONNumber(3.1), new JSONNumber(3.1));
-
-    JSONObject object = parseStrictVsLenient("{}").isObject();
-    assertHashCodeEquals(object, new JSONObject(object.getJavaScriptObject()));
-
-    assertHashCodeEquals(new JSONString("foo"), new JSONString("foo"));
-  }
-
   public void testLargeArrays() {
     JSONArray arr = null;
     for (int j = 1; j < 500; j *= 2) {
@@ -242,33 +246,8 @@
     }
   }
 
-  public void testLenientAndStrict() {
-    String jsonString = "{ a:27, 'b': 'value' }";
-    
-    // parseLenient should succeed
-    JSONValue value = JSONParser.parseLenient(jsonString);
-    JSONObject object = value.isObject();
-    assertEquals(27.0, object.get("a").isNumber().doubleValue());
-    assertEquals("value", object.get("b").isString().stringValue());
-    
-    // parseStrict should fail
-    try {
-      parseStrictVsLenient(jsonString);
-      fail();
-    } catch (JSONException e) {
-    }
-    
-    // Must fail even on browsers that lack JSON.parse()
-    jsonString = "function f() { return 5; }";
-    try {
-      parseStrictVsLenient(jsonString);
-      fail();
-    } catch (JSONException e) {
-    }
-  }
-  
   public void testMenu() {
-    JSONObject v = (JSONObject) parseStrictVsLenient(menuTest);
+    JSONObject v = (JSONObject) JSONParser.parse(menuTest);
     assertTrue(v.containsKey("menu"));
     JSONObject menu = ((JSONObject) v.get("menu"));
     assertEquals(3, menu.keySet().size());
@@ -278,7 +257,7 @@
     JSONObject obj = new JSONObject();
     nestedAux(obj, 3);
     String s1 = obj.toString();
-    String s2 = parseStrictVsLenient(s1).toString();
+    String s2 = JSONParser.parse(s1).toString();
     assertEquals(s1, s2);
     assertEquals(
         "{\"string3\":\"s3\", \"Number3\":3.1, \"Boolean3\":false, "
@@ -352,7 +331,7 @@
       obj.put("Object " + i, new JSONNumber(i));
     }
     String s = obj.toString();
-    JSONValue v = parseStrictVsLenient(s);
+    JSONValue v = JSONParser.parse(s);
     JSONObject objIn = v.isObject();
     assertTrue("v must be an object", objIn != null);
     assertEquals("Object size must be 10", 10, objIn.keySet().size());
@@ -372,27 +351,27 @@
     } catch (NullPointerException t) {
     }
     try {
-      parseStrictVsLenient(null);
+      JSONParser.parse(null);
       fail();
     } catch (NullPointerException t) {
     }
     try {
-      parseStrictVsLenient("");
+      JSONParser.parse("");
       fail();
     } catch (IllegalArgumentException t) {
     }
     try {
-      parseStrictVsLenient("{\"menu\": {\n" + "  \"id\": \"file\",\n");
+      JSONParser.parse("{\"menu\": {\n" + "  \"id\": \"file\",\n");
       fail();
     } catch (JSONException e) {
     }
     assertEquals("\"null\" should be null JSONValue", JSONNull.getInstance(),
-        parseStrictVsLenient("null"));
+        JSONParser.parse("null"));
     assertEquals("5 should be JSONNumber 5", 5d,
-        parseStrictVsLenient("5").isNumber().doubleValue(), 0.001);
+        JSONParser.parse("5").isNumber().doubleValue(), 0.001);
     assertEquals("\"null\" should be null JSONValue", JSONNull.getInstance(),
-        parseStrictVsLenient("null"));
-    JSONValue somethingHello = parseStrictVsLenient("[{\"something\":\"hello\"}]");
+        JSONParser.parse("null"));
+    JSONValue somethingHello = JSONParser.parse("[{\"something\":\"hello\"}]");
     JSONArray somethingHelloArray = somethingHello.isArray();
     assertTrue("somethingHello must be a JSONArray",
         somethingHelloArray != null);
@@ -414,108 +393,11 @@
 
     String toString = obj.toString();
     assertEquals("{\"a\":42, \"\\\\\":43.5, \"\\\"\":44}", toString.trim());
-    JSONValue parseResponse = parseStrictVsLenient(toString);
+    JSONValue parseResponse = JSONParser.parse(toString);
     JSONObject obj2 = parseResponse.isObject();
     assertJSONObjectEquals(obj, obj2);
   }
 
-  // Break up long test into smaller chunks
-  public void testParseUnescaped0() {
-    for (int i = 0x20; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescaped1() {
-    for (int i = 0x20 + 1; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescaped2() {
-    for (int i = 0x20 + 2; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescaped3() {
-    for (int i = 0x20 + 3; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescaped4() {
-    for (int i = 0x20 + 4; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescaped5() {
-    for (int i = 0x20 + 5; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescaped6() {
-    for (int i = 0x20 + 6; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescaped7() {
-    for (int i = 0x20 + 7; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescaped8() {
-    for (int i = 0x20 + 8; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescaped9() {
-    for (int i = 0x20 + 9; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescapeda() {
-    for (int i = 0x20 + 10; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescapedb() {
-    for (int i = 0x20 + 11; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescapedc() {
-    for (int i = 0x20 + 12; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescapedd() {
-    for (int i = 0x20 + 13; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescapede() {
-    for (int i = 0x20 + 14; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
-  public void testParseUnescapedf() {
-    for (int i = 0x20 + 15; i <= 0xffff; i += 16) {
-      doTestParseUnescaped(i);
-    }
-  }
-
   public void testSimpleNested() {
     JSONObject j1 = new JSONObject();
     j1.put("test1", new JSONString(""));
@@ -551,7 +433,7 @@
   }
 
   public void testStringTypes() {
-    JSONObject object = parseStrictVsLenient("{\"a\":\"b\",\"null\":\"foo\"}").isObject();
+    JSONObject object = JSONParser.parse("{\"a\":\"b\",\"null\":\"foo\"}").isObject();
     assertNotNull(object);
 
     assertEquals("b",
@@ -570,7 +452,7 @@
   }
 
   public void testUndefined() {
-    JSONObject o = parseStrictVsLenient("{\"foo\":\"foo\",\"bar\":null}").isObject();
+    JSONObject o = JSONParser.parse("{foo:'foo',bar:null}").isObject();
     assertEquals(new JSONString("foo"), o.get("foo"));
     assertEquals(JSONNull.getInstance(), o.get("bar"));
     assertNull(o.get("baz"));
@@ -580,7 +462,7 @@
     o.put("foo", null);
     assertNull(o.get("foo"));
 
-    JSONArray array = parseStrictVsLenient("[\"foo\",null]").isArray();
+    JSONArray array = JSONParser.parse("['foo',null]").isArray();
     assertEquals(new JSONString("foo"), array.get(0));
     assertEquals(JSONNull.getInstance(), array.get(1));
     assertNull(array.get(2));
@@ -591,61 +473,8 @@
     assertNull(array.get(0));
   }
 
-  public void testUnicodeSeparators() {
-    /*
-     * ECMAScript 5 allows unescaped U+2028 (line separator) and U+2029
-     * (paragraph separator) characters to occur inside strings.
-     */
-    String jsonString = "{ \"name\": \"miles\u2028da\u2029vis\", \"ins\u2028tru\u2029ment\": \"trumpet\" }";
-    try {
-      JSONValue parsed = parseStrictVsLenient(jsonString);
-      JSONObject result = parsed.isObject();
-      assertNotNull(result);
-
-      JSONValue nameValue = result.get("name");
-      assertNotNull(nameValue);
-      JSONString nameJsonString = nameValue.isString();
-      assertNotNull(nameJsonString);
-      String nameString = nameJsonString.stringValue();
-      assertEquals("miles\u2028da\u2029vis", nameString);
-      String nameStringQuoted = nameJsonString.toString();
-      assertEquals("\"miles\\u2028da\\u2029vis\"", nameStringQuoted);
-
-      JSONValue instrumentValue = result.get("ins\u2028tru\u2029ment");
-      assertNotNull(instrumentValue);
-      JSONValue instrumentValue2 = result.get("instrument");
-      assertNull(instrumentValue2); // check no name collision
-      JSONString instrumentJsonString = instrumentValue.isString();
-      assertNotNull(instrumentJsonString);
-      String instrumentString = instrumentJsonString.stringValue();
-      assertEquals("trumpet", instrumentString);
-    } catch (JSONException e) {
-      fail(e.getMessage());
-    }
-
-    // U+2028 and U+2029 should not appear outside a string
-    jsonString = "{ \"name\": \"miles davis\",\u2028\"instrument\": \"trumpet\" }";
-    try {
-      parseStrictVsLenient(jsonString);
-      fail();
-    } catch (JSONException e) {
-    }
-
-    jsonString = "{ \"name\":\u2029\"miles davis\", \"instrument\": \"trumpet\" }";
-    try {
-      parseStrictVsLenient(jsonString);
-      fail();
-    } catch (JSONException e) {
-    }
-  }
-
-  public void testUnsafeEval() {
-    JsonUtils.unsafeEval("{\"name\":\"value\"}");
-    JsonUtils.unsafeEval("[0,1,2,3,4]");
-  }
-  
   public void testWidget() {
-    JSONObject v = (JSONObject) parseStrictVsLenient(widgetTest);
+    JSONObject v = (JSONObject) JSONParser.parse(widgetTest);
     JSONObject widget = (JSONObject) v.get("widget");
     JSONObject window = (JSONObject) widget.get("window");
     JSONValue title = window.get("title");
@@ -654,13 +483,8 @@
     assertNotNull(hOffSet.isNumber());
   }
 
-  private void assertHashCodeEquals(Object expected, Object actual) {
-    assertEquals("hashCodes are not equal", expected.hashCode(),
-        actual.hashCode());
-  }
-
   private void checkRoundTripJsonText(String jsonText, String normaltext) {
-    JSONString parsed = parseStrictVsLenient(jsonText).isString();
+    JSONString parsed = JSONParser.parse(jsonText).isString();
     assertEquals(normaltext, parsed.stringValue());
     assertEquals(jsonText, parsed.toString());
   }
@@ -673,36 +497,6 @@
     return arr;
   }
 
-  private void doTestParseUnescaped(int i) {
-    // Skip surrogate pairs
-    if (i >= 0xD800 && i <= 0xDFFF) {
-      return;
-    }
-    char c = (char) i;
-    if (c == '\"' || c == '\\') {
-      return;
-    }
-
-    String key = "na" + c + "me";
-    String value = "miles" + c + "davis";
-    String jsonString = "{ \"" + key + "\": \"" + value + "\"}";
-    try {
-      JSONValue parsed = parseStrictVsLenient(jsonString);
-      JSONObject result = parsed.isObject();
-      assertNotNull("i = " + i, result);
-      Set<String> keys = result.keySet();
-      assertTrue("i = " + i, keys.contains(key));
-      JSONValue nameValue = result.get(key);
-      assertNotNull("i = " + i, nameValue);
-      JSONString nameJsonString = nameValue.isString();
-      assertNotNull("i = " + i, nameJsonString);
-      String nameString = nameJsonString.stringValue();
-      assertEquals("i = " + i, value, nameString);
-    } catch (JSONException e) {
-      fail("i = " + i + ", e = " + e.getMessage());
-    }
-  }
-
   private void nestedAux(JSONObject obj, int i) {
     JSONArray array = new JSONArray();
     JSONString str = new JSONString("s" + i);
@@ -726,14 +520,6 @@
     obj.put("Array" + i, array);
   }
 
-  // Check that parseLenient produces the same results as parseStrict
-  private JSONValue parseStrictVsLenient(String jsonString) {
-    JSONValue strictValue = JSONParser.parseStrict(jsonString);
-    JSONValue lenientValue = JSONParser.parseLenient(jsonString);
-    assertJSONValueEquals(strictValue, lenientValue);
-    return strictValue;
-  }
-
   private JSONArray populateRecursiveArray(int numElements, int recursion) {
     JSONArray newArray = new JSONArray();
     if (recursion <= 0) {