]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/LiteralParser.cpp
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / runtime / LiteralParser.cpp
index ed42d0d2fd960f9ec0b26c59519437db1dfc9927..f594518b6cf2acc208d3204c9a04d453ca035897 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "config.h"
 #include "LiteralParser.h"
 
+#include "ButterflyInlines.h"
+#include "CopiedSpaceInlines.h"
 #include "JSArray.h"
 #include "JSString.h"
 #include "Lexer.h"
-#include "UStringBuilder.h"
+#include "ObjectConstructor.h"
+#include "Operations.h"
+#include "StrongInlines.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/dtoa.h>
+#include <wtf/text/StringBuilder.h>
 
 namespace JSC {
 
-static inline bool isJSONWhiteSpace(const UChar& c)
+template <typename CharType>
+static inline bool isJSONWhiteSpace(const CharType& c)
 {
     // The JSON RFC 4627 defines a list of allowed characters to be considered
     // insignificant white space: http://www.ietf.org/rfc/rfc4627.txt (2. JSON Grammar).
     return c == ' ' || c == 0x9 || c == 0xA || c == 0xD;
 }
 
-bool LiteralParser::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo)
+template <typename CharType>
+bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo)
 {
     if (m_lexer.next() != TokIdentifier)
         return false;
     do {
         Vector<JSONPPathEntry> path;
         // Unguarded next to start off the lexer
-        Identifier name = Identifier(m_exec, m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+        Identifier name = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
         JSONPPathEntry entry;
-        if (name == m_exec->globalData().propertyNames->varKeyword) {
+        if (name == m_exec->vm().propertyNames->varKeyword) {
             if (m_lexer.next() != TokIdentifier)
                 return false;
             entry.m_type = JSONPPathEntryTypeDeclare;
-            entry.m_pathEntryName = Identifier(m_exec, m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+            entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
             path.append(entry);
         } else {
             entry.m_type = JSONPPathEntryTypeDot;
-            entry.m_pathEntryName = Identifier(m_exec, m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+            entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
             path.append(entry);
         }
-        if (m_exec->globalData().lexer->isKeyword(entry.m_pathEntryName))
+        if (m_exec->vm().keywords->isKeyword(entry.m_pathEntryName))
             return false;
         TokenType tokenType = m_lexer.next();
+        if (entry.m_type == JSONPPathEntryTypeDeclare && tokenType != TokAssign)
+            return false;
         while (tokenType != TokAssign) {
             switch (tokenType) {
             case TokLBracket: {
@@ -84,7 +94,7 @@ bool LiteralParser::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSour
                 entry.m_type = JSONPPathEntryTypeDot;
                 if (m_lexer.next() != TokIdentifier)
                     return false;
-                entry.m_pathEntryName = Identifier(m_exec, m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+                entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
                 break;
             }
             case TokLParen: {
@@ -103,7 +113,7 @@ bool LiteralParser::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSour
     startJSON:
         m_lexer.next();
         results.append(JSONPData());
-        results.last().m_value.set(m_exec->globalData(), parse(StartParseExpression));
+        results.last().m_value.set(m_exec->vm(), parse(StartParseExpression));
         if (!results.last().m_value)
             return false;
         results.last().m_path.swap(path);
@@ -119,26 +129,48 @@ bool LiteralParser::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSour
     return m_lexer.currentToken().type == TokEnd;
 }
     
-ALWAYS_INLINE const Identifier LiteralParser::makeIdentifier(const UChar* characters, size_t length)
+template <typename CharType>
+ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const LChar* characters, size_t length)
 {
     if (!length)
-        return m_exec->globalData().propertyNames->emptyIdentifier;
+        return m_exec->vm().propertyNames->emptyIdentifier;
     if (characters[0] >= MaximumCachableCharacter)
-        return Identifier(&m_exec->globalData(), characters, length);
+        return Identifier(&m_exec->vm(), characters, length);
 
     if (length == 1) {
         if (!m_shortIdentifiers[characters[0]].isNull())
             return m_shortIdentifiers[characters[0]];
-        m_shortIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+        m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
         return m_shortIdentifiers[characters[0]];
     }
     if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
         return m_recentIdentifiers[characters[0]];
-    m_recentIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+    m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
     return m_recentIdentifiers[characters[0]];
 }
 
-template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
+template <typename CharType>
+ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const UChar* characters, size_t length)
+{
+    if (!length)
+        return m_exec->vm().propertyNames->emptyIdentifier;
+    if (characters[0] >= MaximumCachableCharacter)
+        return Identifier(&m_exec->vm(), characters, length);
+
+    if (length == 1) {
+        if (!m_shortIdentifiers[characters[0]].isNull())
+            return m_shortIdentifiers[characters[0]];
+        m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
+        return m_shortIdentifiers[characters[0]];
+    }
+    if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
+        return m_recentIdentifiers[characters[0]];
+    m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
+    return m_recentIdentifiers[characters[0]];
+}
+
+template <typename CharType>
+template <ParserMode mode> TokenType LiteralParser<CharType>::Lexer::lex(LiteralParserToken<CharType>& token)
 {
     while (m_ptr < m_end && isJSONWhiteSpace(*m_ptr))
         ++m_ptr;
@@ -239,25 +271,48 @@ template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser
             token.end = ++m_ptr;
             return TokAssign;
         }
-        if (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$') {
-            while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$'))
-                m_ptr++;
-            token.stringToken = token.start;
-            token.stringLength = m_ptr - token.start;
-            token.type = TokIdentifier;
-            token.end = m_ptr;
-            return TokIdentifier;
-        }
+        if (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$')
+            return lexIdentifier(token);
         if (*m_ptr == '\'') {
-            if (mode == StrictJSON)
+            if (mode == StrictJSON) {
+                m_lexErrorMessage = ASCIILiteral("Single quotes (\') are not allowed in JSON");
                 return TokError;
+            }
             return lexString<mode, '\''>(token);
         }
     }
+    m_lexErrorMessage = String::format("Unrecognized token '%c'", *m_ptr).impl();
     return TokError;
 }
 
-LiteralParser::TokenType LiteralParser::Lexer::next()
+template <>
+ALWAYS_INLINE TokenType LiteralParser<LChar>::Lexer::lexIdentifier(LiteralParserToken<LChar>& token)
+{
+    while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$'))
+        m_ptr++;
+    token.stringIs8Bit = 1;
+    token.stringToken8 = token.start;
+    token.stringLength = m_ptr - token.start;
+    token.type = TokIdentifier;
+    token.end = m_ptr;
+    return TokIdentifier;
+}
+
+template <>
+ALWAYS_INLINE TokenType LiteralParser<UChar>::Lexer::lexIdentifier(LiteralParserToken<UChar>& token)
+{
+    while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$' || *m_ptr == 0x200C || *m_ptr == 0x200D))
+        m_ptr++;
+    token.stringIs8Bit = 0;
+    token.stringToken16 = token.start;
+    token.stringLength = m_ptr - token.start;
+    token.type = TokIdentifier;
+    token.end = m_ptr;
+    return TokIdentifier;
+}
+
+template <typename CharType>
+TokenType LiteralParser<CharType>::Lexer::next()
 {
     if (m_mode == NonStrictJSON)
         return lex<NonStrictJSON>(m_currentToken);
@@ -266,20 +321,39 @@ LiteralParser::TokenType LiteralParser::Lexer::next()
     return lex<StrictJSON>(m_currentToken);
 }
 
-template <LiteralParser::ParserMode mode, UChar terminator> static inline bool isSafeStringCharacter(UChar c)
+template <>
+ALWAYS_INLINE void setParserTokenString<LChar>(LiteralParserToken<LChar>& token, const LChar* string)
+{
+    token.stringIs8Bit = 1;
+    token.stringToken8 = string;
+}
+
+template <>
+ALWAYS_INLINE void setParserTokenString<UChar>(LiteralParserToken<UChar>& token, const UChar* string)
+{
+    token.stringIs8Bit = 0;
+    token.stringToken16 = string;
+}
+
+template <ParserMode mode, typename CharType, LChar terminator> static inline bool isSafeStringCharacter(LChar c)
 {
-    return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || c == '\t';
+    return (c >= ' ' && c != '\\' && c != terminator) || (c == '\t' && mode != StrictJSON);
 }
 
-// "inline" is required here to help WINSCW compiler resolve specialized argument in templated functions.
-template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
+template <ParserMode mode, typename CharType, UChar terminator> static inline bool isSafeStringCharacter(UChar c)
+{
+    return (c >= ' ' && (mode == StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || (c == '\t' && mode != StrictJSON);
+}
+
+template <typename CharType>
+template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParser<CharType>::Lexer::lexString(LiteralParserToken<CharType>& token)
 {
     ++m_ptr;
-    const UChar* runStart = m_ptr;
-    UStringBuilder builder;
+    const CharType* runStart = m_ptr;
+    StringBuilder builder;
     do {
         runStart = m_ptr;
-        while (m_ptr < m_end && isSafeStringCharacter<mode, terminator>(*m_ptr))
+        while (m_ptr < m_end && isSafeStringCharacter<mode, CharType, terminator>(*m_ptr))
             ++m_ptr;
         if (builder.length())
             builder.append(runStart, m_ptr - runStart);
@@ -287,8 +361,10 @@ template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser
             if (builder.isEmpty() && runStart < m_ptr)
                 builder.append(runStart, m_ptr - runStart);
             ++m_ptr;
-            if (m_ptr >= m_end)
+            if (m_ptr >= m_end) {
+                m_lexErrorMessage = ASCIILiteral("Unterminated string");
                 return TokError;
+            }
             switch (*m_ptr) {
                 case '"':
                     builder.append('"');
@@ -324,13 +400,17 @@ template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser
                     break;
 
                 case 'u':
-                    if ((m_end - m_ptr) < 5) // uNNNN == 5 characters
+                    if ((m_end - m_ptr) < 5) { 
+                        m_lexErrorMessage = ASCIILiteral("\\u must be followed by 4 hex digits");
                         return TokError;
+                    } // uNNNN == 5 characters
                     for (int i = 1; i < 5; i++) {
-                        if (!isASCIIHexDigit(m_ptr[i]))
+                        if (!isASCIIHexDigit(m_ptr[i])) {
+                            m_lexErrorMessage = String::format("\"\\%s\" is not a valid unicode escape", String(m_ptr, 5).ascii().data()).impl();
                             return TokError;
+                        }
                     }
-                    builder.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
+                    builder.append(JSC::Lexer<CharType>::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
                     m_ptr += 5;
                     break;
 
@@ -340,21 +420,30 @@ template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser
                         m_ptr++;
                         break;
                     }
+                    m_lexErrorMessage = String::format("Invalid escape character %c", *m_ptr).impl();
                     return TokError;
             }
         }
     } while ((mode != NonStrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != terminator);
 
-    if (m_ptr >= m_end || *m_ptr != terminator)
+    if (m_ptr >= m_end || *m_ptr != terminator) {
+        m_lexErrorMessage = ASCIILiteral("Unterminated string");
         return TokError;
+    }
 
     if (builder.isEmpty()) {
-        token.stringBuffer = UString();
-        token.stringToken = runStart;
+        token.stringBuffer = String();
+        setParserTokenString<CharType>(token, runStart);
         token.stringLength = m_ptr - runStart;
     } else {
-        token.stringBuffer = builder.toUString();
-        token.stringToken = token.stringBuffer.characters();
+        token.stringBuffer = builder.toString();
+        if (token.stringBuffer.is8Bit()) {
+            token.stringIs8Bit = 1;
+            token.stringToken8 = token.stringBuffer.characters8();
+        } else {
+            token.stringIs8Bit = 0;
+            token.stringToken16 = token.stringBuffer.characters16();
+        }
         token.stringLength = token.stringBuffer.length();
     }
     token.type = TokString;
@@ -362,7 +451,8 @@ template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser
     return TokString;
 }
 
-LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& token)
+template <typename CharType>
+TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>& token)
 {
     // ES5 and json.org define numbers as
     // number
@@ -389,15 +479,19 @@ LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& tok
         // [0-9]*
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
             ++m_ptr;
-    } else
+    } else {
+        m_lexErrorMessage = ASCIILiteral("Invalid number");
         return TokError;
+    }
 
     // ('.' [0-9]+)?
     if (m_ptr < m_end && *m_ptr == '.') {
         ++m_ptr;
         // [0-9]+
-        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
+        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
+            m_lexErrorMessage = ASCIILiteral("Invalid digits after decimal point");
             return TokError;
+        }
 
         ++m_ptr;
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
@@ -406,7 +500,7 @@ LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& tok
         int result = 0;
         token.type = TokNumber;
         token.end = m_ptr;
-        const UChar* digit = token.start;
+        const CharType* digit = token.start;
         int negative = 1;
         if (*digit == '-') {
             negative = -1;
@@ -429,8 +523,10 @@ LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& tok
             ++m_ptr;
 
         // [0-9]+
-        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
+        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
+            m_lexErrorMessage = ASCIILiteral("Exponent symbols should be followed by an optional '+' or '-' and then by at least one number");
             return TokError;
+        }
         
         ++m_ptr;
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
@@ -439,31 +535,24 @@ LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& tok
     
     token.type = TokNumber;
     token.end = m_ptr;
-    Vector<char, 64> buffer(token.end - token.start + 1);
-    int i;
-    for (i = 0; i < token.end - token.start; i++) {
-        ASSERT(static_cast<char>(token.start[i]) == token.start[i]);
-        buffer[i] = static_cast<char>(token.start[i]);
-    }
-    buffer[i] = 0;
-    char* end;
-    token.numberToken = WTF::strtod(buffer.data(), &end);
-    ASSERT(buffer.data() + (token.end - token.start) == end);
+    size_t parsedLength;
+    token.numberToken = parseDouble(token.start, token.end - token.start, parsedLength);
     return TokNumber;
 }
 
-JSValue LiteralParser::parse(ParserState initialState)
+template <typename CharType>
+JSValue LiteralParser<CharType>::parse(ParserState initialState)
 {
     ParserState state = initialState;
     MarkedArgumentBuffer objectStack;
     JSValue lastValue;
-    Vector<ParserState, 16> stateStack;
-    Vector<Identifier, 16> identifierStack;
+    Vector<ParserState, 16, UnsafeVectorOverflow> stateStack;
+    Vector<Identifier, 16, UnsafeVectorOverflow> identifierStack;
     while (1) {
         switch(state) {
             startParseArray:
             case StartParseArray: {
-                JSArray* array = constructEmptyArray(m_exec);
+                JSArray* array = constructEmptyArray(m_exec, 0);
                 objectStack.append(array);
                 // fallthrough
             }
@@ -471,8 +560,10 @@ JSValue LiteralParser::parse(ParserState initialState)
             case DoParseArrayStartExpression: {
                 TokenType lastToken = m_lexer.currentToken().type;
                 if (m_lexer.next() == TokRBracket) {
-                    if (lastToken == TokComma)
+                    if (lastToken == TokComma) {
+                        m_parseErrorMessage = ASCIILiteral("Unexpected comma at the end of array expression");
                         return JSValue();
+                    }
                     m_lexer.next();
                     lastValue = objectStack.last();
                     objectStack.removeLast();
@@ -483,13 +574,16 @@ JSValue LiteralParser::parse(ParserState initialState)
                 goto startParseExpression;
             }
             case DoParseArrayEndExpression: {
-                 asArray(objectStack.last())->push(m_exec, lastValue);
+                JSArray* array = asArray(objectStack.last());
+                array->putDirectIndex(m_exec, array->length(), lastValue);
                 
                 if (m_lexer.currentToken().type == TokComma)
                     goto doParseArrayStartExpression;
 
-                if (m_lexer.currentToken().type != TokRBracket)
+                if (m_lexer.currentToken().type != TokRBracket) {
+                    m_parseErrorMessage = ASCIILiteral("Expected ']'");
                     return JSValue();
+                }
                 
                 m_lexer.next();
                 lastValue = objectStack.last();
@@ -503,19 +597,26 @@ JSValue LiteralParser::parse(ParserState initialState)
 
                 TokenType type = m_lexer.next();
                 if (type == TokString || (m_mode != StrictJSON && type == TokIdentifier)) {
-                    Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
+                    LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
 
                     // Check for colon
-                    if (m_lexer.next() != TokColon)
+                    if (m_lexer.next() != TokColon) {
+                        m_parseErrorMessage = ASCIILiteral("Expected ':' before value in object property definition");
                         return JSValue();
+                    }
                     
                     m_lexer.next();
-                    identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength));
+                    if (identifierToken.stringIs8Bit)
+                        identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength));
+                    else
+                        identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength));
                     stateStack.append(DoParseObjectEndExpression);
                     goto startParseExpression;
                 }
-                if (type != TokRBrace) 
+                if (type != TokRBrace)  {
+                    m_parseErrorMessage = ASCIILiteral("Expected '}'");
                     return JSValue();
+                }
                 m_lexer.next();
                 lastValue = objectStack.last();
                 objectStack.removeLast();
@@ -524,27 +625,42 @@ JSValue LiteralParser::parse(ParserState initialState)
             doParseObjectStartExpression:
             case DoParseObjectStartExpression: {
                 TokenType type = m_lexer.next();
-                if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier))
+                if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier)) {
+                    m_parseErrorMessage = ASCIILiteral("Property name must be a string literal");
                     return JSValue();
-                Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
+                }
+                LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
 
                 // Check for colon
