]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/LiteralParser.cpp
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / runtime / LiteralParser.cpp
index e1f85cefe6ea4e44e40c83ef6ff7c7650efe604a..f594518b6cf2acc208d3204c9a04d453ca035897 100644 (file)
 #include "config.h"
 #include "LiteralParser.h"
 
+#include "ButterflyInlines.h"
+#include "CopiedSpaceInlines.h"
 #include "JSArray.h"
 #include "JSString.h"
 #include "Lexer.h"
+#include "ObjectConstructor.h"
+#include "Operations.h"
 #include "StrongInlines.h"
-#include "UStringBuilder.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/dtoa.h>
+#include <wtf/text/StringBuilder.h>
 
 namespace JSC {
 
@@ -53,22 +57,24 @@ bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool nee
     do {
         Vector<JSONPPathEntry> path;
         // Unguarded next to start off the lexer
-        Identifier name = Identifier(&m_exec->globalData(), 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->globalData(), 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->globalData(), 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().keywords->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: {
@@ -88,7 +94,7 @@ bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool nee
                 entry.m_type = JSONPPathEntryTypeDot;
                 if (m_lexer.next() != TokIdentifier)
                     return false;
-                entry.m_pathEntryName = Identifier(&m_exec->globalData(), 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: {
@@ -107,7 +113,7 @@ bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool nee
     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);
@@ -127,19 +133,19 @@ 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]];
 }
 
@@ -147,19 +153,19 @@ template <typename CharType>
 ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const UChar* 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]];
 }
 
@@ -269,7 +275,7 @@ template <ParserMode mode> TokenType LiteralParser<CharType>::Lexer::lex(Literal
             return lexIdentifier(token);
         if (*m_ptr == '\'') {
             if (mode == StrictJSON) {
-                m_lexErrorMessage = "Single quotes (\') are not allowed in JSON";
+                m_lexErrorMessage = ASCIILiteral("Single quotes (\') are not allowed in JSON");
                 return TokError;
             }
             return lexString<mode, '\''>(token);
@@ -344,7 +350,7 @@ template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParse
 {
     ++m_ptr;
     const CharType* runStart = m_ptr;
-    UStringBuilder builder;
+    StringBuilder builder;
     do {
         runStart = m_ptr;
         while (m_ptr < m_end && isSafeStringCharacter<mode, CharType, terminator>(*m_ptr))
@@ -356,7 +362,7 @@ template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParse
                 builder.append(runStart, m_ptr - runStart);
             ++m_ptr;
             if (m_ptr >= m_end) {
-                m_lexErrorMessage = "Unterminated string";
+                m_lexErrorMessage = ASCIILiteral("Unterminated string");
                 return TokError;
             }
             switch (*m_ptr) {
@@ -395,12 +401,12 @@ template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParse
 
                 case 'u':
                     if ((m_end - m_ptr) < 5) { 
-                        m_lexErrorMessage = "\\u must be followed by 4 hex digits";
+                        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])) {
-                            m_lexErrorMessage = String::format("\"\\%s\" is not a valid unicode escape", UString(m_ptr, 5).ascii().data()).impl();
+                            m_lexErrorMessage = String::format("\"\\%s\" is not a valid unicode escape", String(m_ptr, 5).ascii().data()).impl();
                             return TokError;
                         }
                     }
@@ -421,16 +427,16 @@ template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParse
     } while ((mode != NonStrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != terminator);
 
     if (m_ptr >= m_end || *m_ptr != terminator) {
-        m_lexErrorMessage = "Unterminated string";
+        m_lexErrorMessage = ASCIILiteral("Unterminated string");
         return TokError;
     }
 
     if (builder.isEmpty()) {
-        token.stringBuffer = UString();
+        token.stringBuffer = String();
         setParserTokenString<CharType>(token, runStart);
         token.stringLength = m_ptr - runStart;
     } else {
-        token.stringBuffer = builder.toUString();
+        token.stringBuffer = builder.toString();
         if (token.stringBuffer.is8Bit()) {
             token.stringIs8Bit = 1;
             token.stringToken8 = token.stringBuffer.characters8();
@@ -474,7 +480,7 @@ TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
             ++m_ptr;
     } else {
-        m_lexErrorMessage = "Invalid number";
+        m_lexErrorMessage = ASCIILiteral("Invalid number");
         return TokError;
     }
 
@@ -483,7 +489,7 @@ TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>
         ++m_ptr;
         // [0-9]+
         if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
-            m_lexErrorMessage = "Invalid digits after decimal point";
+            m_lexErrorMessage = ASCIILiteral("Invalid digits after decimal point");
             return TokError;
         }
 
@@ -518,7 +524,7 @@ TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>
 
         // [0-9]+
         if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
-            m_lexErrorMessage = "Exponent symbols should be followed by an optional '+' or '-' and then by at least one number";
+            m_lexErrorMessage = ASCIILiteral("Exponent symbols should be followed by an optional '+' or '-' and then by at least one number");
             return TokError;
         }
         
@@ -540,13 +546,13 @@ 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
             }
