X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/6fe7ccc865dc7d7541b93c5bcaf6368d2c98a174..cb9aa2694aba0ae4f946ed34b8e0f6c99c1cfe44:/runtime/LiteralParser.cpp?ds=inline diff --git a/runtime/LiteralParser.cpp b/runtime/LiteralParser.cpp index e1f85ce..9b01951 100644 --- a/runtime/LiteralParser.cpp +++ b/runtime/LiteralParser.cpp @@ -27,13 +27,17 @@ #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 "JSCInlines.h" #include "StrongInlines.h" -#include "UStringBuilder.h" #include #include +#include namespace JSC { @@ -53,22 +57,24 @@ bool LiteralParser::tryJSONPParse(Vector& results, bool nee do { Vector 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::tryJSONPParse(Vector& 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::tryJSONPParse(Vector& 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 ALWAYS_INLINE const Identifier LiteralParser::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 ALWAYS_INLINE const Identifier LiteralParser::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 TokenType LiteralParser::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(token); @@ -344,7 +350,7 @@ template 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(*m_ptr)) @@ -356,7 +362,7 @@ template 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 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 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(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::Lexer::lexNumber(LiteralParserToken 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::Lexer::lexNumber(LiteralParserToken ++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::Lexer::lexNumber(LiteralParserToken // [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,22 +546,22 @@ JSValue LiteralParser::parse(ParserState initialState) ParserState state = initialState; MarkedArgumentBuffer objectStack; JSValue lastValue; - Vector stateStack; - Vector identifierStack; + Vector stateStack; + Vector identifierStack; while (1) { switch(state) { startParseArray: case StartParseArray: { - JSArray* array = constructEmptyArray(m_exec); + JSArray* array = constructEmptyArray(m_exec, 0); objectStack.append(array); - // fallthrough } doParseArrayStartExpression: + FALLTHROUGH; case DoParseArrayStartExpression: { 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::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::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::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::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 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::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::parse(ParserState initialState) LiteralParserToken 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::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& 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::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::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;