put_by_val_direct need to check the property is index or not for using putDirect...
[WebKit-https.git] / Source / JavaScriptCore / runtime / LiteralParser.cpp
1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "LiteralParser.h"
29
30 #include "ButterflyInlines.h"
31 #include "CopiedSpaceInlines.h"
32 #include "JSArray.h"
33 #include "JSString.h"
34 #include "Lexer.h"
35 #include "ObjectConstructor.h"
36 #include "JSCInlines.h"
37 #include "StrongInlines.h"
38 #include <wtf/ASCIICType.h>
39 #include <wtf/dtoa.h>
40 #include <wtf/text/StringBuilder.h>
41
42 namespace JSC {
43
44 template <typename CharType>
45 static inline bool isJSONWhiteSpace(const CharType& c)
46 {
47     // The JSON RFC 4627 defines a list of allowed characters to be considered
48     // insignificant white space: http://www.ietf.org/rfc/rfc4627.txt (2. JSON Grammar).
49     return c == ' ' || c == 0x9 || c == 0xA || c == 0xD;
50 }
51
52 template <typename CharType>
53 bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo)
54 {
55     if (m_lexer.next() != TokIdentifier)
56         return false;
57     do {
58         Vector<JSONPPathEntry> path;
59         // Unguarded next to start off the lexer
60         Identifier name = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
61         JSONPPathEntry entry;
62         if (name == m_exec->vm().propertyNames->varKeyword) {
63             if (m_lexer.next() != TokIdentifier)
64                 return false;
65             entry.m_type = JSONPPathEntryTypeDeclare;
66             entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
67             path.append(entry);
68         } else {
69             entry.m_type = JSONPPathEntryTypeDot;
70             entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
71             path.append(entry);
72         }
73         if (m_exec->vm().keywords->isKeyword(entry.m_pathEntryName))
74             return false;
75         TokenType tokenType = m_lexer.next();
76         if (entry.m_type == JSONPPathEntryTypeDeclare && tokenType != TokAssign)
77             return false;
78         while (tokenType != TokAssign) {
79             switch (tokenType) {
80             case TokLBracket: {
81                 entry.m_type = JSONPPathEntryTypeLookup;
82                 if (m_lexer.next() != TokNumber)
83                     return false;
84                 double doubleIndex = m_lexer.currentToken().numberToken;
85                 int index = (int)doubleIndex;
86                 if (index != doubleIndex || index < 0)
87                     return false;
88                 entry.m_pathIndex = index;
89                 if (m_lexer.next() != TokRBracket)
90                     return false;
91                 break;
92             }
93             case TokDot: {
94                 entry.m_type = JSONPPathEntryTypeDot;
95                 if (m_lexer.next() != TokIdentifier)
96                     return false;
97                 entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
98                 break;
99             }
100             case TokLParen: {
101                 if (path.last().m_type != JSONPPathEntryTypeDot || needsFullSourceInfo)
102                     return false;
103                 path.last().m_type = JSONPPathEntryTypeCall;
104                 entry = path.last();
105                 goto startJSON;
106             }
107             default:
108                 return false;
109             }
110             path.append(entry);
111             tokenType = m_lexer.next();
112         }
113     startJSON:
114         m_lexer.next();
115         results.append(JSONPData());
116         results.last().m_value.set(m_exec->vm(), parse(StartParseExpression));
117         if (!results.last().m_value)
118             return false;
119         results.last().m_path.swap(path);
120         if (entry.m_type == JSONPPathEntryTypeCall) {
121             if (m_lexer.currentToken().type != TokRParen)
122                 return false;
123             m_lexer.next();
124         }
125         if (m_lexer.currentToken().type != TokSemi)
126             break;
127         m_lexer.next();
128     } while (m_lexer.currentToken().type == TokIdentifier);
129     return m_lexer.currentToken().type == TokEnd;
130 }
131     
132 template <typename CharType>
133 ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const LChar* characters, size_t length)
134 {
135     if (!length)
136         return m_exec->vm().propertyNames->emptyIdentifier;
137     if (characters[0] >= MaximumCachableCharacter)
138         return Identifier(&m_exec->vm(), characters, length);
139
140     if (length == 1) {
141         if (!m_shortIdentifiers[characters[0]].isNull())
142             return m_shortIdentifiers[characters[0]];
143         m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
144         return m_shortIdentifiers[characters[0]];
145     }
146     if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
147         return m_recentIdentifiers[characters[0]];
148     m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
149     return m_recentIdentifiers[characters[0]];
150 }
151
152 template <typename CharType>
153 ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const UChar* characters, size_t length)
154 {
155     if (!length)
156         return m_exec->vm().propertyNames->emptyIdentifier;
157     if (characters[0] >= MaximumCachableCharacter)
158         return Identifier(&m_exec->vm(), characters, length);
159
160     if (length == 1) {
161         if (!m_shortIdentifiers[characters[0]].isNull())
162             return m_shortIdentifiers[characters[0]];
163         m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
164         return m_shortIdentifiers[characters[0]];
165     }
166     if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
167         return m_recentIdentifiers[characters[0]];
168     m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
169     return m_recentIdentifiers[characters[0]];
170 }
171
172 template <typename CharType>
173 template <ParserMode mode> TokenType LiteralParser<CharType>::Lexer::lex(LiteralParserToken<CharType>& token)
174 {
175     while (m_ptr < m_end && isJSONWhiteSpace(*m_ptr))
176         ++m_ptr;
177
178     ASSERT(m_ptr <= m_end);
179     if (m_ptr >= m_end) {
180         token.type = TokEnd;
181         token.start = token.end = m_ptr;
182         return TokEnd;
183     }
184     token.type = TokError;
185     token.start = m_ptr;
186     switch (*m_ptr) {
187         case '[':
188             token.type = TokLBracket;
189             token.end = ++m_ptr;
190             return TokLBracket;
191         case ']':
192             token.type = TokRBracket;
193             token.end = ++m_ptr;
194             return TokRBracket;
195         case '(':
196             token.type = TokLParen;
197             token.end = ++m_ptr;
198             return TokLParen;
199         case ')':
200             token.type = TokRParen;
201             token.end = ++m_ptr;
202             return TokRParen;
203         case '{':
204             token.type = TokLBrace;
205             token.end = ++m_ptr;
206             return TokLBrace;
207         case '}':
208             token.type = TokRBrace;
209             token.end = ++m_ptr;
210             return TokRBrace;
211         case ',':
212             token.type = TokComma;
213             token.end = ++m_ptr;
214             return TokComma;
215         case ':':
216             token.type = TokColon;
217             token.end = ++m_ptr;
218             return TokColon;
219         case '"':
220             return lexString<mode, '"'>(token);
221         case 't':
222             if (m_end - m_ptr >= 4 && m_ptr[1] == 'r' && m_ptr[2] == 'u' && m_ptr[3] == 'e') {
223                 m_ptr += 4;
224                 token.type = TokTrue;
225                 token.end = m_ptr;
226                 return TokTrue;
227             }
228             break;
229         case 'f':
230             if (m_end - m_ptr >= 5 && m_ptr[1] == 'a' && m_ptr[2] == 'l' && m_ptr[3] == 's' && m_ptr[4] == 'e') {
231                 m_ptr += 5;
232                 token.type = TokFalse;
233                 token.end = m_ptr;
234                 return TokFalse;
235             }
236             break;
237         case 'n':
238             if (m_end - m_ptr >= 4 && m_ptr[1] == 'u' && m_ptr[2] == 'l' && m_ptr[3] == 'l') {
239                 m_ptr += 4;
240                 token.type = TokNull;
241                 token.end = m_ptr;
242                 return TokNull;
243             }
244             break;
245         case '-':
246         case '0':
247         case '1':
248         case '2':
249         case '3':
250         case '4':
251         case '5':
252         case '6':
253         case '7':
254         case '8':
255         case '9':
256             return lexNumber(token);
257     }
258     if (m_ptr < m_end) {
259         if (*m_ptr == '.') {
260             token.type = TokDot;
261             token.end = ++m_ptr;
262             return TokDot;
263         }
264         if (*m_ptr == '=') {
265             token.type = TokAssign;
266             token.end = ++m_ptr;
267             return TokAssign;
268         }
269         if (*m_ptr == ';') {
270             token.type = TokSemi;
271             token.end = ++m_ptr;
272             return TokAssign;
273         }
274         if (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$')
275             return lexIdentifier(token);
276         if (*m_ptr == '\'') {
277             if (mode == StrictJSON) {
278                 m_lexErrorMessage = ASCIILiteral("Single quotes (\') are not allowed in JSON");
279                 return TokError;
280             }
281             return lexString<mode, '\''>(token);
282         }
283     }
284     m_lexErrorMessage = String::format("Unrecognized token '%c'", *m_ptr);
285     return TokError;
286 }
287
288 template <>
289 ALWAYS_INLINE TokenType LiteralParser<LChar>::Lexer::lexIdentifier(LiteralParserToken<LChar>& token)
290 {
291     while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$'))
292         m_ptr++;
293     token.stringIs8Bit = 1;
294     token.stringToken8 = token.start;
295     token.stringLength = m_ptr - token.start;
296     token.type = TokIdentifier;
297     token.end = m_ptr;
298     return TokIdentifier;
299 }
300
301 template <>
302 ALWAYS_INLINE TokenType LiteralParser<UChar>::Lexer::lexIdentifier(LiteralParserToken<UChar>& token)
303 {
304     while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$' || *m_ptr == 0x200C || *m_ptr == 0x200D))
305         m_ptr++;
306     token.stringIs8Bit = 0;
307     token.stringToken16 = token.start;
308     token.stringLength = m_ptr - token.start;
309     token.type = TokIdentifier;
310     token.end = m_ptr;
311     return TokIdentifier;
312 }
313
314 template <typename CharType>
315 TokenType LiteralParser<CharType>::Lexer::next()
316 {
317     if (m_mode == NonStrictJSON)
318         return lex<NonStrictJSON>(m_currentToken);
319     if (m_mode == JSONP)
320         return lex<JSONP>(m_currentToken);
321     return lex<StrictJSON>(m_currentToken);
322 }
323
324 template <>
325 ALWAYS_INLINE void setParserTokenString<LChar>(LiteralParserToken<LChar>& token, const LChar* string)
326 {
327     token.stringIs8Bit = 1;
328     token.stringToken8 = string;
329 }
330
331 template <>
332 ALWAYS_INLINE void setParserTokenString<UChar>(LiteralParserToken<UChar>& token, const UChar* string)
333 {
334     token.stringIs8Bit = 0;
335     token.stringToken16 = string;
336 }
337
338 template <ParserMode mode, typename CharType, LChar terminator> static inline bool isSafeStringCharacter(LChar c)
339 {
340     return (c >= ' ' && c != '\\' && c != terminator) || (c == '\t' && mode != StrictJSON);
341 }
342
343 template <ParserMode mode, typename CharType, UChar terminator> static inline bool isSafeStringCharacter(UChar c)
344 {
345     return (c >= ' ' && (mode == StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || (c == '\t' && mode != StrictJSON);
346 }
347
348 template <typename CharType>
349 template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParser<CharType>::Lexer::lexString(LiteralParserToken<CharType>& token)
350 {
351     ++m_ptr;
352     const CharType* runStart = m_ptr;
353     StringBuilder builder;
354     do {
355         runStart = m_ptr;
356         while (m_ptr < m_end && isSafeStringCharacter<mode, CharType, terminator>(*m_ptr))
357             ++m_ptr;
358         if (builder.length())
359             builder.append(runStart, m_ptr - runStart);
360         if ((mode != NonStrictJSON) && m_ptr < m_end && *m_ptr == '\\') {
361             if (builder.isEmpty() && runStart < m_ptr)
362                 builder.append(runStart, m_ptr - runStart);
363             ++m_ptr;
364             if (m_ptr >= m_end) {
365                 m_lexErrorMessage = ASCIILiteral("Unterminated string");
366                 return TokError;
367             }
368             switch (*m_ptr) {
369                 case '"':
370                     builder.append('"');
371                     m_ptr++;
372                     break;
373                 case '\\':
374                     builder.append('\\');
375                     m_ptr++;
376                     break;
377                 case '/':
378                     builder.append('/');
379                     m_ptr++;
380                     break;
381                 case 'b':
382                     builder.append('\b');
383                     m_ptr++;
384                     break;
385                 case 'f':
386                     builder.append('\f');
387                     m_ptr++;
388                     break;
389                 case 'n':
390                     builder.append('\n');
391                     m_ptr++;
392                     break;
393                 case 'r':
394                     builder.append('\r');
395                     m_ptr++;
396                     break;
397                 case 't':
398                     builder.append('\t');
399                     m_ptr++;
400                     break;
401
402                 case 'u':
403                     if ((m_end - m_ptr) < 5) { 
404                         m_lexErrorMessage = ASCIILiteral("\\u must be followed by 4 hex digits");
405                         return TokError;
406                     } // uNNNN == 5 characters
407                     for (int i = 1; i < 5; i++) {
408                         if (!isASCIIHexDigit(m_ptr[i])) {
409                             m_lexErrorMessage = String::format("\"\\%s\" is not a valid unicode escape", String(m_ptr, 5).ascii().data());
410                             return TokError;
411                         }
412                     }
413                     builder.append(JSC::Lexer<CharType>::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
414                     m_ptr += 5;
415                     break;
416
417                 default:
418                     if (*m_ptr == '\'' && mode != StrictJSON) {
419                         builder.append('\'');
420                         m_ptr++;
421                         break;
422                     }
423                     m_lexErrorMessage = String::format("Invalid escape character %c", *m_ptr);
424                     return TokError;
425             }
426         }
427     } while ((mode != NonStrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != terminator);
428
429     if (m_ptr >= m_end || *m_ptr != terminator) {
430         m_lexErrorMessage = ASCIILiteral("Unterminated string");
431         return TokError;
432     }
433
434     if (builder.isEmpty()) {
435         token.stringBuffer = String();
436         setParserTokenString<CharType>(token, runStart);
437         token.stringLength = m_ptr - runStart;
438     } else {
439         token.stringBuffer = builder.toString();
440         if (token.stringBuffer.is8Bit()) {
441             token.stringIs8Bit = 1;
442             token.stringToken8 = token.stringBuffer.characters8();
443         } else {
444             token.stringIs8Bit = 0;
445             token.stringToken16 = token.stringBuffer.characters16();
446         }
447         token.stringLength = token.stringBuffer.length();
448     }
449     token.type = TokString;
450     token.end = ++m_ptr;
451     return TokString;
452 }
453
454 template <typename CharType>
455 TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>& token)
456 {
457     // ES5 and json.org define numbers as
458     // number
459     //     int
460     //     int frac? exp?
461     //
462     // int
463     //     -? 0
464     //     -? digit1-9 digits?
465     //
466     // digits
467     //     digit digits?
468     //
469     // -?(0 | [1-9][0-9]*) ('.' [0-9]+)? ([eE][+-]? [0-9]+)?
470
471     if (m_ptr < m_end && *m_ptr == '-') // -?
472         ++m_ptr;
473     
474     // (0 | [1-9][0-9]*)
475     if (m_ptr < m_end && *m_ptr == '0') // 0
476         ++m_ptr;
477     else if (m_ptr < m_end && *m_ptr >= '1' && *m_ptr <= '9') { // [1-9]
478         ++m_ptr;
479         // [0-9]*
480         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
481             ++m_ptr;
482     } else {
483         m_lexErrorMessage = ASCIILiteral("Invalid number");
484         return TokError;
485     }
486
487     // ('.' [0-9]+)?
488     if (m_ptr < m_end && *m_ptr == '.') {
489         ++m_ptr;
490         // [0-9]+
491         if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
492             m_lexErrorMessage = ASCIILiteral("Invalid digits after decimal point");
493             return TokError;
494         }
495
496         ++m_ptr;
497         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
498             ++m_ptr;
499     } else if (m_ptr < m_end && (*m_ptr != 'e' && *m_ptr != 'E') && (m_ptr - token.start) < 10) {
500         int result = 0;
501         token.type = TokNumber;
502         token.end = m_ptr;
503         const CharType* digit = token.start;
504         int negative = 1;
505         if (*digit == '-') {
506             negative = -1;
507             digit++;
508         }
509         
510         while (digit < m_ptr)
511             result = result * 10 + (*digit++) - '0';
512         result *= negative;
513         token.numberToken = result;
514         return TokNumber;
515     }
516
517     //  ([eE][+-]? [0-9]+)?
518     if (m_ptr < m_end && (*m_ptr == 'e' || *m_ptr == 'E')) { // [eE]
519         ++m_ptr;
520
521         // [-+]?
522         if (m_ptr < m_end && (*m_ptr == '-' || *m_ptr == '+'))
523             ++m_ptr;
524
525         // [0-9]+
526         if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
527             m_lexErrorMessage = ASCIILiteral("Exponent symbols should be followed by an optional '+' or '-' and then by at least one number");
528             return TokError;
529         }
530         
531         ++m_ptr;
532         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
533             ++m_ptr;
534     }
535     
536     token.type = TokNumber;
537     token.end = m_ptr;
538     size_t parsedLength;
539     token.numberToken = parseDouble(token.start, token.end - token.start, parsedLength);
540     return TokNumber;
541 }
542
543 template <typename CharType>
544 JSValue LiteralParser<CharType>::parse(ParserState initialState)
545 {
546     ParserState state = initialState;
547     MarkedArgumentBuffer objectStack;
548     JSValue lastValue;
549     Vector<ParserState, 16, UnsafeVectorOverflow> stateStack;
550     Vector<Identifier, 16, UnsafeVectorOverflow> identifierStack;
551     while (1) {
552         switch(state) {
553             startParseArray:
554             case StartParseArray: {
555                 JSArray* array = constructEmptyArray(m_exec, 0);
556                 objectStack.append(array);
557             }
558             doParseArrayStartExpression:
559             FALLTHROUGH;
560             case DoParseArrayStartExpression: {
561                 TokenType lastToken = m_lexer.currentToken().type;
562                 if (m_lexer.next() == TokRBracket) {
563                     if (lastToken == TokComma) {
564                         m_parseErrorMessage = ASCIILiteral("Unexpected comma at the end of array expression");
565                         return JSValue();
566                     }
567                     m_lexer.next();
568                     lastValue = objectStack.last();
569                     objectStack.removeLast();
570                     break;
571                 }
572
573                 stateStack.append(DoParseArrayEndExpression);
574                 goto startParseExpression;
575             }
576             case DoParseArrayEndExpression: {
577                 JSArray* array = asArray(objectStack.last());
578                 array->putDirectIndex(m_exec, array->length(), lastValue);
579                 
580                 if (m_lexer.currentToken().type == TokComma)
581                     goto doParseArrayStartExpression;
582
583                 if (m_lexer.currentToken().type != TokRBracket) {
584                     m_parseErrorMessage = ASCIILiteral("Expected ']'");
585                     return JSValue();
586                 }
587                 
588                 m_lexer.next();
589                 lastValue = objectStack.last();
590                 objectStack.removeLast();
591                 break;
592             }
593             startParseObject:
594             case StartParseObject: {
595                 JSObject* object = constructEmptyObject(m_exec);
596                 objectStack.append(object);
597
598                 TokenType type = m_lexer.next();
599                 if (type == TokString || (m_mode != StrictJSON && type == TokIdentifier)) {
600                     LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
601
602                     // Check for colon
603                     if (m_lexer.next() != TokColon) {
604                         m_parseErrorMessage = ASCIILiteral("Expected ':' before value in object property definition");
605                         return JSValue();
606                     }
607                     
608                     m_lexer.next();
609                     if (identifierToken.stringIs8Bit)
610                         identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength));
611                     else
612                         identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength));
613                     stateStack.append(DoParseObjectEndExpression);
614                     goto startParseExpression;
615                 }
616                 if (type != TokRBrace)  {
617                     m_parseErrorMessage = ASCIILiteral("Expected '}'");
618                     return JSValue();
619                 }
620                 m_lexer.next();
621                 lastValue = objectStack.last();
622                 objectStack.removeLast();
623                 break;
624             }
625             doParseObjectStartExpression:
626             case DoParseObjectStartExpression: {
627                 TokenType type = m_lexer.next();
628                 if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier)) {
629                     m_parseErrorMessage = ASCIILiteral("Property name must be a string literal");
630                     return JSValue();
631                 }
632                 LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
633
634                 // Check for colon
635                 if (m_lexer.next() != TokColon) {
636                     m_parseErrorMessage = ASCIILiteral("Expected ':'");
637                     return JSValue();
638                 }
639
640                 m_lexer.next();
641                 if (identifierToken.stringIs8Bit)
642                     identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength));
643                 else
644                     identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength));
645                 stateStack.append(DoParseObjectEndExpression);
646                 goto startParseExpression;
647             }
648             case DoParseObjectEndExpression:
649             {
650                 JSObject* object = asObject(objectStack.last());
651                 PropertyName ident = identifierStack.last();
652                 if (Optional<uint32_t> index = ident.asIndex())
653                     object->putDirectIndex(m_exec, index.value(), lastValue);
654                 else
655                     object->putDirect(m_exec->vm(), ident, lastValue);
656                 identifierStack.removeLast();
657                 if (m_lexer.currentToken().type == TokComma)
658                     goto doParseObjectStartExpression;
659                 if (m_lexer.currentToken().type != TokRBrace) {
660                     m_parseErrorMessage = ASCIILiteral("Expected '}'");
661                     return JSValue();
662                 }
663                 m_lexer.next();
664                 lastValue = objectStack.last();
665                 objectStack.removeLast();
666                 break;
667             }
668             startParseExpression:
669             case StartParseExpression: {
670                 switch (m_lexer.currentToken().type) {
671                     case TokLBracket:
672                         goto startParseArray;
673                     case TokLBrace:
674                         goto startParseObject;
675                     case TokString: {
676                         LiteralParserToken<CharType> stringToken = m_lexer.currentToken();
677                         m_lexer.next();
678                         if (stringToken.stringIs8Bit)
679                             lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).string());
680                         else
681                             lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).string());
682                         break;
683                     }
684                     case TokNumber: {
685                         LiteralParserToken<CharType> numberToken = m_lexer.currentToken();
686                         m_lexer.next();
687                         lastValue = jsNumber(numberToken.numberToken);
688                         break;
689                     }
690                     case TokNull:
691                         m_lexer.next();
692                         lastValue = jsNull();
693                         break;
694
695                     case TokTrue:
696                         m_lexer.next();
697                         lastValue = jsBoolean(true);
698                         break;
699
700                     case TokFalse:
701                         m_lexer.next();
702                         lastValue = jsBoolean(false);
703                         break;
704                     case TokRBracket:
705                         m_parseErrorMessage = ASCIILiteral("Unexpected token ']'");
706                         return JSValue();
707                     case TokRBrace:
708                         m_parseErrorMessage = ASCIILiteral("Unexpected token '}'");
709                         return JSValue();
710                     case TokIdentifier: {
711                         const LiteralParserToken<CharType>& token = m_lexer.currentToken();
712                         if (token.stringIs8Bit)
713                             m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", String(m_lexer.currentToken().stringToken8, m_lexer.currentToken().stringLength).ascii().data());
714                         else
715                             m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", String(m_lexer.currentToken().stringToken16, m_lexer.currentToken().stringLength).ascii().data());
716                         return JSValue();
717                     }
718                     case TokColon:
719                         m_parseErrorMessage = ASCIILiteral("Unexpected token ':'");
720                         return JSValue();
721                     case TokLParen:
722                         m_parseErrorMessage = ASCIILiteral("Unexpected token '('");
723                         return JSValue();
724                     case TokRParen:
725                         m_parseErrorMessage = ASCIILiteral("Unexpected token ')'");
726                         return JSValue();
727                     case TokComma:
728                         m_parseErrorMessage = ASCIILiteral("Unexpected token ','");
729                         return JSValue();
730                     case TokDot:
731                         m_parseErrorMessage = ASCIILiteral("Unexpected token '.'");
732                         return JSValue();
733                     case TokAssign:
734                         m_parseErrorMessage = ASCIILiteral("Unexpected token '='");
735                         return JSValue();
736                     case TokSemi:
737                         m_parseErrorMessage = ASCIILiteral("Unexpected token ';'");
738                         return JSValue();
739                     case TokEnd:
740                         m_parseErrorMessage = ASCIILiteral("Unexpected EOF");
741                         return JSValue();
742                     case TokError:
743                     default:
744                         // Error
745                         m_parseErrorMessage = ASCIILiteral("Could not parse value expression");
746                         return JSValue();
747                 }
748                 break;
749             }
750             case StartParseStatement: {
751                 switch (m_lexer.currentToken().type) {
752                     case TokLBracket:
753                     case TokNumber:
754                     case TokString:
755                         goto startParseExpression;
756
757                     case TokLParen: {
758                         m_lexer.next();
759                         stateStack.append(StartParseStatementEndStatement);
760                         goto startParseExpression;
761                     }
762                     case TokRBracket:
763                         m_parseErrorMessage = ASCIILiteral("Unexpected token ']'");
764                         return JSValue();
765                     case TokLBrace:
766                         m_parseErrorMessage = ASCIILiteral("Unexpected token '{'");
767                         return JSValue();
768                     case TokRBrace:
769                         m_parseErrorMessage = ASCIILiteral("Unexpected token '}'");
770                         return JSValue();
771                     case TokIdentifier:
772                         m_parseErrorMessage = ASCIILiteral("Unexpected identifier");
773                         return JSValue();
774                     case TokColon:
775                         m_parseErrorMessage = ASCIILiteral("Unexpected token ':'");
776                         return JSValue();
777                     case TokRParen:
778                         m_parseErrorMessage = ASCIILiteral("Unexpected token ')'");
779                         return JSValue();
780                     case TokComma:
781                         m_parseErrorMessage = ASCIILiteral("Unexpected token ','");
782                         return JSValue();
783                     case TokTrue:
784                         m_parseErrorMessage = ASCIILiteral("Unexpected token 'true'");
785                         return JSValue();
786                     case TokFalse:
787                         m_parseErrorMessage = ASCIILiteral("Unexpected token 'false'");
788                         return JSValue();
789                     case TokNull:
790                         m_parseErrorMessage = ASCIILiteral("Unexpected token 'null'");
791                         return JSValue();
792                     case TokEnd:
793                         m_parseErrorMessage = ASCIILiteral("Unexpected EOF");
794                         return JSValue();
795                     case TokDot:
796                         m_parseErrorMessage = ASCIILiteral("Unexpected token '.'");
797                         return JSValue();
798                     case TokAssign:
799                         m_parseErrorMessage = ASCIILiteral("Unexpected token '='");
800                         return JSValue();
801                     case TokSemi:
802                         m_parseErrorMessage = ASCIILiteral("Unexpected token ';'");
803                         return JSValue();
804                     case TokError:
805                     default:
806                         m_parseErrorMessage = ASCIILiteral("Could not parse statement");
807                         return JSValue();
808                 }
809             }
810             case StartParseStatementEndStatement: {
811                 ASSERT(stateStack.isEmpty());
812                 if (m_lexer.currentToken().type != TokRParen)
813                     return JSValue();
814                 if (m_lexer.next() == TokEnd)
815                     return lastValue;
816                 m_parseErrorMessage = ASCIILiteral("Unexpected content at end of JSON literal");
817                 return JSValue();
818             }
819             default:
820                 RELEASE_ASSERT_NOT_REACHED();
821         }
822         if (stateStack.isEmpty())
823             return lastValue;
824         state = stateStack.last();
825         stateStack.removeLast();
826         continue;
827     }
828 }
829
830 // Instantiate the two flavors of LiteralParser we need instead of putting most of this file in LiteralParser.h
831 template class LiteralParser<LChar>;
832 template class LiteralParser<UChar>;
833
834 }