-                if (m_lexer.next() != TokColon)
+                if (m_lexer.next() != TokColon) {
+                    m_parseErrorMessage = ASCIILiteral("Expected ':'");
                     return JSValue();
+                }
 
                 m_lexer.next();
-                identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength));
+                if (identifierToken.stringIs8Bit)
+                    identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength));
+                else
+                    identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength));
                 stateStack.append(DoParseObjectEndExpression);
                 goto startParseExpression;
             }
             case DoParseObjectEndExpression:
             {
-                asObject(objectStack.last())->putDirect(m_exec->globalData(), identifierStack.last(), lastValue);
+                JSObject* object = asObject(objectStack.last());
+                PropertyName ident = identifierStack.last();
+                unsigned i = ident.asIndex();
+                if (i != PropertyName::NotAnIndex)
+                    object->putDirectIndex(m_exec, i, lastValue);
+                else
+                    object->putDirect(m_exec->vm(), ident, lastValue);
                 identifierStack.removeLast();
                 if (m_lexer.currentToken().type == TokComma)
                     goto doParseObjectStartExpression;
-                if (m_lexer.currentToken().type != TokRBrace)
+                if (m_lexer.currentToken().type != TokRBrace) {
+                    m_parseErrorMessage = ASCIILiteral("Expected '}'");
                     return JSValue();
+                }
                 m_lexer.next();
                 lastValue = objectStack.last();
                 objectStack.removeLast();
@@ -558,13 +674,16 @@ JSValue LiteralParser::parse(ParserState initialState)
                     case TokLBrace:
                         goto startParseObject;
                     case TokString: {
-                        Lexer::LiteralParserToken stringToken = m_lexer.currentToken();
+                        LiteralParserToken<CharType> stringToken = m_lexer.currentToken();
                         m_lexer.next();
-                        lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken, stringToken.stringLength).ustring());
+                        if (stringToken.stringIs8Bit)
+                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).string());
+                        else
+                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).string());
                         break;
                     }
                     case TokNumber: {
-                        Lexer::LiteralParserToken numberToken = m_lexer.currentToken();
+                        LiteralParserToken<CharType> numberToken = m_lexer.currentToken();
                         m_lexer.next();
                         lastValue = jsNumber(numberToken.numberToken);
                         break;
@@ -583,9 +702,48 @@ JSValue LiteralParser::parse(ParserState initialState)
                         m_lexer.next();
                         lastValue = jsBoolean(false);
                         break;
-
+                    case TokRBracket:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ']'");
+                        return JSValue();
+                    case TokRBrace:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '}'");
+                        return JSValue();
+                    case TokIdentifier: {
+                        const LiteralParserToken<CharType>& token = m_lexer.currentToken();
+                        if (token.stringIs8Bit)
+                            m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", String(m_lexer.currentToken().stringToken8, m_lexer.currentToken().stringLength).ascii().data()).impl();
+                        else
+                            m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", String(m_lexer.currentToken().stringToken16, m_lexer.currentToken().stringLength).ascii().data()).impl();
+                        return JSValue();
+                    }
+                    case TokColon:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ':'");
+                        return JSValue();
+                    case TokLParen:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '('");
+                        return JSValue();
+                    case TokRParen:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ')'");
+                        return JSValue();
+                    case TokComma:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ','");
+                        return JSValue();
+                    case TokDot:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '.'");
+                        return JSValue();
+                    case TokAssign:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '='");
+                        return JSValue();
+                    case TokSemi:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ';'");
+                        return JSValue();
+                    case TokEnd:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected EOF");
+                        return JSValue();
+                    case TokError:
                     default:
                         // Error
+                        m_parseErrorMessage = ASCIILiteral("Could not parse value expression");
                         return JSValue();
                 }
                 break;
