Blame SOURCES/rhino-backout-686806.patch

b82361
diff --git a/src/org/mozilla/javascript/json/JsonParser.java b/src/org/mozilla/javascript/json/JsonParser.java
b82361
index 5079502..0c06d26 100644
b82361
--- a/src/org/mozilla/javascript/json/JsonParser.java
b82361
+++ b/src/org/mozilla/javascript/json/JsonParser.java
b82361
@@ -86,23 +86,15 @@ public class JsonParser {
b82361
     }
b82361
 
b82361
     private Object readObject() throws ParseException {
b82361
-        consumeWhitespace();
b82361
         Scriptable object = cx.newObject(scope);
b82361
-        // handle empty object literal case early
b82361
-        if (pos < length && src.charAt(pos) == '}') {
b82361
-            pos += 1;
b82361
-            return object;
b82361
-        }
b82361
         String id;
b82361
         Object value;
b82361
         boolean needsComma = false;
b82361
+        consumeWhitespace();
b82361
         while (pos < length) {
b82361
             char c = src.charAt(pos++);
b82361
             switch(c) {
b82361
                 case '}':
b82361
-                    if (!needsComma) {
b82361
-                        throw new ParseException("Unexpected comma in object literal");
b82361
-                    }
b82361
                     return object;
b82361
                 case ',':
b82361
                     if (!needsComma) {
b82361
@@ -136,21 +128,13 @@ public class JsonParser {
b82361
     }
b82361
 
b82361
     private Object readArray() throws ParseException {
b82361
-        consumeWhitespace();
b82361
-        // handle empty array literal case early
b82361
-        if (pos < length && src.charAt(pos) == ']') {
b82361
-            pos += 1;
b82361
-            return cx.newArray(scope, 0);
b82361
-        }
b82361
         List<Object> list = new ArrayList<Object>();
b82361
         boolean needsComma = false;
b82361
+        consumeWhitespace();
b82361
         while (pos < length) {
b82361
             char c = src.charAt(pos);
b82361
             switch(c) {
b82361
                 case ']':
b82361
-                    if (!needsComma) {
b82361
-                        throw new ParseException("Unexpected comma in array literal");
b82361
-                    }
b82361
                     pos += 1;
b82361
                     return cx.newArray(scope, list.toArray());
b82361
                 case ',':
b82361
@@ -173,166 +157,108 @@ public class JsonParser {
b82361
     }
b82361
 
b82361
     private String readString() throws ParseException {
b82361
-        /*
b82361
-         * Optimization: if the source contains no escaped characters, create the
b82361
-         * string directly from the source text.
b82361
-         */
b82361
-        int stringStart = pos;
b82361
+        StringBuilder b = new StringBuilder();
b82361
         while (pos < length) {
b82361
             char c = src.charAt(pos++);
b82361
             if (c <= '\u001F') {
b82361
                 throw new ParseException("String contains control character");
b82361
-            } else if (c == '\\') {
b82361
-                break;
b82361
-            } else if (c == '"') {
b82361
-                return src.substring(stringStart, pos - 1);
b82361
             }
b82361
-        }
b82361
-
b82361
-        /*
b82361
-         * Slow case: string contains escaped characters.  Copy a maximal sequence
b82361
-         * of unescaped characters into a temporary buffer, then an escaped
b82361
-         * character, and repeat until the entire string is consumed.
b82361
-         */
b82361
-        StringBuilder b = new StringBuilder();
b82361
-        while (pos < length) {
b82361
-            assert src.charAt(pos - 1) == '\\';
b82361
-            b.append(src, stringStart, pos - 1);
b82361
-            if (pos >= length) {
b82361
-                throw new ParseException("Unterminated string");
b82361
-            }
b82361
-            char c = src.charAt(pos++);
b82361
-            switch (c) {
b82361
-                case '"':
b82361
-                    b.append('"');
b82361
-                    break;
b82361
+            switch(c) {
b82361
                 case '\\':
b82361
-                    b.append('\\');
b82361
-                    break;
b82361
-                case '/':
b82361
-                    b.append('/');
b82361
-                    break;
b82361
-                case 'b':
b82361
-                    b.append('\b');
b82361
-                    break;
b82361
-                case 'f':
b82361
-                    b.append('\f');
b82361
-                    break;
b82361
-                case 'n':
b82361
-                    b.append('\n');
b82361
-                    break;
b82361
-                case 'r':
b82361
-                    b.append('\r');
b82361
-                    break;
b82361
-                case 't':
b82361
-                    b.append('\t');
b82361
-                    break;
b82361
-                case 'u':
b82361
-                    if (length - pos < 5) {
b82361
-                        throw new ParseException("Invalid character code: \\u" + src.substring(pos));
b82361
+                    if (pos >= length) {
b82361
+                        throw new ParseException("Unterminated string");
b82361
                     }
b82361
-                    int code = fromHex(src.charAt(pos + 0)) << 12
b82361
-                             | fromHex(src.charAt(pos + 1)) << 8
b82361
-                             | fromHex(src.charAt(pos + 2)) << 4
b82361
-                             | fromHex(src.charAt(pos + 3));
b82361
-                    if (code < 0) {
b82361
-                        throw new ParseException("Invalid character code: " + src.substring(pos, pos + 4));
b82361
+                    c = src.charAt(pos++);
b82361
+                    switch (c) {
b82361
+                        case '"':
b82361
+                            b.append('"');
b82361
+                            break;
b82361
+                        case '\\':
b82361
+                            b.append('\\');
b82361
+                            break;
b82361
+                        case '/':
b82361
+                            b.append('/');
b82361
+                            break;
b82361
+                        case 'b':
b82361
+                            b.append('\b');
b82361
+                            break;
b82361
+                        case 'f':
b82361
+                            b.append('\f');
b82361
+                            break;
b82361
+                        case 'n':
b82361
+                            b.append('\n');
b82361
+                            break;
b82361
+                        case 'r':
b82361
+                            b.append('\r');
b82361
+                            break;
b82361
+                        case 't':
b82361
+                            b.append('\t');
b82361
+                            break;
b82361
+                        case 'u':
b82361
+                            if (length - pos < 5) {
b82361
+                                throw new ParseException("Invalid character code: \\u" + src.substring(pos));
b82361
+                            }
b82361
+                            try {
b82361
+                                b.append((char) Integer.parseInt(src.substring(pos, pos + 4), 16));
b82361
+                                pos += 4;
b82361
+                            } catch (NumberFormatException nfx) {
b82361
+                                throw new ParseException("Invalid character code: " + src.substring(pos, pos + 4));
b82361
+                            }
b82361
+                            break;
b82361
+                        default:
b82361
+                            throw new ParseException("Unexcpected character in string: '\\" + c + "'");
b82361
                     }
b82361
-                    pos += 4;
b82361
-                    b.append((char) code);
b82361
                     break;
b82361
+                case '"':
b82361
+                    return b.toString();
b82361
                 default:
b82361
-                    throw new ParseException("Unexpected character in string: '\\" + c + "'");
b82361
-            }
b82361
-            stringStart = pos;
b82361
-            while (pos < length) {
b82361
-                c = src.charAt(pos++);
b82361
-                if (c <= '\u001F') {
b82361
-                    throw new ParseException("String contains control character");
b82361
-                } else if (c == '\\') {
b82361
+                    b.append(c);
b82361
                     break;
b82361
-                } else if (c == '"') {
b82361
-                    b.append(src, stringStart, pos - 1);
b82361
-                    return b.toString();
b82361
-                }
b82361
             }
b82361
         }
b82361
         throw new ParseException("Unterminated string literal");
b82361
     }
b82361
 
b82361
-    private int fromHex(char c) {
b82361
-        return c >= '0' && c <= '9' ? c - '0'
b82361
-                : c >= 'A' && c <= 'F' ? c - 'A' + 10
b82361
-                : c >= 'a' && c <= 'f' ? c - 'a' + 10
b82361
-                : -1;
b82361
-    }
b82361
-
b82361
-    private Number readNumber(char c) throws ParseException {
b82361
-        assert c == '-' || (c >= '0' && c <= '9');
b82361
-        final int numberStart = pos - 1;
b82361
-        if (c == '-') {
b82361
-            c = nextOrNumberError(numberStart);
b82361
-            if (!(c >= '0' && c <= '9')) {
b82361
-                throw numberError(numberStart, pos);
b82361
-            }
b82361
-        }
b82361
-        if (c != '0') {
b82361
-            readDigits();
b82361
-        }
b82361
-        // read optional fraction part
b82361
-        if (pos < length) {
b82361
-            c = src.charAt(pos);
b82361
-            if (c == '.') {
b82361
-                pos += 1;
b82361
-                c = nextOrNumberError(numberStart);
b82361
-                if (!(c >= '0' && c <= '9')) {
b82361
-                    throw numberError(numberStart, pos);
b82361
-                }
b82361
-                readDigits();
b82361
+    private Number readNumber(char first) throws ParseException {
b82361
+        StringBuilder b = new StringBuilder();
b82361
+        b.append(first);
b82361
+        while (pos < length) {
b82361
+            char c = src.charAt(pos);
b82361
+            if (!Character.isDigit(c)
b82361
+                    && c != '-'
b82361
+                    && c != '+'
b82361
+                    && c != '.'
b82361
+                    && c != 'e'
b82361
+                    && c != 'E') {
b82361
+                break;
b82361
             }
b82361
+            pos += 1;
b82361
+            b.append(c);
b82361
         }
b82361
-        // read optional exponent part
b82361
-        if (pos < length) {
b82361
-            c = src.charAt(pos);
b82361
-            if (c == 'e' || c == 'E') {
b82361
-                pos += 1;
b82361
-                c = nextOrNumberError(numberStart);
b82361
-                if (c == '-' || c == '+') {
b82361
-                    c = nextOrNumberError(numberStart);
b82361
-                }
b82361
-                if (!(c >= '0' && c <= '9')) {
b82361
-                    throw numberError(numberStart, pos);
b82361
+        String num = b.toString();
b82361
+        int numLength = num.length();
b82361
+        try {
b82361
+            // check for leading zeroes
b82361
+            for (int i = 0; i < numLength; i++) {
b82361
+                char c = num.charAt(i);
b82361
+                if (Character.isDigit(c)) {
b82361
+                    if (c == '0'
b82361
+                            && numLength > i + 1
b82361
+                            && Character.isDigit(num.charAt(i + 1))) {
b82361
+                        throw new ParseException("Unsupported number format: " + num);
b82361
+                    }
b82361
+                    break;
b82361
                 }
b82361
-                readDigits();
b82361
             }
b82361
-        }
b82361
-        String num = src.substring(numberStart, pos);
b82361
-        final double dval = Double.parseDouble(num);
b82361
-        final int ival = (int)dval;
b82361
-        if (ival == dval) {
b82361
-            return Integer.valueOf(ival);
b82361
-        } else {
b82361
-            return Double.valueOf(dval);
b82361
-        }
b82361
-    }
b82361
-
b82361
-    private ParseException numberError(int start, int end) {
b82361
-        return new ParseException("Unsupported number format: " + src.substring(start, end));
b82361
-    }
b82361
-
b82361
-    private char nextOrNumberError(int numberStart) throws ParseException {
b82361
-        if (pos >= length) {
b82361
-            throw numberError(numberStart, length);
b82361
-        }
b82361
-        return src.charAt(pos++);
b82361
-    }
b82361
-
b82361
-    private void readDigits() {
b82361
-        for (; pos < length; ++pos) {
b82361
-            char c = src.charAt(pos);
b82361
-            if (!(c >= '0' && c <= '9')) {
b82361
-                break;
b82361
+            final double dval = Double.parseDouble(num);
b82361
+            final int ival = (int)dval;
b82361
+            if (ival == dval) {
b82361
+                return Integer.valueOf(ival);
b82361
+            } else {
b82361
+                return Double.valueOf(dval);
b82361
             }
b82361
+        } catch (NumberFormatException nfe) {
b82361
+            throw new ParseException("Unsupported number format: " + num);
b82361
         }
b82361
     }
b82361
 
b82361
diff --git a/testsrc/org/mozilla/javascript/tests/json/JsonParserTest.java b/testsrc/org/mozilla/javascript/tests/json/JsonParserTest.java
b82361
index ee885ae..2783b50 100644
b82361
--- a/testsrc/org/mozilla/javascript/tests/json/JsonParserTest.java
b82361
+++ b/testsrc/org/mozilla/javascript/tests/json/JsonParserTest.java
b82361
@@ -196,66 +196,6 @@ public class JsonParserTest {
b82361
         parser.parseValue("[1 ");
b82361
     }
b82361
 
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseIllegalUnicodeEscapeSeq() throws Exception {
b82361
-        parser.parseValue("\"\\u-123\"");
b82361
-    }
b82361
-
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseIllegalUnicodeEscapeSeq2() throws Exception {
b82361
-        parser.parseValue("\"\\u006\u0661\"");
b82361
-    }
b82361
-
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseIllegalUnicodeEscapeSeq3() throws Exception {
b82361
-        parser.parseValue("\"\\u006ูก\"");
b82361
-    }
b82361
-
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseTrailingCommaInObject1() throws Exception {
b82361
-        parser.parseValue("{\"a\": 1,}");
b82361
-    }
b82361
-
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseTrailingCommaInObject2() throws Exception {
b82361
-        parser.parseValue("{,\"a\": 1}");
b82361
-    }
b82361
-
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseTrailingCommaInObject3() throws Exception {
b82361
-        parser.parseValue("{,}");
b82361
-    }
b82361
-
b82361
-    @Test
b82361
-    public void shouldParseEmptyObject() throws Exception {
b82361
-        parser.parseValue("{}");
b82361
-    }
b82361
-
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseTrailingCommaInArray1() throws Exception {
b82361
-        parser.parseValue("[1,]");
b82361
-    }
b82361
-
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseTrailingCommaInArray2() throws Exception {
b82361
-        parser.parseValue("[,1]");
b82361
-    }
b82361
-
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseTrailingCommaInArray3() throws Exception {
b82361
-        parser.parseValue("[,]");
b82361
-    }
b82361
-
b82361
-    @Test
b82361
-    public void shouldParseEmptyArray() throws Exception {
b82361
-        parser.parseValue("[]");
b82361
-    }
b82361
-
b82361
-    @Test(expected = ParseException.class)
b82361
-    public void shouldFailToParseIllegalNumber() throws Exception {
b82361
-        parser.parseValue("1.");
b82361
-    }
b82361
-
b82361
     private String str(char... chars) {
b82361
         return new String(chars);
b82361
     }