@@ -555,7 +561,7 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
                 TokenType lastToken = m_lexer.currentToken().type;
                 if (m_lexer.next() == TokRBracket) {
                     if (lastToken == TokComma) {
-                        m_parseErrorMessage = "Unexpected comma at the end of array expression";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected comma at the end of array expression");
                         return JSValue();
                     }
                     m_lexer.next();
@@ -568,13 +574,14 @@ JSValue LiteralParser<CharType>::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) {
-                    m_parseErrorMessage = "Expected ']'";
+                    m_parseErrorMessage = ASCIILiteral("Expected ']'");
                     return JSValue();
                 }
                 
@@ -594,7 +601,7 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
 
                     // Check for colon
                     if (m_lexer.next() != TokColon) {
-                        m_parseErrorMessage = "Expected ':' before value in object property definition";
+                        m_parseErrorMessage = ASCIILiteral("Expected ':' before value in object property definition");
                         return JSValue();
                     }
                     
@@ -607,7 +614,7 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
                     goto startParseExpression;
                 }
                 if (type != TokRBrace)  {
-                    m_parseErrorMessage = "Expected '}'";
+                    m_parseErrorMessage = ASCIILiteral("Expected '}'");
                     return JSValue();
                 }
                 m_lexer.next();
@@ -619,14 +626,14 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
             case DoParseObjectStartExpression: {
                 TokenType type = m_lexer.next();
                 if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier)) {
-                    m_parseErrorMessage = "Property name must be a string literal";
+                    m_parseErrorMessage = ASCIILiteral("Property name must be a string literal");
                     return JSValue();
                 }
                 LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
 
                 // Check for colon
                 if (m_lexer.next() != TokColon) {
-                    m_parseErrorMessage = "Expected ':'";
+                    m_parseErrorMessage = ASCIILiteral("Expected ':'");
                     return JSValue();
                 }
 
@@ -640,12 +647,18 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
             }
             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) {
-                    m_parseErrorMessage = "Expected '}'";
+                    m_parseErrorMessage = ASCIILiteral("Expected '}'");
                     return JSValue();
                 }
                 m_lexer.next();
@@ -664,9 +677,9 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
                         LiteralParserToken<CharType> stringToken = m_lexer.currentToken();
                         m_lexer.next();
                         if (stringToken.stringIs8Bit)
-                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).ustring());
+                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).string());
                         else
-                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).ustring());
+                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).string());
                         break;
                     }
                     case TokNumber: {
@@ -690,47 +703,47 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
                         lastValue = jsBoolean(false);
                         break;
                     case TokRBracket:
-                        m_parseErrorMessage = "Unexpected token ']'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ']'");
                         return JSValue();
                     case TokRBrace:
-                        m_parseErrorMessage = "Unexpected token '}'";
+                        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\"", UString(m_lexer.currentToken().stringToken8, m_lexer.currentToken().stringLength).ascii().data()).impl();
+                            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\"", UString(m_lexer.currentToken().stringToken16, m_lexer.currentToken().stringLength).ascii().data()).impl();
+                            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 = "Unexpected token ':'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ':'");
                         return JSValue();
                     case TokLParen:
-                        m_parseErrorMessage = "Unexpected token '('";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '('");
                         return JSValue();
                     case TokRParen:
-                        m_parseErrorMessage = "Unexpected token ')'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ')'");
                         return JSValue();
                     case TokComma:
-                        m_parseErrorMessage = "Unexpected token ','";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ','");
                         return JSValue();
                     case TokDot:
-                        m_parseErrorMessage = "Unexpected token '.'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '.'");
                         return JSValue();
                     case TokAssign:
-                        m_parseErrorMessage = "Unexpected token '='";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '='");
                         return JSValue();
                     case TokSemi:
-                        m_parseErrorMessage = "Unexpected token ';'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ';'");
                         return JSValue();
                     case TokEnd:
-                        m_parseErrorMessage = "Unexpected EOF";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected EOF");
                         return JSValue();
                     case TokError:
                     default:
                         // Error
-                        m_parseErrorMessage = "Could not parse value expression";
+                        m_parseErrorMessage = ASCIILiteral("Could not parse value expression");
                         return JSValue();
                 }
                 break;
@@ -748,50 +761,50 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
                         goto startParseExpression;
                     }
                     case TokRBracket:
-                        m_parseErrorMessage = "Unexpected token ']'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ']'");
                         return JSValue();
                     case TokLBrace:
-                        m_parseErrorMessage = "Unexpected token '{'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '{'");
                         return JSValue();
                     case TokRBrace:
-                        m_parseErrorMessage = "Unexpected token '}'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '}'");
                         return JSValue();
                     case TokIdentifier:
-                        m_parseErrorMessage = "Unexpected identifier";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected identifier");
                         return JSValue();
                     case TokColon:
-                        m_parseErrorMessage = "Unexpected token ':'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ':'");
                         return JSValue();
                     case TokRParen:
-                        m_parseErrorMessage = "Unexpected token ')'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ')'");
                         return JSValue();
                     case TokComma:
-                        m_parseErrorMessage = "Unexpected token ','";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ','");
                         return JSValue();
                     case TokTrue:
-                        m_parseErrorMessage = "Unexpected token 'true'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token 'true'");
                         return JSValue();
                     case TokFalse:
-                        m_parseErrorMessage = "Unexpected token 'false'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token 'false'");
                         return JSValue();
                     case TokNull:
-                        m_parseErrorMessage = "Unexpected token 'null'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token 'null'");
                         return JSValue();
                     case TokEnd:
-                        m_parseErrorMessage = "Unexpected EOF";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected EOF");
                         return JSValue();
                     case TokDot:
-                        m_parseErrorMessage = "Unexpected token '.'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '.'");
                         return JSValue();
                     case TokAssign:
-                        m_parseErrorMessage = "Unexpected token '='";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token '='");
                         return JSValue();
                     case TokSemi:
-                        m_parseErrorMessage = "Unexpected token ';'";
+                        m_parseErrorMessage = ASCIILiteral("Unexpected token ';'");
                         return JSValue();
                     case TokError:
                     default:
-                        m_parseErrorMessage = "Could not parse statement";
+                        m_parseErrorMessage = ASCIILiteral("Could not parse statement");
                         return JSValue();
                 }
             }
@@ -801,11 +814,11 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
                     return JSValue();
                 if (m_lexer.next() == TokEnd)
                     return lastValue;
-                m_parseErrorMessage = "Unexpected content at end of JSON literal";
+                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;