@@ -602,7 +760,51 @@ JSValue LiteralParser::parse(ParserState initialState)
                         stateStack.append(StartParseStatementEndStatement);
                         goto startParseExpression;
                     }
+                    case TokRBracket:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ']'");
+                        return JSValue();
+                    case TokLBrace:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '{'");
+                        return JSValue();
+                    case TokRBrace:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '}'");
+                        return JSValue();
+                    case TokIdentifier:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected identifier");
+                        return JSValue();
+                    case TokColon:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ':'");
+                        return JSValue();
+                    case TokRParen:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ')'");
+                        return JSValue();
+                    case TokComma:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ','");
+                        return JSValue();
+                    case TokTrue:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token 'true'");
+                        return JSValue();
+                    case TokFalse:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token 'false'");
+                        return JSValue();
+                    case TokNull:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token 'null'");
+                        return JSValue();
+                    case TokEnd:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected EOF");
+                        return JSValue();
+                    case TokDot:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '.'");
+                        return JSValue();
+                    case TokAssign:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '='");
+                        return JSValue();
+                    case TokSemi:
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ';'");
+                        return JSValue();
+                    case TokError:
                     default:
+                        m_parseErrorMessage = ASCIILiteral("Could not parse statement");
                         return JSValue();
                 }
             }
@@ -612,10 +814,11 @@ JSValue LiteralParser::parse(ParserState initialState)
                     return JSValue();
                 if (m_lexer.next() == TokEnd)
                     return lastValue;
+                m_parseErrorMessage = ASCIILiteral("Unexpected content at end of JSON literal");
                 return JSValue();
             }
             default:
-                ASSERT_NOT_REACHED();
+                RELEASE_ASSERT_NOT_REACHED();
         }
         if (stateStack.isEmpty())
             return lastValue;
@@ -625,4 +828,8 @@ JSValue LiteralParser::parse(ParserState initialState)
     }
 }
 
+// Instantiate the two flavors of LiteralParser we need instead of putting most of this file in LiteralParser.h
+template class LiteralParser<LChar>;
+template class LiteralParser<UChar>;
+
 }