Changeset 91765 in webkit


Ignore:
Timestamp:
Jul 26, 2011, 10:53:40 AM (14 years ago)
Author:
[email protected]
Message:

JSON errors should be informative
https://bugs.webkit.org/show_bug.cgi?id=63339

Source/JavaScriptCore:

Added error messages to the JSON Parser.

Patch by Juan C. Montemayor <[email protected]> on 2011-07-26
Reviewed by Oliver Hunt.

  • runtime/JSONObject.cpp:

(JSC::JSONProtoFuncParse):

  • runtime/LiteralParser.cpp:

(JSC::LiteralParser::Lexer::lex):
(JSC::LiteralParser::Lexer::lexString):
(JSC::LiteralParser::Lexer::lexNumber):
(JSC::LiteralParser::parse):

  • runtime/LiteralParser.h:

(JSC::LiteralParser::getErrorMessage):
(JSC::LiteralParser::Lexer::sawError):
(JSC::LiteralParser::Lexer::getErrorMessage):

LayoutTests:

Updated expected test results.

Patch by Juan C. Montemayor <[email protected]> on 2011-07-26
Reviewed by Oliver Hunt.

  • fast/js/JSON-parse-expected.txt:
  • platform/chromium/fast/js/JSON-parse-expected.txt: Added.
