Ignore:
Timestamp:
Jul 25, 2011, 11:41: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-25
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-25
Reviewed by Oliver Hunt.

  • fast/js/JSON-parse-expected.txt:
  • platform/chromium/fast/js/JSON-parse-expected.txt: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/LiteralParser.cpp

    r89219 r91686  
    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 = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken).ascii().data()).impl();
     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            }
Note: See TracChangeset for help on using the changeset viewer.