Location:
trunk
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r91763 r91765  
     12011-07-26  Juan C. Montemayor  <[email protected]>
     2
     3        JSON errors should be informative
     4        https://bugs.webkit.org/show_bug.cgi?id=63339
     5
     6        Updated expected test results.
     7
     8        Reviewed by Oliver Hunt.
     9
     10        * fast/js/JSON-parse-expected.txt:
     11        * platform/chromium/fast/js/JSON-parse-expected.txt: Added.
     12
    1132011-07-26  Emil A Eklund  <[email protected]>
    214
  • trunk/LayoutTests/fast/js/JSON-parse-expected.txt

    r91715 r91765  
    66        return jsonObject.parse('');
    77    }
    8 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     8PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected EOF.
    99function (jsonObject) {
    1010        return jsonObject.parse('1');
     
    1818        return jsonObject.parse('Infinity');
    1919    }
    20 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     20PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected identifier "Infinity?".
    2121function (jsonObject) {
    2222        return jsonObject.parse('NaN');
    2323    }
    24 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     24PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected identifier "NaN".
    2525function (jsonObject) {
    2626        return jsonObject.parse('null');
     
    3030        return jsonObject.parse('undefined');
    3131    }
    32 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     32PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected identifier "undefined".
    3333function (jsonObject) {
    3434        return jsonObject.parse('{}');
     
    3838        return jsonObject.parse('({})');
    3939    }
    40 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     40PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected token '('.
    4141function (jsonObject) {
    4242        return jsonObject.parse('{a}');
    4343    }
    44 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     44PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Expected '}'.
    4545function (jsonObject) {
    4646        return jsonObject.parse('{a:}');
    4747    }
    48 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     48PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Expected '}'.
    4949function (jsonObject) {
    5050        return jsonObject.parse('{a:5}');
    5151    }
    52 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     52PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Expected '}'.
    5353function (jsonObject) {
    5454        return jsonObject.parse('{a:5,}');
    5555    }
    56 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     56PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Expected '}'.
    5757function (jsonObject) {
    5858        return jsonObject.parse('{"a"}');
    5959    }
    60 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     60PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Expected ':' before value in object property definition.
    6161function (jsonObject) {
    6262        return jsonObject.parse('{"a":}');
    6363    }
    64 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     64PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected token '}'.
    6565function (jsonObject) {
    6666        return jsonObject.parse('{"a":5}');
     
    7474        return jsonObject.parse('{"a":5,}');
    7575    }
    76 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     76PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Property name must be a string literal.
    7777json2.js did not throw for a test we expect to throw.
    7878function (jsonObject) {
    7979        return jsonObject.parse('{"a":5,,}');
    8080    }
    81 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     81PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Property name must be a string literal.
    8282function (jsonObject) {
    8383        return jsonObject.parse('{"a":5,"a",}');
    8484    }
    85 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     85PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Expected ':'.
    8686function (jsonObject) {
    8787        return jsonObject.parse('{"a":(5,"a"),}');
    8888    }
    89 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     89PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected token '('.
    9090function (jsonObject) {
    9191        return jsonObject.parse('[]');
     
    9999        return jsonObject.parse('[1,]');
    100100    }
    101 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     101PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected comma at the end of array expression.
    102102json2.js did not throw for a test we expect to throw.
    103103function (jsonObject) {
     
    108108        return jsonObject.parse('[1,2,,]');
    109109    }
    110 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     110PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected token ','.
    111111json2.js did not throw for a test we expect to throw.
    112112function (jsonObject) {
    113113        return jsonObject.parse('[1,2,,4]');
    114114    }
    115 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     115PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unexpected token ','.
    116116json2.js did not throw for a test we expect to throw.
    117117function (jsonObject) {
     
    130130        return jsonObject.parse('"a\\"');
    131131    }
    132 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     132PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unterminated string.
    133133function (jsonObject) {
    134134        return jsonObject.parse('"a\\z"');
    135135    }
    136 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     136PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Invalid escape character z.
    137137function (jsonObject) {
    138138        return jsonObject.parse('"a\\\z"');
    139139    }
    140 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     140PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Invalid escape character z.
    141141function (jsonObject) {
    142142        return jsonObject.parse('"a\\\\z"');
     
    154154        return jsonObject.parse('"a\nz"');
    155155    }
    156 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     156PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unterminated string.
    157157function (jsonObject) {
    158158        return jsonObject.parse('"a\\nz"');
     
    162162        return jsonObject.parse('"a\rz"');
    163163    }
    164 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     164PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unterminated string.
    165165function (jsonObject) {
    166166        return jsonObject.parse('"a\\rz"');
     
    178178        return jsonObject.parse('"a\bz"');
    179179    }
    180 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     180PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unterminated string.
    181181json2.js did not throw for a test we expect to throw.
    182182function (jsonObject) {
     
    187187        return jsonObject.parse('"a\rz"');
    188188    }
    189 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     189PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unterminated string.
    190190function (jsonObject) {
    191191        return jsonObject.parse('"a\\rz"');
     
    195195        return jsonObject.parse('"a\\uz"     ');
    196196    }
    197 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     197PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\uz"  " is not a valid unicode escape.
    198198function (jsonObject) {
    199199        return jsonObject.parse('"a\\u0z"    ');
    200200    }
    201 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     201PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\u0z" " is not a valid unicode escape.
    202202function (jsonObject) {
    203203        return jsonObject.parse('"a\\u00z"   ');
    204204    }
    205 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     205PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\u00z"" is not a valid unicode escape.
    206206function (jsonObject) {
    207207        return jsonObject.parse('"a\\u000z"  ');
    208208    }
    209 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     209PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\u000z" is not a valid unicode escape.
    210210function (jsonObject) {
    211211        return jsonObject.parse('"a\\u0000z" ');
     
    223223        return jsonObject.parse('"a\\u000Gz" ');
    224224    }
    225 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     225PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\u000G" is not a valid unicode escape.
    226226function (jsonObject) {
    227227        return jsonObject.parse('"a\\u000gz" ');
    228228    }
    229 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     229PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\u000g" is not a valid unicode escape.
    230230function (jsonObject) {
    231231        return jsonObject.parse('"a\\u00A0z" ');
     
    239239        return jsonObject.parse('"a\\u00G0z" ');
    240240    }
    241 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     241PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\u00G0" is not a valid unicode escape.
    242242function (jsonObject) {
    243243        return jsonObject.parse('"a\\u00g0z" ');
    244244    }
    245 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     245PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\u00g0" is not a valid unicode escape.
    246246function (jsonObject) {
    247247        return jsonObject.parse('"a\\u0A00z" ');
     
    255255        return jsonObject.parse('"a\\u0G00z" ');
    256256    }
    257 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     257PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\u0G00" is not a valid unicode escape.
    258258function (jsonObject) {
    259259        return jsonObject.parse('"a\\u0g00z" ');
    260260    }
    261 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     261PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\u0g00" is not a valid unicode escape.
    262262function (jsonObject) {
    263263        return jsonObject.parse('"a\\uA000z" ');
     
    271271        return jsonObject.parse('"a\\uG000z" ');
    272272    }
    273 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     273PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\uG000" is not a valid unicode escape.
    274274function (jsonObject) {
    275275        return jsonObject.parse('"a\\ug000z" ');
    276276    }
    277 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     277PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: "\ug000" is not a valid unicode escape.
    278278function (jsonObject) {
    279279        return jsonObject.parse('00');
    280280    }
    281 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     281PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unable to parse JSON string.
    282282json2.js did not throw for a test we expect to throw.
    283283function (jsonObject) {
    284284        return jsonObject.parse('01');
    285285    }
    286 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     286PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unable to parse JSON string.
    287287json2.js did not throw for a test we expect to throw.
    288288function (jsonObject) {
    289289        return jsonObject.parse('0.a');
    290290    }
    291 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     291PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Invalid digits after decimal point.
    292292function (jsonObject) {
    293293        return jsonObject.parse('0x0');
    294294    }
    295 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     295PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unable to parse JSON string.
    296296function (jsonObject) {
    297297        return jsonObject.parse('2e1.3');
    298298    }
    299 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     299PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unable to parse JSON string.
    300300function (jsonObject) {
    301301        return jsonObject.parse('2e-+10');
    302302    }
    303 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     303PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Exponent symbols should be followed by an optional '+' or '-' and then by at least one number.
    304304function (jsonObject) {
    305305        return jsonObject.parse('2e+-10');
    306306    }
    307 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     307PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Exponent symbols should be followed by an optional '+' or '-' and then by at least one number.
    308308function (jsonObject) {
    309309        return jsonObject.parse('2e3e4');
    310310    }
    311 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     311PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unable to parse JSON string.
    312312function (jsonObject) {
    313313        return jsonObject.parse('-01.0');
    314314    }
    315 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     315PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unable to parse JSON string.
    316316function (jsonObject) {
    317317        return jsonObject.parse('-01');
    318318    }
    319 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     319PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unable to parse JSON string.
    320320json2.js did not throw for a test we expect to throw.
    321321function (jsonObject) {
    322322        return jsonObject.parse('-01.a');
    323323    }
    324 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     324PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Invalid digits after decimal point.
    325325function (jsonObject) {
    326326        return jsonObject.parse('1.e1');
    327327    }
    328 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     328PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Invalid digits after decimal point.
    329329json2.js did not throw for a test we expect to throw.
    330330function (jsonObject) {
    331331        return jsonObject.parse('{/* block comments are not allowed */}');
    332332    }
    333 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     333PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unrecognized token '/'.
    334334function (jsonObject) {
    335335        return jsonObject.parse('{// line comments are not allowed \n}');
    336336    }
    337 PASS tests[i](nativeJSON) threw exception SyntaxError: Unable to parse JSON string.
     337PASS tests[i](nativeJSON) threw exception SyntaxError: JSON Parse error: Unrecognized token '/'.
    338338function (jsonObject) {
    339339        return jsonObject.parse('true');
  • trunk/Source/JavaScriptCore/ChangeLog

    r91756 r91765  
     12011-07-26  Juan C. Montemayor  <[email protected]>
     2
     3        JSON errors should be informative
     4        https://bugs.webkit.org/show_bug.cgi?id=63339
     5
     6        Added error messages to the JSON Parser.
     7
     8        Reviewed by Oliver Hunt.
     9
     10        * runtime/JSONObject.cpp:
     11        (JSC::JSONProtoFuncParse):
     12        * runtime/LiteralParser.cpp:
     13        (JSC::LiteralParser::Lexer::lex):
     14        (JSC::LiteralParser::Lexer::lexString):
     15        (JSC::LiteralParser::Lexer::lexNumber):
     16        (JSC::LiteralParser::parse):
     17        * runtime/LiteralParser.h:
     18        (JSC::LiteralParser::getErrorMessage):
     19        (JSC::LiteralParser::Lexer::sawError):
     20        (JSC::LiteralParser::Lexer::getErrorMessage):
     21
    1222011-07-26  Sheriff Bot  <[email protected]>
    223
  • trunk/Source/JavaScriptCore/runtime/JSONObject.cpp

    r91715 r91765  
    820820    JSValue unfiltered = jsonParser.tryLiteralParse();
    821821    if (!unfiltered)
    822         return throwVMError(exec, createSyntaxError(exec, "Unable to parse JSON string"));
     822        return throwVMError(exec, createSyntaxError(exec, jsonParser.getErrorMessage()));
    823823   
    824824    if (exec->argumentCount() < 2)
  • trunk/Source/JavaScriptCore/runtime/LiteralParser.cpp

    r91715 r91765  
    237237        }
    238238        if (*m_ptr == '\'') {
    239             if (mode == StrictJSON)
     239            if (mode == StrictJSON) {
     240                m_lexErrorMessage = "Single quotes (\') are not allowed in JSON";
    240241                return TokError;
     242            }
    241243            return lexString<mode, '\''>(token);
    242244        }
    243245    }
     246    m_lexErrorMessage = String::format("Unrecognized token '%c'", *m_ptr).impl();
    244247    return TokError;
    245248}
     
    275278                builder.append(runStart, m_ptr - runStart);
    276279            ++m_ptr;
    277             if (m_ptr >= m_end)
     280            if (m_ptr >= m_end) {
     281                m_lexErrorMessage = "Unterminated string";
    278282                return TokError;
     283            }
    279284            switch (*m_ptr) {
    280285                case '"':
     
    312317
    313318                case 'u':
    314                     if ((m_end - m_ptr) < 5) // uNNNN == 5 characters
     319                    if ((m_end - m_ptr) < 5) {
     320                        m_lexErrorMessage = "\\u must be followed by 4 hex digits";
    315321                        return TokError;
     322                    } // uNNNN == 5 characters
    316323                    for (int i = 1; i < 5; i++) {
    317                         if (!isASCIIHexDigit(m_ptr[i]))
     324                        if (!isASCIIHexDigit(m_ptr[i])) {
     325                            m_lexErrorMessage = String::format("\"\\%s\" is not a valid unicode escape", UString(m_ptr, 5).ascii().data()).impl();
    318326                            return TokError;
     327                        }
    319328                    }
    320329                    builder.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
     
    328337                        break;
    329338                    }
     339                    m_lexErrorMessage = String::format("Invalid escape character %c", *m_ptr).impl();
    330340                    return TokError;
    331341            }
     
    333343    } while ((mode != NonStrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != terminator);
    334344
    335     if (m_ptr >= m_end || *m_ptr != terminator)
     345    if (m_ptr >= m_end || *m_ptr != terminator) {
     346        m_lexErrorMessage = "Unterminated string";
    336347        return TokError;
     348    }
    337349
    338350    if (builder.isEmpty()) {
     
    377389        while (m_ptr < m_end && isASCIIDigit(*m_ptr))
    378390            ++m_ptr;
    379     } else
     391    } else {
     392        m_lexErrorMessage = "Invalid number";
    380393        return TokError;
     394    }
    381395
    382396    // ('.' [0-9]+)?
     
    384398        ++m_ptr;
    385399        // [0-9]+
    386         if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
     400        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
     401            m_lexErrorMessage = "Invalid digits after decimal point";
    387402            return TokError;
     403        }
    388404
    389405        ++m_ptr;
     
    417433
    418434        // [0-9]+
    419         if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
     435        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
     436            m_lexErrorMessage = "Exponent symbols should be followed by an optional '+' or '-' and then by at least one number";
    420437            return TokError;
     438        }
    421439       
    422440        ++m_ptr;
     
    459477                TokenType lastToken = m_lexer.currentToken().type;
    460478                if (m_lexer.next() == TokRBracket) {
    461                     if (lastToken == TokComma)
    462                         return JSValue();
     479                    if (lastToken == TokComma) {
     480                        m_parseErrorMessage = "Unexpected comma at the end of array expression";
     481                        return JSValue();
     482                    }
    463483                    m_lexer.next();
    464484                    lastValue = objectStack.last();
     
    476496                    goto doParseArrayStartExpression;
    477497
    478                 if (m_lexer.currentToken().type != TokRBracket)
     498                if (m_lexer.currentToken().type != TokRBracket) {
     499                    m_parseErrorMessage = "Expected ']'";
    479500                    return JSValue();
     501                }
    480502               
    481503                m_lexer.next();
     
    494516
    495517                    // Check for colon
    496                     if (m_lexer.next() != TokColon)
    497                         return JSValue();
     518                    if (m_lexer.next() != TokColon) {
     519                        m_parseErrorMessage = "Expected ':' before value in object property definition";
     520                        return JSValue();
     521                    }
    498522                   
    499523                    m_lexer.next();
     
    502526                    goto startParseExpression;
    503527                }
    504                 if (type != TokRBrace)
     528                if (type != TokRBrace)  {
     529                    m_parseErrorMessage = "Expected '}'";
    505530                    return JSValue();
     531                }
    506532                m_lexer.next();
    507533                lastValue = objectStack.last();
     
    512538            case DoParseObjectStartExpression: {
    513539                TokenType type = m_lexer.next();
    514                 if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier))
     540                if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier)) {
     541                    m_parseErrorMessage = "Property name must be a string literal";
    515542                    return JSValue();
     543                }
    516544                Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
    517545
    518546                // Check for colon
    519                 if (m_lexer.next() != TokColon)
     547                if (m_lexer.next() != TokColon) {
     548                    m_parseErrorMessage = "Expected ':'";
    520549                    return JSValue();
     550                }
    521551
    522552                m_lexer.next();
     
    531561                if (m_lexer.currentToken().type == TokComma)
    532562                    goto doParseObjectStartExpression;
    533                 if (m_lexer.currentToken().type != TokRBrace)
     563                if (m_lexer.currentToken().type != TokRBrace) {
     564                    m_parseErrorMessage = "Expected '}'";
    534565                    return JSValue();
     566                }
    535567                m_lexer.next();
    536568                lastValue = objectStack.last();
     
    571603                        lastValue = jsBoolean(false);
    572604                        break;
    573 
     605                    case TokRBracket:
     606                        m_parseErrorMessage = "Unexpected token ']'";
     607                        return JSValue();
     608                    case TokRBrace:
     609                        m_parseErrorMessage = "Unexpected token '}'";
     610                        return JSValue();
     611                    case TokIdentifier:
     612                        m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken).ascii().data()).impl();
     613                        return JSValue();
     614                    case TokColon:
     615                        m_parseErrorMessage = "Unexpected token ':'";
     616                        return JSValue();
     617                    case TokLParen:
     618                        m_parseErrorMessage = "Unexpected token '('";
     619                        return JSValue();
     620                    case TokRParen:
     621                        m_parseErrorMessage = "Unexpected token ')'";
     622                        return JSValue();
     623                    case TokComma:
     624                        m_parseErrorMessage = "Unexpected token ','";
     625                        return JSValue();
     626                    case TokDot:
     627                        m_parseErrorMessage = "Unexpected token '.'";
     628                        return JSValue();
     629                    case TokAssign:
     630                        m_parseErrorMessage = "Unexpected token '='";
     631                        return JSValue();
     632                    case TokSemi:
     633                        m_parseErrorMessage = "Unexpected token ';'";
     634                        return JSValue();
     635                    case TokEnd:
     636                        m_parseErrorMessage = "Unexpected EOF";
     637                        return JSValue();
     638                    case TokError:
    574639                    default:
    575640                        // Error
     641                        m_parseErrorMessage = "Could not parse value expression";
    576642                        return JSValue();
    577643                }
     
    590656                        goto startParseExpression;
    591657                    }
     658                    case TokRBracket:
     659                        m_parseErrorMessage = "Unexpected token ']'";
     660                        return JSValue();
     661                    case TokLBrace:
     662                        m_parseErrorMessage = "Unexpected token '{'";
     663                        return JSValue();
     664                    case TokRBrace:
     665                        m_parseErrorMessage = "Unexpected token '}'";
     666                        return JSValue();
     667                    case TokIdentifier:
     668                        m_parseErrorMessage = "Unexpected identifier";
     669                        return JSValue();
     670                    case TokColon:
     671                        m_parseErrorMessage = "Unexpected token ':'";
     672                        return JSValue();
     673                    case TokRParen:
     674                        m_parseErrorMessage = "Unexpected token ')'";
     675                        return JSValue();
     676                    case TokComma:
     677                        m_parseErrorMessage = "Unexpected token ','";
     678                        return JSValue();
     679                    case TokTrue:
     680                        m_parseErrorMessage = "Unexpected token 'true'";
     681                        return JSValue();
     682                    case TokFalse:
     683                        m_parseErrorMessage = "Unexpected token 'false'";
     684                        return JSValue();
     685                    case TokNull:
     686                        m_parseErrorMessage = "Unexpected token 'null'";
     687                        return JSValue();
     688                    case TokEnd:
     689                        m_parseErrorMessage = "Unexpected EOF";
     690                        return JSValue();
     691                    case TokDot:
     692                        m_parseErrorMessage = "Unexpected token '.'";
     693                        return JSValue();
     694                    case TokAssign:
     695                        m_parseErrorMessage = "Unexpected token '='";
     696                        return JSValue();
     697                    case TokSemi:
     698                        m_parseErrorMessage = "Unexpected token ';'";
     699                        return JSValue();
     700                    case TokError:
    592701                    default:
     702                        m_parseErrorMessage = "Could not parse statement";
    593703                        return JSValue();
    594704                }
     
    600710                if (m_lexer.next() == TokEnd)
    601711                    return lastValue;
     712                m_parseErrorMessage = "Unexpected content at end of JSON literal";
    602713                return JSValue();
    603714            }
  • trunk/Source/JavaScriptCore/runtime/LiteralParser.h

    r91715 r91765  
    4242            , m_mode(mode)
    4343        {
     44        }
     45       
     46        UString getErrorMessage()
     47        {
     48            if (!m_lexer.getErrorMessage().isEmpty())
     49                return String::format("JSON Parse error: %s", m_lexer.getErrorMessage().ascii().data()).impl();
     50            if (!m_parseErrorMessage.isEmpty())
     51                return String::format("JSON Parse error: %s", m_parseErrorMessage.ascii().data()).impl();
     52            return "JSON Parse error: Unable to parse JSON string";
    4453        }
    4554       
     
    113122            }
    114123           
     124            UString getErrorMessage() { return m_lexErrorMessage; }
     125           
    115126        private:
     127            UString m_lexErrorMessage;
    116128            template <ParserMode mode> TokenType lex(LiteralParserToken&);
    117129            template <ParserMode mode, UChar terminator> ALWAYS_INLINE TokenType lexString(LiteralParserToken&);
     
    130142        LiteralParser::Lexer m_lexer;
    131143        ParserMode m_mode;
     144        UString m_parseErrorMessage;
    132145        static unsigned const MaximumCachableCharacter = 128;
    133146        FixedArray<Identifier, MaximumCachableCharacter> m_shortIdentifiers;
Note: See TracChangeset for help on using the changeset viewer.